diff --git a/internal/config/config_guardpolicies_test.go b/internal/config/config_guardpolicies_test.go index 492ed408..757d1d68 100644 --- a/internal/config/config_guardpolicies_test.go +++ b/internal/config/config_guardpolicies_test.go @@ -2,7 +2,6 @@ package config import ( "os" - "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -130,10 +129,7 @@ func TestGuardPolicies_AllMinIntegrityLevels(t *testing.T) { // TestGuardPolicies_TOML_ReposAllFormat tests TOML format with repos="all" func TestGuardPolicies_TOML_ReposAllFormat(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [servers.github] command = "docker" args = ["run", "--rm", "-i", "ghcr.io/github/github-mcp-server:latest"] @@ -141,12 +137,9 @@ args = ["run", "--rm", "-i", "ghcr.io/github/github-mcp-server:latest"] [servers.github.guard_policies.github] repos = "all" min-integrity = "unapproved" -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") +`) - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() should succeed with repos='all'") require.NotNil(t, cfg, "Config should not be nil") @@ -160,10 +153,7 @@ min-integrity = "unapproved" // TestGuardPolicies_TOML_ReposWithWildcards tests TOML format with wildcard patterns func TestGuardPolicies_TOML_ReposWithWildcards(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [servers.github] command = "docker" args = ["run", "--rm", "-i", "ghcr.io/github/github-mcp-server:latest"] @@ -171,12 +161,9 @@ args = ["run", "--rm", "-i", "ghcr.io/github/github-mcp-server:latest"] [servers.github.guard_policies.github] repos = ["myorg/*", "partner/shared-repo", "docs/api-*"] min-integrity = "approved" -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") +`) - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() should succeed with wildcard patterns") require.NotNil(t, cfg, "Config should not be nil") @@ -206,23 +193,17 @@ func TestGuardPolicies_TOML_AllMinIntegrityLevels(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [servers.github] command = "docker" args = ["run", "--rm", "-i", "ghcr.io/github/github-mcp-server:latest"] [servers.github.guard_policies.github] repos = "all" -min-integrity = "` + tc.minIntegrity + `" -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") +min-integrity = "`+tc.minIntegrity+`" +`) - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() should succeed with min-integrity='%s' in TOML", tc.minIntegrity) require.NotNil(t, cfg, "Config should not be nil") @@ -412,7 +393,7 @@ func TestGuardPolicies_WriteSink(t *testing.T) { // TestGuardPolicies_WriteSinkTOML tests write-sink guard policy via TOML file func TestGuardPolicies_WriteSinkTOML(t *testing.T) { - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 3000 api_key = "test-key" @@ -425,14 +406,9 @@ args = ["run", "--rm", "-i", "ghcr.io/github/safe-outputs:latest"] [servers.safeoutputs.guard_policies.write-sink] Accept = ["private:github/gh-aw*"] -` - - tmpDir := t.TempDir() - configPath := filepath.Join(tmpDir, "config.toml") - err := os.WriteFile(configPath, []byte(tomlContent), 0644) - require.NoError(t, err) +`) - cfg, err := LoadFromFile(configPath) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() should succeed with write-sink TOML config") require.NotNil(t, cfg) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 867f077a..1f87b705 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "os" - "path/filepath" "strings" "testing" @@ -893,23 +892,16 @@ func TestLoadFromStdin_InvalidMountFormat(t *testing.T) { // Tests for LoadFromFile function with TOML files func TestLoadFromFile_ValidTOML(t *testing.T) { - // Create a temporary TOML file - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] [servers.test.env] TEST_VAR = "value" -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") +`) - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() failed") require.NotNil(t, cfg, "LoadFromFile() returned nil config") @@ -922,10 +914,7 @@ TEST_VAR = "value" } func TestLoadFromFile_WithGatewayConfig(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 8080 api_key = "test-key-123" @@ -936,12 +925,9 @@ tool_timeout = 60 [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] -` +`) - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") - - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() failed") require.NotNil(t, cfg, "LoadFromFile() returned nil config") require.NotNil(t, cfg.Gateway, "Gateway config should not be nil") @@ -954,10 +940,7 @@ args = ["run", "--rm", "-i", "test/container:latest"] } func TestLoadFromFile_WithGatewayPayloadDir(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 8080 api_key = "test-key-123" @@ -967,12 +950,9 @@ payload_dir = "/custom/payload/path" [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] -` +`) - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") - - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() failed") require.NotNil(t, cfg, "LoadFromFile() returned nil config") require.NotNil(t, cfg.Gateway, "Gateway config should not be nil") @@ -981,10 +961,7 @@ args = ["run", "--rm", "-i", "test/container:latest"] } func TestLoadFromFile_WithoutGatewayPayloadDir(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 8080 api_key = "test-key-123" @@ -993,12 +970,9 @@ domain = "localhost" [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] -` +`) - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") - - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() failed") require.NotNil(t, cfg, "LoadFromFile() returned nil config") require.NotNil(t, cfg.Gateway, "Gateway config should not be nil") @@ -1007,19 +981,13 @@ args = ["run", "--rm", "-i", "test/container:latest"] } func TestLoadFromFile_InvalidTOMLWithLineNumber(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - // Invalid TOML: unterminated string on line 2 - tomlContent := `[servers.test] + path := writeTempTOML(t, `[servers.test] command = "docker args = ["run"] -` +`) - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") - - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.Error(t, err, "Expected error for invalid TOML") assert.Nil(t, cfg, "Config should be nil on error") @@ -1028,22 +996,15 @@ args = ["run"] } func TestLoadFromFile_UnknownKeys(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - // TOML with unknown key "unknown_field" - tomlContent := ` + path := writeTempTOML(t, ` [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] unknown_field = "should trigger error" -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") +`) // Must now return an error per spec §4.3.1: unknown fields MUST be rejected - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.Error(t, err, "LoadFromFile() should fail with unknown keys") assert.Nil(t, cfg, "Config should be nil on error") assert.ErrorContains(t, err, "unrecognized field", "Error should mention unrecognized field") @@ -1056,13 +1017,9 @@ func TestLoadFromFile_NonExistentFile(t *testing.T) { } func TestLoadFromFile_EmptyFile(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "empty.toml") - - err := os.WriteFile(tmpFile, []byte(""), 0644) - require.NoError(t, err, "Failed to write temp TOML file") + path := writeTempTOML(t, "") - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.Error(t, err, "LoadFromFile() should fail with empty file (no servers)") assert.Nil(t, cfg, "Config should be nil on error") assert.ErrorContains(t, err, "no servers defined", "Error should mention missing servers") @@ -1070,18 +1027,10 @@ func TestLoadFromFile_EmptyFile(t *testing.T) { // TestLoadFromFile_ParseErrorWithColumnNumber tests that parse errors include column information func TestLoadFromFile_ParseErrorWithColumnNumber(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - // Invalid TOML: missing equals sign - tomlContent := `[gateway] -port 3000 -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") + path := writeTempTOML(t, "[gateway]\nport 3000\n") - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.Error(t, err, "Expected error for invalid TOML") assert.Nil(t, cfg, "Config should be nil on error") @@ -1095,11 +1044,8 @@ port 3000 // TestLoadFromFile_UnknownKeysInGateway tests that unknown keys in gateway section are rejected func TestLoadFromFile_UnknownKeysInGateway(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - // TOML with typo in gateway field: "prot" instead of "port" - tomlContent := ` + path := writeTempTOML(t, ` [gateway] prot = 3000 api_key = "test-key" @@ -1107,13 +1053,10 @@ api_key = "test-key" [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") +`) // Must return an error per spec §4.3.1: unknown fields MUST be rejected - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.Error(t, err, "LoadFromFile() should fail with unknown keys") assert.Nil(t, cfg, "Config should be nil on error") assert.ErrorContains(t, err, "unrecognized field", "Error should mention unrecognized field") @@ -1121,11 +1064,8 @@ args = ["run", "--rm", "-i", "test/container:latest"] // TestLoadFromFile_MultipleUnknownKeys tests that multiple unknown keys are rejected func TestLoadFromFile_MultipleUnknownKeys(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - // TOML with multiple typos - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 8080 startup_timout = 30 @@ -1135,13 +1075,10 @@ tool_timout = 60 command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] typ = "stdio" -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") +`) // Must return an error per spec §4.3.1: unknown fields MUST be rejected - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.Error(t, err, "LoadFromFile() should fail with multiple unknown keys") assert.Nil(t, cfg, "Config should be nil on error") assert.ErrorContains(t, err, "unrecognized field", "Error should mention unrecognized field") @@ -1149,10 +1086,7 @@ typ = "stdio" // TestLoadFromFile_StreamingLargeFile tests that streaming decoder works efficiently func TestLoadFromFile_StreamingLargeFile(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "large-config.toml") - - // Create a TOML file with many servers + // Create a TOML config with many servers var tomlContent strings.Builder tomlContent.WriteString("[gateway]\nport = 3000\n\n") @@ -1162,11 +1096,10 @@ func TestLoadFromFile_StreamingLargeFile(t *testing.T) { tomlContent.WriteString(fmt.Sprintf("args = [\"run\", \"--rm\", \"-i\", \"test/server%d:latest\"]\n\n", i)) } - err := os.WriteFile(tmpFile, []byte(tomlContent.String()), 0644) - require.NoError(t, err, "Failed to write temp TOML file") + path := writeTempTOML(t, tomlContent.String()) // Should load successfully using streaming decoder - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() should handle large files") require.NotNil(t, cfg, "Config should not be nil") assert.Len(t, cfg.Servers, 100, "Expected 100 servers") @@ -1174,11 +1107,8 @@ func TestLoadFromFile_StreamingLargeFile(t *testing.T) { // TestLoadFromFile_InvalidTOMLDuplicateKey tests handling of duplicate keys func TestLoadFromFile_InvalidTOMLDuplicateKey(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - // TOML 1.1+ should detect duplicate keys (available in v1.6.0) - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 3000 port = 8080 @@ -1186,12 +1116,9 @@ port = 8080 [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] -` +`) - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") - - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.Error(t, err, "Expected error for duplicate key") assert.Nil(t, cfg, "Config should be nil on error") @@ -1460,10 +1387,7 @@ func TestLoadFromStdin_WithRegistryField(t *testing.T) { // TestLoadFromFile_WithRegistryField tests that the registry field works with TOML files func TestLoadFromFile_WithRegistryField(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 8080 api_key = "test-key" @@ -1472,12 +1396,9 @@ api_key = "test-key" command = "docker" args = ["run", "--rm", "-i", "ghcr.io/github/github-mcp-server:latest"] registry = "https://api.mcp.github.com/v0/servers/github/github-mcp-server" -` +`) - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err, "Failed to write temp TOML file") - - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err, "LoadFromFile() failed") require.NotNil(t, cfg, "Config should not be nil") @@ -1583,10 +1504,7 @@ func TestGetAPIKey(t *testing.T) { // TestLoadFromFile_WithTrustedBots verifies TOML parsing of trusted_bots. // Covers spec §4.1.3.4 (Trusted Bot Identity Configuration). func TestLoadFromFile_WithTrustedBots(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 8080 api_key = "test-key-123" @@ -1595,12 +1513,9 @@ trusted_bots = ["copilot-swe-agent[bot]", "my-org-bot"] [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] -` +`) - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err) - - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err) require.NotNil(t, cfg.Gateway) @@ -1609,10 +1524,7 @@ args = ["run", "--rm", "-i", "test/container:latest"] // TestLoadFromFile_WithoutTrustedBots verifies TOML parsing when trusted_bots is absent. func TestLoadFromFile_WithoutTrustedBots(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 8080 api_key = "test-key-123" @@ -1620,12 +1532,9 @@ api_key = "test-key-123" [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err) +`) - cfg, err := LoadFromFile(tmpFile) + cfg, err := LoadFromFile(path) require.NoError(t, err) require.NotNil(t, cfg.Gateway) @@ -1633,10 +1542,7 @@ args = ["run", "--rm", "-i", "test/container:latest"] } func TestLoadFromFile_WithEmptyTrustedBotsToml(t *testing.T) { - tmpDir := t.TempDir() - tmpFile := filepath.Join(tmpDir, "config.toml") - - tomlContent := ` + path := writeTempTOML(t, ` [gateway] port = 8080 api_key = "test-key-123" @@ -1645,12 +1551,9 @@ trusted_bots = [] [servers.test] command = "docker" args = ["run", "--rm", "-i", "test/container:latest"] -` - - err := os.WriteFile(tmpFile, []byte(tomlContent), 0644) - require.NoError(t, err) +`) - _, err = LoadFromFile(tmpFile) + _, err := LoadFromFile(path) require.Error(t, err) }