iop/apps/node/internal/adapters/adapters_blackbox_test.go
toki af0da6b822 refactor: reorganize cli adapters test structure
- 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
2026-05-05 07:12:47 +09:00

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)
}
}