This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/sandbox/provider_module_test.go
Jeffrey Smith 11fd8c1e57 step 1: rename module chat-switchboard → switchboard-core
- go.mod module name
- All 714 import references across 289 Go files
- VERSION: 0.1.0
- CI DB names: switchboard_core_{ci,dev,test}
- Docker image: gobha/switchboard-core
- Test fixtures: JWT issuer, repo names
- .env.example, docker-compose container name
- Compiles clean (go build exit 0)
2026-03-25 19:48:04 -04:00

242 lines
6.2 KiB
Go

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