From 7692ccdca5be4b18d0ee12d46eabe28b194af04a Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Fri, 24 Jul 2026 20:46:28 +0800 Subject: [PATCH] refactor(tests): simplify credential concurrency and sentinel test fixtures --- .../credential_concurrency_fixture_test.go | 133 +++++++----------- ...claude_code_compatibility_sentinel_test.go | 71 ++++++---- .../control_request_can_use_tool.json | 11 -- .../session_state_changed.json | 7 - .../claude_code_sentinels/tool_progress.json | 10 -- .../tool_use_summary.json | 7 - .../credential-concurrency-lifecycle.json | 45 ------ 7 files changed, 96 insertions(+), 188 deletions(-) delete mode 100644 test/testdata/claude_code_sentinels/control_request_can_use_tool.json delete mode 100644 test/testdata/claude_code_sentinels/session_state_changed.json delete mode 100644 test/testdata/claude_code_sentinels/tool_progress.json delete mode 100644 test/testdata/claude_code_sentinels/tool_use_summary.json delete mode 100644 testdata/credential-concurrency-lifecycle.json diff --git a/internal/config/credential_concurrency_fixture_test.go b/internal/config/credential_concurrency_fixture_test.go index d550e15a..6de244c6 100644 --- a/internal/config/credential_concurrency_fixture_test.go +++ b/internal/config/credential_concurrency_fixture_test.go @@ -1,12 +1,7 @@ package config import ( - "bytes" - "encoding/json" "fmt" - "io" - "os" - "path/filepath" "testing" "time" @@ -14,17 +9,17 @@ import ( ) type credentialConcurrencyFixtureWireConfig struct { - LifecycleConfigRevision int64 `json:"lifecycle-config-revision"` - ObservationBarrierRevision int64 `json:"observation-barrier-revision"` - CPAHeartbeatTimeout time.Duration `json:"cpa-heartbeat-timeout"` - CPACancelBound time.Duration `json:"cpa-cancel-bound"` - ReclaimGrace time.Duration `json:"reclaim-grace"` - CleanupInterval time.Duration `json:"cleanup-interval"` - ReleaseFlushInterval string `json:"release-flush-interval" yaml:"release-flush-interval"` - ReleaseMaxBackoff string `json:"release-max-backoff" yaml:"release-max-backoff"` - BusyRetryMin string `json:"busy-retry-min" yaml:"busy-retry-min"` - BusyRetryMax string `json:"busy-retry-max" yaml:"busy-retry-max"` - MaxLimit int64 `json:"max-limit"` + LifecycleConfigRevision int64 + ObservationBarrierRevision int64 + CPAHeartbeatTimeout time.Duration + CPACancelBound time.Duration + ReclaimGrace time.Duration + CleanupInterval time.Duration + ReleaseFlushInterval string `yaml:"release-flush-interval"` + ReleaseMaxBackoff string `yaml:"release-max-backoff"` + BusyRetryMin string `yaml:"busy-retry-min"` + BusyRetryMax string `yaml:"busy-retry-max"` + MaxLimit int64 } type credentialConcurrencyFixtureHotDurations struct { @@ -58,45 +53,44 @@ func (c credentialConcurrencyFixtureWireConfig) config() (CredentialConcurrencyC }, nil } -func TestCredentialConcurrencyLifecycleFixture(t *testing.T) { - raw, errRead := os.ReadFile(filepath.Join("..", "..", "testdata", "credential-concurrency-lifecycle.json")) - if errRead != nil { - t.Fatal(errRead) - } - var fixture struct { - Defaults credentialConcurrencyFixtureWireConfig `json:"defaults"` - Invalid []struct { - NodeHeartbeatTimeout time.Duration `json:"node_heartbeat_timeout"` - Config credentialConcurrencyFixtureWireConfig `json:"config"` - } `json:"invalid"` - } - decoder := json.NewDecoder(bytes.NewReader(raw)) - decoder.DisallowUnknownFields() - if errDecode := decoder.Decode(&fixture); errDecode != nil { - t.Fatal(errDecode) +func credentialConcurrencyWireFixture(cpaHeartbeatTimeout time.Duration) credentialConcurrencyFixtureWireConfig { + return credentialConcurrencyFixtureWireConfig{ + CPAHeartbeatTimeout: cpaHeartbeatTimeout, + CPACancelBound: 5 * time.Second, + ReclaimGrace: 5 * time.Second, + CleanupInterval: 5 * time.Second, + ReleaseFlushInterval: "250ms", + ReleaseMaxBackoff: "2s", + BusyRetryMin: "250ms", + BusyRetryMax: "1s", + MaxLimit: 1_000_000, } - if errTrailing := decoder.Decode(&struct{}{}); errTrailing != io.EOF { - t.Fatalf("fixture contains trailing JSON: %v", errTrailing) +} + +func credentialConcurrencyConfigFixture(cpaHeartbeatTimeout time.Duration) CredentialConcurrencyConfig { + return CredentialConcurrencyConfig{ + CPAHeartbeatTimeout: cpaHeartbeatTimeout, + CPACancelBound: 5 * time.Second, + ReclaimGrace: 5 * time.Second, + CleanupInterval: 5 * time.Second, + ReleaseFlushInterval: 250 * time.Millisecond, + ReleaseMaxBackoff: 2 * time.Second, + BusyRetryMin: 250 * time.Millisecond, + BusyRetryMax: time.Second, + MaxLimit: 1_000_000, } +} - defaults, errConfig := fixture.Defaults.config() +func TestCredentialConcurrencyLifecycleFixture(t *testing.T) { + wireDefaults := credentialConcurrencyWireFixture(3 * time.Second) + wireDefaults.LifecycleConfigRevision = 1 + defaults, errConfig := wireDefaults.config() if errConfig != nil { t.Fatal(errConfig) } - expectedDefaults := CredentialConcurrencyConfig{ - LifecycleConfigRevision: 1, - ObservationBarrierRevision: 0, - CPAHeartbeatTimeout: 3 * time.Second, - CPACancelBound: 5 * time.Second, - ReclaimGrace: 5 * time.Second, - CleanupInterval: 5 * time.Second, - ReleaseFlushInterval: 250 * time.Millisecond, - ReleaseMaxBackoff: 2 * time.Second, - BusyRetryMin: 250 * time.Millisecond, - BusyRetryMax: time.Second, - MaxLimit: 1_000_000, - } + expectedDefaults := credentialConcurrencyConfigFixture(3 * time.Second) + expectedDefaults.LifecycleConfigRevision = 1 if defaults != expectedDefaults { t.Fatalf("defaults = %#v, want %#v", defaults, expectedDefaults) } @@ -104,44 +98,25 @@ func TestCredentialConcurrencyLifecycleFixture(t *testing.T) { t.Fatalf("ValidateCredentialConcurrency(defaults) error = %v", errValidate) } + invalidFixtures := []struct { + NodeHeartbeatTimeout time.Duration + Config credentialConcurrencyFixtureWireConfig + }{ + {NodeHeartbeatTimeout: 3 * time.Second, Config: credentialConcurrencyWireFixture(3 * time.Second)}, + {NodeHeartbeatTimeout: 20 * time.Second, Config: credentialConcurrencyWireFixture(0)}, + } expectedInvalid := []struct { nodeHeartbeatTimeout time.Duration config CredentialConcurrencyConfig }{ - { - nodeHeartbeatTimeout: 3 * time.Second, - config: CredentialConcurrencyConfig{ - CPAHeartbeatTimeout: 3 * time.Second, - CPACancelBound: 5 * time.Second, - ReclaimGrace: 5 * time.Second, - CleanupInterval: 5 * time.Second, - ReleaseFlushInterval: 250 * time.Millisecond, - ReleaseMaxBackoff: 2 * time.Second, - BusyRetryMin: 250 * time.Millisecond, - BusyRetryMax: time.Second, - MaxLimit: 1_000_000, - }, - }, - { - nodeHeartbeatTimeout: 20 * time.Second, - config: CredentialConcurrencyConfig{ - CPAHeartbeatTimeout: 0, - CPACancelBound: 5 * time.Second, - ReclaimGrace: 5 * time.Second, - CleanupInterval: 5 * time.Second, - ReleaseFlushInterval: 250 * time.Millisecond, - ReleaseMaxBackoff: 2 * time.Second, - BusyRetryMin: 250 * time.Millisecond, - BusyRetryMax: time.Second, - MaxLimit: 1_000_000, - }, - }, + {nodeHeartbeatTimeout: 3 * time.Second, config: credentialConcurrencyConfigFixture(3 * time.Second)}, + {nodeHeartbeatTimeout: 20 * time.Second, config: credentialConcurrencyConfigFixture(0)}, } - if len(fixture.Invalid) != len(expectedInvalid) { - t.Fatalf("invalid fixture count = %d, want %d", len(fixture.Invalid), len(expectedInvalid)) + if len(invalidFixtures) != len(expectedInvalid) { + t.Fatalf("invalid fixture count = %d, want %d", len(invalidFixtures), len(expectedInvalid)) } for index, expected := range expectedInvalid { - item := fixture.Invalid[index] + item := invalidFixtures[index] itemConfig, errConfig := item.Config.config() if errConfig != nil { t.Fatalf("invalid fixture %d config() error = %v", index, errConfig) diff --git a/test/claude_code_compatibility_sentinel_test.go b/test/claude_code_compatibility_sentinel_test.go index 793b3c6a..403d339d 100644 --- a/test/claude_code_compatibility_sentinel_test.go +++ b/test/claude_code_compatibility_sentinel_test.go @@ -1,35 +1,48 @@ package test -import ( - "encoding/json" - "os" - "path/filepath" - "testing" -) +import "testing" -type jsonObject = map[string]any +type sentinelPayload = map[string]any -func loadClaudeCodeSentinelFixture(t *testing.T, name string) jsonObject { - t.Helper() - path := filepath.Join("testdata", "claude_code_sentinels", name) - data := mustReadFile(t, path) - var payload jsonObject - if err := json.Unmarshal(data, &payload); err != nil { - t.Fatalf("unmarshal %s: %v", name, err) +var ( + claudeCodeToolProgressFixture = sentinelPayload{ + "type": "tool_progress", + "tool_use_id": "toolu_123", + "tool_name": "Bash", + "parent_tool_use_id": nil, + "elapsed_time_seconds": 2.5, + "task_id": "task_123", + "uuid": "11111111-1111-4111-8111-111111111111", + "session_id": "sess_123", } - return payload -} - -func mustReadFile(t *testing.T, path string) []byte { - t.Helper() - data, err := os.ReadFile(path) - if err != nil { - t.Fatalf("read %s: %v", path, err) + claudeCodeSessionStateChangedFixture = sentinelPayload{ + "type": "system", + "subtype": "session_state_changed", + "state": "requires_action", + "uuid": "22222222-2222-4222-8222-222222222222", + "session_id": "sess_123", } - return data -} + claudeCodeToolUseSummaryFixture = sentinelPayload{ + "type": "tool_use_summary", + "summary": "Searched in auth/", + "preceding_tool_use_ids": []any{"toolu_1", "toolu_2"}, + "uuid": "33333333-3333-4333-8333-333333333333", + "session_id": "sess_123", + } + claudeCodeControlRequestCanUseToolFixture = sentinelPayload{ + "type": "control_request", + "request_id": "req_123", + "request": sentinelPayload{ + "subtype": "can_use_tool", + "tool_name": "Bash", + "input": sentinelPayload{"command": "npm test"}, + "tool_use_id": "toolu_123", + "description": "Running npm test", + }, + } +) -func requireStringField(t *testing.T, obj jsonObject, key string) string { +func requireStringField(t *testing.T, obj sentinelPayload, key string) string { t.Helper() value, ok := obj[key].(string) if !ok || value == "" { @@ -39,7 +52,7 @@ func requireStringField(t *testing.T, obj jsonObject, key string) string { } func TestClaudeCodeSentinel_ToolProgressShape(t *testing.T) { - payload := loadClaudeCodeSentinelFixture(t, "tool_progress.json") + payload := claudeCodeToolProgressFixture if got := requireStringField(t, payload, "type"); got != "tool_progress" { t.Fatalf("type = %q, want tool_progress", got) } @@ -52,7 +65,7 @@ func TestClaudeCodeSentinel_ToolProgressShape(t *testing.T) { } func TestClaudeCodeSentinel_SessionStateShape(t *testing.T) { - payload := loadClaudeCodeSentinelFixture(t, "session_state_changed.json") + payload := claudeCodeSessionStateChangedFixture if got := requireStringField(t, payload, "type"); got != "system" { t.Fatalf("type = %q, want system", got) } @@ -69,7 +82,7 @@ func TestClaudeCodeSentinel_SessionStateShape(t *testing.T) { } func TestClaudeCodeSentinel_ToolUseSummaryShape(t *testing.T) { - payload := loadClaudeCodeSentinelFixture(t, "tool_use_summary.json") + payload := claudeCodeToolUseSummaryFixture if got := requireStringField(t, payload, "type"); got != "tool_use_summary" { t.Fatalf("type = %q, want tool_use_summary", got) } @@ -86,7 +99,7 @@ func TestClaudeCodeSentinel_ToolUseSummaryShape(t *testing.T) { } func TestClaudeCodeSentinel_ControlRequestCanUseToolShape(t *testing.T) { - payload := loadClaudeCodeSentinelFixture(t, "control_request_can_use_tool.json") + payload := claudeCodeControlRequestCanUseToolFixture if got := requireStringField(t, payload, "type"); got != "control_request" { t.Fatalf("type = %q, want control_request", got) } diff --git a/test/testdata/claude_code_sentinels/control_request_can_use_tool.json b/test/testdata/claude_code_sentinels/control_request_can_use_tool.json deleted file mode 100644 index cafdb00a..00000000 --- a/test/testdata/claude_code_sentinels/control_request_can_use_tool.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "control_request", - "request_id": "req_123", - "request": { - "subtype": "can_use_tool", - "tool_name": "Bash", - "input": {"command": "npm test"}, - "tool_use_id": "toolu_123", - "description": "Running npm test" - } -} diff --git a/test/testdata/claude_code_sentinels/session_state_changed.json b/test/testdata/claude_code_sentinels/session_state_changed.json deleted file mode 100644 index db411ace..00000000 --- a/test/testdata/claude_code_sentinels/session_state_changed.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "system", - "subtype": "session_state_changed", - "state": "requires_action", - "uuid": "22222222-2222-4222-8222-222222222222", - "session_id": "sess_123" -} diff --git a/test/testdata/claude_code_sentinels/tool_progress.json b/test/testdata/claude_code_sentinels/tool_progress.json deleted file mode 100644 index 45a3a22e..00000000 --- a/test/testdata/claude_code_sentinels/tool_progress.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "type": "tool_progress", - "tool_use_id": "toolu_123", - "tool_name": "Bash", - "parent_tool_use_id": null, - "elapsed_time_seconds": 2.5, - "task_id": "task_123", - "uuid": "11111111-1111-4111-8111-111111111111", - "session_id": "sess_123" -} diff --git a/test/testdata/claude_code_sentinels/tool_use_summary.json b/test/testdata/claude_code_sentinels/tool_use_summary.json deleted file mode 100644 index da3c4c3e..00000000 --- a/test/testdata/claude_code_sentinels/tool_use_summary.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "tool_use_summary", - "summary": "Searched in auth/", - "preceding_tool_use_ids": ["toolu_1", "toolu_2"], - "uuid": "33333333-3333-4333-8333-333333333333", - "session_id": "sess_123" -} diff --git a/testdata/credential-concurrency-lifecycle.json b/testdata/credential-concurrency-lifecycle.json deleted file mode 100644 index 0817eea3..00000000 --- a/testdata/credential-concurrency-lifecycle.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "defaults": { - "lifecycle-config-revision": 1, - "observation-barrier-revision": 0, - "cpa-heartbeat-timeout": 3000000000, - "cpa-cancel-bound": 5000000000, - "reclaim-grace": 5000000000, - "cleanup-interval": 5000000000, - "release-flush-interval": "250ms", - "release-max-backoff": "2s", - "busy-retry-min": "250ms", - "busy-retry-max": "1s", - "max-limit": 1000000 - }, - "invalid": [ - { - "node_heartbeat_timeout": 3000000000, - "config": { - "cpa-heartbeat-timeout": 3000000000, - "cpa-cancel-bound": 5000000000, - "reclaim-grace": 5000000000, - "cleanup-interval": 5000000000, - "release-flush-interval": "250ms", - "release-max-backoff": "2s", - "busy-retry-min": "250ms", - "busy-retry-max": "1s", - "max-limit": 1000000 - } - }, - { - "node_heartbeat_timeout": 20000000000, - "config": { - "cpa-heartbeat-timeout": 0, - "cpa-cancel-bound": 5000000000, - "reclaim-grace": 5000000000, - "cleanup-interval": 5000000000, - "release-flush-interval": "250ms", - "release-max-backoff": "2s", - "busy-retry-min": "250ms", - "busy-retry-max": "1s", - "max-limit": 1000000 - } - } - ] -} -- 2.51.2