243 lines
4.8 KiB
Go
243 lines
4.8 KiB
Go
package serviceadapter
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestRegistryAdd(t *testing.T) {
|
||
|
|
logger := &MockLogger{}
|
||
|
|
reg := NewRegistry(logger)
|
||
|
|
|
||
|
|
adapter := &ServiceAdapter{
|
||
|
|
Namespace: "api",
|
||
|
|
ServiceName: "test-service",
|
||
|
|
Spec: Spec{
|
||
|
|
ServiceName: "test-service",
|
||
|
|
Upstream: Upstream{
|
||
|
|
URL: "http://example.com",
|
||
|
|
TimeoutSeconds: 30,
|
||
|
|
},
|
||
|
|
Auth: Auth{
|
||
|
|
Required: false,
|
||
|
|
},
|
||
|
|
Resources: []Resource{
|
||
|
|
{
|
||
|
|
Name: "default",
|
||
|
|
Methods: []Method{
|
||
|
|
{
|
||
|
|
Verb: "POST",
|
||
|
|
UpstreamPath: "/api",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
err := reg.Add(adapter)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Add failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
retrieved := reg.Get("test-service")
|
||
|
|
if retrieved == nil {
|
||
|
|
t.Errorf("expected adapter to be retrievable")
|
||
|
|
}
|
||
|
|
if retrieved.ServiceName != "test-service" {
|
||
|
|
t.Errorf("expected service name test-service, got %s", retrieved.ServiceName)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRegistryDelete(t *testing.T) {
|
||
|
|
logger := &MockLogger{}
|
||
|
|
reg := NewRegistry(logger)
|
||
|
|
|
||
|
|
adapter := &ServiceAdapter{
|
||
|
|
Namespace: "api",
|
||
|
|
ServiceName: "to-delete",
|
||
|
|
Spec: Spec{
|
||
|
|
ServiceName: "to-delete",
|
||
|
|
Upstream: Upstream{
|
||
|
|
URL: "http://example.com",
|
||
|
|
TimeoutSeconds: 30,
|
||
|
|
},
|
||
|
|
Auth: Auth{Required: false},
|
||
|
|
Resources: []Resource{
|
||
|
|
{
|
||
|
|
Name: "default",
|
||
|
|
Methods: []Method{
|
||
|
|
{Verb: "GET", UpstreamPath: "/"},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
reg.Add(adapter)
|
||
|
|
if reg.Count() != 1 {
|
||
|
|
t.Errorf("expected count 1 after add, got %d", reg.Count())
|
||
|
|
}
|
||
|
|
|
||
|
|
reg.Delete("to-delete")
|
||
|
|
if reg.Count() != 0 {
|
||
|
|
t.Errorf("expected count 0 after delete, got %d", reg.Count())
|
||
|
|
}
|
||
|
|
|
||
|
|
if reg.Get("to-delete") != nil {
|
||
|
|
t.Errorf("expected deleted adapter to be nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRegistryMalformedSchema(t *testing.T) {
|
||
|
|
logger := &MockLogger{}
|
||
|
|
reg := NewRegistry(logger)
|
||
|
|
|
||
|
|
adapter := &ServiceAdapter{
|
||
|
|
Namespace: "api",
|
||
|
|
ServiceName: "bad-schema",
|
||
|
|
Spec: Spec{
|
||
|
|
ServiceName: "bad-schema",
|
||
|
|
Upstream: Upstream{
|
||
|
|
URL: "http://example.com",
|
||
|
|
TimeoutSeconds: 30,
|
||
|
|
},
|
||
|
|
Auth: Auth{Required: false},
|
||
|
|
Resources: []Resource{
|
||
|
|
{
|
||
|
|
Name: "default",
|
||
|
|
Methods: []Method{
|
||
|
|
{
|
||
|
|
Verb: "POST",
|
||
|
|
UpstreamPath: "/",
|
||
|
|
RequestSchema: "{{ unclosed", // malformed
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
// Should not crash, should log error
|
||
|
|
err := reg.Add(adapter)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("Add should not return error (should skip malformed), got: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Adapter should be skipped (not added)
|
||
|
|
if reg.Get("bad-schema") != nil {
|
||
|
|
t.Errorf("expected malformed adapter to be skipped")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Should have logged an error
|
||
|
|
entries := logger.Entries()
|
||
|
|
errorLogged := false
|
||
|
|
for _, entry := range entries {
|
||
|
|
if strings.Contains(entry, "invalid schema") {
|
||
|
|
errorLogged = true
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if !errorLogged {
|
||
|
|
t.Errorf("expected error to be logged for malformed schema")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRegistryList(t *testing.T) {
|
||
|
|
logger := &MockLogger{}
|
||
|
|
reg := NewRegistry(logger)
|
||
|
|
|
||
|
|
for i := 0; i < 3; i++ {
|
||
|
|
adapter := &ServiceAdapter{
|
||
|
|
Namespace: "api",
|
||
|
|
ServiceName: "service-" + string(rune('1'+i)),
|
||
|
|
Spec: Spec{
|
||
|
|
ServiceName: "service-" + string(rune('1'+i)),
|
||
|
|
Upstream: Upstream{
|
||
|
|
URL: "http://example.com",
|
||
|
|
TimeoutSeconds: 30,
|
||
|
|
},
|
||
|
|
Auth: Auth{Required: false},
|
||
|
|
Resources: []Resource{},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
reg.Add(adapter)
|
||
|
|
}
|
||
|
|
|
||
|
|
list := reg.List()
|
||
|
|
if len(list) != 3 {
|
||
|
|
t.Errorf("expected 3 adapters, got %d", len(list))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRegistryThreadSafety(t *testing.T) {
|
||
|
|
logger := &MockLogger{}
|
||
|
|
reg := NewRegistry(logger)
|
||
|
|
|
||
|
|
done := make(chan bool, 2)
|
||
|
|
|
||
|
|
// Writer goroutine
|
||
|
|
go func() {
|
||
|
|
for i := 0; i < 10; i++ {
|
||
|
|
adapter := &ServiceAdapter{
|
||
|
|
Namespace: "api",
|
||
|
|
ServiceName: "writer-service",
|
||
|
|
Spec: Spec{
|
||
|
|
ServiceName: "writer-service",
|
||
|
|
Upstream: Upstream{
|
||
|
|
URL: "http://example.com",
|
||
|
|
TimeoutSeconds: 30,
|
||
|
|
},
|
||
|
|
Auth: Auth{Required: false},
|
||
|
|
Resources: []Resource{},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
reg.Add(adapter)
|
||
|
|
}
|
||
|
|
done <- true
|
||
|
|
}()
|
||
|
|
|
||
|
|
// Reader goroutine
|
||
|
|
go func() {
|
||
|
|
for i := 0; i < 10; i++ {
|
||
|
|
_ = reg.Get("writer-service")
|
||
|
|
_ = reg.List()
|
||
|
|
_ = reg.Count()
|
||
|
|
}
|
||
|
|
done <- true
|
||
|
|
}()
|
||
|
|
|
||
|
|
<-done
|
||
|
|
<-done
|
||
|
|
|
||
|
|
if reg.Count() != 1 {
|
||
|
|
t.Errorf("expected 1 adapter after concurrent access, got %d", reg.Count())
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBasicSchemaCheck(t *testing.T) {
|
||
|
|
tests := []struct {
|
||
|
|
name string
|
||
|
|
schema string
|
||
|
|
valid bool
|
||
|
|
}{
|
||
|
|
{"empty", "", true},
|
||
|
|
{"valid", "key1: string, key2: int", true},
|
||
|
|
{"unclosed braces", "{{ unclosed", false},
|
||
|
|
{"mismatched parens", "func(arg", false},
|
||
|
|
{"balanced parens", "func(arg)", true},
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, tc := range tests {
|
||
|
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
|
err := basicSchemaCheck(tc.schema)
|
||
|
|
if tc.valid && err != nil {
|
||
|
|
t.Errorf("expected valid schema to pass, got: %v", err)
|
||
|
|
}
|
||
|
|
if !tc.valid && err == nil {
|
||
|
|
t.Errorf("expected invalid schema to fail")
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|