106 lines
3.2 KiB
Go
106 lines
3.2 KiB
Go
package settings
|
|
|
|
import (
|
|
"errors"
|
|
"path/filepath"
|
|
"slices"
|
|
"testing"
|
|
|
|
"agent-system-backend/internal/store"
|
|
core "agent-system-core"
|
|
)
|
|
|
|
var routeContractKeys = []string{
|
|
"models.routeContractEOF.model",
|
|
"models.routeContractEOF.baseUrl",
|
|
"models.routeContractEOF.identitySha256",
|
|
}
|
|
|
|
func TestRouteContractSettingsDeclaredAsSystemManaged(t *testing.T) {
|
|
declared := map[string]core.SettingDesc{}
|
|
for _, desc := range Schema() {
|
|
declared[desc.Key] = desc
|
|
}
|
|
managed := NewService(nil).ManagedSettingPaths()
|
|
for _, key := range routeContractKeys {
|
|
desc, ok := declared[key]
|
|
if !ok {
|
|
t.Fatalf("schema missing %s", key)
|
|
}
|
|
if desc.Group != "models" || desc.Type != core.SettingString || desc.Default != "" ||
|
|
desc.Scope != core.SettingScopeSystem || desc.Effect != core.EffectNewRun || desc.Label == "" || desc.Description == "" {
|
|
t.Fatalf("%s declared as %+v", key, desc)
|
|
}
|
|
if !slices.Contains(managed, key) {
|
|
t.Fatalf("%s is not a managed path", key)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRouteContractSettingsIgnoreUserAndProjectLayers(t *testing.T) {
|
|
st, err := store.OpenSQLite(filepath.Join(t.TempDir(), "settings.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() { st.Close() })
|
|
svc := NewService(st)
|
|
|
|
for _, key := range routeContractKeys {
|
|
var managed *ErrManagedPath
|
|
if err := svc.MergeUser("local", map[string]any{key: "user-value"}); !errors.As(err, &managed) {
|
|
t.Fatalf("user write of %s = %v, want ErrManagedPath", key, err)
|
|
}
|
|
if err := svc.MergeProject("local", "p1", map[string]any{key: "project-value"}); !errors.As(err, &managed) {
|
|
t.Fatalf("project write of %s = %v, want ErrManagedPath", key, err)
|
|
}
|
|
}
|
|
if eff := svc.Effective("local", "p1"); eff.GetString(routeContractKeys[0], "") != "" {
|
|
t.Fatalf("default must be off, got %#v", eff)
|
|
}
|
|
|
|
legacy := map[string]any{"models": map[string]any{"routeContractEOF": map[string]any{
|
|
"model": "m", "baseUrl": "https://api.example.com/v1", "identitySha256": "abc",
|
|
}}}
|
|
if err := st.MergeSettingsScope("local", ScopeUser, legacy); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := st.MergeSettingsScope("local", ScopeProjectPrefix+"p1", legacy); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
eff := svc.Effective("local", "p1")
|
|
for _, key := range routeContractKeys {
|
|
if got := eff.GetString(key, ""); got != "" {
|
|
t.Fatalf("stored user/project %s leaked into effective settings: %q", key, got)
|
|
}
|
|
}
|
|
user, err := svc.UserScope("local")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
project, err := svc.ProjectScope("local", "p1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, scope := range []core.EffectiveSettings{user, project} {
|
|
for _, key := range routeContractKeys {
|
|
if got := scope.GetString(key, ""); got != "" {
|
|
t.Fatalf("stripped scope still echoes %s=%q", key, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := svc.MergeSystem(map[string]any{
|
|
routeContractKeys[0]: "sys-model",
|
|
routeContractKeys[1]: "https://sys.example.com/v1",
|
|
routeContractKeys[2]: "sys-digest",
|
|
}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
eff = svc.Effective("local", "p1")
|
|
for key, want := range map[string]string{routeContractKeys[0]: "sys-model", routeContractKeys[1]: "https://sys.example.com/v1", routeContractKeys[2]: "sys-digest"} {
|
|
if got := eff.GetString(key, ""); got != want {
|
|
t.Fatalf("system %s = %q, want %q", key, got, want)
|
|
}
|
|
}
|
|
}
|