217 lines
4.8 KiB
Go
217 lines
4.8 KiB
Go
package serviceadapter
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestValidateString(t *testing.T) {
|
||
|
|
schema := &FieldSchema{Type: "string"}
|
||
|
|
v := &Validator{schema: schema}
|
||
|
|
|
||
|
|
errs := v.Validate("hello")
|
||
|
|
if len(errs) != 0 {
|
||
|
|
t.Errorf("expected no errors for valid string, got %v", errs)
|
||
|
|
}
|
||
|
|
|
||
|
|
errs = v.Validate(42)
|
||
|
|
if len(errs) == 0 {
|
||
|
|
t.Errorf("expected error for non-string")
|
||
|
|
}
|
||
|
|
if len(errs) > 0 && !stringContains(errs[0].Reason, "type_mismatch") {
|
||
|
|
t.Errorf("expected type_mismatch error, got %s", errs[0].Reason)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateNumber(t *testing.T) {
|
||
|
|
schema := &FieldSchema{Type: "number"}
|
||
|
|
v := &Validator{schema: schema}
|
||
|
|
|
||
|
|
errs := v.Validate(42.0)
|
||
|
|
if len(errs) != 0 {
|
||
|
|
t.Errorf("expected no errors for float64, got %v", errs)
|
||
|
|
}
|
||
|
|
|
||
|
|
errs = v.Validate("not a number")
|
||
|
|
if len(errs) == 0 {
|
||
|
|
t.Errorf("expected error for non-number")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateNullable(t *testing.T) {
|
||
|
|
schemaNullable := &FieldSchema{Type: "string", Nullable: true}
|
||
|
|
vNullable := &Validator{schema: schemaNullable}
|
||
|
|
|
||
|
|
errs := vNullable.Validate(nil)
|
||
|
|
if len(errs) != 0 {
|
||
|
|
t.Errorf("expected no errors for null on nullable field, got %v", errs)
|
||
|
|
}
|
||
|
|
|
||
|
|
schemaNotNullable := &FieldSchema{Type: "string", Nullable: false}
|
||
|
|
vNotNullable := &Validator{schema: schemaNotNullable}
|
||
|
|
|
||
|
|
errs = vNotNullable.Validate(nil)
|
||
|
|
if len(errs) == 0 {
|
||
|
|
t.Errorf("expected error for null on non-nullable field")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateObject(t *testing.T) {
|
||
|
|
schema := &FieldSchema{
|
||
|
|
Type: "object",
|
||
|
|
Required: []string{"name"},
|
||
|
|
Fields: map[string]FieldSchema{
|
||
|
|
"name": {Type: "string"},
|
||
|
|
"age": {Type: "number"},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
v := &Validator{schema: schema}
|
||
|
|
|
||
|
|
// Valid object
|
||
|
|
obj := map[string]interface{}{
|
||
|
|
"name": "Alice",
|
||
|
|
"age": 30.0,
|
||
|
|
}
|
||
|
|
errs := v.Validate(obj)
|
||
|
|
if len(errs) != 0 {
|
||
|
|
t.Errorf("expected no errors for valid object, got %v", errs)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Missing required field
|
||
|
|
objMissing := map[string]interface{}{
|
||
|
|
"age": 30.0,
|
||
|
|
}
|
||
|
|
errs = v.Validate(objMissing)
|
||
|
|
if len(errs) == 0 {
|
||
|
|
t.Errorf("expected error for missing required field")
|
||
|
|
}
|
||
|
|
if len(errs) > 0 && errs[0].Reason != "missing" {
|
||
|
|
t.Errorf("expected 'missing' error, got %s", errs[0].Reason)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Type mismatch
|
||
|
|
objBadType := map[string]interface{}{
|
||
|
|
"name": "Alice",
|
||
|
|
"age": "thirty",
|
||
|
|
}
|
||
|
|
errs = v.Validate(objBadType)
|
||
|
|
if len(errs) == 0 {
|
||
|
|
t.Errorf("expected error for type mismatch")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateObjectStrict(t *testing.T) {
|
||
|
|
schema := &FieldSchema{
|
||
|
|
Type: "object",
|
||
|
|
Strict: true,
|
||
|
|
Fields: map[string]FieldSchema{
|
||
|
|
"name": {Type: "string"},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
v := &Validator{schema: schema}
|
||
|
|
|
||
|
|
// Unknown field rejected in strict mode
|
||
|
|
obj := map[string]interface{}{
|
||
|
|
"name": "Alice",
|
||
|
|
"unknown": "field",
|
||
|
|
}
|
||
|
|
errs := v.Validate(obj)
|
||
|
|
if len(errs) == 0 {
|
||
|
|
t.Errorf("expected error for unknown field in strict mode")
|
||
|
|
}
|
||
|
|
found := false
|
||
|
|
for _, err := range errs {
|
||
|
|
if err.Reason == "unknown_field" {
|
||
|
|
found = true
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if !found {
|
||
|
|
t.Errorf("expected unknown_field error")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateArray(t *testing.T) {
|
||
|
|
schema := &FieldSchema{
|
||
|
|
Type: "array",
|
||
|
|
Items: &FieldSchema{
|
||
|
|
Type: "string",
|
||
|
|
},
|
||
|
|
}
|
||
|
|
v := &Validator{schema: schema}
|
||
|
|
|
||
|
|
// Valid array
|
||
|
|
arr := []interface{}{"a", "b", "c"}
|
||
|
|
errs := v.Validate(arr)
|
||
|
|
if len(errs) != 0 {
|
||
|
|
t.Errorf("expected no errors for valid string array, got %v", errs)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Invalid element type
|
||
|
|
arrBad := []interface{}{"a", 42, "c"}
|
||
|
|
errs = v.Validate(arrBad)
|
||
|
|
if len(errs) == 0 {
|
||
|
|
t.Errorf("expected error for wrong type in array")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateArrayOfObjects(t *testing.T) {
|
||
|
|
schema := &FieldSchema{
|
||
|
|
Type: "array",
|
||
|
|
Items: &FieldSchema{
|
||
|
|
Type: "object",
|
||
|
|
Fields: map[string]FieldSchema{
|
||
|
|
"id": {Type: "number"},
|
||
|
|
"name": {Type: "string"},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
v := &Validator{schema: schema}
|
||
|
|
|
||
|
|
arr := []interface{}{
|
||
|
|
map[string]interface{}{"id": 1.0, "name": "Alice"},
|
||
|
|
map[string]interface{}{"id": 2.0, "name": "Bob"},
|
||
|
|
}
|
||
|
|
errs := v.Validate(arr)
|
||
|
|
if len(errs) != 0 {
|
||
|
|
t.Errorf("expected no errors for valid array of objects, got %v", errs)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestValidateNoSchema(t *testing.T) {
|
||
|
|
// No schema means no validation
|
||
|
|
v := &Validator{schema: nil}
|
||
|
|
|
||
|
|
errs := v.Validate(map[string]interface{}{"anything": "goes"})
|
||
|
|
if len(errs) != 0 {
|
||
|
|
t.Errorf("expected no errors when schema is nil")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestParseSchema(t *testing.T) {
|
||
|
|
schema, err := parseSchema("name: string, age: number")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("parse error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if schema.Type != "object" {
|
||
|
|
t.Errorf("expected type object, got %s", schema.Type)
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(schema.Fields) != 2 {
|
||
|
|
t.Errorf("expected 2 fields, got %d", len(schema.Fields))
|
||
|
|
}
|
||
|
|
|
||
|
|
if f, ok := schema.Fields["name"]; !ok || f.Type != "string" {
|
||
|
|
t.Errorf("expected name: string in parsed schema")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func stringContains(s, substr string) bool {
|
||
|
|
for i := 0; i < len(s); i++ {
|
||
|
|
if i+len(substr) <= len(s) && s[i:i+len(substr)] == substr {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|