gomcp/internal/domain/router/router_test.go
DmitrL-dev 694e32be26 refactor: rename identity to syntrex, add root orchestration and CI/CD
- Rename Go module: sentinel-community/gomcp -> syntrex/gomcp (50+ files)
- Rename npm package: sentinel-dashboard -> syntrex-dashboard
- Update Cargo.toml repository URL to syntrex/syntrex
- Update all doc references from DmitrL-dev/AISecurity to syntrex
- Add root Makefile (build-all, test-all, lint-all, clean-all)
- Add MIT LICENSE
- Add .editorconfig (Go/Rust/TS/C cross-language)
- Add .github/workflows/ci.yml (Go + Rust + Dashboard)
- Add dashboard next.config.ts and .env.example
- Clean ARCHITECTURE.md: remove brain/immune/strike/micro-swarm, fix 61->67 engines
2026-03-11 15:30:49 +10:00

107 lines
3.4 KiB
Go

package router
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/syntrex/gomcp/internal/domain/vectorstore"
)
func seedStore() *vectorstore.Store {
s := vectorstore.New(nil)
s.Add(&vectorstore.IntentRecord{
ID: "read-1", Text: "read user profile", Route: "read",
Vector: []float64{0.9, 0.1, 0.0}, Verdict: "ALLOW",
})
s.Add(&vectorstore.IntentRecord{
ID: "write-1", Text: "save configuration", Route: "write",
Vector: []float64{0.1, 0.9, 0.0}, Verdict: "ALLOW",
})
s.Add(&vectorstore.IntentRecord{
ID: "exec-1", Text: "run shell command", Route: "exec",
Vector: []float64{0.0, 0.1, 0.9}, Verdict: "DENY",
})
return s
}
func TestRouter_HighConfidence_Route(t *testing.T) {
r := New(seedStore(), nil)
result := r.Route(context.Background(),
"read data", []float64{0.9, 0.1, 0.0}, "ALLOW")
assert.Equal(t, "ROUTE", result.Decision)
assert.Equal(t, "read", result.Route)
assert.GreaterOrEqual(t, result.Confidence, 0.85)
assert.Contains(t, result.Reason, "matched")
}
func TestRouter_MediumConfidence_Review(t *testing.T) {
r := New(seedStore(), nil)
// Vector between read(0.9,0.1,0) and write(0.1,0.9,0).
result := r.Route(context.Background(),
"update data", []float64{0.5, 0.5, 0.0}, "ALLOW")
assert.Equal(t, "REVIEW", result.Decision)
assert.Contains(t, result.Reason, "review")
}
func TestRouter_LowConfidence_Deny(t *testing.T) {
r := New(seedStore(), &Config{HighConfidence: 0.99, LowConfidence: 0.99})
// Even a decent match won't pass extreme threshold.
result := r.Route(context.Background(),
"something", []float64{0.5, 0.3, 0.2}, "ALLOW")
assert.Equal(t, "DENY", result.Decision)
}
func TestRouter_EmptyStore_Learn(t *testing.T) {
r := New(vectorstore.New(nil), nil)
result := r.Route(context.Background(),
"first ever intent", []float64{1.0, 0.0, 0.0}, "ALLOW")
assert.Equal(t, "LEARN", result.Decision)
assert.NotEmpty(t, result.LearnedID)
assert.Equal(t, 1, r.GetStore().Count())
}
func TestRouter_EmptyStore_NoAutoLearn_Deny(t *testing.T) {
r := New(vectorstore.New(nil), &Config{AutoLearn: false})
result := r.Route(context.Background(),
"intent", []float64{1.0}, "ALLOW")
assert.Equal(t, "DENY", result.Decision)
assert.Equal(t, 0, r.GetStore().Count())
}
func TestRouter_AutoLearn_StoresNew(t *testing.T) {
store := seedStore()
r := New(store, nil)
initialCount := store.Count()
// Medium confidence → review + auto-learn.
result := r.Route(context.Background(),
"update profile", []float64{0.5, 0.5, 0.0}, "ALLOW")
assert.NotEmpty(t, result.LearnedID)
assert.Equal(t, initialCount+1, store.Count())
}
func TestRouter_Alternatives(t *testing.T) {
r := New(seedStore(), nil)
result := r.Route(context.Background(),
"get data", []float64{0.8, 0.2, 0.0}, "ALLOW")
require.NotNil(t, result.Alternatives)
assert.Greater(t, len(result.Alternatives), 0)
}
func TestRouter_DecisionString(t *testing.T) {
assert.Equal(t, "ROUTE", DecisionRoute.String())
assert.Equal(t, "REVIEW", DecisionReview.String())
assert.Equal(t, "DENY", DecisionDeny.String())
assert.Equal(t, "LEARN", DecisionLearn.String())
assert.Equal(t, "UNKNOWN", Decision(99).String())
}
func TestRouter_DurationMeasured(t *testing.T) {
r := New(seedStore(), nil)
result := r.Route(context.Background(),
"test", []float64{1.0, 0.0, 0.0}, "ALLOW")
assert.GreaterOrEqual(t, result.DurationUs, int64(0))
}