diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-02-08 21:35:45 -1000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-02-08 21:35:45 -1000 |
| commit | 2e2b2187b957e9af78797a67ec5c6874615fae02 (patch) | |
| tree | 1181dbb7e43f5d30cb025fa4d50fd4e7a2c893b3 /internal/task/task_test.go | |
Initial project: task model, executor, API server, CLI, storage, reporter
Claudomator automation toolkit for Claude Code with:
- Task model with YAML parsing, validation, state machine (49 tests, 0 races)
- SQLite storage for tasks and executions
- Executor pool with bounded concurrency, timeout, cancellation
- REST API + WebSocket for mobile PWA integration
- Webhook/multi-notifier system
- CLI: init, run, serve, list, status commands
- Console, JSON, HTML reporters with cost tracking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/task/task_test.go')
| -rw-r--r-- | internal/task/task_test.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/internal/task/task_test.go b/internal/task/task_test.go new file mode 100644 index 0000000..96f5f6f --- /dev/null +++ b/internal/task/task_test.go @@ -0,0 +1,80 @@ +package task + +import ( + "testing" + "time" +) + +func TestValidTransition_AllowedTransitions(t *testing.T) { + tests := []struct { + name string + from State + to State + }{ + {"pending to queued", StatePending, StateQueued}, + {"pending to cancelled", StatePending, StateCancelled}, + {"queued to running", StateQueued, StateRunning}, + {"queued to cancelled", StateQueued, StateCancelled}, + {"running to completed", StateRunning, StateCompleted}, + {"running to failed", StateRunning, StateFailed}, + {"running to timed out", StateRunning, StateTimedOut}, + {"running to cancelled", StateRunning, StateCancelled}, + {"running to budget exceeded", StateRunning, StateBudgetExceeded}, + {"failed to queued (retry)", StateFailed, StateQueued}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if !ValidTransition(tt.from, tt.to) { + t.Errorf("expected transition %s -> %s to be valid", tt.from, tt.to) + } + }) + } +} + +func TestValidTransition_DisallowedTransitions(t *testing.T) { + tests := []struct { + name string + from State + to State + }{ + {"pending to running", StatePending, StateRunning}, + {"pending to completed", StatePending, StateCompleted}, + {"queued to completed", StateQueued, StateCompleted}, + {"completed to running", StateCompleted, StateRunning}, + {"completed to queued", StateCompleted, StateQueued}, + {"failed to completed", StateFailed, StateCompleted}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if ValidTransition(tt.from, tt.to) { + t.Errorf("expected transition %s -> %s to be invalid", tt.from, tt.to) + } + }) + } +} + +func TestDuration_UnmarshalYAML(t *testing.T) { + var d Duration + unmarshal := func(v interface{}) error { + ptr := v.(*string) + *ptr = "30m" + return nil + } + if err := d.UnmarshalYAML(unmarshal); err != nil { + t.Fatalf("unexpected error: %v", err) + } + if d.Duration != 30*time.Minute { + t.Errorf("expected 30m, got %v", d.Duration) + } +} + +func TestDuration_MarshalYAML(t *testing.T) { + d := Duration{Duration: 15 * time.Minute} + v, err := d.MarshalYAML() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if v != "15m0s" { + t.Errorf("expected '15m0s', got %v", v) + } +} |
