package ldmodel import ( "encoding/json" "testing" "github.com/launchdarkly/go-jsonstream/v3/jreader" "github.com/launchdarkly/go-jsonstream/v3/jwriter" "github.com/launchdarkly/go-test-helpers/v3/jsonhelpers" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) type testMarshalFlagFn func(FeatureFlag) ([]byte, error) type testUnmarshalFlagFn func([]byte) (FeatureFlag, error) type testMarshalSegmentFn func(Segment) ([]byte, error) type testUnmarshalSegmentFn func([]byte) (Segment, error) func doMarshalFlagTest(t *testing.T, marshalFn testMarshalFlagFn) { for _, p := range makeFlagSerializationTestParams() { t.Run(p.name, func(t *testing.T) { bytes, err := marshalFn(p.flag) require.NoError(t, err) expected := mergeDefaultProperties(json.RawMessage(p.jsonString), flagTopLevelDefaultProperties) jsonhelpers.AssertEqual(t, expected, bytes) }) } } func doMarshalSegmentTest(t *testing.T, marshalFn testMarshalSegmentFn) { for _, p := range makeSegmentSerializationTestParams() { t.Run(p.name, func(t *testing.T) { bytes, err := marshalFn(p.segment) require.NoError(t, err) expected := mergeDefaultProperties(json.RawMessage(p.jsonString), segmentTopLevelDefaultProperties) jsonhelpers.AssertEqual(t, expected, bytes) }) } } func doUnmarshalFlagTest(t *testing.T, unmarshalFn testUnmarshalFlagFn) { for _, p := range makeFlagSerializationTestParams() { t.Run(p.name, func(t *testing.T) { flag, err := unmarshalFn([]byte(p.jsonString)) require.NoError(t, err) expectedFlag := p.flag PreprocessFlag(&expectedFlag) if !p.isCustomClientSideAvailability { expectedFlag.ClientSideAvailability = ClientSideAvailability{UsingMobileKey: true} // this is the default } assert.Equal(t, expectedFlag, flag) for _, altJSON := range p.jsonAltInputs { t.Run(altJSON, func(t *testing.T) { flag, err := unmarshalFn([]byte(altJSON)) require.NoError(t, err) assert.Equal(t, expectedFlag, flag) }) } }) } } func doUnmarshalSegmentTest(t *testing.T, unmarshalFn testUnmarshalSegmentFn) { for _, p := range makeSegmentSerializationTestParams() { t.Run(p.name, func(t *testing.T) { segment, err := unmarshalFn([]byte(p.jsonString)) require.NoError(t, err) expectedSegment := p.segment PreprocessSegment(&expectedSegment) assert.Equal(t, expectedSegment, segment) for _, altJSON := range p.jsonAltInputs { t.Run(altJSON, func(t *testing.T) { segment, err := unmarshalFn([]byte(altJSON)) require.NoError(t, err) assert.Equal(t, expectedSegment, segment) }) } }) } } func TestMarshalFlagWithJSONMarshal(t *testing.T) { doMarshalFlagTest(t, func(flag FeatureFlag) ([]byte, error) { return json.Marshal(flag) }) } func TestMarshalFlagWithDefaultSerialization(t *testing.T) { doMarshalFlagTest(t, NewJSONDataModelSerialization().MarshalFeatureFlag) } func TestMarshalFlagWithJSONWriter(t *testing.T) { doMarshalFlagTest(t, func(flag FeatureFlag) ([]byte, error) { w := jwriter.NewWriter() MarshalFeatureFlagToJSONWriter(flag, &w) return w.Bytes(), w.Error() }) } func TestUnmarshalFlagWithJSONUnmarshal(t *testing.T) { doUnmarshalFlagTest(t, func(data []byte) (FeatureFlag, error) { var flag FeatureFlag err := json.Unmarshal(data, &flag) return flag, err }) } func TestUnmarshalFlagWithDefaultSerialization(t *testing.T) { doUnmarshalFlagTest(t, NewJSONDataModelSerialization().UnmarshalFeatureFlag) } func TestUnmarshalFlagWithJSONReader(t *testing.T) { doUnmarshalFlagTest(t, func(data []byte) (FeatureFlag, error) { r := jreader.NewReader(data) flag := UnmarshalFeatureFlagFromJSONReader(&r) return flag, r.Error() }) } func TestMarshalSegmentWithJSONMarshal(t *testing.T) { doMarshalSegmentTest(t, func(segment Segment) ([]byte, error) { return json.Marshal(segment) }) } func TestMarshalSegmentWithDefaultSerialization(t *testing.T) { doMarshalSegmentTest(t, NewJSONDataModelSerialization().MarshalSegment) } func TestMarshalSegmentWithJSONWriter(t *testing.T) { doMarshalSegmentTest(t, func(segment Segment) ([]byte, error) { w := jwriter.NewWriter() MarshalSegmentToJSONWriter(segment, &w) return w.Bytes(), w.Error() }) } func TestUnmarshalSegmentWithJSONUnmarshal(t *testing.T) { doUnmarshalSegmentTest(t, func(data []byte) (Segment, error) { var segment Segment err := json.Unmarshal(data, &segment) return segment, err }) } func TestUnmarshalSegmentWithDefaultSerialization(t *testing.T) { doUnmarshalSegmentTest(t, NewJSONDataModelSerialization().UnmarshalSegment) } func TestUnmarshalSegmentWithJSONReader(t *testing.T) { doUnmarshalSegmentTest(t, func(data []byte) (Segment, error) { r := jreader.NewReader(data) segment := UnmarshalSegmentFromJSONReader(&r) return segment, r.Error() }) } func TestUnmarshalFlagErrors(t *testing.T) { _, err := NewJSONDataModelSerialization().UnmarshalFeatureFlag([]byte(`{`)) assert.Error(t, err) _, err = NewJSONDataModelSerialization().UnmarshalFeatureFlag([]byte(`{"key":[]}`)) assert.Error(t, err) } func TestUnmarshalSegmentErrors(t *testing.T) { _, err := NewJSONDataModelSerialization().UnmarshalSegment([]byte(`{`)) assert.Error(t, err) _, err = NewJSONDataModelSerialization().UnmarshalSegment([]byte(`{"key":[]}`)) assert.Error(t, err) }