177 lines
3.4 KiB
Go
177 lines
3.4 KiB
Go
package validation
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
type User struct {
|
|
Name string
|
|
Age int
|
|
Address *Address
|
|
Tags []string
|
|
License License
|
|
}
|
|
|
|
type Address struct {
|
|
City string
|
|
Country string
|
|
}
|
|
|
|
type License struct {
|
|
ID string
|
|
Categories []string
|
|
}
|
|
|
|
func TestFilterAllowedStructFields(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input interface{}
|
|
existing interface{}
|
|
allowedFields map[string]bool
|
|
expectedResult interface{}
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "Filter top-level fields",
|
|
input: &User{
|
|
Name: "Alice",
|
|
Age: 30,
|
|
},
|
|
existing: &User{
|
|
Name: "Bob",
|
|
Age: 25,
|
|
},
|
|
allowedFields: map[string]bool{
|
|
"Name": true,
|
|
},
|
|
expectedResult: &User{
|
|
Name: "Alice", // Allowed field
|
|
Age: 25, // Kept from existing
|
|
},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Filter nested struct fields",
|
|
input: &User{
|
|
Name: "Alice",
|
|
Address: &Address{
|
|
City: "New York",
|
|
Country: "USA",
|
|
},
|
|
},
|
|
existing: &User{
|
|
Name: "Bob",
|
|
Address: &Address{
|
|
City: "London",
|
|
Country: "UK",
|
|
},
|
|
},
|
|
allowedFields: map[string]bool{
|
|
"Address.City": true,
|
|
},
|
|
expectedResult: &User{
|
|
Name: "Bob", // Kept from existing
|
|
Address: &Address{
|
|
City: "New York", // Allowed field
|
|
Country: "UK", // Kept from existing
|
|
},
|
|
},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Filter slice fields",
|
|
input: &User{
|
|
Tags: []string{"admin", "user"},
|
|
},
|
|
existing: &User{
|
|
Tags: []string{"guest"},
|
|
},
|
|
allowedFields: map[string]bool{
|
|
"Tags": true,
|
|
},
|
|
expectedResult: &User{
|
|
Tags: []string{"admin", "user"}, // Allowed slice
|
|
},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Filter slice of structs",
|
|
input: &User{
|
|
License: License{
|
|
ID: "123",
|
|
Categories: []string{"A", "B"},
|
|
},
|
|
},
|
|
existing: &User{
|
|
License: License{
|
|
ID: "456",
|
|
Categories: []string{"C"},
|
|
},
|
|
},
|
|
allowedFields: map[string]bool{
|
|
"License.ID": true,
|
|
},
|
|
expectedResult: &User{
|
|
License: License{
|
|
ID: "123", // Allowed field
|
|
Categories: []string{"C"}, // Kept from existing
|
|
},
|
|
},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Filter pointer fields",
|
|
input: &User{
|
|
Address: &Address{
|
|
City: "Paris",
|
|
},
|
|
},
|
|
existing: &User{
|
|
Address: &Address{
|
|
City: "Berlin",
|
|
Country: "Germany",
|
|
},
|
|
},
|
|
allowedFields: map[string]bool{
|
|
"Address.City": true,
|
|
},
|
|
expectedResult: &User{
|
|
Address: &Address{
|
|
City: "Paris", // Allowed field
|
|
Country: "Germany", // Kept from existing
|
|
},
|
|
},
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Invalid input (non-pointer)",
|
|
input: User{
|
|
Name: "Alice",
|
|
},
|
|
existing: &User{
|
|
Name: "Bob",
|
|
},
|
|
allowedFields: map[string]bool{
|
|
"Name": true,
|
|
},
|
|
expectedResult: nil,
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := FilterAllowedStructFields(tt.input, tt.existing, tt.allowedFields, "")
|
|
if (err != nil) != tt.expectError {
|
|
t.Errorf("FilterAllowedStructFields() error = %v, expectError %v", err, tt.expectError)
|
|
return
|
|
}
|
|
|
|
if !tt.expectError && !reflect.DeepEqual(tt.input, tt.expectedResult) {
|
|
t.Errorf("FilterAllowedStructFields() = %+v, expected %+v", tt.input, tt.expectedResult)
|
|
}
|
|
})
|
|
}
|
|
}
|