package node_test import ( "context" "errors" "strconv" "strings" "sync" "testing" "time" "iop/apps/node/internal/transport" runtime "iop/packages/go/execution" iop "iop/proto/gen/iop" ) type providerCommandAdapter struct { mu sync.Mutex commands []runtime.CommandType runs []runtime.ExecutionSpec started chan struct{} release chan struct{} probe runtime.ProviderProbeResult probeErr error probes int } func (a *providerCommandAdapter) Name() string { return "provider" } func (a *providerCommandAdapter) Capabilities(context.Context) (runtime.Capabilities, error) { return runtime.Capabilities{AdapterName: a.Name(), InstanceKey: "provider-instance", Targets: []string{"model"}, MaxConcurrency: 2}, nil } func (a *providerCommandAdapter) Execute(ctx context.Context, spec runtime.ExecutionSpec, sink runtime.EventSink) error { a.mu.Lock() a.runs = append(a.runs, spec) a.mu.Unlock() if a.started != nil { select { case a.started <- struct{}{}: default: } select { case <-ctx.Done(): return runtime.ErrRunCancelled case <-a.release: } } return nil } func (a *providerCommandAdapter) HandleCommand(_ context.Context, req runtime.CommandRequest) (runtime.CommandResponse, error) { a.mu.Lock() a.commands = append(a.commands, req.Type) a.mu.Unlock() return runtime.CommandResponse{ RequestID: req.RequestID, Type: req.Type, Adapter: req.Adapter, Target: req.Target, SessionID: req.SessionID, Result: map[string]string{"status": "ok"}, }, nil } func (a *providerCommandAdapter) ProbeProvider(_ context.Context, target string) (runtime.ProviderProbeResult, error) { a.mu.Lock() defer a.mu.Unlock() a.probes++ result := a.probe if result.InstanceKey == "" { result.InstanceKey = "provider-instance" } if result.Target == "" { result.Target = target } return result, a.probeErr } func TestCapabilitiesHealthEvidence(t *testing.T) { t.Run("exact available evidence is session sequenced", func(t *testing.T) { adapter := &providerCommandAdapter{probe: runtime.ProviderProbeResult{ AdapterName: "provider", Target: "model", Status: runtime.ProviderStatusAvailable, }} router := &fixedRouter{adapterName: "provider", adapters: map[string]runtime.Provider{"provider": adapter}} n, _ := makeNode(t, router) sess := &transport.Session{} for wantSeq := uint64(1); wantSeq <= 2; wantSeq++ { resp, err := n.OnCommandRequest(context.Background(), sess, &iop.NodeCommandRequest{ RequestId: "caps", Type: iop.NodeCommandType_NODE_COMMAND_TYPE_CAPABILITIES, Adapter: "provider", Target: "model", }) if err != nil || resp.GetError() != "" { t.Fatalf("response=%v err=%v", resp, err) } result := resp.GetResult() if result["adapter_key"] != "provider" || result["target"] != "model" || result["provider_status"] != "available" { t.Fatalf("unstable exact evidence: %#v", result) } if result["health_observation_seq"] != strconv.FormatUint(wantSeq, 10) { t.Fatalf("sequence=%q, want %d", result["health_observation_seq"], wantSeq) } if len(resp.GetProviderSnapshots()) != 1 || resp.GetProviderSnapshots()[0].GetHealth() != "available" { t.Fatalf("provider snapshot did not carry normalized health: %#v", resp.GetProviderSnapshots()) } } if adapter.probes != 2 { t.Fatalf("probe calls=%d, want 2", adapter.probes) } }) for _, tc := range []struct { name string result runtime.ProviderProbeResult err error wantStatus string }{ {name: "transport error", result: runtime.ProviderProbeResult{AdapterName: "provider", Target: "model", Status: runtime.ProviderStatusAvailable}, err: errors.New("probe failed"), wantStatus: "unknown"}, {name: "identity mismatch", result: runtime.ProviderProbeResult{AdapterName: "other", Target: "model", Status: runtime.ProviderStatusAvailable}, wantStatus: "unknown"}, {name: "unknown", result: runtime.ProviderProbeResult{AdapterName: "provider", Target: "model", Status: runtime.ProviderStatusUnknown}, wantStatus: "unknown"}, {name: "exact unavailable", result: runtime.ProviderProbeResult{AdapterName: "provider", Target: "model", Status: runtime.ProviderStatusUnavailable}, wantStatus: "unavailable"}, } { t.Run(tc.name, func(t *testing.T) { adapter := &providerCommandAdapter{probe: tc.result, probeErr: tc.err} router := &fixedRouter{adapterName: "provider", adapters: map[string]runtime.Provider{"provider": adapter}} n, _ := makeNode(t, router) resp, err := n.OnCommandRequest(context.Background(), &transport.Session{}, &iop.NodeCommandRequest{ RequestId: "caps", Type: iop.NodeCommandType_NODE_COMMAND_TYPE_CAPABILITIES, Adapter: "provider", Target: "model", }) if err != nil || resp.GetError() != "" { t.Fatalf("response=%v err=%v", resp, err) } if got := resp.GetResult()["provider_status"]; got != tc.wantStatus { t.Fatalf("provider_status=%q, want %q", got, tc.wantStatus) } if resp.GetResult()["health_observation_seq"] != "1" { t.Fatalf("missing Session sequence: %#v", resp.GetResult()) } }) } } func TestNodeCommandProviderAllowlist(t *testing.T) { adapter := &providerCommandAdapter{} router := &fixedRouter{adapterName: "provider", adapters: map[string]runtime.Provider{"provider": adapter}} n, _ := makeNode(t, router) for _, commandType := range []iop.NodeCommandType{ iop.NodeCommandType_NODE_COMMAND_TYPE_CAPABILITIES, iop.NodeCommandType_NODE_COMMAND_TYPE_TRANSPORT_STATUS, iop.NodeCommandType_NODE_COMMAND_TYPE_OLLAMA_API, } { resp, err := n.OnCommandRequest(context.Background(), &transport.Session{}, &iop.NodeCommandRequest{ RequestId: "request", Type: commandType, Adapter: "provider", Target: "model", }) if err != nil || resp.GetError() != "" { t.Fatalf("command %v: response=%v error=%v", commandType, resp, err) } } } func TestNodeCommandRejectsUnknownAgentAndShell(t *testing.T) { router := &fixedRouter{adapterName: "missing", adapters: map[string]runtime.Provider{}} n, _ := makeNode(t, router) for _, removedType := range []iop.NodeCommandType{100, 101} { resp, err := n.OnCommandRequest(context.Background(), &transport.Session{}, &iop.NodeCommandRequest{ RequestId: "removed", Type: removedType, Adapter: "missing", }) if err != nil || !strings.Contains(resp.GetError(), "unsupported command type") { t.Fatalf("removed command %d: response=%v error=%v", removedType, resp, err) } } } func TestSessionIDIsCorrelationOnly(t *testing.T) { adapter := &providerCommandAdapter{} router := &fixedRouter{adapterName: "provider", adapters: map[string]runtime.Provider{"provider": adapter}} n, _ := makeNode(t, router) for _, runID := range []string{"run-one", "run-two"} { if err := n.OnRunRequest(context.Background(), &transport.Session{}, &iop.RunRequest{ RunId: runID, Adapter: "provider", Target: "model", SessionId: "same-correlation", }); err != nil { t.Fatal(err) } } adapter.mu.Lock() defer adapter.mu.Unlock() if len(adapter.runs) != 2 || adapter.runs[0].RunID == adapter.runs[1].RunID || adapter.runs[0].SessionID != adapter.runs[1].SessionID { t.Fatalf("runs = %#v", adapter.runs) } } func TestCancelByRunIDOnly(t *testing.T) { adapter := &providerCommandAdapter{started: make(chan struct{}, 1), release: make(chan struct{})} router := &fixedRouter{adapterName: "provider", adapters: map[string]runtime.Provider{"provider": adapter}} n, _ := makeNode(t, router) if err := n.OnRunRequest(context.Background(), &transport.Session{}, &iop.RunRequest{ RunId: "cancel-me", Adapter: "provider", Target: "model", Background: true, }); err != nil { t.Fatal(err) } select { case <-adapter.started: case <-time.After(2 * time.Second): t.Fatal("provider did not start") } if err := n.OnCancel(context.Background(), &transport.Session{}, &iop.CancelRequest{RunId: "cancel-me"}); err != nil { t.Fatal(err) } if err := n.OnCancel(context.Background(), &transport.Session{}, &iop.CancelRequest{}); err == nil { t.Fatal("empty run id was accepted") } }