From 52248ca6b39ea38ca910fbdfba57720d5b946b5d Mon Sep 17 00:00:00 2001 From: aniket866 Date: Sat, 1 Aug 2026 00:15:13 +0530 Subject: [PATCH] fixing-null-pointer-deref-executor Signed-off-by: aniket866 --- pkg/watcher/executor.go | 1 + pkg/watcher/executor_test.go | 74 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 pkg/watcher/executor_test.go diff --git a/pkg/watcher/executor.go b/pkg/watcher/executor.go index 151e9d5f..0998c4d5 100644 --- a/pkg/watcher/executor.go +++ b/pkg/watcher/executor.go @@ -33,6 +33,7 @@ func TriggerImport(entry config.WatchEntry) { mc, err = connectors.NewClient(*globalClientOpts) if err != nil { fmt.Printf("[ERROR] Cannot connect to Microcks client: %v in context '%s'\n", err, context) + continue } } else { // We have no config file, so just create a client with context as server URL. diff --git a/pkg/watcher/executor_test.go b/pkg/watcher/executor_test.go new file mode 100644 index 00000000..dd6d915f --- /dev/null +++ b/pkg/watcher/executor_test.go @@ -0,0 +1,74 @@ +package watcher + +import ( + "os" + "path/filepath" + "testing" + + "github.com/microcks/microcks-cli/pkg/config" +) + +func TestTriggerImport_NewClientErrorNoPanic(t *testing.T) { + // Create a temp directory for the config dir. + tmpDir := t.TempDir() + + // Set MICROCKS_CONFIG_DIR env var to point to our temp directory + os.Setenv("MICROCKS_CONFIG_DIR", tmpDir) + defer os.Unsetenv("MICROCKS_CONFIG_DIR") + + // We create an invalid config file that fails validation or context resolution. + // This will cause connectors.NewClient to fail when resolving config context. + configPath := filepath.Join(tmpDir, "config") + invalidYAML := []byte(` +currentContext: non-existent-context +contexts: + - name: invalid +`) + if err := os.WriteFile(configPath, invalidYAML, 0600); err != nil { + t.Fatalf("failed to write invalid config file: %v", err) + } + + // TriggerImport should run and log the failure but not panic. + entry := config.WatchEntry{ + FilePath: "dummy.yaml", + MainArtifact: true, + Context: []string{"non-existent-context"}, + } + + // Wrap in recover to assert no panic. + defer func() { + if r := recover(); r != nil { + t.Errorf("TriggerImport panicked: %v", r) + } + }() + + TriggerImport(entry) +} + +func TestTriggerImport_NoConfigFile_NewMicrocksClientErrorNoPanic(t *testing.T) { + // Create a temp directory for the config dir to ensure config doesn't exist. + tmpDir := t.TempDir() + + // Set MICROCKS_CONFIG_DIR env var to point to our empty temp directory. + os.Setenv("MICROCKS_CONFIG_DIR", tmpDir) + defer os.Unsetenv("MICROCKS_CONFIG_DIR") + + // Since there is no config file in the temp directory, TriggerImport will fall back + // to creating a headless client via connectors.NewMicrocksClient(context). + // We pass a context containing a control character, which causes url.Parse to fail, + // ensuring NewMicrocksClient returns an error and does not panic. + entry := config.WatchEntry{ + FilePath: "dummy.yaml", + MainArtifact: true, + Context: []string{"http://\x7f.com"}, + } + + // Wrap in recover to assert no panic. + defer func() { + if r := recover(); r != nil { + t.Errorf("TriggerImport panicked: %v", r) + } + }() + + TriggerImport(entry) +}