1398 lines
40 KiB
Go
1398 lines
40 KiB
Go
package model
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/tech/sendico/pkg/mservice"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
)
|
|
|
|
func createTestPermissionBound() PermissionBound {
|
|
pb := PermissionBound{
|
|
PermissionRef: primitive.NewObjectID(),
|
|
}
|
|
pb.OrganizationRef = primitive.NewObjectID()
|
|
return pb
|
|
}
|
|
|
|
func createTestRecordRef() ObjectRef {
|
|
return ObjectRef{
|
|
Ref: primitive.NewObjectID(),
|
|
}
|
|
}
|
|
|
|
func createTestPropertyScheme(propertyType PropertyType, key string) PropertySchema {
|
|
desc := "Test property scheme"
|
|
|
|
ps := PropertySchema{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Describable: Describable{
|
|
Name: key,
|
|
Description: &desc,
|
|
},
|
|
Key: key,
|
|
Type: propertyType,
|
|
Multiplicity: Multiplicity{
|
|
Mode: One, // Default to single values
|
|
},
|
|
}
|
|
ps.ID = primitive.NewObjectID()
|
|
|
|
// Set appropriate Props based on type
|
|
switch propertyType {
|
|
case PTString:
|
|
ps.Props = StringProps{}
|
|
case PTColor:
|
|
ps.Props = ColorProps{}
|
|
case PTInteger:
|
|
ps.Props = IntegerProps{}
|
|
case PTFloat:
|
|
ps.Props = FloatProps{}
|
|
case PTDateTime:
|
|
ps.Props = DateTimeProps{}
|
|
case PTMonetary:
|
|
ps.Props = MonetaryProps{}
|
|
case PTReference:
|
|
ps.Props = ReferenceProps{}
|
|
case PTObject:
|
|
ps.Props = ObjectProps{}
|
|
}
|
|
|
|
return ps
|
|
}
|
|
|
|
func createTestPropertySchemeMany(propertyType PropertyType, key string) PropertySchema {
|
|
desc := "Test property scheme"
|
|
|
|
ps := PropertySchema{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Describable: Describable{
|
|
Name: key,
|
|
Description: &desc,
|
|
},
|
|
Key: key,
|
|
Type: propertyType,
|
|
Multiplicity: Multiplicity{
|
|
Mode: Many, // Allow multiple values
|
|
},
|
|
}
|
|
ps.ID = primitive.NewObjectID()
|
|
|
|
// Set appropriate Props based on type
|
|
switch propertyType {
|
|
case PTString:
|
|
ps.Props = StringProps{}
|
|
case PTColor:
|
|
ps.Props = ColorProps{}
|
|
case PTInteger:
|
|
ps.Props = IntegerProps{}
|
|
case PTFloat:
|
|
ps.Props = FloatProps{}
|
|
case PTDateTime:
|
|
ps.Props = DateTimeProps{}
|
|
case PTMonetary:
|
|
ps.Props = MonetaryProps{}
|
|
case PTReference:
|
|
ps.Props = ReferenceProps{}
|
|
case PTObject:
|
|
ps.Props = ObjectProps{}
|
|
}
|
|
|
|
return ps
|
|
}
|
|
|
|
func TestValue(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTString, "test_string")
|
|
|
|
value := Value{
|
|
PermissionBound: scope,
|
|
Target: target,
|
|
Type: PTString,
|
|
Cardinality: One,
|
|
PropertySchemaRef: scheme.ID,
|
|
Values: SettingsT{"string": "test_value"},
|
|
}
|
|
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTString, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
}
|
|
|
|
func TestAsString(t *testing.T) {
|
|
t.Run("valid string value", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTString,
|
|
Cardinality: One,
|
|
Values: SettingsT{"string": "hello"},
|
|
}
|
|
|
|
result, err := value.AsString()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "hello", result)
|
|
})
|
|
|
|
t.Run("invalid type", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTInteger,
|
|
Cardinality: One,
|
|
Values: SettingsT{"integer": 42},
|
|
}
|
|
|
|
_, err := value.AsString()
|
|
|
|
assert.Error(t, err)
|
|
})
|
|
|
|
t.Run("invalid cardinality", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTString,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"strings": []string{"hello"}},
|
|
}
|
|
|
|
_, err := value.AsString()
|
|
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestAsColor(t *testing.T) {
|
|
t.Run("valid color value", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTColor,
|
|
Cardinality: One,
|
|
Values: SettingsT{"color": "#FF0000"},
|
|
}
|
|
|
|
result, err := value.AsColor()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "#FF0000", result)
|
|
})
|
|
}
|
|
|
|
func TestAsInteger(t *testing.T) {
|
|
t.Run("valid integer value", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTInteger,
|
|
Cardinality: One,
|
|
Values: SettingsT{"integer": int64(42)},
|
|
}
|
|
|
|
result, err := value.AsInteger()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(42), result)
|
|
})
|
|
}
|
|
|
|
func TestAsFloat(t *testing.T) {
|
|
t.Run("valid float value", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTFloat,
|
|
Cardinality: One,
|
|
Values: SettingsT{"float": 3.14},
|
|
}
|
|
|
|
result, err := value.AsFloat()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 3.14, result)
|
|
})
|
|
}
|
|
|
|
func TestAsDateTime(t *testing.T) {
|
|
t.Run("valid datetime value", func(t *testing.T) {
|
|
now := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
value := Value{
|
|
Type: PTDateTime,
|
|
Cardinality: One,
|
|
Values: SettingsT{"date_time": now},
|
|
}
|
|
|
|
result, err := value.AsDateTime()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, now, result)
|
|
})
|
|
}
|
|
|
|
func TestAsMonetary(t *testing.T) {
|
|
t.Run("valid monetary value", func(t *testing.T) {
|
|
money := Money{
|
|
Amount: primitive.NewDecimal128(10000, 0), // $100.00
|
|
Currency: CurrencyUSD,
|
|
}
|
|
value := Value{
|
|
Type: PTMonetary,
|
|
Cardinality: One,
|
|
Values: SettingsT{"monetary": money},
|
|
}
|
|
|
|
result, err := value.AsMonetary()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, money, result)
|
|
})
|
|
}
|
|
|
|
func TestAsReference(t *testing.T) {
|
|
t.Run("valid reference value", func(t *testing.T) {
|
|
ref := primitive.NewObjectID()
|
|
value := Value{
|
|
Type: PTReference,
|
|
Cardinality: One,
|
|
Values: SettingsT{"reference": ref},
|
|
}
|
|
|
|
result, err := value.AsReference()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, ref, result)
|
|
})
|
|
}
|
|
|
|
func TestAsObject(t *testing.T) {
|
|
t.Run("valid object value", func(t *testing.T) {
|
|
obj := Object{
|
|
"field1": Value{
|
|
Type: PTString,
|
|
Cardinality: One,
|
|
Values: SettingsT{"string": "value1"},
|
|
},
|
|
}
|
|
value := Value{
|
|
Type: PTObject,
|
|
Cardinality: One,
|
|
Values: SettingsT{"object": obj},
|
|
}
|
|
|
|
result, err := value.AsObject()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, obj, result)
|
|
})
|
|
}
|
|
|
|
func TestAsStrings(t *testing.T) {
|
|
t.Run("valid strings value", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTString,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"strings": []string{"hello", "world"}},
|
|
}
|
|
|
|
result, err := value.AsStrings()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []string{"hello", "world"}, result)
|
|
})
|
|
}
|
|
|
|
func TestAsColors(t *testing.T) {
|
|
t.Run("valid colors value", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTColor,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"colors": []string{"#FF0000", "#00FF00"}},
|
|
}
|
|
|
|
result, err := value.AsColors()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []string{"#FF0000", "#00FF00"}, result)
|
|
})
|
|
}
|
|
|
|
func TestAsIntegers(t *testing.T) {
|
|
t.Run("valid integers value", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTInteger,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"integers": []int64{1, 2, 3}},
|
|
}
|
|
|
|
result, err := value.AsIntegers()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []int64{1, 2, 3}, result)
|
|
})
|
|
}
|
|
|
|
func TestAsFloats(t *testing.T) {
|
|
t.Run("valid floats value", func(t *testing.T) {
|
|
value := Value{
|
|
Type: PTFloat,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"floats": []float64{1.1, 2.2, 3.3}},
|
|
}
|
|
|
|
result, err := value.AsFloats()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []float64{1.1, 2.2, 3.3}, result)
|
|
})
|
|
}
|
|
|
|
func TestAsDateTimes(t *testing.T) {
|
|
t.Run("valid datetimes value", func(t *testing.T) {
|
|
now1 := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
now2 := time.Date(2023, 1, 2, 12, 0, 0, 0, time.UTC)
|
|
value := Value{
|
|
Type: PTDateTime,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"date_times": []time.Time{now1, now2}},
|
|
}
|
|
|
|
result, err := value.AsDateTimes()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []time.Time{now1, now2}, result)
|
|
})
|
|
}
|
|
|
|
func TestAsMonetaries(t *testing.T) {
|
|
t.Run("valid monetaries value", func(t *testing.T) {
|
|
money1 := Money{Amount: primitive.NewDecimal128(10000, 0), Currency: CurrencyUSD}
|
|
money2 := Money{Amount: primitive.NewDecimal128(20000, 0), Currency: CurrencyUSD}
|
|
value := Value{
|
|
Type: PTMonetary,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"monetaries": []Money{money1, money2}},
|
|
}
|
|
|
|
result, err := value.AsMonetaries()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []Money{money1, money2}, result)
|
|
})
|
|
}
|
|
|
|
func TestAsReferences(t *testing.T) {
|
|
t.Run("valid references value", func(t *testing.T) {
|
|
ref1 := primitive.NewObjectID()
|
|
ref2 := primitive.NewObjectID()
|
|
value := Value{
|
|
Type: PTReference,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"references": []primitive.ObjectID{ref1, ref2}},
|
|
}
|
|
|
|
result, err := value.AsReferences()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []primitive.ObjectID{ref1, ref2}, result)
|
|
})
|
|
}
|
|
|
|
func TestAsObjects(t *testing.T) {
|
|
t.Run("valid objects value", func(t *testing.T) {
|
|
obj1 := Object{"field1": Value{Type: PTString, Cardinality: One, Values: SettingsT{"string": "value1"}}}
|
|
obj2 := Object{"field2": Value{Type: PTString, Cardinality: One, Values: SettingsT{"string": "value2"}}}
|
|
value := Value{
|
|
Type: PTObject,
|
|
Cardinality: Many,
|
|
Values: SettingsT{"objects": []Object{obj1, obj2}},
|
|
}
|
|
|
|
result, err := value.AsObjects()
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []Object{obj1, obj2}, result)
|
|
})
|
|
}
|
|
|
|
func TestNewStringValue(t *testing.T) {
|
|
t.Run("valid string value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTString, "test_string")
|
|
|
|
value, err := NewStringValue(scope, target, scheme, "hello")
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTString, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"string": "hello"}, value.Values)
|
|
})
|
|
|
|
t.Run("invalid type", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTInteger, "test_int")
|
|
|
|
_, err := NewStringValue(scope, target, scheme, "hello")
|
|
|
|
assert.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestNewStringsValue(t *testing.T) {
|
|
t.Run("valid strings value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertySchemeMany(PTString, "test_strings")
|
|
|
|
value, err := NewStringsValue(scope, target, scheme, []string{"hello", "world"})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTString, value.Type)
|
|
assert.Equal(t, Many, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"strings": []string{"hello", "world"}}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewColorValue(t *testing.T) {
|
|
t.Run("valid color value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTColor, "test_color")
|
|
|
|
value, err := NewColorValue(scope, target, scheme, "#FF0000")
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTColor, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"color": "#FF0000"}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewColorsValue(t *testing.T) {
|
|
t.Run("valid colors value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertySchemeMany(PTColor, "test_colors")
|
|
|
|
value, err := NewColorsValue(scope, target, scheme, []string{"#FF0000", "#00FF00"})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTColor, value.Type)
|
|
assert.Equal(t, Many, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"colors": []string{"#FF0000", "#00FF00"}}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewIntegerValue(t *testing.T) {
|
|
t.Run("valid integer value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTInteger, "test_int")
|
|
|
|
value, err := NewIntegerValue(scope, target, scheme, 42)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTInteger, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"integer": int64(42)}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewIntegersValue(t *testing.T) {
|
|
t.Run("valid integers value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertySchemeMany(PTInteger, "test_ints")
|
|
|
|
value, err := NewIntegersValue(scope, target, scheme, []int64{1, 2, 3})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTInteger, value.Type)
|
|
assert.Equal(t, Many, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"integers": []int64{1, 2, 3}}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewFloatValue(t *testing.T) {
|
|
t.Run("valid float value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTFloat, "test_float")
|
|
|
|
value, err := NewFloatValue(scope, target, scheme, 3.14)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTFloat, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"float": 3.14}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewFloatsValue(t *testing.T) {
|
|
t.Run("valid floats value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertySchemeMany(PTFloat, "test_floats")
|
|
|
|
value, err := NewFloatsValue(scope, target, scheme, []float64{1.1, 2.2, 3.3})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTFloat, value.Type)
|
|
assert.Equal(t, Many, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"floats": []float64{1.1, 2.2, 3.3}}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewDateTimeValue(t *testing.T) {
|
|
t.Run("valid datetime value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTDateTime, "test_datetime")
|
|
now := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
|
|
value, err := NewDateTimeValue(scope, target, scheme, now)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTDateTime, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"date_time": now}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewDateTimesValue(t *testing.T) {
|
|
t.Run("valid datetimes value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertySchemeMany(PTDateTime, "test_datetimes")
|
|
now1 := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
now2 := time.Date(2023, 1, 2, 12, 0, 0, 0, time.UTC)
|
|
|
|
value, err := NewDateTimesValue(scope, target, scheme, []time.Time{now1, now2})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTDateTime, value.Type)
|
|
assert.Equal(t, Many, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"date_times": []time.Time{now1, now2}}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewMonetaryValue(t *testing.T) {
|
|
t.Run("valid monetary value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTMonetary, "test_monetary")
|
|
money := Money{
|
|
Amount: primitive.NewDecimal128(10000, 0), // $100.00
|
|
Currency: CurrencyUSD,
|
|
}
|
|
|
|
value, err := NewMonetaryValue(scope, target, scheme, money, CurrencyUSD)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTMonetary, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"monetary": money}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewMonetariesValue(t *testing.T) {
|
|
t.Run("valid monetaries value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertySchemeMany(PTMonetary, "test_monetaries")
|
|
money1 := Money{Amount: primitive.NewDecimal128(10000, 0), Currency: CurrencyUSD}
|
|
money2 := Money{Amount: primitive.NewDecimal128(20000, 0), Currency: CurrencyUSD}
|
|
|
|
value, err := NewMonetariesValue(scope, target, scheme, []Money{money1, money2}, CurrencyUSD)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTMonetary, value.Type)
|
|
assert.Equal(t, Many, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"monetaries": []Money{money1, money2}}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewReferenceValue(t *testing.T) {
|
|
t.Run("valid reference value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTReference, "test_reference")
|
|
ref := primitive.NewObjectID()
|
|
|
|
value, err := NewReferenceValue(scope, target, scheme, ref, func(resource mservice.Type, id primitive.ObjectID, filter bson.M) (bool, error) { return true, nil })
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTReference, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"reference": ref}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewReferencesValue(t *testing.T) {
|
|
t.Run("valid references value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertySchemeMany(PTReference, "test_references")
|
|
ref1 := primitive.NewObjectID()
|
|
ref2 := primitive.NewObjectID()
|
|
|
|
value, err := NewReferencesValue(scope, target, scheme, []primitive.ObjectID{ref1, ref2}, func(resource mservice.Type, id primitive.ObjectID, filter bson.M) (bool, error) { return true, nil })
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTReference, value.Type)
|
|
assert.Equal(t, Many, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"references": []primitive.ObjectID{ref1, ref2}}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewObjectValue(t *testing.T) {
|
|
t.Run("valid object value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertyScheme(PTObject, "test_object")
|
|
obj := Object{
|
|
"field1": Value{
|
|
Type: PTString,
|
|
Cardinality: One,
|
|
Values: SettingsT{"string": "value1"},
|
|
},
|
|
}
|
|
|
|
value, err := NewObjectValue(scope, target, scheme, obj)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTObject, value.Type)
|
|
assert.Equal(t, One, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"object": obj}, value.Values)
|
|
})
|
|
}
|
|
|
|
func TestNewObjectsValue(t *testing.T) {
|
|
t.Run("valid objects value", func(t *testing.T) {
|
|
scope := createTestPermissionBound()
|
|
target := createTestRecordRef()
|
|
scheme := createTestPropertySchemeMany(PTObject, "test_objects")
|
|
obj1 := Object{"field1": Value{Type: PTString, Cardinality: One, Values: SettingsT{"string": "value1"}}}
|
|
obj2 := Object{"field2": Value{Type: PTString, Cardinality: One, Values: SettingsT{"string": "value2"}}}
|
|
|
|
value, err := NewObjectsValue(scope, target, scheme, []Object{obj1, obj2})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, scope, value.PermissionBound)
|
|
assert.Equal(t, target, value.Target)
|
|
assert.Equal(t, PTObject, value.Type)
|
|
assert.Equal(t, Many, value.Cardinality)
|
|
assert.Equal(t, scheme.ID, value.PropertySchemaRef)
|
|
assert.Equal(t, SettingsT{"objects": []Object{obj1, obj2}}, value.Values)
|
|
})
|
|
}
|
|
|
|
// ----------------------------
|
|
// Serialization/Deserialization Tests
|
|
// ----------------------------
|
|
|
|
func TestValueBSONSerialization(t *testing.T) {
|
|
t.Run("string value BSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTString,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"string": "hello world"},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.PermissionBound, restored.PermissionBound)
|
|
assert.Equal(t, original.Target, restored.Target)
|
|
assert.Equal(t, original.Type, restored.Type)
|
|
assert.Equal(t, original.Cardinality, restored.Cardinality)
|
|
assert.Equal(t, original.PropertySchemaRef, restored.PropertySchemaRef)
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the value
|
|
str, err := restored.AsString()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "hello world", str)
|
|
})
|
|
|
|
t.Run("strings value BSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTString,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"strings": []string{"hello", "world", "test"}},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the values
|
|
strings, err := restored.AsStrings()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []string{"hello", "world", "test"}, strings)
|
|
})
|
|
|
|
t.Run("integer value BSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTInteger,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"integer": int64(42)},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the value
|
|
val, err := restored.AsInteger()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(42), val)
|
|
})
|
|
|
|
t.Run("float value BSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTFloat,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"float": 3.14159},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the value
|
|
val, err := restored.AsFloat()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 3.14159, val)
|
|
})
|
|
|
|
t.Run("datetime value BSON round-trip", func(t *testing.T) {
|
|
// Use millisecond precision to match primitive.DateTime
|
|
now := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC).Truncate(time.Millisecond)
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTDateTime,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"date_time": now},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare all fields except Values (which may have timezone differences)
|
|
assert.Equal(t, original.PermissionBound, restored.PermissionBound)
|
|
assert.Equal(t, original.Target, restored.Target)
|
|
assert.Equal(t, original.Type, restored.Type)
|
|
assert.Equal(t, original.Cardinality, restored.Cardinality)
|
|
assert.Equal(t, original.PropertySchemaRef, restored.PropertySchemaRef)
|
|
|
|
// Test that we can still access the value
|
|
val, err := restored.AsDateTime()
|
|
require.NoError(t, err)
|
|
// Compare only the actual time value, not timezone metadata
|
|
assert.Equal(t, now.Unix(), val.Unix())
|
|
})
|
|
|
|
t.Run("monetary value BSON round-trip", func(t *testing.T) {
|
|
money := Money{
|
|
Amount: primitive.NewDecimal128(10000, 0), // $100.00
|
|
Currency: CurrencyUSD,
|
|
}
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTMonetary,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"monetary": money},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the value
|
|
val, err := restored.AsMonetary()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, money, val)
|
|
})
|
|
|
|
t.Run("reference value BSON round-trip", func(t *testing.T) {
|
|
ref := primitive.NewObjectID()
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTReference,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"reference": ref},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the value
|
|
val, err := restored.AsReference()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, ref, val)
|
|
})
|
|
|
|
t.Run("color value BSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTColor,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"color": "#FF0000"},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the value
|
|
val, err := restored.AsColor()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "#FF0000", val)
|
|
})
|
|
|
|
t.Run("object value BSON round-trip", func(t *testing.T) {
|
|
obj := Object{
|
|
"field1": Value{
|
|
Type: PTString,
|
|
Cardinality: One,
|
|
Values: SettingsT{"string": "value1"},
|
|
},
|
|
"field2": Value{
|
|
Type: PTInteger,
|
|
Cardinality: One,
|
|
Values: SettingsT{"integer": int64(42)},
|
|
},
|
|
}
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTObject,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"object": obj},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the value
|
|
val, err := restored.AsObject()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, obj, val)
|
|
})
|
|
}
|
|
|
|
func TestValueJSONSerialization(t *testing.T) {
|
|
t.Run("string value JSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTString,
|
|
Cardinality: One,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"string": "hello world"},
|
|
}
|
|
|
|
// Marshal to JSON
|
|
jsonData, err := bson.MarshalExtJSON(original, true, false)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from JSON
|
|
var restored Value
|
|
err = bson.UnmarshalExtJSON(jsonData, true, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.PermissionBound, restored.PermissionBound)
|
|
assert.Equal(t, original.Target, restored.Target)
|
|
assert.Equal(t, original.Type, restored.Type)
|
|
assert.Equal(t, original.Cardinality, restored.Cardinality)
|
|
assert.Equal(t, original.PropertySchemaRef, restored.PropertySchemaRef)
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the value
|
|
str, err := restored.AsString()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "hello world", str)
|
|
})
|
|
|
|
t.Run("integers value JSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTInteger,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"integers": []int64{1, 2, 3, 4, 5}},
|
|
}
|
|
|
|
// Marshal to JSON
|
|
jsonData, err := bson.MarshalExtJSON(original, true, false)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from JSON
|
|
var restored Value
|
|
err = bson.UnmarshalExtJSON(jsonData, true, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the values
|
|
vals, err := restored.AsIntegers()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []int64{1, 2, 3, 4, 5}, vals)
|
|
})
|
|
|
|
t.Run("floats value JSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTFloat,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"floats": []float64{1.1, 2.2, 3.3}},
|
|
}
|
|
|
|
// Marshal to JSON
|
|
jsonData, err := bson.MarshalExtJSON(original, true, false)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from JSON
|
|
var restored Value
|
|
err = bson.UnmarshalExtJSON(jsonData, true, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the values
|
|
vals, err := restored.AsFloats()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []float64{1.1, 2.2, 3.3}, vals)
|
|
})
|
|
|
|
t.Run("datetimes value JSON round-trip", func(t *testing.T) {
|
|
// Use millisecond precision to match primitive.DateTime
|
|
now1 := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC).Truncate(time.Millisecond)
|
|
now2 := time.Date(2023, 1, 2, 12, 0, 0, 0, time.UTC).Truncate(time.Millisecond)
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTDateTime,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"date_times": []time.Time{now1, now2}},
|
|
}
|
|
|
|
// Marshal to JSON
|
|
jsonData, err := bson.MarshalExtJSON(original, true, false)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from JSON
|
|
var restored Value
|
|
err = bson.UnmarshalExtJSON(jsonData, true, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare all fields except Values (which may have timezone differences)
|
|
assert.Equal(t, original.PermissionBound, restored.PermissionBound)
|
|
assert.Equal(t, original.Target, restored.Target)
|
|
assert.Equal(t, original.Type, restored.Type)
|
|
assert.Equal(t, original.Cardinality, restored.Cardinality)
|
|
assert.Equal(t, original.PropertySchemaRef, restored.PropertySchemaRef)
|
|
|
|
// Test that we can still access the values
|
|
vals, err := restored.AsDateTimes()
|
|
require.NoError(t, err)
|
|
// Compare only the actual time values, not timezone metadata
|
|
assert.Equal(t, 2, len(vals))
|
|
assert.Equal(t, now1.Unix(), vals[0].Unix())
|
|
assert.Equal(t, now2.Unix(), vals[1].Unix())
|
|
})
|
|
|
|
t.Run("monetaries value JSON round-trip", func(t *testing.T) {
|
|
money1 := Money{Amount: primitive.NewDecimal128(10000, 0), Currency: CurrencyUSD}
|
|
money2 := Money{Amount: primitive.NewDecimal128(20000, 0), Currency: CurrencyUSD}
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTMonetary,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"monetaries": []Money{money1, money2}},
|
|
}
|
|
|
|
// Marshal to JSON
|
|
jsonData, err := bson.MarshalExtJSON(original, true, false)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from JSON
|
|
var restored Value
|
|
err = bson.UnmarshalExtJSON(jsonData, true, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the values
|
|
vals, err := restored.AsMonetaries()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []Money{money1, money2}, vals)
|
|
})
|
|
|
|
t.Run("references value JSON round-trip", func(t *testing.T) {
|
|
ref1 := primitive.NewObjectID()
|
|
ref2 := primitive.NewObjectID()
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTReference,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"references": []primitive.ObjectID{ref1, ref2}},
|
|
}
|
|
|
|
// Marshal to JSON
|
|
jsonData, err := bson.MarshalExtJSON(original, true, false)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from JSON
|
|
var restored Value
|
|
err = bson.UnmarshalExtJSON(jsonData, true, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the values
|
|
vals, err := restored.AsReferences()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []primitive.ObjectID{ref1, ref2}, vals)
|
|
})
|
|
|
|
t.Run("colors value JSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTColor,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"colors": []string{"#FF0000", "#00FF00", "#0000FF"}},
|
|
}
|
|
|
|
// Marshal to JSON
|
|
jsonData, err := bson.MarshalExtJSON(original, true, false)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from JSON
|
|
var restored Value
|
|
err = bson.UnmarshalExtJSON(jsonData, true, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the values
|
|
vals, err := restored.AsColors()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []string{"#FF0000", "#00FF00", "#0000FF"}, vals)
|
|
})
|
|
|
|
t.Run("objects value JSON round-trip", func(t *testing.T) {
|
|
obj1 := Object{"field1": Value{Type: PTString, Cardinality: One, Values: SettingsT{"string": "value1"}}}
|
|
obj2 := Object{"field2": Value{Type: PTInteger, Cardinality: One, Values: SettingsT{"integer": int64(42)}}}
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTObject,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"objects": []Object{obj1, obj2}},
|
|
}
|
|
|
|
// Marshal to JSON
|
|
jsonData, err := bson.MarshalExtJSON(original, true, false)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from JSON
|
|
var restored Value
|
|
err = bson.UnmarshalExtJSON(jsonData, true, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the values
|
|
vals, err := restored.AsObjects()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []Object{obj1, obj2}, vals)
|
|
})
|
|
}
|
|
|
|
func TestValueSerializationEdgeCases(t *testing.T) {
|
|
t.Run("empty values BSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTString,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"strings": []string{}},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the empty values
|
|
vals, err := restored.AsStrings()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, []string{}, vals)
|
|
})
|
|
|
|
t.Run("nil values BSON round-trip", func(t *testing.T) {
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTString,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"strings": []string(nil)},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the nil values
|
|
vals, err := restored.AsStrings()
|
|
require.NoError(t, err)
|
|
assert.Nil(t, vals)
|
|
})
|
|
|
|
t.Run("large values BSON round-trip", func(t *testing.T) {
|
|
// Create a large slice of strings
|
|
largeStrings := make([]string, 1000)
|
|
for i := 0; i < 1000; i++ {
|
|
largeStrings[i] = fmt.Sprintf("string_%d", i)
|
|
}
|
|
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTString,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"strings": largeStrings},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the large values
|
|
vals, err := restored.AsStrings()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, largeStrings, vals)
|
|
})
|
|
|
|
t.Run("special characters BSON round-trip", func(t *testing.T) {
|
|
specialStrings := []string{
|
|
"hello world",
|
|
"привет мир", // Cyrillic
|
|
"你好世界", // Chinese
|
|
"مرحبا بالعالم", // Arabic
|
|
"🚀🌟💫", // Emojis
|
|
"line\nbreak\ttab",
|
|
"quotes\"and'apostrophes",
|
|
"backslash\\and/slash",
|
|
}
|
|
|
|
original := Value{
|
|
PermissionBound: createTestPermissionBound(),
|
|
Target: createTestRecordRef(),
|
|
Type: PTString,
|
|
Cardinality: Many,
|
|
PropertySchemaRef: primitive.NewObjectID(),
|
|
Values: SettingsT{"strings": specialStrings},
|
|
}
|
|
|
|
// Marshal to BSON
|
|
bsonData, err := bson.Marshal(original)
|
|
require.NoError(t, err)
|
|
|
|
// Unmarshal from BSON
|
|
var restored Value
|
|
err = bson.Unmarshal(bsonData, &restored)
|
|
require.NoError(t, err)
|
|
|
|
// Compare
|
|
assert.Equal(t, original.Values, restored.Values)
|
|
|
|
// Test that we can still access the special character values
|
|
vals, err := restored.AsStrings()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, specialStrings, vals)
|
|
})
|
|
}
|