- Remove redundant test files (cancel_reason_test, cli_test, codex_exec_args_test, emitters_internal_test, factory_test, registry_test) - Consolidate adapter tests into adapters_blackbox_test.go - Add cli_internal_test.go for internal CLI tests - Update lifecycle_blackbox_test.go
234 lines
6.7 KiB
Go
234 lines
6.7 KiB
Go
package adapters_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"iop/apps/node/internal/adapters"
|
|
noderuntime "iop/apps/node/internal/runtime"
|
|
iop "iop/proto/gen/iop"
|
|
)
|
|
|
|
// --- BuildFromPayload tests ---
|
|
|
|
func TestBuildFromPayload_MockAlwaysPresent(t *testing.T) {
|
|
reg, err := adapters.BuildFromPayload(&iop.NodeConfigPayload{}, zap.NewNop())
|
|
if err != nil {
|
|
t.Fatalf("build from payload: %v", err)
|
|
}
|
|
if _, ok := reg.Get("mock"); !ok {
|
|
t.Fatal("expected mock adapter to be registered")
|
|
}
|
|
if got := len(reg.All()); got != 1 {
|
|
t.Fatalf("expected 1 adapter, got %d", got)
|
|
}
|
|
}
|
|
|
|
func TestBuildFromPayload_OllamaEnabled(t *testing.T) {
|
|
reg, err := adapters.BuildFromPayload(&iop.NodeConfigPayload{
|
|
Adapters: []*iop.AdapterConfig{
|
|
{
|
|
Type: "ollama",
|
|
Enabled: true,
|
|
Config: &iop.AdapterConfig_Ollama{Ollama: &iop.OllamaAdapterConfig{BaseUrl: "http://localhost:11434"}},
|
|
},
|
|
},
|
|
}, zap.NewNop())
|
|
if err != nil {
|
|
t.Fatalf("build from payload: %v", err)
|
|
}
|
|
if _, ok := reg.Get("mock"); !ok {
|
|
t.Fatal("expected mock adapter to be registered")
|
|
}
|
|
if _, ok := reg.Get("ollama"); !ok {
|
|
t.Fatal("expected ollama adapter to be registered")
|
|
}
|
|
}
|
|
|
|
func TestBuildFromPayload_MultipleAdapters(t *testing.T) {
|
|
reg, err := adapters.BuildFromPayload(&iop.NodeConfigPayload{
|
|
Adapters: []*iop.AdapterConfig{
|
|
{Type: "ollama", Enabled: true, Config: &iop.AdapterConfig_Ollama{Ollama: &iop.OllamaAdapterConfig{BaseUrl: "x"}}},
|
|
{Type: "vllm", Enabled: true, Config: &iop.AdapterConfig_Vllm{Vllm: &iop.VllmAdapterConfig{Endpoint: "y"}}},
|
|
{Type: "cli", Enabled: true, Config: &iop.AdapterConfig_Cli{Cli: &iop.CLIAdapterConfig{
|
|
Profiles: map[string]*iop.CLIProfileConfig{
|
|
"codex": {Command: "codex", Persistent: true, ResponseIdleTimeoutMs: 1500, StartupIdleTimeoutMs: 300},
|
|
},
|
|
}}},
|
|
},
|
|
}, zap.NewNop())
|
|
if err != nil {
|
|
t.Fatalf("build from payload: %v", err)
|
|
}
|
|
for _, name := range []string{"mock", "ollama", "vllm", "cli"} {
|
|
if _, ok := reg.Get(name); !ok {
|
|
t.Fatalf("expected %s adapter to be registered", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestBuildFromPayload_UnknownType(t *testing.T) {
|
|
_, err := adapters.BuildFromPayload(&iop.NodeConfigPayload{
|
|
Adapters: []*iop.AdapterConfig{
|
|
{Type: "unknown", Enabled: true},
|
|
},
|
|
}, zap.NewNop())
|
|
if err == nil {
|
|
t.Fatal("expected unknown adapter type error")
|
|
}
|
|
}
|
|
|
|
// --- Registry lifecycle tests ---
|
|
|
|
type lifecycleAdapter struct {
|
|
name string
|
|
log *[]string
|
|
}
|
|
|
|
func (a *lifecycleAdapter) Name() string { return a.name }
|
|
func (a *lifecycleAdapter) Capabilities(_ context.Context) (noderuntime.Capabilities, error) {
|
|
return noderuntime.Capabilities{AdapterName: a.name}, nil
|
|
}
|
|
func (a *lifecycleAdapter) Execute(_ context.Context, _ noderuntime.ExecutionSpec, _ noderuntime.EventSink) error {
|
|
return nil
|
|
}
|
|
func (a *lifecycleAdapter) Start(_ context.Context) error {
|
|
*a.log = append(*a.log, "start:"+a.name)
|
|
return nil
|
|
}
|
|
func (a *lifecycleAdapter) Stop(_ context.Context) error {
|
|
*a.log = append(*a.log, "stop:"+a.name)
|
|
return nil
|
|
}
|
|
|
|
type failingLifecycleAdapter struct {
|
|
name string
|
|
log *[]string
|
|
}
|
|
|
|
func (a *failingLifecycleAdapter) Name() string { return a.name }
|
|
func (a *failingLifecycleAdapter) Capabilities(_ context.Context) (noderuntime.Capabilities, error) {
|
|
return noderuntime.Capabilities{AdapterName: a.name}, nil
|
|
}
|
|
func (a *failingLifecycleAdapter) Execute(_ context.Context, _ noderuntime.ExecutionSpec, _ noderuntime.EventSink) error {
|
|
return nil
|
|
}
|
|
func (a *failingLifecycleAdapter) Start(_ context.Context) error {
|
|
*a.log = append(*a.log, "start:"+a.name)
|
|
return fmt.Errorf("start failed: %s", a.name)
|
|
}
|
|
func (a *failingLifecycleAdapter) Stop(_ context.Context) error {
|
|
*a.log = append(*a.log, "stop:"+a.name)
|
|
return nil
|
|
}
|
|
|
|
type failingStopAdapter struct {
|
|
name string
|
|
log *[]string
|
|
stopErr error
|
|
}
|
|
|
|
func (a *failingStopAdapter) Name() string { return a.name }
|
|
func (a *failingStopAdapter) Capabilities(_ context.Context) (noderuntime.Capabilities, error) {
|
|
return noderuntime.Capabilities{AdapterName: a.name}, nil
|
|
}
|
|
func (a *failingStopAdapter) Execute(_ context.Context, _ noderuntime.ExecutionSpec, _ noderuntime.EventSink) error {
|
|
return nil
|
|
}
|
|
func (a *failingStopAdapter) Start(_ context.Context) error {
|
|
*a.log = append(*a.log, "start:"+a.name)
|
|
return nil
|
|
}
|
|
func (a *failingStopAdapter) Stop(_ context.Context) error {
|
|
*a.log = append(*a.log, "stop:"+a.name)
|
|
return a.stopErr
|
|
}
|
|
|
|
func TestRegistryLifecycle_StartStopOrder(t *testing.T) {
|
|
log := []string{}
|
|
reg := adapters.NewRegistry()
|
|
reg.Register(&lifecycleAdapter{name: "first", log: &log})
|
|
reg.Register(&lifecycleAdapter{name: "second", log: &log})
|
|
|
|
ctx := context.Background()
|
|
if err := reg.Start(ctx); err != nil {
|
|
t.Fatalf("Start: %v", err)
|
|
}
|
|
if err := reg.Stop(ctx); err != nil {
|
|
t.Fatalf("Stop: %v", err)
|
|
}
|
|
|
|
want := []string{"start:first", "start:second", "stop:second", "stop:first"}
|
|
if len(log) != len(want) {
|
|
t.Fatalf("expected %v, got %v", want, log)
|
|
}
|
|
for i, got := range log {
|
|
if got != want[i] {
|
|
t.Fatalf("log[%d]: want %q, got %q", i, want[i], got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRegistryLifecycle_StartFailureStopsStartedAdapters(t *testing.T) {
|
|
log := []string{}
|
|
reg := adapters.NewRegistry()
|
|
reg.Register(&lifecycleAdapter{name: "first", log: &log})
|
|
reg.Register(&failingLifecycleAdapter{name: "second", log: &log})
|
|
|
|
ctx := context.Background()
|
|
if err := reg.Start(ctx); err == nil {
|
|
t.Fatal("expected Start to return error")
|
|
}
|
|
|
|
want := []string{"start:first", "start:second", "stop:first"}
|
|
if len(log) != len(want) {
|
|
t.Fatalf("expected log %v, got %v", want, log)
|
|
}
|
|
for i, got := range log {
|
|
if got != want[i] {
|
|
t.Fatalf("log[%d]: want %q, got %q", i, want[i], got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRegistryLifecycle_StopContinuesOnFailingAdapter(t *testing.T) {
|
|
log := []string{}
|
|
reg := adapters.NewRegistry()
|
|
reg.Register(&lifecycleAdapter{name: "first", log: &log})
|
|
reg.Register(&failingStopAdapter{name: "second", log: &log, stopErr: fmt.Errorf("stop failed: second")})
|
|
|
|
ctx := context.Background()
|
|
if err := reg.Start(ctx); err != nil {
|
|
t.Fatalf("Start: %v", err)
|
|
}
|
|
if err := reg.Stop(ctx); err == nil {
|
|
t.Fatal("expected non-nil error from Stop")
|
|
}
|
|
|
|
want := []string{"start:first", "start:second", "stop:second", "stop:first"}
|
|
if len(log) != len(want) {
|
|
t.Fatalf("expected log %v, got %v", want, log)
|
|
}
|
|
for i, got := range log {
|
|
if got != want[i] {
|
|
t.Fatalf("log[%d]: want %q, got %q", i, want[i], got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRegistryLifecycle_NonLifecycleAdapterSkipped(t *testing.T) {
|
|
reg, err := adapters.BuildFromPayload(&iop.NodeConfigPayload{}, zap.NewNop())
|
|
if err != nil {
|
|
t.Fatalf("build: %v", err)
|
|
}
|
|
ctx := context.Background()
|
|
if err := reg.Start(ctx); err != nil {
|
|
t.Fatalf("Start: %v", err)
|
|
}
|
|
if err := reg.Stop(ctx); err != nil {
|
|
t.Fatalf("Stop: %v", err)
|
|
}
|
|
}
|