diff --git a/cmd/opencodereview/emit_run_result_test.go b/cmd/opencodereview/emit_run_result_test.go index 3770fee..6ad71bb 100644 --- a/cmd/opencodereview/emit_run_result_test.go +++ b/cmd/opencodereview/emit_run_result_test.go @@ -181,7 +181,7 @@ func TestEmitRunResult_NilQuietHandle(t *testing.T) { func TestEmitRunResult_JSONTraceIDFromContext(t *testing.T) { tp := sdktrace.NewTracerProvider() - defer tp.Shutdown(context.Background()) + defer func() { _ = tp.Shutdown(context.Background()) }() otel.SetTracerProvider(tp) ctx, span := tp.Tracer("test").Start(context.Background(), "test-root") @@ -211,7 +211,7 @@ func TestEmitRunResult_JSONTraceIDFromContext(t *testing.T) { func TestEmitRunResult_JSONNoFilesTraceID(t *testing.T) { tp := sdktrace.NewTracerProvider() - defer tp.Shutdown(context.Background()) + defer func() { _ = tp.Shutdown(context.Background()) }() otel.SetTracerProvider(tp) ctx, span := tp.Tracer("test").Start(context.Background(), "test-root") diff --git a/cmd/opencodereview/git_test.go b/cmd/opencodereview/git_test.go index 0630a4c..4528b29 100644 --- a/cmd/opencodereview/git_test.go +++ b/cmd/opencodereview/git_test.go @@ -23,11 +23,17 @@ func initTestGitRepo(t *testing.T) string { } } f := filepath.Join(dir, "README.md") - os.WriteFile(f, []byte("hello"), 0o644) + if err := os.WriteFile(f, []byte("hello"), 0o644); err != nil { + t.Fatalf("write README: %v", err) + } cmd := exec.Command("git", "-C", dir, "add", ".") - cmd.CombinedOutput() + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("git add: %v: %s", err, out) + } cmd = exec.Command("git", "-C", dir, "commit", "-m", "initial commit") - cmd.CombinedOutput() + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("git commit: %v: %s", err, out) + } return dir } @@ -93,9 +99,18 @@ func TestResolveRepoDir_NotGitRepo(t *testing.T) { func TestResolveRepoDir_EmptyUsesWd(t *testing.T) { dir := initTestGitRepo(t) - origDir, _ := os.Getwd() - defer os.Chdir(origDir) - os.Chdir(dir) + origDir, err := os.Getwd() + if err != nil { + t.Fatalf("getwd: %v", err) + } + defer func() { + if err := os.Chdir(origDir); err != nil { + t.Errorf("restore chdir: %v", err) + } + }() + if err := os.Chdir(dir); err != nil { + t.Fatalf("chdir: %v", err) + } resolved, err := resolveRepoDir("") if err != nil { diff --git a/cmd/opencodereview/output_helpers_test.go b/cmd/opencodereview/output_helpers_test.go index f3d9127..31001e7 100644 --- a/cmd/opencodereview/output_helpers_test.go +++ b/cmd/opencodereview/output_helpers_test.go @@ -169,7 +169,7 @@ func TestOutputJSONWithWarnings_NoCommentsSubtaskError(t *testing.T) { warnings := []agent.AgentWarning{{Type: "subtask_error", File: "x.go", Message: "fail"}} err := outputJSONWithWarnings(nil, warnings, 1, 10, 5, 15, 0, 0, time.Second, "", nil, "abc123trace") - w.Close() + _ = w.Close() os.Stdout = old if err != nil { @@ -177,10 +177,12 @@ func TestOutputJSONWithWarnings_NoCommentsSubtaskError(t *testing.T) { } var buf bytes.Buffer - buf.ReadFrom(r) + _, _ = buf.ReadFrom(r) var out jsonOutput - json.Unmarshal(buf.Bytes(), &out) + if err := json.Unmarshal(buf.Bytes(), &out); err != nil { + t.Fatalf("unmarshal: %v", err) + } if out.Status != "completed_with_errors" { t.Errorf("status = %q, want completed_with_errors", out.Status) } @@ -224,7 +226,7 @@ func TestOutputJSON(t *testing.T) { } err := outputJSON(comments) - w.Close() + _ = w.Close() os.Stdout = old if err != nil { @@ -232,7 +234,7 @@ func TestOutputJSON(t *testing.T) { } var buf bytes.Buffer - buf.ReadFrom(r) + _, _ = buf.ReadFrom(r) var out jsonOutput if err := json.Unmarshal(buf.Bytes(), &out); err != nil { @@ -253,7 +255,7 @@ func TestOutputJSON_NoComments(t *testing.T) { err := outputJSON(nil) - w.Close() + _ = w.Close() os.Stdout = old if err != nil { @@ -261,10 +263,12 @@ func TestOutputJSON_NoComments(t *testing.T) { } var buf bytes.Buffer - buf.ReadFrom(r) + _, _ = buf.ReadFrom(r) var out jsonOutput - json.Unmarshal(buf.Bytes(), &out) + if err := json.Unmarshal(buf.Bytes(), &out); err != nil { + t.Fatalf("unmarshal: %v", err) + } if out.Message == "" { t.Error("expected non-empty message when no comments") } @@ -278,7 +282,7 @@ func TestOutputJSONWithWarnings(t *testing.T) { comments := []model.LlmComment{{Path: "b.go", Content: "test"}} warnings := []agent.AgentWarning{{Type: "subtask_error", File: "c.go", Message: "failed"}} err := outputJSONWithWarnings(comments, warnings, 5, 100, 50, 150, 10, 5, 3*time.Second, "summary", map[string]int64{"file_read": 3}, "trace-xyz-789") - w.Close() + _ = w.Close() os.Stdout = old if err != nil { @@ -286,10 +290,12 @@ func TestOutputJSONWithWarnings(t *testing.T) { } var buf bytes.Buffer - buf.ReadFrom(r) + _, _ = buf.ReadFrom(r) var out jsonOutput - json.Unmarshal(buf.Bytes(), &out) + if err := json.Unmarshal(buf.Bytes(), &out); err != nil { + t.Fatalf("unmarshal: %v", err) + } if out.Status != "completed_with_errors" { t.Errorf("status = %q, want completed_with_errors", out.Status) } @@ -314,7 +320,7 @@ func TestOutputJSONWithWarnings_NoCommentsNoErrors(t *testing.T) { warnings := []agent.AgentWarning{{Type: "warning", Message: "something"}} err := outputJSONWithWarnings(nil, warnings, 2, 50, 20, 70, 0, 0, time.Second, "", nil, "") - w.Close() + _ = w.Close() os.Stdout = old if err != nil { @@ -322,10 +328,12 @@ func TestOutputJSONWithWarnings_NoCommentsNoErrors(t *testing.T) { } var buf bytes.Buffer - buf.ReadFrom(r) + _, _ = buf.ReadFrom(r) var out jsonOutput - json.Unmarshal(buf.Bytes(), &out) + if err := json.Unmarshal(buf.Bytes(), &out); err != nil { + t.Fatalf("unmarshal: %v", err) + } if out.Status != "completed_with_warnings" { t.Errorf("status = %q, want completed_with_warnings", out.Status) } @@ -341,7 +349,7 @@ func TestOutputJSONNoFiles(t *testing.T) { err := outputJSONNoFiles("test-trace-id-456") - w.Close() + _ = w.Close() os.Stdout = old if err != nil { @@ -349,10 +357,12 @@ func TestOutputJSONNoFiles(t *testing.T) { } var buf bytes.Buffer - buf.ReadFrom(r) + _, _ = buf.ReadFrom(r) var out jsonOutput - json.Unmarshal(buf.Bytes(), &out) + if err := json.Unmarshal(buf.Bytes(), &out); err != nil { + t.Fatalf("unmarshal: %v", err) + } if out.Status != "skipped" { t.Errorf("status = %q, want skipped", out.Status) } @@ -370,10 +380,10 @@ func captureStdout(t *testing.T, fn func()) string { } os.Stdout = w fn() - w.Close() + _ = w.Close() os.Stdout = old var buf bytes.Buffer - buf.ReadFrom(r) + _, _ = buf.ReadFrom(r) return buf.String() } diff --git a/cmd/opencodereview/output_test.go b/cmd/opencodereview/output_test.go index c5b8487..038cd84 100644 --- a/cmd/opencodereview/output_test.go +++ b/cmd/opencodereview/output_test.go @@ -93,8 +93,8 @@ func TestSanitizeTerminal(t *testing.T) { {"only control chars", "\x1b\x07\x00\x7f", ""}, {"unicode preserved", "代码审查 レビュー 🔍", "代码审查 レビュー 🔍"}, {"mixed safe and unsafe", "path\x1b[0m/file.go", "path[0m/file.go"}, - {"strips C1 CSI (U+009B)", "before›after", "beforeafter"}, - {"strips C1 OSC (U+009D)", "beforeafter", "beforeafter"}, + {"strips C1 CSI (U+009B)", "before\u009bafter", "beforeafter"}, + {"strips C1 OSC (U+009D)", "before\u009dafter", "beforeafter"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/cmd/opencodereview/provider_cmd_test.go b/cmd/opencodereview/provider_cmd_test.go index e8d84db..d1f03bb 100644 --- a/cmd/opencodereview/provider_cmd_test.go +++ b/cmd/opencodereview/provider_cmd_test.go @@ -364,7 +364,7 @@ func TestPrintWizardCancelled(t *testing.T) { } os.Stdout = w printWizardCancelled(tc.savedInSession, tc.scope) - w.Close() + _ = w.Close() os.Stdout = old got, err := io.ReadAll(r) if err != nil { diff --git a/cmd/opencodereview/provider_tui_test.go b/cmd/opencodereview/provider_tui_test.go index 4c9de47..624bc50 100644 --- a/cmd/opencodereview/provider_tui_test.go +++ b/cmd/opencodereview/provider_tui_test.go @@ -2169,7 +2169,7 @@ func TestProviderTUI_ApiKeyTypingShowsOneStarPerChar(t *testing.T) { m.loadExistingAPIKey() m.apiKeyInput.Focus() - for _, ch := range []rune("abc") { + for _, ch := range "abc" { result, _ := m.Update(charKey(ch)) m = result.(providerTUIModel) } diff --git a/cmd/opencodereview/shared_test.go b/cmd/opencodereview/shared_test.go index 21e7553..417a65f 100644 --- a/cmd/opencodereview/shared_test.go +++ b/cmd/opencodereview/shared_test.go @@ -79,9 +79,18 @@ func TestQuietHandle_IdempotentRestore(t *testing.T) { func TestResolveWorkingDir_CurrentDir(t *testing.T) { dir := t.TempDir() - origDir, _ := os.Getwd() - defer os.Chdir(origDir) - os.Chdir(dir) + origDir, err := os.Getwd() + if err != nil { + t.Fatalf("getwd: %v", err) + } + defer func() { + if err := os.Chdir(origDir); err != nil { + t.Errorf("restore chdir: %v", err) + } + }() + if err := os.Chdir(dir); err != nil { + t.Fatalf("chdir: %v", err) + } absPath, isGit, err := resolveWorkingDir("", false) if err != nil { diff --git a/internal/agent/util_test.go b/internal/agent/util_test.go index af3b8ff..caf030c 100644 --- a/internal/agent/util_test.go +++ b/internal/agent/util_test.go @@ -157,6 +157,9 @@ func TestCopyMessages(t *testing.T) { } cp = append(cp, llm.NewTextMessage("user", "c")) + if len(cp) != len(orig)+1 { + t.Errorf("appended copy length = %d, want %d", len(cp), len(orig)+1) + } if len(orig) != 2 { t.Error("copyMessages: appending to copy modified original slice") } diff --git a/internal/config/toolsconfig/toolsconfig_test.go b/internal/config/toolsconfig/toolsconfig_test.go index bd25bb1..ce6bf30 100644 --- a/internal/config/toolsconfig/toolsconfig_test.go +++ b/internal/config/toolsconfig/toolsconfig_test.go @@ -31,7 +31,9 @@ func TestLoad_CustomFile(t *testing.T) { data := `[ {"name": "test_tool", "plan_task": true, "main_task": false, "definition": {"name": "test_tool"}} ]` - os.WriteFile(path, []byte(data), 0644) + if err := os.WriteFile(path, []byte(data), 0644); err != nil { + t.Fatalf("write tools.json: %v", err) + } tools, err := Load(path) if err != nil { @@ -61,7 +63,9 @@ func TestLoad_FileNotFound(t *testing.T) { func TestLoad_InvalidJSON(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "tools.json") - os.WriteFile(path, []byte("not json"), 0644) + if err := os.WriteFile(path, []byte("not json"), 0644); err != nil { + t.Fatalf("write tools.json: %v", err) + } _, err := Load(path) if err == nil { diff --git a/internal/llm/message_test.go b/internal/llm/message_test.go index 53ee185..4a03499 100644 --- a/internal/llm/message_test.go +++ b/internal/llm/message_test.go @@ -243,7 +243,9 @@ func TestParseShellRC_ModelOverride(t *testing.T) { export ANTHROPIC_AUTH_TOKEN="token" export ANTHROPIC_MODEL=claude-3-opus ` - os.WriteFile(rcPath, []byte(content), 0644) + if err := os.WriteFile(rcPath, []byte(content), 0644); err != nil { + t.Fatalf("write rc: %v", err) + } ep, ok, err := parseShellRC(rcPath, "override-model") if err != nil { @@ -265,7 +267,9 @@ func TestParseShellRC_Incomplete(t *testing.T) { export ANTHROPIC_AUTH_TOKEN="token" # missing ANTHROPIC_MODEL ` - os.WriteFile(rcPath, []byte(content), 0644) + if err := os.WriteFile(rcPath, []byte(content), 0644); err != nil { + t.Fatalf("write rc: %v", err) + } _, ok, err := parseShellRC(rcPath, "") if err != nil { diff --git a/internal/llm/resolver_test.go b/internal/llm/resolver_test.go index 5b2cace..6c933aa 100644 --- a/internal/llm/resolver_test.go +++ b/internal/llm/resolver_test.go @@ -104,7 +104,9 @@ func TestResolveEndpoint_ConfigFileStripsModelSuffix(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -137,7 +139,9 @@ func TestResolveEndpoint_ConfigAnthropicDefaultsToAuthorization(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -168,7 +172,9 @@ func TestResolveEndpoint_ConfigAuthHeaderOverrideToXAPIKey(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -199,7 +205,9 @@ func TestResolveEndpoint_ConfigOpenAIIgnoresAuthHeader(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -271,7 +279,9 @@ func TestResolveEndpoint_ProviderAnthropic(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -305,7 +315,9 @@ func TestResolveEndpoint_ProviderOpenAI(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -334,7 +346,9 @@ func TestResolveEndpoint_ProviderModelOverride(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -356,7 +370,9 @@ func TestResolveEndpoint_ProviderEntryModelOverridesDefault(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -383,7 +399,9 @@ func TestResolveEndpointWithModelOverride_CustomProviderWithoutConfiguredModel(t } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpointWithModelOverride(cfgPath, "llama-3-8b") if err != nil { @@ -409,7 +427,9 @@ func TestResolveEndpoint_ProviderAPIKeyEnvFallback(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -431,7 +451,9 @@ func TestResolveEndpoint_ProviderMissingAPIKey(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpoint(cfgPath) if err == nil { @@ -448,7 +470,9 @@ func TestResolveEndpoint_ProviderNotConfigured(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpoint(cfgPath) if err == nil { @@ -472,7 +496,9 @@ func TestResolveEndpoint_CustomProvider(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -508,7 +534,9 @@ func TestResolveEndpoint_CustomProviderInvalidProtocol(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpoint(cfgPath) if err == nil { @@ -531,7 +559,9 @@ func TestResolveEndpoint_CustomProviderMissingFields(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpoint(cfgPath) if err == nil { @@ -555,7 +585,9 @@ func TestResolveEndpoint_CustomProviderModelFromTopLevel(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -578,7 +610,9 @@ func TestResolveEndpoint_LegacyLlmStillWorks(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -603,7 +637,9 @@ func TestResolveEndpoint_ProviderAnthropicURLHasMessagesSuffix(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -629,7 +665,9 @@ func TestResolveEndpoint_ProviderExtraBody(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -654,7 +692,9 @@ func TestResolveEndpointWithModelOverride_ValidModelInPresetList(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpointWithModelOverride(cfgPath, "claude-opus-4-8") if err != nil { @@ -676,7 +716,9 @@ func TestResolveEndpointWithModelOverride_InvalidModelInPresetList(t *testing.T) } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpointWithModelOverride(cfgPath, "claude-opsu-4-6") if err == nil { @@ -706,7 +748,9 @@ func TestResolveEndpointWithModelOverride_ValidModelInCustomProviderList(t *test } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpointWithModelOverride(cfgPath, "llama-3-8b") if err != nil { @@ -733,7 +777,9 @@ func TestResolveEndpointWithModelOverride_InvalidModelInCustomProviderList(t *te } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpointWithModelOverride(cfgPath, "gpt-4") if err == nil { @@ -760,7 +806,9 @@ func TestResolveEndpointWithModelOverride_NoValidationWhenNoModelList(t *testing } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpointWithModelOverride(cfgPath, "any-model-name") if err != nil { @@ -785,7 +833,9 @@ func TestResolveEndpointWithModelOverride_MergesPresetAndEntryModels(t *testing. } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } // Should accept both preset models and entry models. ep1, err := ResolveEndpointWithModelOverride(cfgPath, "claude-opus-4-8") @@ -823,7 +873,9 @@ func TestResolveEndpointWithModelOverride_LegacyConfigNoValidation(t *testing.T) } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } // Legacy config has no model list, so any override should be accepted. ep, err := ResolveEndpointWithModelOverride(cfgPath, "any-override-model") @@ -1087,7 +1139,9 @@ func TestResolveEndpoint_ProviderExtraHeaders(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -1114,7 +1168,9 @@ func TestResolveEndpoint_LegacyLlmExtraHeaders(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -1218,7 +1274,9 @@ func TestResolveEndpoint_ConfigTimeoutSec(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -1242,7 +1300,9 @@ func TestResolveEndpoint_NegativeConfigTimeoutSec(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpoint(cfgPath) if err == nil { @@ -1308,7 +1368,9 @@ func TestResolveEndpoint_ProviderConfigTimeoutSec(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -1334,7 +1396,9 @@ func TestResolveEndpoint_ProviderConfigNegativeTimeoutSec(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpoint(cfgPath) if err == nil { @@ -1359,7 +1423,9 @@ func TestResolveEndpoint_EnvTimeoutOverridesConfigTimeout(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -1387,7 +1453,9 @@ func TestResolveEndpoint_EnvTimeoutOverridesProviderTimeout(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } ep, err := ResolveEndpoint(cfgPath) if err != nil { @@ -1412,7 +1480,9 @@ func TestResolveEndpoint_InvalidEnvTimeoutWithConfig(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpoint(cfgPath) if err == nil { @@ -1436,7 +1506,9 @@ func TestResolveEndpoint_NegativeEnvTimeoutWithConfig(t *testing.T) { } data, _ := json.Marshal(cfg) cfgPath := filepath.Join(t.TempDir(), "config.json") - os.WriteFile(cfgPath, data, 0644) + if err := os.WriteFile(cfgPath, data, 0644); err != nil { + t.Fatalf("write config: %v", err) + } _, err := ResolveEndpoint(cfgPath) if err == nil { diff --git a/internal/mcp/client_test.go b/internal/mcp/client_test.go index 07aee15..c5f04da 100644 --- a/internal/mcp/client_test.go +++ b/internal/mcp/client_test.go @@ -113,7 +113,7 @@ func TestProvider_Execute_Integration(t *testing.T) { } c := &Client{name: "test-srv", session: session, tools: toolsResult.Tools} - defer c.Close() + defer func() { _ = c.Close() }() p := &Provider{toolName: "greet", client: c} result, err := p.Execute(ctx, map[string]any{"name": "world"}) @@ -193,7 +193,7 @@ func TestNewClient_Integration(t *testing.T) { session: session, tools: toolsResult.Tools, } - defer c.Close() + defer func() { _ = c.Close() }() if c.Name() != "test-srv" { t.Errorf("Name() = %q", c.Name()) diff --git a/internal/mcp/stdio_test.go b/internal/mcp/stdio_test.go index ea9f3d0..b851cad 100644 --- a/internal/mcp/stdio_test.go +++ b/internal/mcp/stdio_test.go @@ -68,7 +68,7 @@ func TestNewClient_Stdio(t *testing.T) { if err != nil { t.Fatalf("NewClient: %v", err) } - defer c.Close() + defer func() { _ = c.Close() }() if c.Name() != "test-srv" { t.Errorf("Name() = %q, want %q", c.Name(), "test-srv") diff --git a/internal/model/model_test.go b/internal/model/model_test.go index 8da62b8..5ac6273 100644 --- a/internal/model/model_test.go +++ b/internal/model/model_test.go @@ -65,14 +65,18 @@ func TestPreviewEntry_ExcludeReasonOmitEmpty(t *testing.T) { } data, _ := json.Marshal(e) var m map[string]any - json.Unmarshal(data, &m) + if err := json.Unmarshal(data, &m); err != nil { + t.Fatalf("unmarshal: %v", err) + } if _, ok := m["exclude_reason"]; ok { t.Error("expected exclude_reason to be omitted when empty") } e.ExcludeReason = ExcludeUserRule data, _ = json.Marshal(e) - json.Unmarshal(data, &m) + if err := json.Unmarshal(data, &m); err != nil { + t.Fatalf("unmarshal: %v", err) + } if m["exclude_reason"] != "user_exclude" { t.Errorf("expected exclude_reason=user_exclude, got %v", m["exclude_reason"]) } diff --git a/internal/pathutil/path_test.go b/internal/pathutil/path_test.go index 3664e75..ecc4985 100644 --- a/internal/pathutil/path_test.go +++ b/internal/pathutil/path_test.go @@ -72,7 +72,7 @@ func TestCanonicalPath_RelativePath(t *testing.T) { if err != nil { t.Fatalf("Getwd: %v", err) } - t.Cleanup(func() { os.Chdir(oldWd) }) + t.Cleanup(func() { _ = os.Chdir(oldWd) }) if err := os.Chdir(dir); err != nil { t.Fatalf("Chdir: %v", err) } diff --git a/internal/session/persist_test.go b/internal/session/persist_test.go index ddf99c2..6231341 100644 --- a/internal/session/persist_test.go +++ b/internal/session/persist_test.go @@ -109,7 +109,7 @@ func readJSONLRecords(t *testing.T, path string) []map[string]any { if err != nil { t.Fatalf("open jsonl: %v", err) } - defer f.Close() + defer func() { _ = f.Close() }() var records []map[string]any scanner := bufio.NewScanner(f) @@ -165,8 +165,11 @@ func TestSetErrorWritesJSONL(t *testing.T) { if sh.persist != nil { sh.persist.mu.Lock() - sh.persist.writer.Flush() + err := sh.persist.writer.Flush() sh.persist.mu.Unlock() + if err != nil { + t.Fatalf("flush: %v", err) + } } path := sessionJSONLPath(t, repoDir, sh.SessionID) diff --git a/internal/telemetry/config_test.go b/internal/telemetry/config_test.go index 1e4011a..9a1c215 100644 --- a/internal/telemetry/config_test.go +++ b/internal/telemetry/config_test.go @@ -103,7 +103,7 @@ func TestResolveEnv(t *testing.T) { } for _, k := range envKeys { t.Setenv(k, "") - os.Unsetenv(k) + _ = os.Unsetenv(k) } for k, v := range tc.envs { t.Setenv(k, v) @@ -128,7 +128,9 @@ func TestLoadFromJSON(t *testing.T) { t.Run("malformed json returns nil error", func(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "config.json") - os.WriteFile(path, []byte("{invalid json"), 0644) + if err := os.WriteFile(path, []byte("{invalid json"), 0644); err != nil { + t.Fatalf("write file: %v", err) + } cfg := DefaultConfig() err := LoadFromJSON(&cfg, path) @@ -140,7 +142,9 @@ func TestLoadFromJSON(t *testing.T) { t.Run("no telemetry section", func(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "config.json") - os.WriteFile(path, []byte(`{"other": "value"}`), 0644) + if err := os.WriteFile(path, []byte(`{"other": "value"}`), 0644); err != nil { + t.Fatalf("write file: %v", err) + } cfg := DefaultConfig() err := LoadFromJSON(&cfg, path) @@ -163,7 +167,9 @@ func TestLoadFromJSON(t *testing.T) { "content_logging": true } }` - os.WriteFile(path, []byte(data), 0644) + if err := os.WriteFile(path, []byte(data), 0644); err != nil { + t.Fatalf("write file: %v", err) + } cfg := DefaultConfig() err := LoadFromJSON(&cfg, path) @@ -188,7 +194,9 @@ func TestLoadFromJSON(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "config.json") data := `{"telemetry": {"otlp_endpoint": "localhost:4317"}}` - os.WriteFile(path, []byte(data), 0644) + if err := os.WriteFile(path, []byte(data), 0644); err != nil { + t.Fatalf("write file: %v", err) + } cfg := DefaultConfig() err := LoadFromJSON(&cfg, path) @@ -204,7 +212,9 @@ func TestLoadFromJSON(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "config.json") data := `{"telemetry": {"exporter": "otlp"}}` - os.WriteFile(path, []byte(data), 0644) + if err := os.WriteFile(path, []byte(data), 0644); err != nil { + t.Fatalf("write file: %v", err) + } cfg := DefaultConfig() cfg.Exporter = "custom" @@ -227,7 +237,7 @@ func TestResolveConfig(t *testing.T) { } for _, k := range envKeys { t.Setenv(k, "") - os.Unsetenv(k) + _ = os.Unsetenv(k) } cfg := ResolveConfig("") @@ -240,7 +250,9 @@ func TestResolveConfig(t *testing.T) { tmp := t.TempDir() path := filepath.Join(tmp, "config.json") data := `{"telemetry": {"enabled": false}}` - os.WriteFile(path, []byte(data), 0644) + if err := os.WriteFile(path, []byte(data), 0644); err != nil { + t.Fatalf("write file: %v", err) + } t.Setenv("OCR_ENABLE_TELEMETRY", "1") diff --git a/internal/telemetry/events_test.go b/internal/telemetry/events_test.go index 1bcd170..d9d1efa 100644 --- a/internal/telemetry/events_test.go +++ b/internal/telemetry/events_test.go @@ -54,7 +54,7 @@ func captureStderr(t *testing.T, fn func()) string { defer func() { os.Stderr = oldStderr }() fn() - w.Close() + _ = w.Close() var buf bytes.Buffer _, _ = io.Copy(&buf, r) diff --git a/internal/telemetry/exporter_test.go b/internal/telemetry/exporter_test.go index 1a3c9be..97ebaa2 100644 --- a/internal/telemetry/exporter_test.go +++ b/internal/telemetry/exporter_test.go @@ -161,7 +161,9 @@ func TestInitOTLPProviders_ProtocolRouting(t *testing.T) { OTLPProtocol: tc.protocol, } initOTLPProviders(context.Background(), resource.Default(), cfg) - w.Close() + if err := w.Close(); err != nil { + t.Fatalf("close stderr pipe: %v", err) + } os.Stderr = oldStderr defer func() { @@ -184,7 +186,9 @@ func TestInitOTLPProviders_ProtocolRouting(t *testing.T) { } var buf bytes.Buffer - io.Copy(&buf, r) + if _, err := io.Copy(&buf, r); err != nil { + t.Fatalf("read stderr pipe: %v", err) + } stderrOut := buf.String() if tc.wantWarning { if !strings.Contains(stderrOut, "falling back to gRPC") { diff --git a/internal/telemetry/provider_test.go b/internal/telemetry/provider_test.go index 3895636..bdbc380 100644 --- a/internal/telemetry/provider_test.go +++ b/internal/telemetry/provider_test.go @@ -63,7 +63,7 @@ func TestContentLogging_EnabledWithEnv(t *testing.T) { func TestContentLogging_EnabledWithoutEnv(t *testing.T) { setupEnabledTelemetry(t) t.Setenv("OCR_CONTENT_LOGGING", "") - os.Unsetenv("OCR_CONTENT_LOGGING") + _ = os.Unsetenv("OCR_CONTENT_LOGGING") if ContentLogging() { t.Error("expected ContentLogging()=false when enabled but env var not set") } @@ -112,7 +112,7 @@ func TestInit_DisabledByDefault(t *testing.T) { } for _, k := range envKeys { t.Setenv(k, "") - os.Unsetenv(k) + _ = os.Unsetenv(k) } defer func() { @@ -140,7 +140,7 @@ func TestInit_EnabledConsole(t *testing.T) { } for _, k := range envKeys { t.Setenv(k, "") - os.Unsetenv(k) + _ = os.Unsetenv(k) } defer func() { diff --git a/internal/viewer/handler_test.go b/internal/viewer/handler_test.go index c7e9179..c24349c 100644 --- a/internal/viewer/handler_test.go +++ b/internal/viewer/handler_test.go @@ -82,7 +82,7 @@ func TestHandleRepos_PermissionDenied(t *testing.T) { if err := os.Chmod(root, 0000); err != nil { t.Fatal(err) } - t.Cleanup(func() { os.Chmod(root, 0755) }) + t.Cleanup(func() { _ = os.Chmod(root, 0755) }) req := httptest.NewRequest("GET", "/", nil) rr := httptest.NewRecorder() diff --git a/internal/viewer/server_extra_test.go b/internal/viewer/server_extra_test.go index c4e8b63..04be65d 100644 --- a/internal/viewer/server_extra_test.go +++ b/internal/viewer/server_extra_test.go @@ -167,7 +167,7 @@ func TestStaticFS(t *testing.T) { if err != nil { t.Fatalf("failed to open style.css from staticFS: %v", err) } - f.Close() + _ = f.Close() } func TestResolveAllowedHostsFromEnv(t *testing.T) { diff --git a/internal/viewer/store_load_test.go b/internal/viewer/store_load_test.go index 3ed4a92..a4da1db 100644 --- a/internal/viewer/store_load_test.go +++ b/internal/viewer/store_load_test.go @@ -405,7 +405,7 @@ func TestDiscoverRepos_SkipsUnreadableSubdir(t *testing.T) { if err := os.Chmod(badRepo, 0000); err != nil { t.Fatal(err) } - t.Cleanup(func() { os.Chmod(badRepo, 0755) }) + t.Cleanup(func() { _ = os.Chmod(badRepo, 0755) }) repos, err := DiscoverRepos(root) if err != nil { @@ -439,7 +439,7 @@ func TestListSessions_SkipsUnreadableFiles(t *testing.T) { if err := os.Chmod(badPath, 0000); err != nil { t.Fatal(err) } - t.Cleanup(func() { os.Chmod(badPath, 0644) }) + t.Cleanup(func() { _ = os.Chmod(badPath, 0644) }) sessions, err := ListSessions(root, "repo") if err != nil {