From 54f355daba4c8caf197e438aae915e1e3e781c0e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 17:20:23 +0000 Subject: [PATCH 1/4] Add tests for logger.writeJSONToFile and initAndSetGlobalNoFileLogger MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds comprehensive table-driven tests for writeJSONToFile (0→100% coverage) and an additional test for the uncovered error path in initAndSetGlobalNoFileLogger (81.8%→90.9% coverage). Tests cover: - Happy path: simple map, nil value, struct, slice, empty struct - Overwrite existing file atomically - json.MarshalIndent failure for unmarshalable type (channel) - atomicWriteFile failure when destination directory does not exist - factory.setup() error path in initAndSetGlobalNoFileLogger Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- internal/logger/write_json_to_file_test.go | 160 +++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 internal/logger/write_json_to_file_test.go diff --git a/internal/logger/write_json_to_file_test.go b/internal/logger/write_json_to_file_test.go new file mode 100644 index 00000000..f59cc116 --- /dev/null +++ b/internal/logger/write_json_to_file_test.go @@ -0,0 +1,160 @@ +package logger + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestWriteJSONToFile exercises all code paths in writeJSONToFile. +// +// writeJSONToFile: +// 1. Marshals data as indented JSON (fails on unmarshalable types like channels). +// 2. Delegates to atomicWriteFile to persist the result. +// +// Coverage targets: +// - Success path: marshalable data written to a new file. +// - Success path: existing file is overwritten atomically. +// - Error path: json.MarshalIndent fails for an unmarshalable value (channel). +// - Error path: atomicWriteFile fails when the destination directory does not exist. +func TestWriteJSONToFile(t *testing.T) { + t.Run("success – simple map written to file", func(t *testing.T) { + tmpDir := t.TempDir() + + data := map[string]string{"key": "value"} + err := writeJSONToFile(tmpDir, "out.json", data, 0o644) + require.NoError(t, err) + + got, err := os.ReadFile(filepath.Join(tmpDir, "out.json")) + require.NoError(t, err) + assert.Contains(t, string(got), `"key"`) + assert.Contains(t, string(got), `"value"`) + }) + + t.Run("success – nil value written as null", func(t *testing.T) { + tmpDir := t.TempDir() + + err := writeJSONToFile(tmpDir, "null.json", nil, 0o644) + require.NoError(t, err) + + got, err := os.ReadFile(filepath.Join(tmpDir, "null.json")) + require.NoError(t, err) + assert.Equal(t, "null", string(got)) + }) + + t.Run("success – struct with indented formatting", func(t *testing.T) { + tmpDir := t.TempDir() + + type payload struct { + Name string `json:"name"` + Count int `json:"count"` + } + data := payload{Name: "test", Count: 42} + + err := writeJSONToFile(tmpDir, "payload.json", data, 0o644) + require.NoError(t, err) + + got, err := os.ReadFile(filepath.Join(tmpDir, "payload.json")) + require.NoError(t, err) + // Indented JSON should contain newlines and spaces. + assert.Contains(t, string(got), "\n") + assert.Contains(t, string(got), `"name"`) + assert.Contains(t, string(got), `"test"`) + assert.Contains(t, string(got), `"count"`) + assert.Contains(t, string(got), "42") + }) + + t.Run("success – overwrite existing file", func(t *testing.T) { + tmpDir := t.TempDir() + + first := map[string]string{"version": "1"} + second := map[string]string{"version": "2"} + + require.NoError(t, writeJSONToFile(tmpDir, "out.json", first, 0o644)) + require.NoError(t, writeJSONToFile(tmpDir, "out.json", second, 0o644)) + + got, err := os.ReadFile(filepath.Join(tmpDir, "out.json")) + require.NoError(t, err) + assert.Contains(t, string(got), `"2"`) + assert.NotContains(t, string(got), `"1"`) + }) + + t.Run("error – json.MarshalIndent fails for unmarshalable type", func(t *testing.T) { + tmpDir := t.TempDir() + + // Channels cannot be marshaled to JSON; json.MarshalIndent returns an error. + unmarshalable := make(chan int) + err := writeJSONToFile(tmpDir, "bad.json", unmarshalable, 0o644) + require.Error(t, err) + assert.Contains(t, err.Error(), "failed to marshal JSON data") + // The error should reference the target file path. + assert.Contains(t, err.Error(), "bad.json") + + // No file should have been created. + _, statErr := os.Stat(filepath.Join(tmpDir, "bad.json")) + assert.True(t, os.IsNotExist(statErr), "file must not be created when marshal fails") + }) + + t.Run("error – atomicWriteFile fails when directory does not exist", func(t *testing.T) { + // Pass a logDir that does not exist so atomicWriteFile cannot create the temp file. + err := writeJSONToFile("/nonexistent/dir/that/cannot/exist", "out.json", map[string]string{}, 0o644) + require.Error(t, err) + // The error surfaces from atomicWriteFile's os.WriteFile call. + assert.Contains(t, err.Error(), "failed to write temp file") + }) + + t.Run("success – empty struct written", func(t *testing.T) { + tmpDir := t.TempDir() + + err := writeJSONToFile(tmpDir, "empty.json", struct{}{}, 0o644) + require.NoError(t, err) + + got, err := os.ReadFile(filepath.Join(tmpDir, "empty.json")) + require.NoError(t, err) + assert.Equal(t, "{}", string(got)) + }) + + t.Run("success – slice of strings written", func(t *testing.T) { + tmpDir := t.TempDir() + + data := []string{"alpha", "beta", "gamma"} + err := writeJSONToFile(tmpDir, "list.json", data, 0o644) + require.NoError(t, err) + + got, err := os.ReadFile(filepath.Join(tmpDir, "list.json")) + require.NoError(t, err) + assert.Contains(t, string(got), `"alpha"`) + assert.Contains(t, string(got), `"gamma"`) + }) +} + +// TestInitAndSetGlobalNoFileLogger_SetupError verifies that initAndSetGlobalNoFileLogger +// returns the error when factory.setup fails after the directory is successfully created. +func TestInitAndSetGlobalNoFileLogger_SetupError(t *testing.T) { + resetAllGlobalLoggers(t) + t.Cleanup(func() { resetAllGlobalLoggers(t) }) + + tmpDir := t.TempDir() + + // Build a factory whose setup always returns an error. + errFactory := newLoggerFactory( + func(_ *os.File, logDir, _ string) (*ServerFileLogger, error) { + return nil, os.ErrInvalid + }, + func(err error, logDir, _ string) (*ServerFileLogger, error) { + // onError is only called when MkdirAll fails; it should not be reached here. + return newServerFileLogger(logDir, true), nil + }, + ) + + err := initAndSetGlobalNoFileLogger( + &globalServerLoggerMu, + &globalServerFileLogger, + tmpDir, + errFactory, + ) + require.Error(t, err, "initAndSetGlobalNoFileLogger must return error when factory.setup fails") +} From 9ef0af46f89d69617d598fe8002a06f34fae8194 Mon Sep 17 00:00:00 2001 From: Landon Cox Date: Mon, 13 Jul 2026 16:26:30 -0700 Subject: [PATCH 2/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- internal/logger/write_json_to_file_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/logger/write_json_to_file_test.go b/internal/logger/write_json_to_file_test.go index f59cc116..38d45edd 100644 --- a/internal/logger/write_json_to_file_test.go +++ b/internal/logger/write_json_to_file_test.go @@ -100,7 +100,8 @@ func TestWriteJSONToFile(t *testing.T) { t.Run("error – atomicWriteFile fails when directory does not exist", func(t *testing.T) { // Pass a logDir that does not exist so atomicWriteFile cannot create the temp file. - err := writeJSONToFile("/nonexistent/dir/that/cannot/exist", "out.json", map[string]string{}, 0o644) +missingDir := filepath.Join(t.TempDir(), "missing") + err := writeJSONToFile(missingDir, "out.json", map[string]string{}, 0o644) require.Error(t, err) // The error surfaces from atomicWriteFile's os.WriteFile call. assert.Contains(t, err.Error(), "failed to write temp file") From d1c1ca9034efb841099dad7d699725bdbba8b5b6 Mon Sep 17 00:00:00 2001 From: Landon Cox Date: Mon, 13 Jul 2026 16:26:37 -0700 Subject: [PATCH 3/4] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- internal/logger/write_json_to_file_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/logger/write_json_to_file_test.go b/internal/logger/write_json_to_file_test.go index 38d45edd..951279e8 100644 --- a/internal/logger/write_json_to_file_test.go +++ b/internal/logger/write_json_to_file_test.go @@ -157,5 +157,5 @@ func TestInitAndSetGlobalNoFileLogger_SetupError(t *testing.T) { tmpDir, errFactory, ) - require.Error(t, err, "initAndSetGlobalNoFileLogger must return error when factory.setup fails") +require.ErrorIs(t, err, os.ErrInvalid, "initAndSetGlobalNoFileLogger must return the factory.setup error") } From 1f65b6628840065f1dbfa68b973fcc6aa917550a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Jul 2026 23:35:22 +0000 Subject: [PATCH 4/4] test: gofmt write_json_to_file_test --- internal/logger/write_json_to_file_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/logger/write_json_to_file_test.go b/internal/logger/write_json_to_file_test.go index 951279e8..806828dc 100644 --- a/internal/logger/write_json_to_file_test.go +++ b/internal/logger/write_json_to_file_test.go @@ -100,7 +100,7 @@ func TestWriteJSONToFile(t *testing.T) { t.Run("error – atomicWriteFile fails when directory does not exist", func(t *testing.T) { // Pass a logDir that does not exist so atomicWriteFile cannot create the temp file. -missingDir := filepath.Join(t.TempDir(), "missing") + missingDir := filepath.Join(t.TempDir(), "missing") err := writeJSONToFile(missingDir, "out.json", map[string]string{}, 0o644) require.Error(t, err) // The error surfaces from atomicWriteFile's os.WriteFile call. @@ -157,5 +157,5 @@ func TestInitAndSetGlobalNoFileLogger_SetupError(t *testing.T) { tmpDir, errFactory, ) -require.ErrorIs(t, err, os.ErrInvalid, "initAndSetGlobalNoFileLogger must return the factory.setup error") + require.ErrorIs(t, err, os.ErrInvalid, "initAndSetGlobalNoFileLogger must return the factory.setup error") }