341 lines
10 KiB
Go
341 lines
10 KiB
Go
package diff
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"cosmossdk.io/schema"
|
|
)
|
|
|
|
func TestCompareModuleSchemas(t *testing.T) {
|
|
tt := []struct {
|
|
name string
|
|
oldSchema schema.ModuleSchema
|
|
newSchema schema.ModuleSchema
|
|
diff ModuleSchemaDiff
|
|
hasCompatibleChanges bool
|
|
empty bool
|
|
}{
|
|
{
|
|
name: "no change",
|
|
oldSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
}),
|
|
newSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
}),
|
|
diff: ModuleSchemaDiff{},
|
|
hasCompatibleChanges: true,
|
|
empty: true,
|
|
},
|
|
{
|
|
name: "object type added",
|
|
oldSchema: requireModuleSchema(t),
|
|
newSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
}),
|
|
diff: ModuleSchemaDiff{
|
|
AddedObjectTypes: []schema.ObjectType{
|
|
{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
},
|
|
},
|
|
},
|
|
hasCompatibleChanges: true,
|
|
},
|
|
{
|
|
name: "object type removed",
|
|
oldSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
}),
|
|
newSchema: requireModuleSchema(t),
|
|
diff: ModuleSchemaDiff{
|
|
RemovedObjectTypes: []schema.ObjectType{
|
|
{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
},
|
|
},
|
|
},
|
|
hasCompatibleChanges: false,
|
|
},
|
|
{
|
|
name: "object type changed, key field added",
|
|
oldSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
}),
|
|
newSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}, {Name: "key2", Kind: schema.StringKind}},
|
|
}),
|
|
diff: ModuleSchemaDiff{
|
|
ChangedObjectTypes: []ObjectTypeDiff{
|
|
{
|
|
Name: "object1",
|
|
KeyFieldsDiff: FieldsDiff{
|
|
Added: []schema.Field{
|
|
{Name: "key2", Kind: schema.StringKind},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
hasCompatibleChanges: false,
|
|
},
|
|
{
|
|
name: "object type changed, nullable value field added",
|
|
oldSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
}),
|
|
newSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
ValueFields: []schema.Field{{Name: "value1", Kind: schema.StringKind, Nullable: true}},
|
|
}),
|
|
diff: ModuleSchemaDiff{
|
|
ChangedObjectTypes: []ObjectTypeDiff{
|
|
{
|
|
Name: "object1",
|
|
ValueFieldsDiff: FieldsDiff{
|
|
Added: []schema.Field{{Name: "value1", Kind: schema.StringKind, Nullable: true}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
hasCompatibleChanges: true,
|
|
},
|
|
{
|
|
name: "object type changed, non-nullable value field added",
|
|
oldSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
}),
|
|
newSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}},
|
|
ValueFields: []schema.Field{{Name: "value1", Kind: schema.StringKind}},
|
|
}),
|
|
diff: ModuleSchemaDiff{
|
|
ChangedObjectTypes: []ObjectTypeDiff{
|
|
{
|
|
Name: "object1",
|
|
ValueFieldsDiff: FieldsDiff{
|
|
Added: []schema.Field{{Name: "value1", Kind: schema.StringKind}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
hasCompatibleChanges: false,
|
|
},
|
|
{
|
|
name: "object type changed, fields reordered",
|
|
oldSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.StringKind}, {Name: "key2", Kind: schema.StringKind}},
|
|
}),
|
|
newSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key2", Kind: schema.StringKind}, {Name: "key1", Kind: schema.StringKind}},
|
|
}),
|
|
diff: ModuleSchemaDiff{
|
|
ChangedObjectTypes: []ObjectTypeDiff{
|
|
{
|
|
Name: "object1",
|
|
KeyFieldsDiff: FieldsDiff{
|
|
OldOrder: []string{"key1", "key2"},
|
|
NewOrder: []string{"key2", "key1"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
hasCompatibleChanges: false,
|
|
},
|
|
{
|
|
name: "enum type added, nullable value field added",
|
|
oldSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.Int32Kind}},
|
|
}),
|
|
newSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.Int32Kind}},
|
|
ValueFields: []schema.Field{
|
|
{
|
|
Name: "value1",
|
|
Kind: schema.EnumKind,
|
|
ReferencedType: "enum1",
|
|
Nullable: true,
|
|
},
|
|
},
|
|
},
|
|
schema.EnumType{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}}),
|
|
diff: ModuleSchemaDiff{
|
|
ChangedObjectTypes: []ObjectTypeDiff{
|
|
{
|
|
Name: "object1",
|
|
ValueFieldsDiff: FieldsDiff{
|
|
Added: []schema.Field{
|
|
{
|
|
Name: "value1",
|
|
Kind: schema.EnumKind,
|
|
ReferencedType: "enum1",
|
|
Nullable: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
AddedEnumTypes: []schema.EnumType{
|
|
{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}},
|
|
},
|
|
},
|
|
hasCompatibleChanges: true,
|
|
},
|
|
{
|
|
name: "enum type removed",
|
|
oldSchema: requireModuleSchema(t,
|
|
schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.Int32Kind}},
|
|
ValueFields: []schema.Field{
|
|
{
|
|
Name: "value1",
|
|
Kind: schema.EnumKind,
|
|
ReferencedType: "enum1",
|
|
},
|
|
},
|
|
},
|
|
schema.EnumType{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}}),
|
|
newSchema: requireModuleSchema(t, schema.ObjectType{
|
|
Name: "object1",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.Int32Kind}},
|
|
}),
|
|
diff: ModuleSchemaDiff{
|
|
ChangedObjectTypes: []ObjectTypeDiff{
|
|
{
|
|
Name: "object1",
|
|
ValueFieldsDiff: FieldsDiff{
|
|
Removed: []schema.Field{
|
|
{
|
|
Name: "value1",
|
|
Kind: schema.EnumKind,
|
|
ReferencedType: "enum1",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
RemovedEnumTypes: []schema.EnumType{
|
|
{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}},
|
|
},
|
|
},
|
|
hasCompatibleChanges: false,
|
|
},
|
|
{
|
|
name: "enum value added",
|
|
oldSchema: requireModuleSchema(t,
|
|
schema.EnumType{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}}},
|
|
),
|
|
newSchema: requireModuleSchema(t,
|
|
schema.EnumType{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}},
|
|
),
|
|
diff: ModuleSchemaDiff{
|
|
ChangedEnumTypes: []EnumTypeDiff{
|
|
{
|
|
Name: "enum1",
|
|
AddedValues: []schema.EnumValueDefinition{{Name: "b", Value: 2}},
|
|
},
|
|
},
|
|
},
|
|
hasCompatibleChanges: true,
|
|
},
|
|
{
|
|
name: "enum value removed",
|
|
oldSchema: requireModuleSchema(t,
|
|
schema.EnumType{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}, {Name: "c", Value: 3}}},
|
|
),
|
|
newSchema: requireModuleSchema(t,
|
|
schema.EnumType{Name: "enum1", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}, {Name: "b", Value: 2}}},
|
|
),
|
|
diff: ModuleSchemaDiff{
|
|
ChangedEnumTypes: []EnumTypeDiff{
|
|
{
|
|
Name: "enum1",
|
|
RemovedValues: []schema.EnumValueDefinition{{Name: "c", Value: 3}},
|
|
},
|
|
},
|
|
},
|
|
hasCompatibleChanges: false,
|
|
},
|
|
{
|
|
name: "object type and enum type name switched",
|
|
oldSchema: requireModuleSchema(t,
|
|
schema.ObjectType{
|
|
Name: "foo",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, ReferencedType: "bar"}},
|
|
},
|
|
schema.EnumType{Name: "bar", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}}},
|
|
),
|
|
newSchema: requireModuleSchema(t,
|
|
schema.ObjectType{
|
|
Name: "bar",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, ReferencedType: "foo"}},
|
|
},
|
|
schema.EnumType{Name: "foo", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}}},
|
|
),
|
|
diff: ModuleSchemaDiff{
|
|
RemovedObjectTypes: []schema.ObjectType{
|
|
{
|
|
Name: "foo",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, ReferencedType: "bar"}},
|
|
},
|
|
},
|
|
AddedObjectTypes: []schema.ObjectType{
|
|
{
|
|
Name: "bar",
|
|
KeyFields: []schema.Field{{Name: "key1", Kind: schema.EnumKind, ReferencedType: "foo"}},
|
|
},
|
|
},
|
|
RemovedEnumTypes: []schema.EnumType{
|
|
{Name: "bar", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}}},
|
|
},
|
|
AddedEnumTypes: []schema.EnumType{
|
|
{Name: "foo", Values: []schema.EnumValueDefinition{{Name: "a", Value: 1}}},
|
|
},
|
|
},
|
|
hasCompatibleChanges: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := CompareModuleSchemas(tc.oldSchema, tc.newSchema)
|
|
if !reflect.DeepEqual(got, tc.diff) {
|
|
t.Errorf("CompareModuleSchemas() = %v, want %v", got, tc.diff)
|
|
}
|
|
hasCompatibleChanges := got.HasCompatibleChanges()
|
|
if hasCompatibleChanges != tc.hasCompatibleChanges {
|
|
t.Errorf("HasCompatibleChanges() = %v, want %v", hasCompatibleChanges, tc.hasCompatibleChanges)
|
|
}
|
|
if tc.empty != got.Empty() {
|
|
t.Errorf("Empty() = %v, want %v", got.Empty(), tc.empty)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func requireModuleSchema(t *testing.T, types ...schema.Type) schema.ModuleSchema {
|
|
s, err := schema.CompileModuleSchema(types...)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return s
|
|
}
|