package sandbox import ( "testing" "go.starlark.net/starlark" "switchboard-core/providers" ) // ─── ParseRequiresProvider ────────────────── func TestParseRequiresProvider_Missing(t *testing.T) { _, ok := ParseRequiresProvider(map[string]any{}) if ok { t.Error("missing requires_provider should return false") } } func TestParseRequiresProvider_BoolTrue(t *testing.T) { cfg, ok := ParseRequiresProvider(map[string]any{"requires_provider": true}) if !ok { t.Fatal("boolean true should return ok=true") } if cfg.ProviderConfigID != "" || cfg.DefaultModel != "" { t.Errorf("boolean true should produce empty config, got %+v", cfg) } } func TestParseRequiresProvider_BoolFalse(t *testing.T) { _, ok := ParseRequiresProvider(map[string]any{"requires_provider": false}) if ok { t.Error("boolean false should return ok=false") } } func TestParseRequiresProvider_ObjectFull(t *testing.T) { cfg, ok := ParseRequiresProvider(map[string]any{ "requires_provider": map[string]any{ "provider_config_id": "cfg-uuid-123", "model": "claude-3-haiku", }, }) if !ok { t.Fatal("object form should return ok=true") } if cfg.ProviderConfigID != "cfg-uuid-123" { t.Errorf("provider_config_id = %q", cfg.ProviderConfigID) } if cfg.DefaultModel != "claude-3-haiku" { t.Errorf("model = %q", cfg.DefaultModel) } } func TestParseRequiresProvider_ObjectPartial(t *testing.T) { cfg, ok := ParseRequiresProvider(map[string]any{ "requires_provider": map[string]any{ "model": "gpt-4o-mini", }, }) if !ok { t.Fatal("should return ok=true") } if cfg.ProviderConfigID != "" { t.Errorf("provider_config_id should be empty, got %q", cfg.ProviderConfigID) } if cfg.DefaultModel != "gpt-4o-mini" { t.Errorf("model = %q", cfg.DefaultModel) } } func TestParseRequiresProvider_InvalidType(t *testing.T) { _, ok := ParseRequiresProvider(map[string]any{"requires_provider": "yes"}) if ok { t.Error("string value should return false") } } // ─── starlarkToMessages ───────────────────── func TestStarlarkToMessages_Valid(t *testing.T) { list := starlark.NewList(nil) msg1 := starlark.NewDict(2) _ = msg1.SetKey(starlark.String("role"), starlark.String("system")) _ = msg1.SetKey(starlark.String("content"), starlark.String("You are helpful.")) list.Append(msg1) msg2 := starlark.NewDict(2) _ = msg2.SetKey(starlark.String("role"), starlark.String("user")) _ = msg2.SetKey(starlark.String("content"), starlark.String("Hello")) list.Append(msg2) msgs, err := starlarkToMessages(list) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(msgs) != 2 { t.Fatalf("expected 2 messages, got %d", len(msgs)) } if msgs[0].Role != "system" || msgs[0].Content != "You are helpful." { t.Errorf("msg[0] = %+v", msgs[0]) } if msgs[1].Role != "user" || msgs[1].Content != "Hello" { t.Errorf("msg[1] = %+v", msgs[1]) } } func TestStarlarkToMessages_Empty(t *testing.T) { list := starlark.NewList(nil) msgs, err := starlarkToMessages(list) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(msgs) != 0 { t.Errorf("expected 0 messages, got %d", len(msgs)) } } func TestStarlarkToMessages_Nil(t *testing.T) { msgs, err := starlarkToMessages(nil) if err != nil { t.Fatalf("unexpected error: %v", err) } if msgs != nil { t.Errorf("expected nil, got %v", msgs) } } func TestStarlarkToMessages_MissingRole(t *testing.T) { list := starlark.NewList(nil) msg := starlark.NewDict(1) _ = msg.SetKey(starlark.String("content"), starlark.String("hello")) list.Append(msg) _, err := starlarkToMessages(list) if err == nil { t.Error("expected error for missing role") } } func TestStarlarkToMessages_MissingContent(t *testing.T) { list := starlark.NewList(nil) msg := starlark.NewDict(1) _ = msg.SetKey(starlark.String("role"), starlark.String("user")) list.Append(msg) _, err := starlarkToMessages(list) if err == nil { t.Error("expected error for missing content") } } func TestStarlarkToMessages_NonDictItem(t *testing.T) { list := starlark.NewList([]starlark.Value{starlark.String("not a dict")}) _, err := starlarkToMessages(list) if err == nil { t.Error("expected error for non-dict item") } } func TestStarlarkToMessages_NonStringRole(t *testing.T) { list := starlark.NewList(nil) msg := starlark.NewDict(2) _ = msg.SetKey(starlark.String("role"), starlark.MakeInt(42)) _ = msg.SetKey(starlark.String("content"), starlark.String("hello")) list.Append(msg) _, err := starlarkToMessages(list) if err == nil { t.Error("expected error for non-string role") } } // ─── completionToStarlark ─────────────────── func TestCompletionToStarlark(t *testing.T) { resp := &providers.CompletionResponse{ Content: "Hello! How can I help?", Model: "claude-3-haiku-20240307", FinishReason: "stop", InputTokens: 15, OutputTokens: 8, } val, err := completionToStarlark(resp) if err != nil { t.Fatalf("unexpected error: %v", err) } d, ok := val.(*starlark.Dict) if !ok { t.Fatalf("expected dict, got %T", val) } // content cv, found, _ := d.Get(starlark.String("content")) if !found { t.Fatal("missing 'content'") } if s, _ := starlark.AsString(cv); s != "Hello! How can I help?" { t.Errorf("content = %q", s) } // model mv, found, _ := d.Get(starlark.String("model")) if !found { t.Fatal("missing 'model'") } if s, _ := starlark.AsString(mv); s != "claude-3-haiku-20240307" { t.Errorf("model = %q", s) } // finish_reason fv, found, _ := d.Get(starlark.String("finish_reason")) if !found { t.Fatal("missing 'finish_reason'") } if s, _ := starlark.AsString(fv); s != "stop" { t.Errorf("finish_reason = %q", s) } // input_tokens iv, found, _ := d.Get(starlark.String("input_tokens")) if !found { t.Fatal("missing 'input_tokens'") } if i, err := starlark.AsInt32(iv); err != nil || i != 15 { t.Errorf("input_tokens = %v (err=%v)", i, err) } // output_tokens ov, found, _ := d.Get(starlark.String("output_tokens")) if !found { t.Fatal("missing 'output_tokens'") } if i, err := starlark.AsInt32(ov); err != nil || i != 8 { t.Errorf("output_tokens = %v (err=%v)", i, err) } }