From 90cce2cbee999127646c4b73b0a69dcebfc9752d Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Mon, 20 Jan 2025 17:48:28 +0100
Subject: [PATCH 01/18]  fix

---
 config/config.go                              | 38 ++++++++++++
 config/config_test.go                         | 61 +++++++++++++++++++
 config/testdata/fromenv/config.ini            |  8 +++
 .../.config/ArduinoCreateAgent/config.ini     |  8 +++
 .../.config/ArduinoCreateAgent/config.ini     | 10 +++
 main.go                                       | 34 +----------
 6 files changed, 128 insertions(+), 31 deletions(-)
 create mode 100644 config/config_test.go
 create mode 100644 config/testdata/fromenv/config.ini
 create mode 100644 config/testdata/home/.config/ArduinoCreateAgent/config.ini
 create mode 100644 config/testdata/noconfig/.config/ArduinoCreateAgent/config.ini

diff --git a/config/config.go b/config/config.go
index 69d29eeee..50978eb82 100644
--- a/config/config.go
+++ b/config/config.go
@@ -142,3 +142,41 @@ func SetInstallCertsIni(filename string, value string) error {
 	}
 	return nil
 }
+
+func GetConfigPath() *paths.Path {
+	// Let's handle the config
+	configDir := GetDefaultConfigDir()
+	var configPath *paths.Path
+
+	// see if the env var is defined, if it is take the config from there, this will override the default path
+	if envConfig := os.Getenv("ARDUINO_CREATE_AGENT_CONFIG"); envConfig != "" {
+		configPath = paths.New(envConfig)
+		if configPath.NotExist() {
+			log.Panicf("config from env var %s does not exists", envConfig)
+		}
+		log.Infof("using config from env variable: %s", configPath)
+	} else if defaultConfigPath := configDir.Join("config.ini"); defaultConfigPath.Exist() {
+		// by default take the config from the ~/.arduino-create/config.ini file
+		configPath = defaultConfigPath
+		log.Infof("using config from default: %s", configPath)
+	} else {
+		// Fall back to the old config.ini location
+		src, _ := os.Executable()
+		oldConfigPath := paths.New(src).Parent().Join("config.ini")
+		if oldConfigPath.Exist() {
+			err := oldConfigPath.CopyTo(defaultConfigPath)
+			if err != nil {
+				log.Errorf("cannot copy old %s, to %s, generating new config", oldConfigPath, configPath)
+			} else {
+				configPath = defaultConfigPath
+				log.Infof("copied old %s, to %s", oldConfigPath, configPath)
+			}
+		}
+	}
+	if configPath == nil {
+		configPath = GenerateConfig(configDir)
+	}
+
+	return configPath
+
+}
diff --git a/config/config_test.go b/config/config_test.go
new file mode 100644
index 000000000..76e6988c0
--- /dev/null
+++ b/config/config_test.go
@@ -0,0 +1,61 @@
+package config
+
+import (
+	"fmt"
+	"os"
+	"testing"
+
+	"github.com/arduino/go-paths-helper"
+	"github.com/sirupsen/logrus"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestGetConfigPath(t *testing.T) {
+	t.Run("read config.ini from ARDUINO_CREATE_AGENT_CONFIG", func(t *testing.T) {
+		os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/fromenv/config.ini")
+		defer os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
+		configPath := GetConfigPath()
+		assert.Equal(t, "./testdata/fromenv/config.ini", configPath.String())
+	})
+
+	t.Run("panic if config.ini does not exist", func(t *testing.T) {
+		os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/nonexistent_config.ini")
+		defer os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
+
+		defer func() {
+			if r := recover(); r != nil {
+				entry, ok := r.(*logrus.Entry)
+				if !ok {
+					t.Errorf("Expected panic of type *logrus.Entry but got %T", r)
+				} else {
+					assert.Equal(t, "config from env var ./testdata/nonexistent_config.ini does not exists", entry.Message)
+				}
+			} else {
+				t.Errorf("Expected panic but did not get one")
+			}
+		}()
+
+		GetConfigPath()
+	})
+
+	t.Run("read config.ini from $HOME", func(t *testing.T) {
+		os.Setenv("HOME", "./testdata/home")
+		defer os.Unsetenv("HOME")
+		configPath := GetConfigPath()
+		assert.Equal(t, "testdata/home/.config/ArduinoCreateAgent/config.ini", configPath.String())
+	})
+
+	t.Run("fallback old : read config.ini where the binary is launched", func(t *testing.T) {
+		src, _ := os.Executable()
+		paths.New(src).Parent().Join("config.ini").Create() // create a config.ini in the same directory as the binary
+		// The fallback path is the directory where the binary is launched
+		fmt.Println(src)
+		os.Setenv("HOME", "./testdata/noconfig") // force to not have a config in the home directory
+		defer os.Unsetenv("HOME")
+
+		// expect it creates a config.ini in the same directory as the binary
+		configPath := GetConfigPath()
+		assert.Equal(t, "testdata/home/.config/ArduinoCreateAgent/config.ini", configPath.String())
+	})
+
+}
diff --git a/config/testdata/fromenv/config.ini b/config/testdata/fromenv/config.ini
new file mode 100644
index 000000000..5b31315b9
--- /dev/null
+++ b/config/testdata/fromenv/config.ini
@@ -0,0 +1,8 @@
+gc = std
+hostname = unknown-hostname
+regex = usb|acm|com
+v = true
+appName = CreateAgent/Stable
+updateUrl = https://downloads.arduino.cc/
+origins = https://local.arduino.cc:8000, https://local.arduino.cc:8001, https://create-dev.arduino.cc, https://*.sparklyunicorn.cc, https://*.iot-cloud-arduino-cc.pages.dev, https://cloud.oniudra.cc, https://app.oniudra.cc,https://*.iot-cloud-arduino-cc.pages.dev
+crashreport = false
diff --git a/config/testdata/home/.config/ArduinoCreateAgent/config.ini b/config/testdata/home/.config/ArduinoCreateAgent/config.ini
new file mode 100644
index 000000000..92f231faf
--- /dev/null
+++ b/config/testdata/home/.config/ArduinoCreateAgent/config.ini
@@ -0,0 +1,8 @@
+gc = std
+hostname = unknown-hostname
+regex = usb|acm|com
+v = true
+appName = config-from-home-dir
+updateUrl = https://downloads.arduino.cc/
+origins = https://local.arduino.cc:8000, https://local.arduino.cc:8001, https://*.iot-cloud-arduino-cc.pages.dev
+crashreport = false
diff --git a/config/testdata/noconfig/.config/ArduinoCreateAgent/config.ini b/config/testdata/noconfig/.config/ArduinoCreateAgent/config.ini
new file mode 100644
index 000000000..f63377db5
--- /dev/null
+++ b/config/testdata/noconfig/.config/ArduinoCreateAgent/config.ini
@@ -0,0 +1,10 @@
+gc = std  # Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)
+hostname = unknown-hostname  # Override the hostname we get from the OS
+regex = usb|acm|com  # Regular expression to filter serial port list
+v = true  # show debug logging
+appName = CreateAgent/Stable
+updateUrl = https://downloads.arduino.cc/
+origins = https://local.arduino.cc:8000
+#httpProxy = http://your.proxy:port # Proxy server for HTTP requests
+crashreport = false # enable crashreport logging
+autostartMacOS = true # the Arduino Create Agent is able to start automatically after login on macOS (launchd agent)
\ No newline at end of file
diff --git a/main.go b/main.go
index 1ca857b02..a83d7f4c5 100755
--- a/main.go
+++ b/main.go
@@ -22,6 +22,7 @@ import (
 	_ "embed"
 	"encoding/json"
 	"flag"
+	"fmt"
 	"html/template"
 	"io"
 	"os"
@@ -188,38 +189,9 @@ func loop() {
 		h.broadcastSys <- mapB
 	}
 
-	// Let's handle the config
-	configDir := config.GetDefaultConfigDir()
-	var configPath *paths.Path
+	configPath := config.GetConfigPath()
 
-	// see if the env var is defined, if it is take the config from there, this will override the default path
-	if envConfig := os.Getenv("ARDUINO_CREATE_AGENT_CONFIG"); envConfig != "" {
-		configPath = paths.New(envConfig)
-		if configPath.NotExist() {
-			log.Panicf("config from env var %s does not exists", envConfig)
-		}
-		log.Infof("using config from env variable: %s", configPath)
-	} else if defaultConfigPath := configDir.Join("config.ini"); defaultConfigPath.Exist() {
-		// by default take the config from the ~/.arduino-create/config.ini file
-		configPath = defaultConfigPath
-		log.Infof("using config from default: %s", configPath)
-	} else {
-		// Fall back to the old config.ini location
-		src, _ := os.Executable()
-		oldConfigPath := paths.New(src).Parent().Join("config.ini")
-		if oldConfigPath.Exist() {
-			err := oldConfigPath.CopyTo(defaultConfigPath)
-			if err != nil {
-				log.Errorf("cannot copy old %s, to %s, generating new config", oldConfigPath, configPath)
-			} else {
-				configPath = defaultConfigPath
-				log.Infof("copied old %s, to %s", oldConfigPath, configPath)
-			}
-		}
-	}
-	if configPath == nil {
-		configPath = config.GenerateConfig(configDir)
-	}
+	fmt.Println("configPath: ", configPath)
 
 	// if the default browser is Safari, prompt the user to install HTTPS certificates
 	// and eventually install them

From c96490b00cc260f6ee243d679d079a44864d8ad5 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Tue, 21 Jan 2025 11:33:56 +0100
Subject: [PATCH 02/18] feat(config): add default configuration file and update
 config handling

---
 config/config-default.ini             | 10 ++++++
 config/config.go                      |  2 +-
 config/config_test.go                 | 48 +++++++++++++++++++++------
 config/testdata/fromlegacy/.gitignore |  1 +
 4 files changed, 50 insertions(+), 11 deletions(-)
 create mode 100644 config/config-default.ini
 create mode 100644 config/testdata/fromlegacy/.gitignore

diff --git a/config/config-default.ini b/config/config-default.ini
new file mode 100644
index 000000000..f63377db5
--- /dev/null
+++ b/config/config-default.ini
@@ -0,0 +1,10 @@
+gc = std  # Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)
+hostname = unknown-hostname  # Override the hostname we get from the OS
+regex = usb|acm|com  # Regular expression to filter serial port list
+v = true  # show debug logging
+appName = CreateAgent/Stable
+updateUrl = https://downloads.arduino.cc/
+origins = https://local.arduino.cc:8000
+#httpProxy = http://your.proxy:port # Proxy server for HTTP requests
+crashreport = false # enable crashreport logging
+autostartMacOS = true # the Arduino Create Agent is able to start automatically after login on macOS (launchd agent)
\ No newline at end of file
diff --git a/config/config.go b/config/config.go
index 50978eb82..9919bfbbc 100644
--- a/config/config.go
+++ b/config/config.go
@@ -108,7 +108,7 @@ func GetDefaultHomeDir() *paths.Path {
 	return paths.New(homeDir)
 }
 
-//go:embed config.ini
+//go:embed config-default.ini
 var configContent []byte
 
 // GenerateConfig function will take a directory path as an input
diff --git a/config/config_test.go b/config/config_test.go
index 76e6988c0..4d1c64ec8 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -1,9 +1,9 @@
 package config
 
 import (
-	"fmt"
 	"os"
 	"testing"
+	"time"
 
 	"github.com/arduino/go-paths-helper"
 	"github.com/sirupsen/logrus"
@@ -38,24 +38,52 @@ func TestGetConfigPath(t *testing.T) {
 		GetConfigPath()
 	})
 
-	t.Run("read config.ini from $HOME", func(t *testing.T) {
+	t.Run("read config.ini from $HOME/.config/ArduinoCreateAgent folder", func(t *testing.T) {
 		os.Setenv("HOME", "./testdata/home")
 		defer os.Unsetenv("HOME")
 		configPath := GetConfigPath()
 		assert.Equal(t, "testdata/home/.config/ArduinoCreateAgent/config.ini", configPath.String())
 	})
 
-	t.Run("fallback old : read config.ini where the binary is launched", func(t *testing.T) {
-		src, _ := os.Executable()
-		paths.New(src).Parent().Join("config.ini").Create() // create a config.ini in the same directory as the binary
-		// The fallback path is the directory where the binary is launched
-		fmt.Println(src)
-		os.Setenv("HOME", "./testdata/noconfig") // force to not have a config in the home directory
+	t.Run("legacy config are copied to new location", func(t *testing.T) {
+
+		createLegacyConfig := func() string {
+			// Create a "legacy" config.ini in the same directory as the binary executable
+			src, err := os.Executable()
+			if err != nil {
+				t.Fatal(err)
+			}
+			legacyConfigPath, err := paths.New(src).Parent().Join("config.ini").Create()
+			if err != nil {
+				t.Fatal(err)
+			}
+			// adding a timestamp to the content to make it unique
+			c := "hostname = legacy-config-file-" + time.Now().String()
+			n, err := legacyConfigPath.WriteString(c)
+			if err != nil || n <= 0 {
+				t.Fatalf("Failed to write legacy config file: %v", err)
+			}
+			return c
+		}
+
+		wantContent := createLegacyConfig()
+
+		// Expectation: it copies the "legacy" config.ini into the location pointed by $HOME
+		os.Setenv("HOME", "./testdata/fromlegacy")
 		defer os.Unsetenv("HOME")
 
-		// expect it creates a config.ini in the same directory as the binary
+		// remove any existing config.ini in the into the location pointed by $HOME
+		err := os.Remove("./testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini")
+		if err != nil && !os.IsNotExist(err) {
+			t.Fatal(err)
+		}
+
 		configPath := GetConfigPath()
-		assert.Equal(t, "testdata/home/.config/ArduinoCreateAgent/config.ini", configPath.String())
+		assert.Equal(t, "testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini", configPath.String())
+
+		given, err := paths.New(configPath.String()).ReadFile()
+		assert.Nil(t, err)
+		assert.Equal(t, wantContent, string(given))
 	})
 
 }
diff --git a/config/testdata/fromlegacy/.gitignore b/config/testdata/fromlegacy/.gitignore
new file mode 100644
index 000000000..2fa7ce7c4
--- /dev/null
+++ b/config/testdata/fromlegacy/.gitignore
@@ -0,0 +1 @@
+config.ini

From 7b4859a7b35003f5323bc70a45eea87ed38a292c Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Tue, 21 Jan 2025 11:34:07 +0100
Subject: [PATCH 03/18] fix(.gitignore): add entry to ignore config.ini file

---
 config/testdata/fromlegacy/.gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/config/testdata/fromlegacy/.gitignore b/config/testdata/fromlegacy/.gitignore
index 2fa7ce7c4..f67b7f089 100644
--- a/config/testdata/fromlegacy/.gitignore
+++ b/config/testdata/fromlegacy/.gitignore
@@ -1 +1,2 @@
+# ingore because this config file
 config.ini

From 279de2ac65f7bfe6ad8597fcaaf00f6fc2df90e0 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Tue, 21 Jan 2025 12:48:37 +0100
Subject: [PATCH 04/18] test(config): add test for writing default config.ini
 file and update test data

---
 config/config_test.go                         | 19 +++++++++++++++++++
 config/testdata/fromdefault/.gitignore        |  1 +
 config/testdata/fromenv/config.ini            |  2 +-
 .../.config/ArduinoCreateAgent/config.ini     |  2 +-
 4 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 config/testdata/fromdefault/.gitignore

diff --git a/config/config_test.go b/config/config_test.go
index 4d1c64ec8..666d85fbc 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -86,4 +86,23 @@ func TestGetConfigPath(t *testing.T) {
 		assert.Equal(t, wantContent, string(given))
 	})
 
+	t.Run("write the default config.ini file", func(t *testing.T) {
+		os.Setenv("HOME", "./testdata/fromdefault")
+		os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
+
+		// ensure the config.ini does not exist in the target directory
+		os.Remove("./testdata/fromdefault/.config/ArduinoCreateAgent/config.ini")
+
+		configPath := GetConfigPath()
+
+		assert.Equal(t, "testdata/fromdefault/.config/ArduinoCreateAgent/config.ini", configPath.String())
+
+		givenContent, err := paths.New(configPath.String()).ReadFile()
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		assert.Equal(t, configContent, givenContent)
+	})
+
 }
diff --git a/config/testdata/fromdefault/.gitignore b/config/testdata/fromdefault/.gitignore
new file mode 100644
index 000000000..2fa7ce7c4
--- /dev/null
+++ b/config/testdata/fromdefault/.gitignore
@@ -0,0 +1 @@
+config.ini
diff --git a/config/testdata/fromenv/config.ini b/config/testdata/fromenv/config.ini
index 5b31315b9..cfd58d812 100644
--- a/config/testdata/fromenv/config.ini
+++ b/config/testdata/fromenv/config.ini
@@ -1,5 +1,5 @@
 gc = std
-hostname = unknown-hostname
+hostname = this-is-a-config-file-from-home-dir-from-ARDUINO_CREATE_AGENT_CONFIG-env
 regex = usb|acm|com
 v = true
 appName = CreateAgent/Stable
diff --git a/config/testdata/home/.config/ArduinoCreateAgent/config.ini b/config/testdata/home/.config/ArduinoCreateAgent/config.ini
index 92f231faf..a023d62d1 100644
--- a/config/testdata/home/.config/ArduinoCreateAgent/config.ini
+++ b/config/testdata/home/.config/ArduinoCreateAgent/config.ini
@@ -1,5 +1,5 @@
 gc = std
-hostname = unknown-hostname
+hostname = this-is-a-config-file-from-home-dir
 regex = usb|acm|com
 v = true
 appName = config-from-home-dir

From 4f3ac5a2ce1680ec895db5039357f0f7dddf30c8 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Tue, 21 Jan 2025 17:27:03 +0100
Subject: [PATCH 05/18] test(config): add tests for retrieving config paths
 from XDG_CONFIG_HOME and HOME directories

---
 config/config_test.go                         | 176 ++++++++----------
 .../.config/ArduinoCreateAgent/config.ini     |   8 +
 .../fromxdghome/ArduinoCreateAgent/config.ini |  10 +
 3 files changed, 99 insertions(+), 95 deletions(-)
 create mode 100644 config/testdata/fromhome/.config/ArduinoCreateAgent/config.ini
 create mode 100644 config/testdata/fromxdghome/ArduinoCreateAgent/config.ini

diff --git a/config/config_test.go b/config/config_test.go
index 666d85fbc..447f3793e 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -6,103 +6,89 @@ import (
 	"time"
 
 	"github.com/arduino/go-paths-helper"
-	"github.com/sirupsen/logrus"
 	"github.com/stretchr/testify/assert"
 )
 
-func TestGetConfigPath(t *testing.T) {
-	t.Run("read config.ini from ARDUINO_CREATE_AGENT_CONFIG", func(t *testing.T) {
-		os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/fromenv/config.ini")
-		defer os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
-		configPath := GetConfigPath()
-		assert.Equal(t, "./testdata/fromenv/config.ini", configPath.String())
-	})
-
-	t.Run("panic if config.ini does not exist", func(t *testing.T) {
-		os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/nonexistent_config.ini")
-		defer os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
-
-		defer func() {
-			if r := recover(); r != nil {
-				entry, ok := r.(*logrus.Entry)
-				if !ok {
-					t.Errorf("Expected panic of type *logrus.Entry but got %T", r)
-				} else {
-					assert.Equal(t, "config from env var ./testdata/nonexistent_config.ini does not exists", entry.Message)
-				}
-			} else {
-				t.Errorf("Expected panic but did not get one")
-			}
-		}()
-
-		GetConfigPath()
-	})
-
-	t.Run("read config.ini from $HOME/.config/ArduinoCreateAgent folder", func(t *testing.T) {
-		os.Setenv("HOME", "./testdata/home")
-		defer os.Unsetenv("HOME")
-		configPath := GetConfigPath()
-		assert.Equal(t, "testdata/home/.config/ArduinoCreateAgent/config.ini", configPath.String())
-	})
-
-	t.Run("legacy config are copied to new location", func(t *testing.T) {
-
-		createLegacyConfig := func() string {
-			// Create a "legacy" config.ini in the same directory as the binary executable
-			src, err := os.Executable()
-			if err != nil {
-				t.Fatal(err)
-			}
-			legacyConfigPath, err := paths.New(src).Parent().Join("config.ini").Create()
-			if err != nil {
-				t.Fatal(err)
-			}
-			// adding a timestamp to the content to make it unique
-			c := "hostname = legacy-config-file-" + time.Now().String()
-			n, err := legacyConfigPath.WriteString(c)
-			if err != nil || n <= 0 {
-				t.Fatalf("Failed to write legacy config file: %v", err)
-			}
-			return c
-		}
-
-		wantContent := createLegacyConfig()
-
-		// Expectation: it copies the "legacy" config.ini into the location pointed by $HOME
-		os.Setenv("HOME", "./testdata/fromlegacy")
-		defer os.Unsetenv("HOME")
-
-		// remove any existing config.ini in the into the location pointed by $HOME
-		err := os.Remove("./testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini")
-		if err != nil && !os.IsNotExist(err) {
-			t.Fatal(err)
-		}
-
-		configPath := GetConfigPath()
-		assert.Equal(t, "testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini", configPath.String())
-
-		given, err := paths.New(configPath.String()).ReadFile()
-		assert.Nil(t, err)
-		assert.Equal(t, wantContent, string(given))
-	})
-
-	t.Run("write the default config.ini file", func(t *testing.T) {
-		os.Setenv("HOME", "./testdata/fromdefault")
-		os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
-
-		// ensure the config.ini does not exist in the target directory
-		os.Remove("./testdata/fromdefault/.config/ArduinoCreateAgent/config.ini")
-
-		configPath := GetConfigPath()
-
-		assert.Equal(t, "testdata/fromdefault/.config/ArduinoCreateAgent/config.ini", configPath.String())
-
-		givenContent, err := paths.New(configPath.String()).ReadFile()
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		assert.Equal(t, configContent, givenContent)
-	})
+func TestGetConfigPathFromXDG_CONFIG_HOME(t *testing.T) {
+	// read config from $XDG_CONFIG_HOME/ArduinoCreateAgent/config.ini
+	os.Setenv("XDG_CONFIG_HOME", "./testdata/fromxdghome")
+	defer os.Unsetenv("XDG_CONFIG_HOME")
+	configPath := GetConfigPath()
+	assert.Equal(t, "testdata/fromxdghome/ArduinoCreateAgent/config.ini", configPath.String())
+}
+
+func TestGetConfigPathFromHOME(t *testing.T) {
+	// Test case 2: read config from $HOME/.config/ArduinoCreateAgent/config.ini "
+	os.Setenv("HOME", "./testdata/fromhome")
+	defer os.Unsetenv("HOME")
+	configPath := GetConfigPath()
+	assert.Equal(t, "testdata/fromhome/.config/ArduinoCreateAgent/config.ini", configPath.String())
+
+}
+
+func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
+	// read config from ARDUINO_CREATE_AGENT_CONFIG/config.ini"
+	os.Setenv("HOME", "./fromhome")
+	os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/fromenv/config.ini")
+	defer os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
+
+	configPath := GetConfigPath()
+	assert.Equal(t, "./testdata/fromenv/config.ini", configPath.String())
+}
 
+func TestGetConfigPathFromLegacyConfig(t *testing.T) {
+	// If no config is found, copy the legacy config to the new location
+	src, err := os.Executable()
+	if err != nil {
+		t.Fatal(err)
+	}
+	legacyConfigPath, err := paths.New(src).Parent().Join("config.ini").Create()
+	if err != nil {
+		t.Fatal(err)
+	}
+	// adding a timestamp to the content to make it unique
+	legacyContent := "hostname = legacy-config-file-" + time.Now().String()
+	n, err := legacyConfigPath.WriteString(legacyContent)
+	if err != nil || n <= 0 {
+		t.Fatalf("Failed to write legacy config file: %v", err)
+	}
+
+	// remove any existing config.ini in the into the location pointed by $HOME
+	err = os.Remove("./testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini")
+	if err != nil && !os.IsNotExist(err) {
+		t.Fatal(err)
+	}
+
+	// Expectation: it copies the "legacy" config.ini into the location pointed by $HOME
+	os.Setenv("HOME", "./testdata/fromlegacy")
+	defer os.Unsetenv("HOME")
+
+	configPath := GetConfigPath()
+	assert.Equal(t, "testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini", configPath.String())
+
+	given, err := paths.New(configPath.String()).ReadFile()
+	assert.Nil(t, err)
+	assert.Equal(t, legacyContent, string(given))
 }
+
+// func TestGetConfigPathCreateDefaultConfig(t *testing.T) {
+// 	os.Setenv("HOME", "./testdata/noconfig")
+// 	os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
+
+// 	// ensure the config.ini does not exist in HOME directory
+// 	os.Remove("./testdata/noconfig/.config/ArduinoCreateAgent/config.ini")
+// 	// ensure the config.ini does not exist in target directory
+// 	os.Remove("./testdata/fromdefault/.config/ArduinoCreateAgent/config.ini")
+
+// 	configPath := GetConfigPath()
+
+// 	assert.Equal(t, "testdata/fromdefault/.config/ArduinoCreateAgent/config.ini", configPath.String())
+
+// 	givenContent, err := paths.New(configPath.String()).ReadFile()
+// 	if err != nil {
+// 		t.Fatal(err)
+// 	}
+
+// 	assert.Equal(t, string(configContent), string(givenContent))
+
+// }
diff --git a/config/testdata/fromhome/.config/ArduinoCreateAgent/config.ini b/config/testdata/fromhome/.config/ArduinoCreateAgent/config.ini
new file mode 100644
index 000000000..a023d62d1
--- /dev/null
+++ b/config/testdata/fromhome/.config/ArduinoCreateAgent/config.ini
@@ -0,0 +1,8 @@
+gc = std
+hostname = this-is-a-config-file-from-home-dir
+regex = usb|acm|com
+v = true
+appName = config-from-home-dir
+updateUrl = https://downloads.arduino.cc/
+origins = https://local.arduino.cc:8000, https://local.arduino.cc:8001, https://*.iot-cloud-arduino-cc.pages.dev
+crashreport = false
diff --git a/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini b/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini
new file mode 100644
index 000000000..f63377db5
--- /dev/null
+++ b/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini
@@ -0,0 +1,10 @@
+gc = std  # Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)
+hostname = unknown-hostname  # Override the hostname we get from the OS
+regex = usb|acm|com  # Regular expression to filter serial port list
+v = true  # show debug logging
+appName = CreateAgent/Stable
+updateUrl = https://downloads.arduino.cc/
+origins = https://local.arduino.cc:8000
+#httpProxy = http://your.proxy:port # Proxy server for HTTP requests
+crashreport = false # enable crashreport logging
+autostartMacOS = true # the Arduino Create Agent is able to start automatically after login on macOS (launchd agent)
\ No newline at end of file

From c41b815787b77a60660461f9d9896666e27bd412 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 22 Jan 2025 17:14:05 +0100
Subject: [PATCH 06/18] feat(config): pass config path to main loop and update
 handling

---
 main.go | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/main.go b/main.go
index a83d7f4c5..4bda82c0d 100755
--- a/main.go
+++ b/main.go
@@ -142,8 +142,11 @@ func main() {
 	// Check if certificates made with Agent <=1.2.7 needs to be moved over the new location
 	cert.MigrateCertificatesGeneratedWithOldAgentVersions(config.GetCertificatesDir())
 
+	configPath := config.GetConfigPath()
+	fmt.Println("configPath: ", configPath)
+
 	// Launch main loop in a goroutine
-	go loop()
+	go loop(configPath)
 
 	// SetupSystray is the main thread
 	configDir := config.GetDefaultConfigDir()
@@ -156,6 +159,7 @@ func main() {
 		AdditionalConfig: *additionalConfig,
 		ConfigDir:        configDir,
 	}
+	Systray.SetCurrentConfigFile(configPath)
 
 	if src, err := os.Executable(); err != nil {
 		panic(err)
@@ -166,11 +170,15 @@ func main() {
 	}
 }
 
-func loop() {
+func loop(configPath *paths.Path) {
 	if *hibernate {
 		return
 	}
 
+	if configPath == nil {
+		log.Panic("configPath is nil")
+	}
+
 	log.SetLevel(log.InfoLevel)
 	log.SetOutput(os.Stdout)
 
@@ -189,10 +197,6 @@ func loop() {
 		h.broadcastSys <- mapB
 	}
 
-	configPath := config.GetConfigPath()
-
-	fmt.Println("configPath: ", configPath)
-
 	// if the default browser is Safari, prompt the user to install HTTPS certificates
 	// and eventually install them
 	if runtime.GOOS == "darwin" {
@@ -230,7 +234,6 @@ func loop() {
 	if err != nil {
 		log.Panicf("cannot parse arguments: %s", err)
 	}
-	Systray.SetCurrentConfigFile(configPath)
 
 	// Parse additional ini config if defined
 	if len(*additionalConfig) > 0 {

From 716e8fccb6a4038381509a26a84de7b75675e225 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 11:46:05 +0100
Subject: [PATCH 07/18] refactor(config): revert to use the `config.ini` to
 default  and remove testing that branch

---
 config/config.go      |  2 +-
 config/config_test.go | 66 +++++++++++++++++++++----------------------
 2 files changed, 33 insertions(+), 35 deletions(-)

diff --git a/config/config.go b/config/config.go
index 9919bfbbc..50978eb82 100644
--- a/config/config.go
+++ b/config/config.go
@@ -108,7 +108,7 @@ func GetDefaultHomeDir() *paths.Path {
 	return paths.New(homeDir)
 }
 
-//go:embed config-default.ini
+//go:embed config.ini
 var configContent []byte
 
 // GenerateConfig function will take a directory path as an input
diff --git a/config/config_test.go b/config/config_test.go
index 447f3793e..5bc4ebd94 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -3,9 +3,7 @@ package config
 import (
 	"os"
 	"testing"
-	"time"
 
-	"github.com/arduino/go-paths-helper"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -36,40 +34,40 @@ func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
 	assert.Equal(t, "./testdata/fromenv/config.ini", configPath.String())
 }
 
-func TestGetConfigPathFromLegacyConfig(t *testing.T) {
-	// If no config is found, copy the legacy config to the new location
-	src, err := os.Executable()
-	if err != nil {
-		t.Fatal(err)
-	}
-	legacyConfigPath, err := paths.New(src).Parent().Join("config.ini").Create()
-	if err != nil {
-		t.Fatal(err)
-	}
-	// adding a timestamp to the content to make it unique
-	legacyContent := "hostname = legacy-config-file-" + time.Now().String()
-	n, err := legacyConfigPath.WriteString(legacyContent)
-	if err != nil || n <= 0 {
-		t.Fatalf("Failed to write legacy config file: %v", err)
-	}
-
-	// remove any existing config.ini in the into the location pointed by $HOME
-	err = os.Remove("./testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini")
-	if err != nil && !os.IsNotExist(err) {
-		t.Fatal(err)
-	}
-
-	// Expectation: it copies the "legacy" config.ini into the location pointed by $HOME
-	os.Setenv("HOME", "./testdata/fromlegacy")
-	defer os.Unsetenv("HOME")
+// func TestGetConfigPathFromLegacyConfig(t *testing.T) {
+// 	// If no config is found, copy the legacy config to the new location
+// 	src, err := os.Executable()
+// 	if err != nil {
+// 		t.Fatal(err)
+// 	}
+// 	legacyConfigPath, err := paths.New(src).Parent().Join("config.ini").Create()
+// 	if err != nil {
+// 		t.Fatal(err)
+// 	}
+// 	// adding a timestamp to the content to make it unique
+// 	legacyContent := "hostname = legacy-config-file-" + time.Now().String()
+// 	n, err := legacyConfigPath.WriteString(legacyContent)
+// 	if err != nil || n <= 0 {
+// 		t.Fatalf("Failed to write legacy config file: %v", err)
+// 	}
 
-	configPath := GetConfigPath()
-	assert.Equal(t, "testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini", configPath.String())
+// 	// remove any existing config.ini in the into the location pointed by $HOME
+// 	err = os.Remove("./testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini")
+// 	if err != nil && !os.IsNotExist(err) {
+// 		t.Fatal(err)
+// 	}
 
-	given, err := paths.New(configPath.String()).ReadFile()
-	assert.Nil(t, err)
-	assert.Equal(t, legacyContent, string(given))
-}
+// 	// Expectation: it copies the "legacy" config.ini into the location pointed by $HOME
+// 	os.Setenv("HOME", "./testdata/fromlegacy")
+// 	defer os.Unsetenv("HOME")
+
+// 	configPath := GetConfigPath()
+// 	assert.Equal(t, "testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini", configPath.String())
+
+// 	given, err := paths.New(configPath.String()).ReadFile()
+// 	assert.Nil(t, err)
+// 	assert.Equal(t, legacyContent, string(given))
+// }
 
 // func TestGetConfigPathCreateDefaultConfig(t *testing.T) {
 // 	os.Setenv("HOME", "./testdata/noconfig")

From 29a1bf343f8f807214fdabe3c96179531afd61af Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 12:11:55 +0100
Subject: [PATCH 08/18] refactor(config): remove default config file and update
 related tests

---
 config/config-default.ini                     | 10 ---
 config/config_test.go                         | 76 ++++++-------------
 .../config.ini                                |  2 +-
 config/testdata/fromdefault/.gitignore        |  1 -
 config/testdata/fromlegacy/.gitignore         |  2 -
 .../fromxdghome/ArduinoCreateAgent/config.ini | 13 ++--
 .../.config/ArduinoCreateAgent/config.ini     |  8 --
 .../.config/ArduinoCreateAgent/config.ini     | 10 ---
 8 files changed, 29 insertions(+), 93 deletions(-)
 delete mode 100644 config/config-default.ini
 rename config/testdata/{fromenv => from-arduino-create-agent-config-env}/config.ini (58%)
 delete mode 100644 config/testdata/fromdefault/.gitignore
 delete mode 100644 config/testdata/fromlegacy/.gitignore
 delete mode 100644 config/testdata/home/.config/ArduinoCreateAgent/config.ini
 delete mode 100644 config/testdata/noconfig/.config/ArduinoCreateAgent/config.ini

diff --git a/config/config-default.ini b/config/config-default.ini
deleted file mode 100644
index f63377db5..000000000
--- a/config/config-default.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-gc = std  # Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)
-hostname = unknown-hostname  # Override the hostname we get from the OS
-regex = usb|acm|com  # Regular expression to filter serial port list
-v = true  # show debug logging
-appName = CreateAgent/Stable
-updateUrl = https://downloads.arduino.cc/
-origins = https://local.arduino.cc:8000
-#httpProxy = http://your.proxy:port # Proxy server for HTTP requests
-crashreport = false # enable crashreport logging
-autostartMacOS = true # the Arduino Create Agent is able to start automatically after login on macOS (launchd agent)
\ No newline at end of file
diff --git a/config/config_test.go b/config/config_test.go
index 5bc4ebd94..c7f204fc0 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -4,6 +4,7 @@ import (
 	"os"
 	"testing"
 
+	"github.com/arduino/go-paths-helper"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -25,68 +26,35 @@ func TestGetConfigPathFromHOME(t *testing.T) {
 }
 
 func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
-	// read config from ARDUINO_CREATE_AGENT_CONFIG/config.ini"
-	os.Setenv("HOME", "./fromhome")
-	os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/fromenv/config.ini")
+	//  $HOME must be always set, otherwise panic
+	os.Setenv("HOME", "./testdata/dummyhome")
+
+	os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/from-arduino-create-agent-config-env/config.ini")
 	defer os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
 
 	configPath := GetConfigPath()
-	assert.Equal(t, "./testdata/fromenv/config.ini", configPath.String())
+	assert.Equal(t, "./testdata/from-arduino-create-agent-config-env/config.ini", configPath.String())
 }
 
-// func TestGetConfigPathFromLegacyConfig(t *testing.T) {
-// 	// If no config is found, copy the legacy config to the new location
-// 	src, err := os.Executable()
-// 	if err != nil {
-// 		t.Fatal(err)
-// 	}
-// 	legacyConfigPath, err := paths.New(src).Parent().Join("config.ini").Create()
-// 	if err != nil {
-// 		t.Fatal(err)
-// 	}
-// 	// adding a timestamp to the content to make it unique
-// 	legacyContent := "hostname = legacy-config-file-" + time.Now().String()
-// 	n, err := legacyConfigPath.WriteString(legacyContent)
-// 	if err != nil || n <= 0 {
-// 		t.Fatalf("Failed to write legacy config file: %v", err)
-// 	}
-
-// 	// remove any existing config.ini in the into the location pointed by $HOME
-// 	err = os.Remove("./testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini")
-// 	if err != nil && !os.IsNotExist(err) {
-// 		t.Fatal(err)
-// 	}
-
-// 	// Expectation: it copies the "legacy" config.ini into the location pointed by $HOME
-// 	os.Setenv("HOME", "./testdata/fromlegacy")
-// 	defer os.Unsetenv("HOME")
-
-// 	configPath := GetConfigPath()
-// 	assert.Equal(t, "testdata/fromlegacy/.config/ArduinoCreateAgent/config.ini", configPath.String())
+// If the ARDUINO_CREATE_AGENT_CONFIG is NOT set and the config.ini does not exist in HOME directory
+// then it copies the default config (the config.ini) into the HOME directory
+func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
+	//  $HOME must be always set, otherwise panic
+	os.Setenv("HOME", "./testdata/home-without-config")
 
-// 	given, err := paths.New(configPath.String()).ReadFile()
-// 	assert.Nil(t, err)
-// 	assert.Equal(t, legacyContent, string(given))
-// }
+	os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
+	// we want to test the case when the config does not exist in the home directory
+	os.Remove("./testdata/home-without-config/.config/ArduinoCreateAgent/config.ini")
 
-// func TestGetConfigPathCreateDefaultConfig(t *testing.T) {
-// 	os.Setenv("HOME", "./testdata/noconfig")
-// 	os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
-
-// 	// ensure the config.ini does not exist in HOME directory
-// 	os.Remove("./testdata/noconfig/.config/ArduinoCreateAgent/config.ini")
-// 	// ensure the config.ini does not exist in target directory
-// 	os.Remove("./testdata/fromdefault/.config/ArduinoCreateAgent/config.ini")
-
-// 	configPath := GetConfigPath()
+	configPath := GetConfigPath()
 
-// 	assert.Equal(t, "testdata/fromdefault/.config/ArduinoCreateAgent/config.ini", configPath.String())
+	assert.Equal(t, "testdata/home-without-config/.config/ArduinoCreateAgent/config.ini", configPath.String())
 
-// 	givenContent, err := paths.New(configPath.String()).ReadFile()
-// 	if err != nil {
-// 		t.Fatal(err)
-// 	}
+	givenContent, err := paths.New(configPath.String()).ReadFile()
+	if err != nil {
+		t.Fatal(err)
+	}
 
-// 	assert.Equal(t, string(configContent), string(givenContent))
+	assert.Equal(t, string(configContent), string(givenContent))
 
-// }
+}
diff --git a/config/testdata/fromenv/config.ini b/config/testdata/from-arduino-create-agent-config-env/config.ini
similarity index 58%
rename from config/testdata/fromenv/config.ini
rename to config/testdata/from-arduino-create-agent-config-env/config.ini
index cfd58d812..99b33cf75 100644
--- a/config/testdata/fromenv/config.ini
+++ b/config/testdata/from-arduino-create-agent-config-env/config.ini
@@ -4,5 +4,5 @@ regex = usb|acm|com
 v = true
 appName = CreateAgent/Stable
 updateUrl = https://downloads.arduino.cc/
-origins = https://local.arduino.cc:8000, https://local.arduino.cc:8001, https://create-dev.arduino.cc, https://*.sparklyunicorn.cc, https://*.iot-cloud-arduino-cc.pages.dev, https://cloud.oniudra.cc, https://app.oniudra.cc,https://*.iot-cloud-arduino-cc.pages.dev
+origins = https://local.arduino.cc:8000, https://local.arduino.cc:8001
 crashreport = false
diff --git a/config/testdata/fromdefault/.gitignore b/config/testdata/fromdefault/.gitignore
deleted file mode 100644
index 2fa7ce7c4..000000000
--- a/config/testdata/fromdefault/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-config.ini
diff --git a/config/testdata/fromlegacy/.gitignore b/config/testdata/fromlegacy/.gitignore
deleted file mode 100644
index f67b7f089..000000000
--- a/config/testdata/fromlegacy/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-# ingore because this config file
-config.ini
diff --git a/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini b/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini
index f63377db5..929f060e0 100644
--- a/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini
+++ b/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini
@@ -1,10 +1,9 @@
-gc = std  # Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)
-hostname = unknown-hostname  # Override the hostname we get from the OS
-regex = usb|acm|com  # Regular expression to filter serial port list
-v = true  # show debug logging
+gc = std
+hostname = this-is-a-config-file-from-xdghome-dir
+regex = usb|acm|com
+v = true
 appName = CreateAgent/Stable
 updateUrl = https://downloads.arduino.cc/
 origins = https://local.arduino.cc:8000
-#httpProxy = http://your.proxy:port # Proxy server for HTTP requests
-crashreport = false # enable crashreport logging
-autostartMacOS = true # the Arduino Create Agent is able to start automatically after login on macOS (launchd agent)
\ No newline at end of file
+crashreport = false
+autostartMacOS = true
diff --git a/config/testdata/home/.config/ArduinoCreateAgent/config.ini b/config/testdata/home/.config/ArduinoCreateAgent/config.ini
deleted file mode 100644
index a023d62d1..000000000
--- a/config/testdata/home/.config/ArduinoCreateAgent/config.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-gc = std
-hostname = this-is-a-config-file-from-home-dir
-regex = usb|acm|com
-v = true
-appName = config-from-home-dir
-updateUrl = https://downloads.arduino.cc/
-origins = https://local.arduino.cc:8000, https://local.arduino.cc:8001, https://*.iot-cloud-arduino-cc.pages.dev
-crashreport = false
diff --git a/config/testdata/noconfig/.config/ArduinoCreateAgent/config.ini b/config/testdata/noconfig/.config/ArduinoCreateAgent/config.ini
deleted file mode 100644
index f63377db5..000000000
--- a/config/testdata/noconfig/.config/ArduinoCreateAgent/config.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-gc = std  # Type of garbage collection. std = Normal garbage collection allowing system to decide (this has been known to cause a stop the world in the middle of a CNC job which can cause lost responses from the CNC controller and thus stalled jobs. use max instead to solve.), off = let memory grow unbounded (you have to send in the gc command manually to garbage collect or you will run out of RAM eventually), max = Force garbage collection on each recv or send on a serial port (this minimizes stop the world events and thus lost serial responses, but increases CPU usage)
-hostname = unknown-hostname  # Override the hostname we get from the OS
-regex = usb|acm|com  # Regular expression to filter serial port list
-v = true  # show debug logging
-appName = CreateAgent/Stable
-updateUrl = https://downloads.arduino.cc/
-origins = https://local.arduino.cc:8000
-#httpProxy = http://your.proxy:port # Proxy server for HTTP requests
-crashreport = false # enable crashreport logging
-autostartMacOS = true # the Arduino Create Agent is able to start automatically after login on macOS (launchd agent)
\ No newline at end of file

From 9143b021cf61645fd8ac9bf2f2784423d82dde5b Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 12:16:54 +0100
Subject: [PATCH 09/18] feat(config): skip tests if not linux

---
 config/config.go                              |  1 +
 .../{config_test.go => config_linux_test.go}  | 20 ++++++++++++++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)
 rename config/{config_test.go => config_linux_test.go} (69%)

diff --git a/config/config.go b/config/config.go
index 50978eb82..b4d20e94e 100644
--- a/config/config.go
+++ b/config/config.go
@@ -143,6 +143,7 @@ func SetInstallCertsIni(filename string, value string) error {
 	return nil
 }
 
+// GetConfigPath returns the path to the config file
 func GetConfigPath() *paths.Path {
 	// Let's handle the config
 	configDir := GetDefaultConfigDir()
diff --git a/config/config_test.go b/config/config_linux_test.go
similarity index 69%
rename from config/config_test.go
rename to config/config_linux_test.go
index c7f204fc0..e3e5e5ae1 100644
--- a/config/config_test.go
+++ b/config/config_linux_test.go
@@ -2,13 +2,18 @@ package config
 
 import (
 	"os"
+	"runtime"
 	"testing"
 
 	"github.com/arduino/go-paths-helper"
 	"github.com/stretchr/testify/assert"
 )
 
+// TestGetConfigPathFromXDG_CONFIG_HOME tests the case when the config.ini is read from XDG_CONFIG_HOME/ArduinoCreateAgent/config.ini
 func TestGetConfigPathFromXDG_CONFIG_HOME(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
 	// read config from $XDG_CONFIG_HOME/ArduinoCreateAgent/config.ini
 	os.Setenv("XDG_CONFIG_HOME", "./testdata/fromxdghome")
 	defer os.Unsetenv("XDG_CONFIG_HOME")
@@ -16,8 +21,11 @@ func TestGetConfigPathFromXDG_CONFIG_HOME(t *testing.T) {
 	assert.Equal(t, "testdata/fromxdghome/ArduinoCreateAgent/config.ini", configPath.String())
 }
 
+// TestGetConfigPathFromHOME tests the case when the config.ini is read from $HOME/.config/ArduinoCreateAgent/config.ini
 func TestGetConfigPathFromHOME(t *testing.T) {
-	// Test case 2: read config from $HOME/.config/ArduinoCreateAgent/config.ini "
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
 	os.Setenv("HOME", "./testdata/fromhome")
 	defer os.Unsetenv("HOME")
 	configPath := GetConfigPath()
@@ -25,7 +33,11 @@ func TestGetConfigPathFromHOME(t *testing.T) {
 
 }
 
+// TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG tests the case when the config.ini is read from ARDUINO_CREATE_AGENT_CONFIG env variable
 func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
 	//  $HOME must be always set, otherwise panic
 	os.Setenv("HOME", "./testdata/dummyhome")
 
@@ -34,11 +46,17 @@ func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
 
 	configPath := GetConfigPath()
 	assert.Equal(t, "./testdata/from-arduino-create-agent-config-env/config.ini", configPath.String())
+
 }
 
+// TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied tests the case when the default config.ini is copied into $HOME/.config/ArduinoCreateAgent/config.ini
+// from the default config.ini
 // If the ARDUINO_CREATE_AGENT_CONFIG is NOT set and the config.ini does not exist in HOME directory
 // then it copies the default config (the config.ini) into the HOME directory
 func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
 	//  $HOME must be always set, otherwise panic
 	os.Setenv("HOME", "./testdata/home-without-config")
 

From e4e926e53240205c4ffc47230cec42a2b2511fd9 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 12:23:55 +0100
Subject: [PATCH 10/18] feat(tests): add .gitignore for test data directories

---
 config/testdata/.gitignore | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 config/testdata/.gitignore

diff --git a/config/testdata/.gitignore b/config/testdata/.gitignore
new file mode 100644
index 000000000..40d957100
--- /dev/null
+++ b/config/testdata/.gitignore
@@ -0,0 +1,5 @@
+# The function that read the HOME fodler automatically creates the home folder if missing.
+
+# This are the folders that are created for testing purpose and there is no need to be tracked
+dummyhome
+home-without-config

From 3dfa496e0c0354cd0c0b51e09eeb261e7b514892 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 12:24:37 +0100
Subject: [PATCH 11/18] fix(tests): handle error when removing config file in
 test

---
 config/config_linux_test.go | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/config/config_linux_test.go b/config/config_linux_test.go
index e3e5e5ae1..aa2584e44 100644
--- a/config/config_linux_test.go
+++ b/config/config_linux_test.go
@@ -62,7 +62,10 @@ func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
 
 	os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
 	// we want to test the case when the config does not exist in the home directory
-	os.Remove("./testdata/home-without-config/.config/ArduinoCreateAgent/config.ini")
+	err := os.Remove("./testdata/home-without-config/.config/ArduinoCreateAgent/config.ini")
+	if err != nil {
+		t.Fatal(err)
+	}
 
 	configPath := GetConfigPath()
 

From aaa97f99139e88107568a4c74fad4cfdb274ee23 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 12:32:27 +0100
Subject: [PATCH 12/18] refactor(main): remove debug print statement for config
 path

---
 main.go | 2 --
 1 file changed, 2 deletions(-)

diff --git a/main.go b/main.go
index 4bda82c0d..5e0c969bb 100755
--- a/main.go
+++ b/main.go
@@ -22,7 +22,6 @@ import (
 	_ "embed"
 	"encoding/json"
 	"flag"
-	"fmt"
 	"html/template"
 	"io"
 	"os"
@@ -143,7 +142,6 @@ func main() {
 	cert.MigrateCertificatesGeneratedWithOldAgentVersions(config.GetCertificatesDir())
 
 	configPath := config.GetConfigPath()
-	fmt.Println("configPath: ", configPath)
 
 	// Launch main loop in a goroutine
 	go loop(configPath)

From f5a9afce6f27c2e77b38fca23affb0c1df24543d Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 14:01:05 +0100
Subject: [PATCH 13/18] feat(tests): enhance config tests with ini name checks
 and update test data

---
 config/config_linux_test.go                   | 21 +++++++++++++++++--
 .../config.ini                                |  3 ++-
 .../.config/ArduinoCreateAgent/config.ini     |  5 +++--
 .../fromxdghome/ArduinoCreateAgent/config.ini |  3 ++-
 4 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/config/config_linux_test.go b/config/config_linux_test.go
index aa2584e44..29eaf01ab 100644
--- a/config/config_linux_test.go
+++ b/config/config_linux_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	"github.com/arduino/go-paths-helper"
+	"github.com/go-ini/ini"
 	"github.com/stretchr/testify/assert"
 )
 
@@ -18,7 +19,9 @@ func TestGetConfigPathFromXDG_CONFIG_HOME(t *testing.T) {
 	os.Setenv("XDG_CONFIG_HOME", "./testdata/fromxdghome")
 	defer os.Unsetenv("XDG_CONFIG_HOME")
 	configPath := GetConfigPath()
+
 	assert.Equal(t, "testdata/fromxdghome/ArduinoCreateAgent/config.ini", configPath.String())
+	checkIniName(t, configPath, "this-is-a-config-file-from-xdghome-dir")
 }
 
 // TestGetConfigPathFromHOME tests the case when the config.ini is read from $HOME/.config/ArduinoCreateAgent/config.ini
@@ -29,8 +32,9 @@ func TestGetConfigPathFromHOME(t *testing.T) {
 	os.Setenv("HOME", "./testdata/fromhome")
 	defer os.Unsetenv("HOME")
 	configPath := GetConfigPath()
-	assert.Equal(t, "testdata/fromhome/.config/ArduinoCreateAgent/config.ini", configPath.String())
 
+	assert.Equal(t, "testdata/fromhome/.config/ArduinoCreateAgent/config.ini", configPath.String())
+	checkIniName(t, configPath, "this-is-a-config-file-from-home-di")
 }
 
 // TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG tests the case when the config.ini is read from ARDUINO_CREATE_AGENT_CONFIG env variable
@@ -46,7 +50,7 @@ func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
 
 	configPath := GetConfigPath()
 	assert.Equal(t, "./testdata/from-arduino-create-agent-config-env/config.ini", configPath.String())
-
+	checkIniName(t, configPath, "this-is-a-config-file-from-home-dir-from-ARDUINO_CREATE_AGENT_CONFIG-env")
 }
 
 // TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied tests the case when the default config.ini is copied into $HOME/.config/ArduinoCreateAgent/config.ini
@@ -70,6 +74,7 @@ func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
 	configPath := GetConfigPath()
 
 	assert.Equal(t, "testdata/home-without-config/.config/ArduinoCreateAgent/config.ini", configPath.String())
+	checkIniName(t, configPath, "") // the name of the default config is missing (an empty string)
 
 	givenContent, err := paths.New(configPath.String()).ReadFile()
 	if err != nil {
@@ -79,3 +84,15 @@ func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
 	assert.Equal(t, string(configContent), string(givenContent))
 
 }
+
+func checkIniName(t *testing.T, confipath *paths.Path, expected string) {
+	cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true, AllowPythonMultilineValues: true}, confipath.String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defaultSection, err := cfg.GetSection("")
+	if err != nil {
+		t.Fatal(err)
+	}
+	assert.Equal(t, expected, defaultSection.Key("name").String())
+}
diff --git a/config/testdata/from-arduino-create-agent-config-env/config.ini b/config/testdata/from-arduino-create-agent-config-env/config.ini
index 99b33cf75..d9f42f6b0 100644
--- a/config/testdata/from-arduino-create-agent-config-env/config.ini
+++ b/config/testdata/from-arduino-create-agent-config-env/config.ini
@@ -1,5 +1,6 @@
+name = this-is-a-config-file-from-home-dir-from-ARDUINO_CREATE_AGENT_CONFIG-env
 gc = std
-hostname = this-is-a-config-file-from-home-dir-from-ARDUINO_CREATE_AGENT_CONFIG-env
+hostname = an-hostname
 regex = usb|acm|com
 v = true
 appName = CreateAgent/Stable
diff --git a/config/testdata/fromhome/.config/ArduinoCreateAgent/config.ini b/config/testdata/fromhome/.config/ArduinoCreateAgent/config.ini
index a023d62d1..d553323f1 100644
--- a/config/testdata/fromhome/.config/ArduinoCreateAgent/config.ini
+++ b/config/testdata/fromhome/.config/ArduinoCreateAgent/config.ini
@@ -1,8 +1,9 @@
+name = this-is-a-config-file-from-home-dir
 gc = std
-hostname = this-is-a-config-file-from-home-dir
+hostname = an-hostname
 regex = usb|acm|com
 v = true
-appName = config-from-home-dir
+appName = an-app-n
 updateUrl = https://downloads.arduino.cc/
 origins = https://local.arduino.cc:8000, https://local.arduino.cc:8001, https://*.iot-cloud-arduino-cc.pages.dev
 crashreport = false
diff --git a/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini b/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini
index 929f060e0..2016169d2 100644
--- a/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini
+++ b/config/testdata/fromxdghome/ArduinoCreateAgent/config.ini
@@ -1,5 +1,6 @@
+name = this-is-a-config-file-from-xdghome-dir
 gc = std
-hostname = this-is-a-config-file-from-xdghome-dir
+hostname = an-hostname
 regex = usb|acm|com
 v = true
 appName = CreateAgent/Stable

From 98898255a3dedafbeea44952e49cb7dabb8edf31 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 14:15:20 +0100
Subject: [PATCH 14/18] feat(config): update error handling in GetConfigPath
 and add test for non-existing config path

---
 config/config.go            |  3 ++-
 config/config_linux_test.go | 24 ++++++++++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/config/config.go b/config/config.go
index b4d20e94e..327411e54 100644
--- a/config/config.go
+++ b/config/config.go
@@ -18,6 +18,7 @@ package config
 import (
 	// we need this for the config ini in this package
 	_ "embed"
+	"fmt"
 	"os"
 
 	"github.com/arduino/go-paths-helper"
@@ -153,7 +154,7 @@ func GetConfigPath() *paths.Path {
 	if envConfig := os.Getenv("ARDUINO_CREATE_AGENT_CONFIG"); envConfig != "" {
 		configPath = paths.New(envConfig)
 		if configPath.NotExist() {
-			log.Panicf("config from env var %s does not exists", envConfig)
+			panic(fmt.Sprintf("config from env var %s does not exists", envConfig))
 		}
 		log.Infof("using config from env variable: %s", configPath)
 	} else if defaultConfigPath := configDir.Join("config.ini"); defaultConfigPath.Exist() {
diff --git a/config/config_linux_test.go b/config/config_linux_test.go
index 29eaf01ab..88e9af16c 100644
--- a/config/config_linux_test.go
+++ b/config/config_linux_test.go
@@ -1,6 +1,7 @@
 package config
 
 import (
+	"fmt"
 	"os"
 	"runtime"
 	"testing"
@@ -82,7 +83,30 @@ func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
 	}
 
 	assert.Equal(t, string(configContent), string(givenContent))
+}
+
+// TestGetConfigPathPanicIfPathDoesNotExist tests that it panics if the ARDUINO_CREATE_AGENT_CONFIG env variable point to an non-existing path
+func TestGetConfigPathPanicIfPathDoesNotExist(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
+	os.Setenv("HOME", "./testdata/dummyhome")
+	defer os.Unsetenv("HOME")
 
+	os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/a-not-existing-path/config.ini")
+
+	defer func() {
+		if r := recover(); r != nil {
+			assert.Equal(t, fmt.Sprintf("config from env var %s does not exists", "./testdata/a-not-existing-path/config.ini"), r)
+		} else {
+			t.Fatal("Expected panic but did not occur")
+		}
+	}()
+
+	configPath := GetConfigPath()
+
+	assert.Equal(t, "testdata/fromxdghome/ArduinoCreateAgent/config.ini", configPath.String())
+	checkIniName(t, configPath, "this-is-a-config-file-from-xdghome-dir")
 }
 
 func checkIniName(t *testing.T, confipath *paths.Path, expected string) {

From a8bcfe7c5f52a6195629443deb7b388ea1725b16 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 14:25:06 +0100
Subject: [PATCH 15/18] fix(tests): correct ini name in
 TestGetConfigPathFromHOME test case

---
 config/config_linux_test.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/config_linux_test.go b/config/config_linux_test.go
index 88e9af16c..c69a2cdba 100644
--- a/config/config_linux_test.go
+++ b/config/config_linux_test.go
@@ -35,7 +35,7 @@ func TestGetConfigPathFromHOME(t *testing.T) {
 	configPath := GetConfigPath()
 
 	assert.Equal(t, "testdata/fromhome/.config/ArduinoCreateAgent/config.ini", configPath.String())
-	checkIniName(t, configPath, "this-is-a-config-file-from-home-di")
+	checkIniName(t, configPath, "this-is-a-config-file-from-home-dir")
 }
 
 // TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG tests the case when the config.ini is read from ARDUINO_CREATE_AGENT_CONFIG env variable

From a0bd3fdb5e2ce56f9641a4cb2bab3d02db49d475 Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 14:37:20 +0100
Subject: [PATCH 16/18] feat(tests): rename tests of config

---
 config/config_test.go | 122 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 122 insertions(+)
 create mode 100644 config/config_test.go

diff --git a/config/config_test.go b/config/config_test.go
new file mode 100644
index 000000000..c69a2cdba
--- /dev/null
+++ b/config/config_test.go
@@ -0,0 +1,122 @@
+package config
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+	"testing"
+
+	"github.com/arduino/go-paths-helper"
+	"github.com/go-ini/ini"
+	"github.com/stretchr/testify/assert"
+)
+
+// TestGetConfigPathFromXDG_CONFIG_HOME tests the case when the config.ini is read from XDG_CONFIG_HOME/ArduinoCreateAgent/config.ini
+func TestGetConfigPathFromXDG_CONFIG_HOME(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
+	// read config from $XDG_CONFIG_HOME/ArduinoCreateAgent/config.ini
+	os.Setenv("XDG_CONFIG_HOME", "./testdata/fromxdghome")
+	defer os.Unsetenv("XDG_CONFIG_HOME")
+	configPath := GetConfigPath()
+
+	assert.Equal(t, "testdata/fromxdghome/ArduinoCreateAgent/config.ini", configPath.String())
+	checkIniName(t, configPath, "this-is-a-config-file-from-xdghome-dir")
+}
+
+// TestGetConfigPathFromHOME tests the case when the config.ini is read from $HOME/.config/ArduinoCreateAgent/config.ini
+func TestGetConfigPathFromHOME(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
+	os.Setenv("HOME", "./testdata/fromhome")
+	defer os.Unsetenv("HOME")
+	configPath := GetConfigPath()
+
+	assert.Equal(t, "testdata/fromhome/.config/ArduinoCreateAgent/config.ini", configPath.String())
+	checkIniName(t, configPath, "this-is-a-config-file-from-home-dir")
+}
+
+// TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG tests the case when the config.ini is read from ARDUINO_CREATE_AGENT_CONFIG env variable
+func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
+	//  $HOME must be always set, otherwise panic
+	os.Setenv("HOME", "./testdata/dummyhome")
+
+	os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/from-arduino-create-agent-config-env/config.ini")
+	defer os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
+
+	configPath := GetConfigPath()
+	assert.Equal(t, "./testdata/from-arduino-create-agent-config-env/config.ini", configPath.String())
+	checkIniName(t, configPath, "this-is-a-config-file-from-home-dir-from-ARDUINO_CREATE_AGENT_CONFIG-env")
+}
+
+// TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied tests the case when the default config.ini is copied into $HOME/.config/ArduinoCreateAgent/config.ini
+// from the default config.ini
+// If the ARDUINO_CREATE_AGENT_CONFIG is NOT set and the config.ini does not exist in HOME directory
+// then it copies the default config (the config.ini) into the HOME directory
+func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
+	//  $HOME must be always set, otherwise panic
+	os.Setenv("HOME", "./testdata/home-without-config")
+
+	os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
+	// we want to test the case when the config does not exist in the home directory
+	err := os.Remove("./testdata/home-without-config/.config/ArduinoCreateAgent/config.ini")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	configPath := GetConfigPath()
+
+	assert.Equal(t, "testdata/home-without-config/.config/ArduinoCreateAgent/config.ini", configPath.String())
+	checkIniName(t, configPath, "") // the name of the default config is missing (an empty string)
+
+	givenContent, err := paths.New(configPath.String()).ReadFile()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	assert.Equal(t, string(configContent), string(givenContent))
+}
+
+// TestGetConfigPathPanicIfPathDoesNotExist tests that it panics if the ARDUINO_CREATE_AGENT_CONFIG env variable point to an non-existing path
+func TestGetConfigPathPanicIfPathDoesNotExist(t *testing.T) {
+	if runtime.GOOS != "linux" {
+		t.Skip("Skipping test on non-linux OS")
+	}
+	os.Setenv("HOME", "./testdata/dummyhome")
+	defer os.Unsetenv("HOME")
+
+	os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/a-not-existing-path/config.ini")
+
+	defer func() {
+		if r := recover(); r != nil {
+			assert.Equal(t, fmt.Sprintf("config from env var %s does not exists", "./testdata/a-not-existing-path/config.ini"), r)
+		} else {
+			t.Fatal("Expected panic but did not occur")
+		}
+	}()
+
+	configPath := GetConfigPath()
+
+	assert.Equal(t, "testdata/fromxdghome/ArduinoCreateAgent/config.ini", configPath.String())
+	checkIniName(t, configPath, "this-is-a-config-file-from-xdghome-dir")
+}
+
+func checkIniName(t *testing.T, confipath *paths.Path, expected string) {
+	cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true, AllowPythonMultilineValues: true}, confipath.String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defaultSection, err := cfg.GetSection("")
+	if err != nil {
+		t.Fatal(err)
+	}
+	assert.Equal(t, expected, defaultSection.Key("name").String())
+}

From 504ce7e8825cb0a56dba91433ef14d7e6972069e Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 14:41:55 +0100
Subject: [PATCH 17/18] refactor(tests): rename test functions for consistency
 and clarity

---
 config/config_linux_test.go | 122 ------------------------------------
 config/config_test.go       |   6 +-
 2 files changed, 3 insertions(+), 125 deletions(-)
 delete mode 100644 config/config_linux_test.go

diff --git a/config/config_linux_test.go b/config/config_linux_test.go
deleted file mode 100644
index c69a2cdba..000000000
--- a/config/config_linux_test.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package config
-
-import (
-	"fmt"
-	"os"
-	"runtime"
-	"testing"
-
-	"github.com/arduino/go-paths-helper"
-	"github.com/go-ini/ini"
-	"github.com/stretchr/testify/assert"
-)
-
-// TestGetConfigPathFromXDG_CONFIG_HOME tests the case when the config.ini is read from XDG_CONFIG_HOME/ArduinoCreateAgent/config.ini
-func TestGetConfigPathFromXDG_CONFIG_HOME(t *testing.T) {
-	if runtime.GOOS != "linux" {
-		t.Skip("Skipping test on non-linux OS")
-	}
-	// read config from $XDG_CONFIG_HOME/ArduinoCreateAgent/config.ini
-	os.Setenv("XDG_CONFIG_HOME", "./testdata/fromxdghome")
-	defer os.Unsetenv("XDG_CONFIG_HOME")
-	configPath := GetConfigPath()
-
-	assert.Equal(t, "testdata/fromxdghome/ArduinoCreateAgent/config.ini", configPath.String())
-	checkIniName(t, configPath, "this-is-a-config-file-from-xdghome-dir")
-}
-
-// TestGetConfigPathFromHOME tests the case when the config.ini is read from $HOME/.config/ArduinoCreateAgent/config.ini
-func TestGetConfigPathFromHOME(t *testing.T) {
-	if runtime.GOOS != "linux" {
-		t.Skip("Skipping test on non-linux OS")
-	}
-	os.Setenv("HOME", "./testdata/fromhome")
-	defer os.Unsetenv("HOME")
-	configPath := GetConfigPath()
-
-	assert.Equal(t, "testdata/fromhome/.config/ArduinoCreateAgent/config.ini", configPath.String())
-	checkIniName(t, configPath, "this-is-a-config-file-from-home-dir")
-}
-
-// TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG tests the case when the config.ini is read from ARDUINO_CREATE_AGENT_CONFIG env variable
-func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
-	if runtime.GOOS != "linux" {
-		t.Skip("Skipping test on non-linux OS")
-	}
-	//  $HOME must be always set, otherwise panic
-	os.Setenv("HOME", "./testdata/dummyhome")
-
-	os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/from-arduino-create-agent-config-env/config.ini")
-	defer os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
-
-	configPath := GetConfigPath()
-	assert.Equal(t, "./testdata/from-arduino-create-agent-config-env/config.ini", configPath.String())
-	checkIniName(t, configPath, "this-is-a-config-file-from-home-dir-from-ARDUINO_CREATE_AGENT_CONFIG-env")
-}
-
-// TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied tests the case when the default config.ini is copied into $HOME/.config/ArduinoCreateAgent/config.ini
-// from the default config.ini
-// If the ARDUINO_CREATE_AGENT_CONFIG is NOT set and the config.ini does not exist in HOME directory
-// then it copies the default config (the config.ini) into the HOME directory
-func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
-	if runtime.GOOS != "linux" {
-		t.Skip("Skipping test on non-linux OS")
-	}
-	//  $HOME must be always set, otherwise panic
-	os.Setenv("HOME", "./testdata/home-without-config")
-
-	os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
-	// we want to test the case when the config does not exist in the home directory
-	err := os.Remove("./testdata/home-without-config/.config/ArduinoCreateAgent/config.ini")
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	configPath := GetConfigPath()
-
-	assert.Equal(t, "testdata/home-without-config/.config/ArduinoCreateAgent/config.ini", configPath.String())
-	checkIniName(t, configPath, "") // the name of the default config is missing (an empty string)
-
-	givenContent, err := paths.New(configPath.String()).ReadFile()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	assert.Equal(t, string(configContent), string(givenContent))
-}
-
-// TestGetConfigPathPanicIfPathDoesNotExist tests that it panics if the ARDUINO_CREATE_AGENT_CONFIG env variable point to an non-existing path
-func TestGetConfigPathPanicIfPathDoesNotExist(t *testing.T) {
-	if runtime.GOOS != "linux" {
-		t.Skip("Skipping test on non-linux OS")
-	}
-	os.Setenv("HOME", "./testdata/dummyhome")
-	defer os.Unsetenv("HOME")
-
-	os.Setenv("ARDUINO_CREATE_AGENT_CONFIG", "./testdata/a-not-existing-path/config.ini")
-
-	defer func() {
-		if r := recover(); r != nil {
-			assert.Equal(t, fmt.Sprintf("config from env var %s does not exists", "./testdata/a-not-existing-path/config.ini"), r)
-		} else {
-			t.Fatal("Expected panic but did not occur")
-		}
-	}()
-
-	configPath := GetConfigPath()
-
-	assert.Equal(t, "testdata/fromxdghome/ArduinoCreateAgent/config.ini", configPath.String())
-	checkIniName(t, configPath, "this-is-a-config-file-from-xdghome-dir")
-}
-
-func checkIniName(t *testing.T, confipath *paths.Path, expected string) {
-	cfg, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true, AllowPythonMultilineValues: true}, confipath.String())
-	if err != nil {
-		t.Fatal(err)
-	}
-	defaultSection, err := cfg.GetSection("")
-	if err != nil {
-		t.Fatal(err)
-	}
-	assert.Equal(t, expected, defaultSection.Key("name").String())
-}
diff --git a/config/config_test.go b/config/config_test.go
index c69a2cdba..e20014620 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -12,7 +12,7 @@ import (
 )
 
 // TestGetConfigPathFromXDG_CONFIG_HOME tests the case when the config.ini is read from XDG_CONFIG_HOME/ArduinoCreateAgent/config.ini
-func TestGetConfigPathFromXDG_CONFIG_HOME(t *testing.T) {
+func TestGetConfigPathFrom_XDG_CONFIG_HOME(t *testing.T) {
 	if runtime.GOOS != "linux" {
 		t.Skip("Skipping test on non-linux OS")
 	}
@@ -26,7 +26,7 @@ func TestGetConfigPathFromXDG_CONFIG_HOME(t *testing.T) {
 }
 
 // TestGetConfigPathFromHOME tests the case when the config.ini is read from $HOME/.config/ArduinoCreateAgent/config.ini
-func TestGetConfigPathFromHOME(t *testing.T) {
+func TestGetConfigPathFrom_HOME(t *testing.T) {
 	if runtime.GOOS != "linux" {
 		t.Skip("Skipping test on non-linux OS")
 	}
@@ -39,7 +39,7 @@ func TestGetConfigPathFromHOME(t *testing.T) {
 }
 
 // TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG tests the case when the config.ini is read from ARDUINO_CREATE_AGENT_CONFIG env variable
-func TestGetConfigPathFromARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
+func TestGetConfigPathFrom_ARDUINO_CREATE_AGENT_CONFIG(t *testing.T) {
 	if runtime.GOOS != "linux" {
 		t.Skip("Skipping test on non-linux OS")
 	}

From 870fac5683c283777361b7201982c32217055c4e Mon Sep 17 00:00:00 2001
From: Davide N <davideneri18@gmail.com>
Date: Wed, 29 Jan 2025 14:52:40 +0100
Subject: [PATCH 18/18] fix(tests): simplify cleanup in
 TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied

---
 config/config_test.go | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/config/config_test.go b/config/config_test.go
index e20014620..14339f340 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -66,11 +66,8 @@ func TestIfHomeDoesNotContainConfigTheDefaultConfigAreCopied(t *testing.T) {
 	os.Setenv("HOME", "./testdata/home-without-config")
 
 	os.Unsetenv("ARDUINO_CREATE_AGENT_CONFIG")
-	// we want to test the case when the config does not exist in the home directory
-	err := os.Remove("./testdata/home-without-config/.config/ArduinoCreateAgent/config.ini")
-	if err != nil {
-		t.Fatal(err)
-	}
+	// Clean the home folder by deleting the config.ini
+	os.Remove("./testdata/home-without-config/.config/ArduinoCreateAgent/config.ini")
 
 	configPath := GetConfigPath()