diff --git a/schema/data/base/accAddressData.go b/schema/data/base/accAddressData.go index dea02575c..7f21570c4 100644 --- a/schema/data/base/accAddressData.go +++ b/schema/data/base/accAddressData.go @@ -30,6 +30,12 @@ func (accAddressData accAddressData) Compare(listable traits.Listable) int { if err != nil { panic(err) } + if sanitizedAccAddressData, err := accAddressData.Sanitize(); err != nil { + accAddressData.Value = sanitizedAccAddressData.(data.AccAddressData).Get() + } + if sanitizedCompareAccAddressData, err := compareAccAddressData.Sanitize(); err != nil { + compareAccAddressData.Value = sanitizedCompareAccAddressData.(data.AccAddressData).Get() + } return bytes.Compare(accAddressData.Value.Bytes(), compareAccAddressData.Value.Bytes()) } @@ -56,6 +62,13 @@ func (accAddressData accAddressData) Get() sdkTypes.AccAddress { return accAddressData.Value } +func (accAddressData accAddressData) Sanitize() (data.Data, error) { + if accAddressData.Value.Empty() { + return accAddressData.ZeroValue(), nil + } + return accAddressData, nil +} + func accAddressDataFromInterface(listable traits.Listable) (accAddressData, error) { switch value := listable.(type) { case accAddressData: diff --git a/schema/data/base/accAddressData_test.go b/schema/data/base/accAddressData_test.go index 7b8b25eaa..992cf3005 100644 --- a/schema/data/base/accAddressData_test.go +++ b/schema/data/base/accAddressData_test.go @@ -85,6 +85,8 @@ func Test_accAddressData_Compare(t *testing.T) { args args want int }{ + {"-ve nil", fields{}, args{NewAccAddressData(nil)}, 0}, + {"+ve with nil", fields{types.AccAddress{}}, args{NewAccAddressData(nil)}, 0}, {"-ve empty String", fields{fromAccAddress}, args{accAddressData{}}, 1}, {"+ve", fields{fromAccAddress}, args{accAddressData{fromAccAddress}}, 0}, } diff --git a/schema/data/base/booleanData.go b/schema/data/base/booleanData.go index 52578add6..66407a106 100644 --- a/schema/data/base/booleanData.go +++ b/schema/data/base/booleanData.go @@ -64,6 +64,10 @@ func (booleanData booleanData) Get() bool { return booleanData.Value } +func (booleanData booleanData) Sanitize() (data.Data, error) { + return booleanData, nil +} + func booleanDataFromInterface(listable traits.Listable) (booleanData, error) { switch value := listable.(type) { case booleanData: diff --git a/schema/data/base/booleanData_test.go b/schema/data/base/booleanData_test.go index c07311928..1306f94da 100644 --- a/schema/data/base/booleanData_test.go +++ b/schema/data/base/booleanData_test.go @@ -35,31 +35,6 @@ func TestNewBooleanData(t *testing.T) { } } -func TestBooleanDataFromInterface(t *testing.T) { - type args struct { - dataString data.Data - } - tests := []struct { - name string - args args - want data.Data - wantErr assert.ErrorAssertionFunc - }{ - {"-ve", args{NewBooleanData(false)}, booleanData{false}, assert.NoError}, - {"+ve", args{NewBooleanData(true)}, booleanData{true}, assert.NoError}, - {"-ve", args{NewStringData("test")}, booleanData{false}, assert.Error}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := booleanDataFromInterface(tt.args.dataString) - if !tt.wantErr(t, err, fmt.Sprintf("booleanDataFromInterface(%v)", tt.args.dataString)) { - return - } - assert.Equalf(t, tt.want, got, "booleanDataFromInterface(%v)", tt.args.dataString) - }) - } -} - func Test_booleanDataFromInterface(t *testing.T) { type args struct { listable traits.Listable @@ -99,6 +74,7 @@ func Test_booleanData_Compare(t *testing.T) { args args want int }{ + {"+ve with nil", fields{}, args{booleanData{}}, 0}, {"+ve", fields{false}, args{booleanData{true}}, -1}, {"+ve", fields{true}, args{booleanData{false}}, 1}, {"+ve", fields{false}, args{booleanData{false}}, 0}, diff --git a/schema/data/base/decData.go b/schema/data/base/decData.go index 0bc4bbb87..0c18d3e2b 100644 --- a/schema/data/base/decData.go +++ b/schema/data/base/decData.go @@ -29,6 +29,13 @@ func (decData decData) Compare(listable traits.Listable) int { panic(err) } + if sanitizedDecData, err := decData.Sanitize(); err != nil { + decData.Value = sanitizedDecData.(data.DecData).Get() + } + if sanitizedDecData, err := compareDecData.Sanitize(); err != nil { + compareDecData.Value = sanitizedDecData.(data.DecData).Get() + } + if decData.Value.GT(compareDecData.Value) { return 1 } else if decData.Value.LT(compareDecData.Value) { @@ -41,6 +48,9 @@ func (decData decData) String() string { return decData.Value.String() } func (decData decData) Bytes() []byte { + if sanitizedDecData, err := decData.Sanitize(); err != nil { + decData.Value = sanitizedDecData.(data.DecData).Get() + } return decData.Value.Bytes() } func (decData decData) GetType() ids.StringID { @@ -60,6 +70,13 @@ func (decData decData) Get() sdkTypes.Dec { return decData.Value } +func (decData decData) Sanitize() (data.Data, error) { + if decData.Value.Int == nil { + return decData.ZeroValue(), constants.MetaDataError + } + return decData, nil +} + func decDataFromInterface(listable traits.Listable) (decData, error) { switch value := listable.(type) { case decData: diff --git a/schema/data/base/decData_test.go b/schema/data/base/decData_test.go index ddcdb8d21..492ad330e 100644 --- a/schema/data/base/decData_test.go +++ b/schema/data/base/decData_test.go @@ -203,11 +203,7 @@ func Test_decData_GetID(t *testing.T) { decData := decData{ Value: tt.fields.Value, } - if tt.wantPanic { - require.Panics(t, func() { - decData.GetID() - }) - } else if got := decData.GetID(); !reflect.DeepEqual(got, tt.want) { + if got := decData.GetID(); !reflect.DeepEqual(got, tt.want) { t.Errorf("GetID() = %v, want %v", got, tt.want) } }) diff --git a/schema/data/base/heightData.go b/schema/data/base/heightData.go index fedea92bc..147152c3e 100644 --- a/schema/data/base/heightData.go +++ b/schema/data/base/heightData.go @@ -32,6 +32,13 @@ func (heightData heightData) Compare(listable traits.Listable) int { panic(err) } + if sanitizedHeightData, err := heightData.Sanitize(); err != nil { + heightData.Value = sanitizedHeightData.(data.HeightData).Get() + } + if sanitizedCompareHeightData, err := compareHeightData.Sanitize(); err != nil { + compareHeightData.Value = sanitizedCompareHeightData.(data.HeightData).Get() + } + return heightData.Value.Compare(compareHeightData.Value) } func (heightData heightData) String() string { @@ -56,9 +63,19 @@ func (heightData heightData) GenerateHashID() ids.HashID { return baseIDs.GenerateHashID(heightData.Bytes()) } func (heightData heightData) Get() types.Height { + if sanitizedHeightData, err := heightData.Sanitize(); err != nil { + return sanitizedHeightData.(data.HeightData).Get() + } return heightData.Value } +func (heightData heightData) Sanitize() (data.Data, error) { + if heightData.Value == nil { + return heightData.ZeroValue(), constants.MetaDataError + } + return heightData, nil +} + func heightDataFromInterface(listable traits.Listable) (heightData, error) { switch value := listable.(type) { case heightData: diff --git a/schema/data/base/heightData_test.go b/schema/data/base/heightData_test.go index f50bb03e4..0b46f6b77 100644 --- a/schema/data/base/heightData_test.go +++ b/schema/data/base/heightData_test.go @@ -92,7 +92,7 @@ func Test_heightData_Compare(t *testing.T) { args args want int }{ - + {"+ve with nil", fields{}, args{heightData{}}, 0}, {"Test for Equal case", fields{baseTypes.NewHeight(100)}, args{heightData{baseTypes.NewHeight(100)}}, 0}, {"Test for LT case", fields{baseTypes.NewHeight(0)}, args{heightData{baseTypes.NewHeight(100)}}, -1}, {"Test for GT case", fields{baseTypes.NewHeight(100)}, args{heightData{baseTypes.NewHeight(0)}}, 1}, @@ -118,7 +118,7 @@ func Test_heightData_GenerateHashID(t *testing.T) { fields fields want ids.HashID }{ - + {"+ve with nil", fields{}, baseIDs.GenerateHashID()}, {"Test for zero value", fields{baseTypes.NewHeight(-1)}, baseIDs.GenerateHashID()}, {"Test for -ve value", fields{baseTypes.NewHeight(-100)}, baseIDs.GenerateHashID()}, {"Test for +ve value", fields{baseTypes.NewHeight(100)}, baseIDs.GenerateHashID(heightData{baseTypes.NewHeight(100)}.Bytes())}, @@ -144,7 +144,7 @@ func Test_heightData_Get(t *testing.T) { fields fields want types.Height }{ - + {"+ve with nil", fields{}, baseTypes.NewHeight(-1)}, {"Test for zero value", fields{baseTypes.NewHeight(0)}, heightData{baseTypes.NewHeight(0)}.Value}, {"Test for +ve value", fields{baseTypes.NewHeight(100)}, heightData{baseTypes.NewHeight(100)}.Value}, {"Test for -ve value", fields{baseTypes.NewHeight(-100)}, heightData{baseTypes.NewHeight(-100)}.Value}, @@ -273,7 +273,7 @@ func Test_heightData_Bytes(t *testing.T) { want []byte }{ {"+ve with ZeroHeight", fields{baseTypes.NewHeight(-1)}, baseTypes.NewHeight(-1).Bytes()}, - {"+ve with nil", fields{nil}, []byte{}}, + {"+ve with nil", fields{nil}, baseTypes.NewHeight(-1).Bytes()}, {"+ve", fields{baseTypes.NewHeight(100)}, baseTypes.NewHeight(100).Bytes()}, {"+ve with max int", fields{baseTypes.NewHeight(int64(^uint(0) >> 1))}, baseTypes.NewHeight(int64(^uint(0) >> 1)).Bytes()}, } diff --git a/schema/data/base/idData.go b/schema/data/base/idData.go index 129fe5484..496a33017 100644 --- a/schema/data/base/idData.go +++ b/schema/data/base/idData.go @@ -29,12 +29,26 @@ func (idData idData) Compare(listable traits.Listable) int { panic(err) } + if sanitizedIDData, err := idData.Sanitize(); err != nil { + idData.Value = sanitizedIDData.(data.IDData).Get() + } + + if sanitizedCompareIDData, err := compareIDData.Sanitize(); err != nil { + compareIDData.Value = sanitizedCompareIDData.(data.IDData).Get() + } + return bytes.Compare(idData.Value.Bytes(), compareIDData.Value.Bytes()) } func (idData idData) String() string { + if sanitizedIDData, err := idData.Sanitize(); err != nil { + idData.Value = sanitizedIDData.(data.IDData).Get() + } return idData.Value.String() } func (idData idData) Bytes() []byte { + if sanitizedIDData, err := idData.Sanitize(); err != nil { + idData.Value = sanitizedIDData.(data.IDData).Get() + } return idData.Value.Bytes() } func (idData idData) GetType() ids.StringID { @@ -47,9 +61,19 @@ func (idData idData) GenerateHashID() ids.HashID { return baseIDs.GenerateHashID(idData.Bytes()) } func (idData idData) Get() ids.ID { + if sanitizedIDData, err := idData.Sanitize(); err != nil { + return sanitizedIDData.(data.IDData).Get() + } return idData.Value } +func (idData idData) Sanitize() (data.Data, error) { + if idData.Value == nil { + return idData.ZeroValue(), constants.MetaDataError + } + return idData, nil +} + func idDataFromInterface(listable traits.Listable) (idData, error) { switch value := listable.(type) { case idData: diff --git a/schema/data/base/idData_test.go b/schema/data/base/idData_test.go index f7c7af404..aa2801f16 100644 --- a/schema/data/base/idData_test.go +++ b/schema/data/base/idData_test.go @@ -47,7 +47,6 @@ func Test_idDataFromInterface(t *testing.T) { }{ {"+ve", args{NewIDData(NewStringData("Data"))}, idData{NewStringData("Data")}, assert.NoError}, {"+ve", args{NewIDData(NewStringData(""))}, idData{NewStringData("")}, assert.NoError}, - {"-ve", args{NewStringData("Data")}, idData{}, assert.Error}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -69,6 +68,7 @@ func Test_idData_Bytes(t *testing.T) { fields fields want []byte }{ + {"+ve with nil", fields{nil}, []byte{}}, {"+ve", fields{NewStringData("")}, []byte{}}, {"+ve", fields{NewStringData("Data")}, NewStringData("Data").Bytes()}, } @@ -95,6 +95,7 @@ func Test_idData_Compare(t *testing.T) { args args want int }{ + {"+ve with nil", fields{nil}, args{idData{}}, 0}, {"+ve", fields{NewStringData("Data")}, args{idData{NewStringData("Data")}}, 0}, {"+ve", fields{NewStringData("Data")}, args{idData{NewStringData("0")}}, 1}, } @@ -139,6 +140,7 @@ func Test_idData_Get(t *testing.T) { fields fields want ids.ID }{ + {"+ve with nil", fields{nil}, baseIDs.NewStringID("")}, {"+ve", fields{NewStringData("Data")}, NewStringData("Data")}, {"+ve", fields{NewStringData("")}, NewStringData("")}, } @@ -203,6 +205,7 @@ func Test_idData_String(t *testing.T) { fields fields want string }{ + {"+ve with nil", fields{nil}, ""}, {"+ve", fields{NewStringData("Data")}, "Data"}, } for _, tt := range tests { diff --git a/schema/data/base/listData.go b/schema/data/base/listData.go index 30385e3c8..6d21f2f5e 100644 --- a/schema/data/base/listData.go +++ b/schema/data/base/listData.go @@ -24,17 +24,29 @@ type listData struct { var _ data.ListData = (*listData)(nil) func (listData listData) Get() []data.Data { + if sanitizedData, err := listData.Sanitize(); err != nil { + listData.Value = base.NewDataList(sanitizedData.(data.ListData).Get()...) + } return listData.Value.GetList() } -func (listData listData) Search(data data.Data) (int, bool) { - return listData.Value.Search(data) +func (listData listData) Search(_data data.Data) (int, bool) { + if sanitizedData, err := listData.Sanitize(); err != nil { + listData.Value = base.NewDataList(sanitizedData.(data.ListData).Get()...) + } + return listData.Value.Search(_data) } -func (listData listData) Add(data ...data.Data) data.ListData { - listData.Value = listData.Value.Add(data...) +func (listData listData) Add(_data ...data.Data) data.ListData { + if sanitizedData, err := listData.Sanitize(); err != nil { + listData.Value = base.NewDataList(sanitizedData.(data.ListData).Get()...) + } + listData.Value = listData.Value.Add(_data...) return listData } -func (listData listData) Remove(data ...data.Data) data.ListData { - listData.Value = listData.Value.Remove(data...) +func (listData listData) Remove(_data ...data.Data) data.ListData { + if sanitizedData, err := listData.Sanitize(); err != nil { + listData.Value = base.NewDataList(sanitizedData.(data.ListData).Get()...) + } + listData.Value = listData.Value.Remove(_data...) return listData } func (listData listData) GetID() ids.DataID { @@ -59,6 +71,9 @@ func (listData listData) String() string { return stringUtilities.JoinListStrings(dataStrings...) } func (listData listData) Bytes() []byte { + if sanitizedData, err := listData.Sanitize(); err != nil { + listData.Value = base.NewDataList(sanitizedData.(data.ListData).Get()...) + } bytesList := make([][]byte, listData.Value.Size()) for i, datum := range listData.Value.GetList() { @@ -83,6 +98,15 @@ func (listData listData) GenerateHashID() ids.HashID { return baseIDs.GenerateHashID(listData.Bytes()) } + +func (listData listData) Sanitize() (data.Data, error) { + //TODO implement me + if listData.Value == nil { + return listData.ZeroValue(), errorConstants.MetaDataError + } + return listData, nil +} + func listDataFromInterface(listable traits.Listable) (listData, error) { switch value := listable.(type) { case listData: diff --git a/schema/data/base/listData_test.go b/schema/data/base/listData_test.go index e93d25c25..b7520a8e1 100644 --- a/schema/data/base/listData_test.go +++ b/schema/data/base/listData_test.go @@ -24,9 +24,10 @@ import ( "github.com/AssetMantle/modules/schema/traits" ) -var fromAddress = "cosmos1x53dugvr4xvew442l9v2r5x7j8gfvged2zk5ef" - -var accAddress = NewAccAddressData(sdkTypes.AccAddress(fromAddress)).String() +var ( + fromAddress = "cosmos1x53dugvr4xvew442l9v2r5x7j8gfvged2zk5ef" + accAddress = NewAccAddressData(sdkTypes.AccAddress(fromAddress)).String() +) func TestListDataPrototype(t *testing.T) { type args struct { @@ -110,6 +111,7 @@ func Test_listData_Add(t *testing.T) { want data.ListData wantFailure bool }{ + {"+ve with nil", fields{nil}, args{[]data.Data{nil}}, listData{baseLists.NewDataList(nil)}, false}, {"+ve for multiple ids", fields{baseLists.NewDataList(NewStringData("Data"), NewStringData("Data"), NewStringData("Data"))}, args{}, listData{baseLists.NewDataList(NewStringData("Data"), NewStringData("Data"), NewStringData("Data"))}, false}, {"+ve for multiple ids/nils", fields{baseLists.NewDataList(NewStringData("Data"), NewStringData(""), NewStringData("Data"))}, args{}, listData{baseLists.NewDataList(NewStringData("Data"), NewStringData("Data"), NewStringData(""))}, false}, {"+ve for some id", fields{baseLists.NewDataList(NewStringData("Data"))}, args{}, listData{baseLists.NewDataList(NewStringData("Data"))}, false}, @@ -140,6 +142,8 @@ func Test_listData_Bytes(t *testing.T) { fields fields want []byte }{ + {"+ve with nil", fields{nil}, []byte{}}, + {"+ve with nil data", fields{baseLists.NewDataList()}, []byte{}}, {"+ve for some id", fields{baseLists.NewDataList(NewStringData("Data"))}, NewStringData("Data").Bytes()}, // for a single data no loop iteration is required, so directly it's byte should match {"+ve for multiple ids", fields{baseLists.NewDataList(NewStringData("Data"), NewStringData("Data1"))}, bytes.Join([][]byte{NewStringData("Data").Bytes(), NewStringData("Data1").Bytes()}, nil)}, {"+ve for empty String", fields{baseLists.NewDataList(NewStringData(""))}, []byte(nil)}, @@ -168,6 +172,7 @@ func Test_listData_Compare(t *testing.T) { want int wantPanic bool }{ + {"+ve with nil", fields{nil}, args{listData{}}, 0, false}, {"+ve for some id", fields{baseLists.NewDataList(NewStringData("Data"))}, args{listData{baseLists.NewDataList(NewStringData("Data"))}}, 0, false}, {"+ve for empty String", fields{baseLists.NewDataList(NewStringData(""))}, args{listData{baseLists.NewDataList(NewStringData("Data"))}}, -1, false}, {"Test for Equal case", fields{baseLists.NewDataList(NewStringData(fromAddress))}, args{listData{baseLists.NewDataList(NewStringData(fromAddress))}}, 0, false}, @@ -226,6 +231,7 @@ func Test_listData_Get(t *testing.T) { fields fields want []data.Data }{ + {"+ve with nil", fields{nil}, []data.Data{}}, {"+ve for some id", fields{baseLists.NewDataList(NewStringData("Data"))}, listData{baseLists.NewDataList(NewStringData("Data"))}.Value.GetList()}, {"+ve for empty String", fields{baseLists.NewDataList(NewStringData(""))}, listData{baseLists.NewDataList(NewStringData(""))}.Value.GetList()}, } @@ -296,6 +302,7 @@ func Test_listData_Remove(t *testing.T) { args args want data.ListData }{ + {"+ve with nil", fields{nil}, args{[]data.Data{NewStringData("Data")}}, listData{baseLists.NewDataList()}}, {"+ve for empty String", fields{baseLists.NewDataList(NewStringData(""))}, args{[]data.Data{}}, listData{baseLists.NewDataList(NewStringData(""))}}, {"+ve for empty String & removing it", fields{baseLists.NewDataList(NewStringData(""))}, args{[]data.Data{NewStringData("")}}, listData{baseLists.NewDataList()}}, {"+ve ", fields{baseLists.NewDataList(NewStringData("data"))}, args{[]data.Data{NewStringData("data")}}, listData{baseLists.NewDataList()}}, @@ -318,11 +325,11 @@ func Test_listData_Search(t *testing.T) { data data.Data } tests := []struct { - name string - fields fields - args args - want int - want1 bool + name string + fields fields + args args + want int + wantError bool }{ {"+ve for some id", fields{baseLists.NewDataList(NewStringData("Data"))}, args{NewStringData("Data")}, 0, true}, {"+ve for empty String", fields{baseLists.NewDataList([]data.Data{NewStringData("Data"), NewStringData("")}...)}, args{NewStringData("")}, 0, true}, @@ -335,7 +342,7 @@ func Test_listData_Search(t *testing.T) { } got, got1 := listData.Search(tt.args.data) assert.Equalf(t, tt.want, got, "Search(%v)", tt.args.data) - assert.Equalf(t, tt.want1, got1, "Search(%v)", tt.args.data) + assert.Equalf(t, tt.wantError, got1, "Search(%v)", tt.args.data) }) } } diff --git a/schema/data/base/stringData.go b/schema/data/base/stringData.go index 3fad6e21f..e1e0f9b6a 100644 --- a/schema/data/base/stringData.go +++ b/schema/data/base/stringData.go @@ -50,6 +50,10 @@ func (stringData stringData) Get() string { return stringData.Value } +func (stringData stringData) Sanitize() (data.Data, error) { + return stringData, nil +} + func stringDataFromInterface(listable traits.Listable) (stringData, error) { switch value := listable.(type) { case stringData: diff --git a/schema/data/base/stringData_test.go b/schema/data/base/stringData_test.go index 69aa1d753..d5ed8b4d2 100644 --- a/schema/data/base/stringData_test.go +++ b/schema/data/base/stringData_test.go @@ -71,6 +71,8 @@ func Test_stringData_Bytes(t *testing.T) { want []byte }{ {"+ve data", fields{"data"}, []byte("data")}, + {"+ve with empty string", fields{""}, []byte("")}, + {"+ve with nil", fields{}, []byte{}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -95,6 +97,7 @@ func Test_stringData_Compare(t *testing.T) { args args want int }{ + {"+ve with nil and empty string", fields{}, args{stringData{""}}, 0}, {"+ve data", fields{"data"}, args{stringData{"data"}}, 0}, {"data with special char", fields{"data"}, args{stringData{"data_!@#$%^&*("}}, -1}, {"empty string", fields{"data"}, args{stringData{""}}, 1}, @@ -118,6 +121,7 @@ func Test_stringData_GenerateHashID(t *testing.T) { fields fields want ids.HashID }{ + {"+ve with nil and empty string", fields{}, baseIDs.GenerateHashID(stringData{}.Bytes())}, {"+ve data", fields{"data"}, baseIDs.GenerateHashID(stringData{"data"}.Bytes())}, {"data with special char", fields{"data_!@#$%^&*("}, baseIDs.GenerateHashID(stringData{"data_!@#$%^&*("}.Bytes())}, {"empty string", fields{""}, baseIDs.GenerateHashID(stringData{""}.Bytes())}, diff --git a/schema/data/data.go b/schema/data/data.go index efcc46e6c..758ab3ef4 100644 --- a/schema/data/data.go +++ b/schema/data/data.go @@ -21,5 +21,9 @@ type Data interface { // * Returns ID of empty bytes when the value of Data is that Data type's zero value GenerateHashID() ids.HashID + // Sanitize returns a sanitized version of the Data with all invalid values replaced with the Data type's zero value and all valid values left unchanged + // returns error and data + Sanitize() (Data, error) + traits.Listable } diff --git a/schema/data/utilities/string.go b/schema/data/utilities/string.go index 24b8a9d1c..d6c1aafd6 100644 --- a/schema/data/utilities/string.go +++ b/schema/data/utilities/string.go @@ -21,7 +21,7 @@ func readAccAddressData(dataString string) (data.AccAddressData, error) { return base.AccAddressDataPrototype(), nil } - accAddress, err := sdkTypes.AccAddressFromBech32(dataString) + accAddress, err := sdkTypes.AccAddressFromBech32(sanitizeDataString(dataString)) if err != nil { return base.AccAddressDataPrototype(), err } @@ -33,7 +33,7 @@ func readBooleanData(dataString string) (data.BooleanData, error) { return base.BooleanDataPrototype(), nil } - Bool, err := strconv.ParseBool(dataString) + Bool, err := strconv.ParseBool(sanitizeDataString(dataString)) if err != nil { return base.BooleanDataPrototype(), err } @@ -45,7 +45,7 @@ func readDecData(dataString string) (data.DecData, error) { return base.DecDataPrototype(), nil } - dec, err := sdkTypes.NewDecFromStr(dataString) + dec, err := sdkTypes.NewDecFromStr(sanitizeDataString(dataString)) if err != nil { return base.DecDataPrototype(), err } @@ -57,7 +57,7 @@ func readHeightData(dataString string) (data.HeightData, error) { return base.HeightDataPrototype(), nil } - height, err := strconv.ParseInt(dataString, 10, 64) + height, err := strconv.ParseInt(sanitizeDataString(dataString), 10, 64) if err != nil { return base.HeightDataPrototype(), err } @@ -71,14 +71,14 @@ func readIDData(dataString string) (data.IDData, error) { return base.IDDataPrototype(), nil } - return base.NewIDData(baseIDs.NewStringID(dataString)), nil + return base.NewIDData(baseIDs.NewStringID(sanitizeDataString(dataString))), nil } func readListData(dataString string) (data.ListData, error) { if dataString == "" { return base.ListDataPrototype(), nil } - dataStringList := stringUtilities.SplitListString(dataString) + dataStringList := stringUtilities.SplitListString(sanitizeDataString(dataString)) dataList := make([]data.Data, len(dataStringList)) for i, datumString := range dataStringList { @@ -96,13 +96,13 @@ func readStringData(dataString string) (data.StringData, error) { if dataString == "" { return base.StringDataPrototype(), nil } - return base.NewStringData(dataString), nil + return base.NewStringData(sanitizeDataString(dataString)), nil } func joinDataTypeAndValueStrings(dataType, dataValue string) string { return strings.Join([]string{dataType, dataValue}, dataConstants.DataTypeAndValueSeparator) } func splitDataTypeAndValueStrings(dataTypeAndValueString string) (dataType, dataValue string) { - if dataTypeAndValue := strings.SplitN(dataTypeAndValueString, dataConstants.DataTypeAndValueSeparator, 2); len(dataTypeAndValue) < 2 { + if dataTypeAndValue := strings.SplitN(sanitizeDataString(dataTypeAndValueString), dataConstants.DataTypeAndValueSeparator, 2); len(dataTypeAndValue) < 2 { return "", "" } else { return dataTypeAndValue[0], dataTypeAndValue[1] @@ -112,7 +112,7 @@ func splitDataTypeAndValueStrings(dataTypeAndValueString string) (dataType, data // ReadData // CHECK-TODO if data type added see if added here func ReadData(dataString string) (data.Data, error) { - dataTypeString, dataValueString := splitDataTypeAndValueStrings(dataString) + dataTypeString, dataValueString := splitDataTypeAndValueStrings(sanitizeDataString(dataString)) if dataTypeString != "" { var Data data.Data @@ -146,3 +146,7 @@ func ReadData(dataString string) (data.Data, error) { return nil, errorConstants.IncorrectFormat } + +func sanitizeDataString(dataString string) string { + return strings.ReplaceAll(dataString, " ", "") +} diff --git a/schema/data/utilities/string_test.go b/schema/data/utilities/string_test.go index a6504f806..fc426660f 100644 --- a/schema/data/utilities/string_test.go +++ b/schema/data/utilities/string_test.go @@ -35,12 +35,16 @@ func TestReadData(t *testing.T) { want data.Data wantErr bool }{ + {"+ve with space in dataString", args{"L|A|cosmos1pkkayn066msg6kn33wnl5srhdt3tnu2vzasz9c, A|cosmos1x53dugvr4xvew442l9v2r5x7j8gfvged2zk5ef"}, base.NewListData(baseLists.NewDataList(dataList...)), false}, + {"+ve with space in dataString", args{"L|A|cosmos1pkkayn066msg6kn33wnl5srhdt3tnu2vzasz9c,A| cosmos1x53dugvr4xvew442l9v2r5x7j8gfvged2zk5ef"}, base.NewListData(baseLists.NewDataList(dataList...)), false}, {"String Data", args{"S|newFact"}, base.NewStringData("newFact"), false}, {"-ve Unknown Data", args{"SomeRandomData"}, nil, true}, {"List Data", args{"L|A|cosmos1pkkayn066msg6kn33wnl5srhdt3tnu2vzasz9c,A|cosmos1x53dugvr4xvew442l9v2r5x7j8gfvged2zk5ef"}, base.NewListData(baseLists.NewDataList(dataList...)), false}, {"List Data empty list", args{"L|"}, base.NewListData(baseLists.NewDataList()), false}, {"Id Data", args{"I|data"}, base.NewIDData(baseIDs.NewStringID("data")), false}, {"Height Data", args{"H|100"}, base.NewHeightData(baseTypes.NewHeight(100)), false}, + {"Height Data with space", args{" H| 100"}, base.NewHeightData(baseTypes.NewHeight(100)), false}, + {"Height Data with space", args{"H |100"}, base.NewHeightData(baseTypes.NewHeight(100)), false}, {"Dec Data", args{"D|100"}, base.NewDecData(types.NewDec(100)), false}, {"Bool Data", args{"B|true"}, base.NewBooleanData(true), false}, {"AccAddress data", args{"A|cosmos1pkkayn066msg6kn33wnl5srhdt3tnu2vzasz9c"}, base.NewAccAddressData(fromAccAddress), false}, diff --git a/schema/documents/base/classification_test.go b/schema/documents/base/classification_test.go index cc1253659..eed205941 100644 --- a/schema/documents/base/classification_test.go +++ b/schema/documents/base/classification_test.go @@ -13,11 +13,13 @@ import ( baseQualified "github.com/AssetMantle/modules/schema/qualified/base" ) -func Test_new_Classification(t *testing.T) { - immutables := baseQualified.NewImmutables(baseLists.NewPropertyList(baseProperties.NewMesaProperty(baseIDs.NewStringID("ID1"), baseData.NewStringData("ImmutableData")))) - mutables := baseQualified.NewMutables(baseLists.NewPropertyList(baseProperties.NewMesaProperty(baseIDs.NewStringID("ID2"), baseData.NewStringData("MutableData")))) +var ( + immutables = baseQualified.NewImmutables(baseLists.NewPropertyList(baseProperties.NewMesaProperty(baseIDs.NewStringID("ID1"), baseData.NewStringData("ImmutableData")))) + mutables = baseQualified.NewMutables(baseLists.NewPropertyList(baseProperties.NewMesaProperty(baseIDs.NewStringID("ID2"), baseData.NewStringData("MutableData")))) + testClassification = NewClassification(immutables, mutables) +) - testClassification := NewClassification(immutables, mutables) +func Test_new_Classification(t *testing.T) { type fields struct { immutables qualified.Immutables mutables qualified.Mutables diff --git a/schema/documents/base/document.go b/schema/documents/base/document.go index 01676e223..ef414891b 100644 --- a/schema/documents/base/document.go +++ b/schema/documents/base/document.go @@ -6,9 +6,11 @@ package base import ( "github.com/AssetMantle/modules/schema/documents" "github.com/AssetMantle/modules/schema/ids" - "github.com/AssetMantle/modules/schema/ids/base" + baseIDs "github.com/AssetMantle/modules/schema/ids/base" + baseLists "github.com/AssetMantle/modules/schema/lists/base" "github.com/AssetMantle/modules/schema/properties" "github.com/AssetMantle/modules/schema/qualified" + baseQualified "github.com/AssetMantle/modules/schema/qualified/base" ) type document struct { @@ -20,12 +22,20 @@ type document struct { var _ documents.Document = (*document)(nil) func (document document) GenerateHashID() ids.HashID { - return base.GenerateHashID(document.GetClassificationID().Bytes(), document.GetImmutables().GenerateHashID().Bytes()) + return baseIDs.GenerateHashID(document.GetClassificationID().Bytes(), document.GetImmutables().GenerateHashID().Bytes()) } func (document document) GetClassificationID() ids.ClassificationID { + if document.ClassificationID == nil { + return baseIDs.PrototypeClassificationID() + } return document.ClassificationID } func (document document) GetProperty(propertyID ids.PropertyID) properties.Property { + if sanitizedDocument, err := document.Sanitize(); err == nil { + document.Immutables = sanitizedDocument.(documents.Document).GetImmutables() + document.Mutables = sanitizedDocument.(documents.Document).GetMutables() + document.ClassificationID = sanitizedDocument.(documents.Document).GetClassificationID() + } if property := document.Immutables.GetImmutablePropertyList().GetProperty(propertyID); property != nil { return property } else if property := document.Mutables.GetMutablePropertyList().GetProperty(propertyID); property != nil { @@ -35,18 +45,42 @@ func (document document) GetProperty(propertyID ids.PropertyID) properties.Prope } } func (document document) GetImmutables() qualified.Immutables { + if document.Immutables == nil { + return baseQualified.NewImmutables(baseLists.NewPropertyList()) + } return document.Immutables } func (document document) GetMutables() qualified.Mutables { + if document.Mutables == nil { + return baseQualified.NewMutables(baseLists.NewPropertyList()) + } return document.Mutables } // TODO write test case func (document document) Mutate(propertyList ...properties.Property) documents.Document { + if sanitizedDocument, err := document.Sanitize(); err == nil { + document.Immutables = sanitizedDocument.(documents.Document).GetImmutables() + document.Mutables = sanitizedDocument.(documents.Document).GetMutables() + document.ClassificationID = sanitizedDocument.(documents.Document).GetClassificationID() + } document.Mutables = document.Mutables.Mutate(propertyList...) return document } +func (document document) Sanitize() (documents.Document, error) { + if document.ClassificationID == nil { + document.ClassificationID = baseIDs.PrototypeClassificationID() + } + if document.Immutables == nil { + document.Immutables = baseQualified.NewImmutables(baseLists.NewPropertyList()) + } + if document.Mutables == nil { + document.Mutables = baseQualified.NewMutables(baseLists.NewPropertyList()) + } + return document, nil +} + func NewDocument(classificationID ids.ClassificationID, immutables qualified.Immutables, mutables qualified.Mutables) documents.Document { return document{ ClassificationID: classificationID, diff --git a/schema/documents/base/document_test.go b/schema/documents/base/document_test.go index 39373d6b5..305390089 100644 --- a/schema/documents/base/document_test.go +++ b/schema/documents/base/document_test.go @@ -7,8 +7,6 @@ import ( "reflect" "testing" - "github.com/stretchr/testify/require" - baseData "github.com/AssetMantle/modules/schema/data/base" "github.com/AssetMantle/modules/schema/documents" "github.com/AssetMantle/modules/schema/ids" @@ -68,10 +66,10 @@ func Test_document_GetClassificationID(t *testing.T) { want ids.ClassificationID }{ {"+ve", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, classificationID}, - {"+ve with nil classificationID", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, nil}, + {"+ve with nil classificationID", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, baseIDs.PrototypeClassificationID()}, {"+ve with nil immutables", fields{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}, classificationID}, {"+ve with nil mutables", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: nil}, classificationID}, - {"+ve with all nil", fields{}, nil}, + {"+ve with all nil", fields{}, baseIDs.PrototypeClassificationID()}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -101,9 +99,9 @@ func Test_document_GetImmutables(t *testing.T) { }{ {"+ve", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, testImmutables}, {"+ve with nil classificationID", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, testImmutables}, - {"+ve with nil immutables", fields{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}, nil}, + {"+ve with nil immutables", fields{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}, baseQualified.NewImmutables(baseLists.NewPropertyList())}, {"+ve with nil mutables", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: nil}, testImmutables}, - {"+ve with all nil", fields{}, nil}, + {"+ve with all nil", fields{}, baseQualified.NewImmutables(baseLists.NewPropertyList())}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -134,8 +132,8 @@ func Test_document_GetMutables(t *testing.T) { {"+ve", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, testMutables}, {"+ve with nil classificationID", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, testMutables}, {"+ve with nil immutables", fields{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}, testMutables}, - {"+ve with nil mutables", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: nil}, nil}, - {"+ve with all nil", fields{}, nil}, + {"+ve with nil mutables", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: nil}, baseQualified.NewMutables(baseLists.NewPropertyList())}, + {"+ve with all nil", fields{}, baseQualified.NewMutables(baseLists.NewPropertyList())}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -165,27 +163,24 @@ func Test_document_GetProperty(t *testing.T) { propertyID ids.PropertyID } tests := []struct { - name string - fields fields - args args - want properties.Property - wantPanic bool + name string + fields fields + args args + want properties.Property }{ // TODO: Update unit test after issue # fix - {"+ve for Immutable Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, args{testImmutablePropertyID}, testImmutables.GetImmutablePropertyList().GetProperty(testImmutablePropertyID), false}, - {"+ve with nil classificationID for Immutable Property", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, args{testImmutablePropertyID}, testImmutables.GetImmutablePropertyList().GetProperty(testImmutablePropertyID), false}, - {"+ve with nil immutables for Immutable Property", fields{ClassificationID: classificationID, Immutables: baseQualified.NewImmutables(baseLists.NewPropertyList()), Mutables: testMutables}, args{testImmutablePropertyID}, nil, false}, // TODO: panics for empty immutable struct - {"+ve with nil mutables for Immutable Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}, args{testImmutablePropertyID}, testImmutables.GetImmutablePropertyList().GetProperty(testImmutablePropertyID), false}, - {"+ve with all nil", fields{nil, baseQualified.NewImmutables(baseLists.NewPropertyList()), baseQualified.NewMutables(baseLists.NewPropertyList())}, args{testImmutablePropertyID}, nil, false}, // TODO: panics for empty immutable struct - {"+ve for Mutable Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, args{testMutablePropertyID}, testMutables.GetMutablePropertyList().GetProperty(testMutablePropertyID), false}, - {"+ve with nil classificationID for Mutable Property", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, args{testMutablePropertyID}, testMutables.GetMutablePropertyList().GetProperty(testMutablePropertyID), false}, - {"+ve with nil immutables for Mutable Property", fields{ClassificationID: classificationID, Immutables: baseQualified.NewImmutables(baseLists.NewPropertyList()), Mutables: testMutables}, args{testMutablePropertyID}, testMutables.GetMutablePropertyList().GetProperty(testMutablePropertyID), false}, // TODO: panics for empty immutable struct - {"+ve with nil mutables for Mutable Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}, args{testMutablePropertyID}, nil, false}, - // Panics for empty structs - // GetProperty() searches by traversing through Immutables and Mutables of a document, hence setting them as nil should cause a fatal panic - {"panic case nil immutables", fields{classificationID, nil, testMutables}, args{testImmutablePropertyID}, nil, true}, - {"panic case nil mutables", fields{classificationID, testImmutables, nil}, args{testImmutablePropertyID}, nil, true}, - {"panic case nil document", fields{nil, nil, nil}, args{testImmutablePropertyID}, nil, true}, + {"+ve for Immutable Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, args{testImmutablePropertyID}, testImmutables.GetImmutablePropertyList().GetProperty(testImmutablePropertyID)}, + {"+ve with nil classificationID for Immutable Property", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, args{testImmutablePropertyID}, testImmutables.GetImmutablePropertyList().GetProperty(testImmutablePropertyID)}, + {"+ve with nil immutables for Immutable Property", fields{ClassificationID: classificationID, Immutables: baseQualified.NewImmutables(baseLists.NewPropertyList()), Mutables: testMutables}, args{testImmutablePropertyID}, nil}, // TODO: panics for empty immutable struct + {"+ve with nil mutables for Immutable Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}, args{testImmutablePropertyID}, testImmutables.GetImmutablePropertyList().GetProperty(testImmutablePropertyID)}, + {"+ve with all nil", fields{nil, baseQualified.NewImmutables(baseLists.NewPropertyList()), baseQualified.NewMutables(baseLists.NewPropertyList())}, args{testImmutablePropertyID}, nil}, // TODO: panics for empty immutable struct + {"+ve for Mutable Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, args{testMutablePropertyID}, testMutables.GetMutablePropertyList().GetProperty(testMutablePropertyID)}, + {"+ve with nil classificationID for Mutable Property", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, args{testMutablePropertyID}, testMutables.GetMutablePropertyList().GetProperty(testMutablePropertyID)}, + {"+ve with nil immutables for Mutable Property", fields{ClassificationID: classificationID, Immutables: baseQualified.NewImmutables(baseLists.NewPropertyList()), Mutables: testMutables}, args{testMutablePropertyID}, testMutables.GetMutablePropertyList().GetProperty(testMutablePropertyID)}, // TODO: panics for empty immutable struct + {"+ve with nil mutables for Mutable Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}, args{testMutablePropertyID}, nil}, + {"+ve nil immutables", fields{classificationID, nil, testMutables}, args{testImmutablePropertyID}, nil}, + {"+ve nil mutables", fields{classificationID, testImmutables, nil}, args{testImmutablePropertyID}, nil}, + {"+ve nil document", fields{nil, nil, nil}, args{testImmutablePropertyID}, nil}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -194,11 +189,7 @@ func Test_document_GetProperty(t *testing.T) { Immutables: tt.fields.Immutables, Mutables: tt.fields.Mutables, } - if tt.wantPanic { - require.Panics(t, func() { - document.GetProperty(tt.args.propertyID) - }) - } else if got := document.GetProperty(tt.args.propertyID); !reflect.DeepEqual(got, tt.want) { + if got := document.GetProperty(tt.args.propertyID); !reflect.DeepEqual(got, tt.want) { t.Errorf("GetProperty() = %v, want %v", got, tt.want) } }) @@ -217,20 +208,19 @@ func Test_document_Mutate(t *testing.T) { propertyList []properties.Property } tests := []struct { - name string - fields fields - args args - want documents.Document - wantPanic bool + name string + fields fields + args args + want documents.Document }{ // TODO: Update after #59 fix https://github.com/AssetMantle/modules/issues/59 - {"+ve with no mutation", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, args{}, document{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, false}, - {"+ve with nil classificationID", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, args{[]properties.Property{testMutateProperty}}, document{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}.Mutate(testMutateProperty), false}, - {"+ve with nil immutables", fields{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}, args{[]properties.Property{testMutateProperty}}, document{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}.Mutate(testMutateProperty), false}, - {"+ve with nil mutables", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}, args{[]properties.Property{testMutateProperty}}, document{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}.Mutate(testMutateProperty), false}, // TODO: fix this - {"+ve with all nil", fields{nil, baseQualified.NewImmutables(baseLists.NewPropertyList()), baseQualified.NewMutables(baseLists.NewPropertyList())}, args{[]properties.Property{testMutateProperty}}, document{nil, baseQualified.NewImmutables(baseLists.NewPropertyList()), baseQualified.NewMutables(baseLists.NewPropertyList())}.Mutate(testMutateProperty), false}, // TODO: fix this - {"panic case nil document", fields{nil, nil, nil}, args{[]properties.Property{testMutateProperty}}, nil, true}, - {"panic case nil mutables", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: nil}, args{[]properties.Property{testMutateProperty}}, document{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}.Mutate(testMutateProperty), true}, // TODO: fix this + {"+ve with no mutation", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, args{}, document{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}}, + {"+ve with nil classificationID", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, args{[]properties.Property{testMutateProperty}}, document{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}.Mutate(testMutateProperty)}, + {"+ve with nil immutables", fields{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}, args{[]properties.Property{testMutateProperty}}, document{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}.Mutate(testMutateProperty)}, + {"+ve with nil mutables", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}, args{[]properties.Property{testMutateProperty}}, document{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}.Mutate(testMutateProperty)}, // TODO: fix this + {"+ve with all nil", fields{nil, baseQualified.NewImmutables(baseLists.NewPropertyList()), baseQualified.NewMutables(baseLists.NewPropertyList())}, args{[]properties.Property{testMutateProperty}}, document{nil, baseQualified.NewImmutables(baseLists.NewPropertyList()), baseQualified.NewMutables(baseLists.NewPropertyList())}.Mutate(testMutateProperty)}, // TODO: fix this + {"+ve nil document", fields{nil, nil, nil}, args{[]properties.Property{testMutateProperty}}, document{baseIDs.PrototypeClassificationID(), baseQualified.NewImmutables(baseLists.NewPropertyList()), baseQualified.NewMutables(baseLists.NewPropertyList())}}, + {"+ve nil mutables", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: nil}, args{[]properties.Property{testMutateProperty}}, document{ClassificationID: classificationID, Immutables: testImmutables, Mutables: baseQualified.NewMutables(baseLists.NewPropertyList())}}, // TODO: fix this } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -239,13 +229,41 @@ func Test_document_Mutate(t *testing.T) { Immutables: tt.fields.Immutables, Mutables: tt.fields.Mutables, } - if tt.wantPanic { - require.Panics(t, func() { - document.Mutate(tt.args.propertyList...) - }) - } else if got := document.Mutate(tt.args.propertyList...); !reflect.DeepEqual(got, tt.want) { + if got := document.Mutate(tt.args.propertyList...); !reflect.DeepEqual(got, tt.want) { t.Errorf("Mutate() = %v, want %v", got, tt.want) } }) } } + +func Test_document_GenerateHashID(t *testing.T) { + classificationID, testImmutables, testMutables, _ := createTestInput() + type fields struct { + ClassificationID ids.ClassificationID + Immutables qualified.Immutables + Mutables qualified.Mutables + } + tests := []struct { + name string + fields fields + want ids.HashID + }{ + {"+ve", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: testMutables}, baseIDs.GenerateHashID(classificationID.Bytes(), testImmutables.GenerateHashID().Bytes())}, + {"+ve with nil immutable Property", fields{ClassificationID: classificationID, Immutables: nil, Mutables: testMutables}, baseIDs.GenerateHashID(classificationID.Bytes(), baseQualified.NewImmutables(baseLists.NewPropertyList()).GenerateHashID().Bytes())}, + {"+ve with nil classificationID Property", fields{ClassificationID: nil, Immutables: testImmutables, Mutables: testMutables}, baseIDs.GenerateHashID(baseIDs.PrototypeClassificationID().Bytes(), testImmutables.GenerateHashID().Bytes())}, + {"+ve with nil immutable and classificationID Property", fields{ClassificationID: nil, Immutables: nil, Mutables: testMutables}, baseIDs.GenerateHashID(baseIDs.PrototypeClassificationID().Bytes(), baseQualified.NewImmutables(baseLists.NewPropertyList()).GenerateHashID().Bytes())}, + {"+ve with nil mutables Property", fields{ClassificationID: classificationID, Immutables: testImmutables, Mutables: nil}, baseIDs.GenerateHashID(classificationID.Bytes(), testImmutables.GenerateHashID().Bytes())}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + document := document{ + ClassificationID: tt.fields.ClassificationID, + Immutables: tt.fields.Immutables, + Mutables: tt.fields.Mutables, + } + if got := document.GenerateHashID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GenerateHashID() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/schema/documents/base/maintainer_test.go b/schema/documents/base/maintainer_test.go new file mode 100644 index 000000000..0efe49243 --- /dev/null +++ b/schema/documents/base/maintainer_test.go @@ -0,0 +1,363 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "github.com/AssetMantle/modules/schema/data" + baseData "github.com/AssetMantle/modules/schema/data/base" + "github.com/AssetMantle/modules/schema/documents" + "github.com/AssetMantle/modules/schema/ids" + baseIDs "github.com/AssetMantle/modules/schema/ids/base" + "github.com/AssetMantle/modules/schema/ids/constansts" + "github.com/AssetMantle/modules/schema/lists" + baseLists "github.com/AssetMantle/modules/schema/lists/base" + schemaProperties "github.com/AssetMantle/modules/schema/properties" + baseProperties "github.com/AssetMantle/modules/schema/properties/base" + "github.com/AssetMantle/modules/schema/properties/constants" + baseQualified "github.com/AssetMantle/modules/schema/qualified/base" + baseTypes "github.com/AssetMantle/modules/schema/types/base" + sdkTypes "github.com/cosmos/cosmos-sdk/types" + "reflect" + "testing" +) + +var ( + testImmutables = baseQualified.NewImmutables(baseLists.NewPropertyList(baseProperties.NewMesaProperty(baseIDs.NewStringID("ID1"), baseData.NewStringData("ImmutableData")), baseProperties.NewMetaProperty(constants.CreationHeightProperty.GetKey(), baseData.NewHeightData(baseTypes.NewHeight(1))), baseProperties.NewMetaProperty(constants.ExchangeRateProperty.GetKey(), baseData.NewDecData(sdkTypes.NewDec(int64(10)))), baseProperties.NewMetaProperty(constants.MakerOwnableIDProperty.GetKey(), baseData.NewIDData(baseIDs.NewOwnableID(baseIDs.NewStringID("MakerOwnableID")))), baseProperties.NewMetaProperty(constants.TakerOwnableIDProperty.GetKey(), baseData.NewIDData(baseIDs.NewOwnableID(baseIDs.NewStringID("TakerOwnableID")))), baseProperties.NewMetaProperty(constants.ExpiryHeightProperty.GetKey(), baseData.NewHeightData(baseTypes.NewHeight(100))), baseProperties.NewMetaProperty(constants.MakerOwnableSplitProperty.GetKey(), baseData.NewDecData(sdkTypes.NewDec(int64(10)))))) + testMutables = baseQualified.NewMutables(baseLists.NewPropertyList(baseProperties.NewMesaProperty(baseIDs.NewStringID("ID2"), baseData.NewStringData("MutableData")), baseProperties.NewMetaProperty(constants.TakerIDProperty.GetKey(), baseData.NewIDData(baseIDs.PrototypeIdentityID())), baseProperties.NewMetaProperty(constants.MakerIDProperty.GetKey(), baseData.NewIDData(baseIDs.PrototypeIdentityID())))) + testPermissionsList = baseLists.NewIDList([]ids.ID{constansts.Mint, constansts.Add, constansts.Remove, constansts.Mutate, constansts.Renumerate, constansts.Burn}...) + testClassificationID = baseIDs.NewClassificationID(immutables, mutables) + testIdentityID = baseIDs.NewIdentityID(testClassificationID, testImmutables) + testMaintainer = NewMaintainer(testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), testPermissionsList) +) + +func TestNewMaintainer(t *testing.T) { + type args struct { + identityID ids.IdentityID + maintainedClassificationID ids.ClassificationID + maintainedPropertyIDList lists.IDList + permissions lists.IDList + } + tests := []struct { + name string + args args + want documents.Maintainer + }{ + {"+ve", args{testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), testPermissionsList}, maintainer{NewDocument(constansts.MaintainerClassificationID, + baseQualified.NewImmutables(baseLists.NewPropertyList( + baseProperties.NewMetaProperty(constants.IdentityIDProperty.GetKey(), baseData.NewIDData(testIdentityID)), + baseProperties.NewMetaProperty(constants.MaintainedClassificationIDProperty.GetKey(), baseData.NewIDData(testClassificationID)), + )), + baseQualified.NewMutables(baseLists.NewPropertyList( + baseProperties.NewMetaProperty(constants.MaintainedPropertiesProperty.GetKey(), baseData.NewListData(idListToDataList(testMutables.GetMutablePropertyList().GetPropertyIDList()))), + baseProperties.NewMetaProperty(constants.PermissionsProperty.GetKey(), baseData.NewListData(idListToDataList(testPermissionsList))), + )), + )}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewMaintainer(tt.args.identityID, tt.args.maintainedClassificationID, tt.args.maintainedPropertyIDList, tt.args.permissions); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewMaintainer() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_idListToDataList(t *testing.T) { + type args struct { + idList lists.IDList + } + tests := []struct { + name string + args args + want lists.DataList + }{ + {"+ve", args{testPermissionsList}, baseLists.NewDataList(baseData.NewIDData(constansts.Mint), baseData.NewIDData(constansts.Add), baseData.NewIDData(constansts.Remove), baseData.NewIDData(constansts.Mutate), baseData.NewIDData(constansts.Renumerate), baseData.NewIDData(constansts.Burn))}, + {"+ve with nil", args{baseLists.NewIDList()}, baseLists.NewDataList()}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := idListToDataList(tt.args.idList); !reflect.DeepEqual(got, tt.want) { + t.Errorf("idListToDataList() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_CanAddMaintainer(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want bool + }{ + {"+ve", fields{testMaintainer}, true}, + {"+ve", fields{testMaintainer2}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.CanAddMaintainer(); got != tt.want { + t.Errorf("CanAddMaintainer() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_CanBurnAsset(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want bool + }{ + {"+ve", fields{testMaintainer}, true}, + {"+ve", fields{testMaintainer2}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.CanBurnAsset(); got != tt.want { + t.Errorf("CanBurnAsset() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_CanMintAsset(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want bool + }{ + {"+ve", fields{testMaintainer}, true}, + {"+ve", fields{testMaintainer2}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.CanMintAsset(); got != tt.want { + t.Errorf("CanMintAsset() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_CanMutateMaintainer(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want bool + }{ + {"+ve", fields{testMaintainer}, true}, + {"+ve", fields{testMaintainer2}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.CanMutateMaintainer(); got != tt.want { + t.Errorf("CanMutateMaintainer() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_CanRemoveMaintainer(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want bool + }{ + {"+ve", fields{testMaintainer}, true}, + {"+ve", fields{testMaintainer2}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.CanRemoveMaintainer(); got != tt.want { + t.Errorf("CanRemoveMaintainer() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_CanRenumerateAsset(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want bool + }{ + {"+ve", fields{testMaintainer}, true}, + {"+ve", fields{testMaintainer2}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.CanRenumerateAsset(); got != tt.want { + t.Errorf("CanRenumerateAsset() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_GetIdentityID(t *testing.T) { + testMaintainer2 := NewMaintainer(baseIDs.PrototypeIdentityID(), testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want ids.IdentityID + }{ + {"+ve", fields{testMaintainer}, testIdentityID}, + {"+ve", fields{testMaintainer2}, baseIDs.PrototypeIdentityID()}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.GetIdentityID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetIdentityID() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_GetMaintainedClassificationID(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, baseIDs.PrototypeClassificationID(), testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want ids.ClassificationID + }{ + {"+ve", fields{testMaintainer}, testClassificationID}, + {"+ve", fields{testMaintainer2}, baseIDs.PrototypeClassificationID()}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.GetMaintainedClassificationID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetMaintainedClassificationID() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_GetMaintainedProperties(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, testClassificationID, baseQualified.NewMutables(baseLists.NewPropertyList()).GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want data.ListData + }{ + {"+ve", fields{testMaintainer}, testMaintainer.GetProperty(constants.MaintainedPropertiesProperty.GetID()).(schemaProperties.MetaProperty).GetData().(data.ListData)}, + {"+ve", fields{testMaintainer2}, constants.MaintainedPropertiesProperty.GetData().(data.ListData)}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.GetMaintainedProperties(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetMaintainedProperties() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_GetPermissions(t *testing.T) { + testMaintainer2 := NewMaintainer(testIdentityID, testClassificationID, testMutables.GetMutablePropertyList().GetPropertyIDList(), baseLists.NewIDList()) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want data.ListData + }{ + {"+ve", fields{testMaintainer}, testMaintainer.GetProperty(constants.PermissionsProperty.GetID()).(schemaProperties.MetaProperty).GetData().(data.ListData)}, + {"+ve", fields{testMaintainer2}, constants.PermissionsProperty.GetData().(data.ListData)}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.GetPermissions(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetPermissions() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_maintainer_MaintainsProperty(t *testing.T) { + type fields struct { + Document documents.Document + } + type args struct { + propertyID ids.PropertyID + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + {"+ve", fields{testMaintainer}, args{baseProperties.NewMetaProperty(baseIDs.NewStringID("ID2"), baseData.NewStringData("MutableData")).GetID()}, true}, + {"+ve", fields{testMaintainer}, args{baseProperties.NewMetaProperty(baseIDs.NewStringID("ID"), baseData.NewStringData("MutableData")).GetID()}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainer := maintainer{ + Document: tt.fields.Document, + } + if got := maintainer.MaintainsProperty(tt.args.propertyID); got != tt.want { + t.Errorf("MaintainsProperty() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/schema/documents/base/order_test.go b/schema/documents/base/order_test.go new file mode 100644 index 000000000..d677be12f --- /dev/null +++ b/schema/documents/base/order_test.go @@ -0,0 +1,235 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + baseData "github.com/AssetMantle/modules/schema/data/base" + "github.com/AssetMantle/modules/schema/documents" + "github.com/AssetMantle/modules/schema/ids" + "github.com/AssetMantle/modules/schema/ids/base" + baseProperties "github.com/AssetMantle/modules/schema/properties/base" + constanstsProperties "github.com/AssetMantle/modules/schema/properties/constants" + "github.com/AssetMantle/modules/schema/qualified" + "github.com/AssetMantle/modules/schema/types" + baseTypes "github.com/AssetMantle/modules/schema/types/base" + sdkType "github.com/cosmos/cosmos-sdk/types" + "reflect" + "testing" +) + +var ( + testOrder = NewOrder(testClassificationID, testImmutables, testMutables) +) + +func TestNewOrder(t *testing.T) { + type args struct { + classificationID ids.ClassificationID + immutables qualified.Immutables + mutables qualified.Mutables + } + tests := []struct { + name string + args args + want documents.Order + }{ + {"+ve with nil immutables", args{testClassificationID, nil, testMutables}, order{NewDocument(testClassificationID, nil, testMutables)}}, + {"+ve with nil mutables", args{testClassificationID, testImmutables, nil}, order{NewDocument(testClassificationID, testImmutables, nil)}}, + {"+ve with nil immutables and mutables", args{testClassificationID, nil, nil}, order{NewDocument(testClassificationID, nil, nil)}}, + {"+ve with nil classificationID", args{nil, testImmutables, testMutables}, order{NewDocument(nil, testImmutables, testMutables)}}, + {"+ve", args{testClassificationID, testImmutables, testMutables}, order{NewDocument(testClassificationID, testImmutables, testMutables)}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewOrder(tt.args.classificationID, tt.args.immutables, tt.args.mutables); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewOrder() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_order_GetCreationHeight(t *testing.T) { + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want types.Height + }{ + {"+ve", fields{testOrder}, baseTypes.NewHeight(int64(1))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + order := order{ + Document: tt.fields.Document, + } + if got := order.GetCreationHeight(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetCreationHeight() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_order_GetExchangeRate(t *testing.T) { + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want sdkType.Dec + }{ + {"+ve", fields{testOrder}, sdkType.NewDec(int64(10))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + order := order{ + Document: tt.fields.Document, + } + if got := order.GetExchangeRate(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetExchangeRate() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_order_GetExpiryHeight(t *testing.T) { + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want types.Height + }{ + {"+ve", fields{testOrder}, baseTypes.NewHeight(int64(100))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + order := order{ + Document: tt.fields.Document, + } + if got := order.GetExpiryHeight(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetExpiryHeight() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_order_GetMakerID(t *testing.T) { + testOrder.Mutate(baseProperties.NewMetaProperty(constanstsProperties.MakerIDProperty.GetKey(), baseData.NewIDData(testIdentityID))) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want ids.IdentityID + }{ + {"+ve", fields{testOrder}, testIdentityID}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + order := order{ + Document: tt.fields.Document, + } + if got := order.GetMakerID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetMakerID() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_order_GetMakerOwnableID(t *testing.T) { + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want ids.OwnableID + }{ + {"+ve", fields{testOrder}, base.NewOwnableID(base.NewStringID("MakerOwnableID"))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + order := order{ + Document: tt.fields.Document, + } + if got := order.GetMakerOwnableID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetMakerOwnableID() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_order_GetMakerOwnableSplit(t *testing.T) { + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want sdkType.Dec + }{ + {"+ve", fields{testOrder}, sdkType.NewDec(int64(10))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + order := order{ + Document: tt.fields.Document, + } + if got := order.GetMakerOwnableSplit(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetMakerOwnableSplit() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_order_GetTakerID(t *testing.T) { + testOrder.Mutate(baseProperties.NewMetaProperty(constanstsProperties.TakerIDProperty.GetKey(), baseData.NewIDData(testIdentityID))) + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want ids.IdentityID + }{ + {"+ve with IdentityID", fields{testOrder}, testIdentityID}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + order := order{ + Document: tt.fields.Document, + } + if got := order.GetTakerID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetTakerID() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_order_GetTakerOwnableID(t *testing.T) { + type fields struct { + Document documents.Document + } + tests := []struct { + name string + fields fields + want ids.OwnableID + }{ + {"+ve", fields{testOrder}, base.NewOwnableID(base.NewStringID("TakerOwnableID"))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + order := order{ + Document: tt.fields.Document, + } + if got := order.GetTakerOwnableID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetTakerOwnableID() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/schema/documents/document.go b/schema/documents/document.go index 86447be1b..24e04eb26 100644 --- a/schema/documents/document.go +++ b/schema/documents/document.go @@ -19,4 +19,7 @@ type Document interface { GetMutables() qualified.Mutables Mutate(...properties.Property) Document + + // Sanitize() Document returns a sanitized document + Sanitize() (Document, error) } diff --git a/schema/helpers/base/auxiliary_test.go b/schema/helpers/base/auxiliary_test.go index 0e695d46a..1ca9e84a4 100644 --- a/schema/helpers/base/auxiliary_test.go +++ b/schema/helpers/base/auxiliary_test.go @@ -4,6 +4,7 @@ package base import ( + "fmt" "reflect" "testing" @@ -115,8 +116,7 @@ func Test_auxiliary_Initialize(t *testing.T) { args args want helpers.Auxiliary }{ - // TODO find fix - // {"+ve", fields{"testAuxiliary", base.TestAuxiliaryKeeperPrototype(), base.TestAuxiliaryKeeperPrototype}, args{mapper: Mapper, parameters: nil, auxiliaryKeepers: nil}, Auxiliary}, + {"+ve", fields{"testAuxiliary", base.TestAuxiliaryKeeperPrototype(), base.TestAuxiliaryKeeperPrototype}, args{mapper: Mapper, parameters: nil, auxiliaryKeepers: nil}, Auxiliary}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -125,7 +125,7 @@ func Test_auxiliary_Initialize(t *testing.T) { auxiliaryKeeper: tt.fields.auxiliaryKeeper, keeperPrototype: tt.fields.keeperPrototype, } - if got := auxiliary.Initialize(tt.args.mapper, tt.args.parameters, tt.args.auxiliaryKeepers...); !reflect.DeepEqual(got, tt.want) { + if got := auxiliary.Initialize(tt.args.mapper, tt.args.parameters, tt.args.auxiliaryKeepers...); !reflect.DeepEqual(fmt.Sprint(got), fmt.Sprint(tt.want)) { t.Errorf("Initialize() = %v, want %v", got, tt.want) } }) diff --git a/schema/helpers/base/storeKeyPrefix_test.go b/schema/helpers/base/storeKeyPrefix_test.go new file mode 100644 index 000000000..4726c69f4 --- /dev/null +++ b/schema/helpers/base/storeKeyPrefix_test.go @@ -0,0 +1,95 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "encoding/binary" + baseData "github.com/AssetMantle/modules/schema/data/base" + "github.com/AssetMantle/modules/schema/helpers" + baseIDs "github.com/AssetMantle/modules/schema/ids/base" + baseLists "github.com/AssetMantle/modules/schema/lists/base" + baseProperties "github.com/AssetMantle/modules/schema/properties/base" + baseQualified "github.com/AssetMantle/modules/schema/qualified/base" + "github.com/stretchr/testify/assert" + "testing" +) + +const ( + assets int8 = iota + 8 + classifications + identities + maintainers + metas + orders + splits +) + +var ( + immutables = baseQualified.NewImmutables(baseLists.NewPropertyList(baseProperties.NewMesaProperty(baseIDs.NewStringID("ID2"), baseData.NewStringData("Data2")))) + mutables = baseQualified.NewMutables(baseLists.NewPropertyList(baseProperties.NewMesaProperty(baseIDs.NewStringID("ID1"), baseData.NewStringData("Data1")))) + testClassificationID = baseIDs.NewClassificationID(immutables, mutables) + assetKeyBytes = baseIDs.NewAssetID(testClassificationID, immutables).Bytes() + classificationKeyBytes = baseIDs.NewClassificationID(immutables, mutables).Bytes() + identityID = baseIDs.NewIdentityID(testClassificationID, immutables) + identityKeyBytes = identityID.Bytes() + maintainerKeyBytes = baseIDs.NewMaintainerID(testClassificationID, immutables).Bytes() + metaKeyBytes = baseIDs.NewDataID(baseData.NewStringData("DataID")).Bytes() + orderKeyBytes = baseIDs.NewOrderID(testClassificationID, immutables).Bytes() + splitsKeyBytes = baseIDs.NewSplitID(identityID, baseIDs.NewOwnableID(baseIDs.NewStringID("OwnerID"))).Bytes() +) + +func TestNewStoreKeyPrefix(t *testing.T) { + type args struct { + value int8 + } + tests := []struct { + name string + args args + want helpers.StoreKeyPrefix + }{ + {"+ve with assets", args{assets}, storeKeyPrefix(assets)}, + {"+ve with classifications", args{classifications}, storeKeyPrefix(classifications)}, + {"+ve with identities", args{identities}, storeKeyPrefix(identities)}, + {"+ve with maintainers", args{maintainers}, storeKeyPrefix(maintainers)}, + {"+ve with metas", args{metas}, storeKeyPrefix(metas)}, + {"+ve with orders", args{orders}, storeKeyPrefix(orders)}, + {"+ve with splits", args{splits}, storeKeyPrefix(splits)}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, NewStoreKeyPrefix(tt.args.value), "NewStoreKeyPrefix(%v)", tt.args.value) + }) + } +} + +func Test_storeKeyPrefix_GenerateStoreKey(t *testing.T) { + type args struct { + key []byte + } + tests := []struct { + name string + storeKeyPrefix storeKeyPrefix + args args + want []byte + }{ + {"+ve for AssetsStoreKeyPrefix", NewStoreKeyPrefix(assets).(storeKeyPrefix), args{assetKeyBytes}, append(getStorePrefixBytes(assets), assetKeyBytes...)}, + {"+ve for ClassificationsStoreKeyPrefix", NewStoreKeyPrefix(classifications).(storeKeyPrefix), args{classificationKeyBytes}, append(getStorePrefixBytes(classifications), classificationKeyBytes...)}, + {"+ve for IdentitiesStoreKeyPrefix", NewStoreKeyPrefix(identities).(storeKeyPrefix), args{identityKeyBytes}, append(getStorePrefixBytes(identities), identityKeyBytes...)}, + {"+ve for MaintainersStoreKeyPrefix", NewStoreKeyPrefix(maintainers).(storeKeyPrefix), args{maintainerKeyBytes}, append(getStorePrefixBytes(maintainers), maintainerKeyBytes...)}, + {"+ve for MetasStoreKeyPrefix", NewStoreKeyPrefix(metas).(storeKeyPrefix), args{metaKeyBytes}, append(getStorePrefixBytes(metas), metaKeyBytes...)}, + {"+ve for OrdersStoreKeyPrefix", NewStoreKeyPrefix(orders).(storeKeyPrefix), args{orderKeyBytes}, append(getStorePrefixBytes(orders), orderKeyBytes...)}, + {"+ve for SplitsStoreKeyPrefix", NewStoreKeyPrefix(splits).(storeKeyPrefix), args{splitsKeyBytes}, append(getStorePrefixBytes(splits), splitsKeyBytes...)}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, tt.storeKeyPrefix.GenerateStoreKey(tt.args.key), "GenerateStoreKey(%v)", tt.args.key) + }) + } +} + +func getStorePrefixBytes(value int8) []byte { + bytes := make([]byte, 2) + binary.LittleEndian.PutUint16(bytes, uint16(value)) + return bytes +} diff --git a/schema/ids/base/assetID_test.go b/schema/ids/base/assetID_test.go new file mode 100644 index 000000000..eb1dfa6f3 --- /dev/null +++ b/schema/ids/base/assetID_test.go @@ -0,0 +1,418 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "fmt" + "github.com/AssetMantle/modules/schema/data" + errorConstants "github.com/AssetMantle/modules/schema/errors/constants" + "github.com/AssetMantle/modules/schema/ids" + "github.com/AssetMantle/modules/schema/lists" + "github.com/AssetMantle/modules/schema/properties" + "github.com/AssetMantle/modules/schema/qualified" + "github.com/AssetMantle/modules/schema/traits" + "github.com/stretchr/testify/assert" + "sort" + "testing" +) + +var ( + testImmutables = NewImmutables(NewPropertyList(NewMetaProperty(NewStringID("testImutable"), NewStringData("testImmutable")))) + testImmutables2 = NewImmutables(NewPropertyList()) + testMutables = NewMutables(NewPropertyList(NewMetaProperty(NewStringID("testMutable"), NewStringData("testImmutable")))) + testMutables2 = NewMutables(NewPropertyList()) + testClassificationID = NewClassificationID(testImmutables, testMutables) + testClassificationID2 = PrototypeClassificationID() + testAssetID = NewAssetID(testClassificationID, testImmutables) + testAssetID2 = PrototypeAssetID() +) + +func TestNewAssetID(t *testing.T) { + type args struct { + classificationID ids.ClassificationID + immutables qualified.Immutables + } + tests := []struct { + name string + args args + want ids.AssetID + }{ + {"+ve with empty immutable", args{testClassificationID, testImmutables2}, assetID{HashID: GenerateHashID(testClassificationID.Bytes())}}, + {"+ve", args{testClassificationID, testImmutables}, NewAssetID(testClassificationID, testImmutables)}, + {"+ve with empty classificationID", args{testClassificationID2, testImmutables}, assetID{HashID: GenerateHashID(testClassificationID2.Bytes(), testImmutables.GenerateHashID().Bytes())}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, NewAssetID(tt.args.classificationID, tt.args.immutables), "NewAssetID(%v, %v)", tt.args.classificationID, tt.args.immutables) + }) + } +} + +func TestPrototypeAssetID(t *testing.T) { + tests := []struct { + name string + want ids.AssetID + }{ + {"+ve", assetID{HashID: PrototypeHashID()}}, + {"+ve", NewAssetID(NewClassificationID(NewImmutables(NewPropertyList()), NewMutables(NewPropertyList())), NewImmutables(NewPropertyList()))}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, PrototypeAssetID(), "PrototypeAssetID()") + }) + } +} + +func TestReadAssetID(t *testing.T) { + type args struct { + assetIDString string + } + tests := []struct { + name string + args args + want ids.AssetID + wantErr assert.ErrorAssertionFunc + }{ + {"+ve", args{testAssetID.String()}, testAssetID, assert.NoError}, + {"+ve with empty immutable", args{NewAssetID(testClassificationID, testImmutables2).String()}, NewAssetID(testClassificationID, testImmutables2), assert.NoError}, + {"+ve with empty classificationID", args{NewAssetID(testClassificationID2, testImmutables).String()}, NewAssetID(testClassificationID2, testImmutables), assert.NoError}, + {"-ve with empty String", args{""}, PrototypeAssetID(), assert.NoError}, + {"-ve with nil", args{}, assetID{}, assert.NoError}, + {"+ve with Random String", args{"Random String"}, assetID{}, assert.Error}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ReadAssetID(tt.args.assetIDString) + if !tt.wantErr(t, err, fmt.Sprintf("ReadAssetID(%v)", tt.args.assetIDString)) { + return + } + assert.Equalf(t, tt.want, got, "ReadAssetID(%v)", tt.args.assetIDString) + }) + } +} + +func Test_assetIDFromInterface(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + args args + want assetID + shouldPanic bool + }{ + {"+ve", args{testAssetID}, testAssetID.(assetID), false}, + {"+ve with PrototypeAssetID", args{PrototypeAssetID()}, PrototypeAssetID().(assetID), false}, + {"+ve with nil", args{}, PrototypeAssetID().(assetID), true}, + {"+ve with identityID", args{testIdentityID}, PrototypeAssetID().(assetID), true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.shouldPanic { + assert.Panicsf(t, func() { assetIDFromInterface(tt.args.i) }, "assetIDFromInterface(%v)", tt.args.i) + } else { + assert.Equalf(t, tt.want, assetIDFromInterface(tt.args.i), "assetIDFromInterface(%v)", tt.args.i) + } + }) + } +} + +func Test_assetID_Compare(t *testing.T) { + type fields struct { + HashID ids.HashID + } + type args struct { + listable traits.Listable + } + tests := []struct { + name string + fields fields + args args + want int + }{ + {"-ve", fields{GenerateHashID(testClassificationID2.Bytes(), testImmutables2.GenerateHashID().Bytes())}, args{testAssetID}, -1}, + {"+ve", fields{GenerateHashID(testClassificationID.Bytes(), testImmutables.GenerateHashID().Bytes())}, args{testAssetID}, 0}, + {"+ve prototype", fields{PrototypeHashID()}, args{testAssetID2}, 0}, + {"-ve prototype", fields{PrototypeHashID()}, args{testAssetID}, -1}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assetID := assetID{ + HashID: tt.fields.HashID, + } + assert.Equalf(t, tt.want, assetID.Compare(tt.args.listable), "Compare(%v)", tt.args.listable) + }) + } +} + +// Immutable Mocks +type immutables struct { + lists.PropertyList +} + +func (i immutables) GetImmutablePropertyList() lists.PropertyList { + //if i.PropertyList.GetList() == nil { + // return base.NewPropertyList() + //} + + return i.PropertyList +} + +func (i immutables) GenerateHashID() ids.HashID { + metaList := make([][]byte, len(i.PropertyList.GetList())) + + for i, property := range i.PropertyList.GetList() { + metaList[i] = property.GetDataID().GetHashID().Bytes() + } + return GenerateHashID(metaList...) +} + +func NewImmutables(propertyList lists.PropertyList) qualified.Immutables { + return immutables{ + PropertyList: propertyList, + } +} + +// Mutable Mocks +type mutables struct { + lists.PropertyList +} + +var _ qualified.Mutables = (*mutables)(nil) + +func (m mutables) GetMutablePropertyList() lists.PropertyList { + //TODO implement me + return m.PropertyList +} + +func (m mutables) Mutate(property ...properties.Property) qualified.Mutables { + //TODO implement me + panic("implement me") +} + +func NewMutables(propertyList lists.PropertyList) qualified.Mutables { + return mutables{ + PropertyList: propertyList, + } +} + +// PropertyList Mocks +type propertyList struct { + lists.List +} + +func (p propertyList) Sanitize() (lists.PropertyList, error) { + //TODO implement me + panic("implement me") +} + +func (p propertyList) GetProperty(id ids.PropertyID) properties.Property { + //TODO implement me + panic("implement me") +} + +func (p propertyList) GetList() []properties.Property { + Properties := make([]properties.Property, p.Size()) + for i, property := range p.List.Get() { + Properties[i] = property.(properties.Property) + } + return Properties +} + +func (p propertyList) GetPropertyIDList() lists.IDList { + //TODO implement me + panic("implement me") +} + +func (p propertyList) Add(property ...properties.Property) lists.PropertyList { + //TODO implement me + panic("implement me") +} + +func (p propertyList) Remove(property ...properties.Property) lists.PropertyList { + //TODO implement me + panic("implement me") +} + +func (p propertyList) Mutate(property ...properties.Property) lists.PropertyList { + //TODO implement me + panic("implement me") +} + +func (p propertyList) ScrubData() lists.PropertyList { + //TODO implement me + panic("implement me") +} + +func propertiesToListables(properties ...properties.Property) []traits.Listable { + listables := make([]traits.Listable, len(properties)) + for i, property := range properties { + listables[i] = property + } + return listables +} + +func NewPropertyList(properties ...properties.Property) lists.PropertyList { + return propertyList{List: NewList(propertiesToListables(properties...)...)} +} + +// NewList Mocks +type list []traits.Listable + +func (l list) Sanitize() (lists.List, error) { + //TODO implement me + panic("implement me") +} + +func (l list) Get() []traits.Listable { + //TODO implement me + List := make([]traits.Listable, l.Size()) + for i, listable := range l { + List[i] = listable + } + return List +} + +func (l list) Size() int { + return len(l) +} + +func (l list) Search(listable traits.Listable) (index int, found bool) { + //TODO implement me + panic("implement me") +} + +func (l list) Add(listable ...traits.Listable) lists.List { + //TODO implement me + panic("implement me") +} + +func (l list) Remove(listable ...traits.Listable) lists.List { + //TODO implement me + panic("implement me") +} + +func (l list) Mutate(listable ...traits.Listable) lists.List { + //TODO implement me + panic("implement me") +} + +func NewList(listables ...traits.Listable) lists.List { + list := list(listables) + sort.Slice(list, func(i, j int) bool { + return list[i].Compare(list[j]) <= 0 + }) + + return list +} + +// MetaProperty Mocks +type metaProperty struct { + ID ids.PropertyID `json:"id"` + Data data.Data `json:"data"` +} + +var _ properties.Property = (*metaProperty)(nil) + +func (m metaProperty) GetData() data.Data { + //TODO implement me + panic("implement me") +} + +func (m metaProperty) ScrubData() properties.MesaProperty { + //TODO implement me + panic("implement me") +} + +func (m metaProperty) GetID() ids.PropertyID { + //TODO implement me + return m.ID + //panic("implement me") +} + +func (m metaProperty) GetDataID() ids.DataID { + //TODO implement me + return m.Data.GetID() +} + +func (m metaProperty) GetKey() ids.StringID { + //TODO implement me + panic("implement me") +} + +func (m metaProperty) GetType() ids.StringID { + //TODO implement me + panic("implement me") +} + +func (m metaProperty) IsMeta() bool { + //TODO implement me + panic("implement me") +} + +func (m metaProperty) Compare(listable traits.Listable) int { + //TODO implement me + panic("implement me") +} + +func NewMetaProperty(key ids.StringID, data data.Data) properties.MetaProperty { + if data == nil || key == nil { + panic(errorConstants.MetaDataError) + } + return metaProperty{ + ID: NewPropertyID(key, data.GetType()), + Data: data, + } +} + +//StringData Mocks +type stringData struct { + Value string `json:"value"` +} + +func (s stringData) GetID() ids.DataID { + //TODO implement me + return NewDataID(s) +} + +func (s stringData) String() string { + //TODO implement me + panic("implement me") +} + +func (s stringData) Bytes() []byte { + //TODO implement me + return []byte(s.Value) +} + +func (s stringData) GetType() ids.StringID { + //TODO implement me + return NewStringID("S") +} + +func (s stringData) ZeroValue() data.Data { + //TODO implement me + panic("implement me") +} + +func (s stringData) GenerateHashID() ids.HashID { + //TODO implement me + return GenerateHashID(s.Bytes()) +} + +func (s stringData) Compare(listable traits.Listable) int { + //TODO implement me + panic("implement me") +} + +func (s stringData) Get() string { + //TODO implement me + panic("implement me") +} + +func NewStringData(value string) data.StringData { + return stringData{ + Value: value, + } +} diff --git a/schema/ids/base/classificationID_test.go b/schema/ids/base/classificationID_test.go new file mode 100644 index 000000000..340f002dc --- /dev/null +++ b/schema/ids/base/classificationID_test.go @@ -0,0 +1,138 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "fmt" + "github.com/AssetMantle/modules/schema/ids" + "github.com/AssetMantle/modules/schema/qualified" + "github.com/AssetMantle/modules/schema/traits" + "github.com/stretchr/testify/assert" + "testing" +) + +func getListBytes(immutables qualified.Immutables, mutables qualified.Mutables) ([][]byte, [][]byte) { + immutableIDByteList := make([][]byte, len(immutables.GetImmutablePropertyList().GetList())) + for i, property := range immutables.GetImmutablePropertyList().GetList() { + immutableIDByteList[i] = property.GetID().Bytes() + } + + mutableIDByteList := make([][]byte, len(mutables.GetMutablePropertyList().GetList())) + for i, property := range mutables.GetMutablePropertyList().GetList() { + mutableIDByteList[i] = property.GetID().Bytes() + } + return immutableIDByteList, mutableIDByteList +} + +func TestNewClassificationID(t *testing.T) { + immutableIDByteList, mutableIDByteList := getListBytes(testImmutables, testMutables) + immutableIDByteList2, mutableIDByteList2 := getListBytes(testImmutables2, testMutables2) + type args struct { + immutables qualified.Immutables + mutables qualified.Mutables + } + tests := []struct { + name string + args args + want ids.ClassificationID + }{ + {"+ve with nil immutables and mutables", args{testImmutables2, testMutables2}, classificationID{GenerateHashID(GenerateHashID(immutableIDByteList2...).Bytes(), GenerateHashID(mutableIDByteList2...).Bytes(), testImmutables2.GenerateHashID().Bytes())}}, + {"+ve", args{testImmutables, testMutables}, classificationID{GenerateHashID(GenerateHashID(immutableIDByteList...).Bytes(), GenerateHashID(mutableIDByteList...).Bytes(), testImmutables.GenerateHashID().Bytes())}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, NewClassificationID(tt.args.immutables, tt.args.mutables), "NewClassificationID(%v, %v)", tt.args.immutables, tt.args.mutables) + }) + } +} + +func TestPrototypeClassificationID(t *testing.T) { + tests := []struct { + name string + want ids.ClassificationID + }{ + {"+ve", classificationID{PrototypeHashID()}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, PrototypeClassificationID(), "PrototypeClassificationID()") + }) + } +} + +func TestReadClassificationID(t *testing.T) { + type args struct { + classificationIDString string + } + tests := []struct { + name string + args args + want ids.ClassificationID + wantErr assert.ErrorAssertionFunc + }{ + {"+ve", args{testClassificationID.String()}, testClassificationID, assert.NoError}, + {"+ve with nil immutables and mutables", args{testClassificationID2.String()}, testClassificationID2, assert.NoError}, + {"-ve", args{"invalid"}, classificationID{}, assert.Error}, + {"+ve with empty string", args{""}, PrototypeClassificationID(), assert.NoError}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ReadClassificationID(tt.args.classificationIDString) + if !tt.wantErr(t, err, fmt.Sprintf("ReadClassificationID(%v)", tt.args.classificationIDString)) { + return + } + assert.Equalf(t, tt.want, got, "ReadClassificationID(%v)", tt.args.classificationIDString) + }) + } +} + +func Test_classificationIDFromInterface(t *testing.T) { + immutableIDByteList, mutableIDByteList := getListBytes(testImmutables, testMutables) + immutableIDByteList2, mutableIDByteList2 := getListBytes(testImmutables2, testMutables2) + type args struct { + i interface{} + } + tests := []struct { + name string + args args + want classificationID + }{ + {"+ve with nil immutables and mutables", args{testClassificationID2}, classificationID{GenerateHashID(GenerateHashID(immutableIDByteList2...).Bytes(), GenerateHashID(mutableIDByteList2...).Bytes(), testImmutables2.GenerateHashID().Bytes())}}, + {"+ve", args{testClassificationID}, classificationID{GenerateHashID(GenerateHashID(immutableIDByteList...).Bytes(), GenerateHashID(mutableIDByteList...).Bytes(), testImmutables.GenerateHashID().Bytes())}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, classificationIDFromInterface(tt.args.i), "classificationIDFromInterface(%v)", tt.args.i) + }) + } +} + +func Test_classificationID_Compare(t *testing.T) { + immutableIDByteList, mutableIDByteList := getListBytes(testImmutables, testMutables) + immutableIDByteList2, mutableIDByteList2 := getListBytes(testImmutables2, testMutables2) + type fields struct { + HashID ids.HashID + } + type args struct { + listable traits.Listable + } + tests := []struct { + name string + fields fields + args args + want int + }{ + {"+ve with nil immutables and mutables", fields{GenerateHashID(GenerateHashID(immutableIDByteList2...).Bytes(), GenerateHashID(mutableIDByteList2...).Bytes(), testImmutables2.GenerateHashID().Bytes())}, args{testClassificationID2}, 0}, + {"-ve", fields{GenerateHashID(GenerateHashID(immutableIDByteList...).Bytes(), GenerateHashID(mutableIDByteList...).Bytes(), testImmutables.GenerateHashID().Bytes())}, args{testClassificationID2}, 1}, + {"+ve", fields{GenerateHashID(GenerateHashID(immutableIDByteList...).Bytes(), GenerateHashID(mutableIDByteList...).Bytes(), testImmutables.GenerateHashID().Bytes())}, args{testClassificationID}, 0}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + classificationID := classificationID{ + HashID: tt.fields.HashID, + } + assert.Equalf(t, tt.want, classificationID.Compare(tt.args.listable), "Compare(%v)", tt.args.listable) + }) + } +} diff --git a/schema/ids/base/dataID_test.go b/schema/ids/base/dataID_test.go index 5802f50fa..8e1008933 100644 --- a/schema/ids/base/dataID_test.go +++ b/schema/ids/base/dataID_test.go @@ -190,6 +190,11 @@ type booleanData struct { Value bool `json:"value"` } +func (booleanData booleanData) Sanitize() (data.Data, error) { + //TODO implement me + panic("implement me") +} + var _ data.BooleanData = (*booleanData)(nil) func (booleanData booleanData) GetID() ids.DataID { diff --git a/schema/ids/base/identityID_test.go b/schema/ids/base/identityID_test.go new file mode 100644 index 000000000..5c5126bac --- /dev/null +++ b/schema/ids/base/identityID_test.go @@ -0,0 +1,198 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "fmt" + "github.com/AssetMantle/modules/schema/ids" + "github.com/AssetMantle/modules/schema/qualified" + "github.com/AssetMantle/modules/schema/traits" + "github.com/stretchr/testify/assert" + "testing" +) + +var ( + testIdentityID = NewIdentityID(testClassificationID, testImmutables) + testIdentityID2 = PrototypeIdentityID() +) + +func TestNewIdentityID(t *testing.T) { + type args struct { + classificationID ids.ClassificationID + immutables qualified.Immutables + } + tests := []struct { + name string + args args + want ids.IdentityID + }{ + {"+ve with nil immutables and mutables", args{testClassificationID2, testImmutables2}, identityID{GenerateHashID(testClassificationID2.Bytes(), testImmutables2.GenerateHashID().Bytes())}}, + {"+ve", args{testClassificationID, testImmutables}, identityID{HashID: GenerateHashID(testClassificationID.Bytes(), testImmutables.GenerateHashID().Bytes())}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, NewIdentityID(tt.args.classificationID, tt.args.immutables), "NewIdentityID(%v, %v)", tt.args.classificationID, tt.args.immutables) + }) + } +} + +func TestPrototypeIdentityID(t *testing.T) { + tests := []struct { + name string + want ids.IdentityID + }{ + {"+ve", identityID{PrototypeHashID()}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, PrototypeIdentityID(), "PrototypeIdentityID()") + }) + } +} + +func TestReadIdentityID(t *testing.T) { + type args struct { + identityIDString string + } + tests := []struct { + name string + args args + want ids.IdentityID + wantErr assert.ErrorAssertionFunc + }{ + {"+ve", args{testIdentityID.String()}, testIdentityID, assert.NoError}, + {"-ve with invalid identityIDString", args{"invalid"}, identityID{}, assert.Error}, + {"+ve with empty identityIDString", args{""}, identityID{}, assert.NoError}, //TODO: change the order for emptyString in ReadHashID + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ReadIdentityID(tt.args.identityIDString) + if !tt.wantErr(t, err, fmt.Sprintf("ReadIdentityID(%v)", tt.args.identityIDString)) { + return + } + assert.Equalf(t, tt.want, got, "ReadIdentityID(%v)", tt.args.identityIDString) + }) + } +} + +func Test_identityIDFromInterface(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + args args + want identityID + shouldPanic bool + }{ + {"+ve", args{testIdentityID}, NewIdentityID(testClassificationID, testImmutables).(identityID), false}, + {"+ve with nil", args{nil}, identityID{}, true}, + {"-ve with invalid type", args{testClassificationID}, identityID{}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.shouldPanic { + assert.Panicsf(t, func() { identityIDFromInterface(tt.args.i) }, "identityIDFromInterface(%v)", tt.args.i) + } else { + assert.Equalf(t, tt.want, identityIDFromInterface(tt.args.i), "identityIDFromInterface(%v)", tt.args.i) + } + + }) + } +} + +func Test_identityID_Bytes(t *testing.T) { + type fields struct { + HashID ids.HashID + } + tests := []struct { + name string + fields fields + want []byte + }{ + {"+ve", fields{testIdentityID.GetHashID()}, testIdentityID.GetHashID().Bytes()}, + {"+ve with nil", fields{nil}, []byte{}}, //TODO: Sanitize it + {"+ve with nil mutable and immutable", fields{identityID{HashID: testIdentityID2.GetHashID()}}, testIdentityID2.GetHashID().Bytes()}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + identityID := identityID{ + HashID: tt.fields.HashID, + } + assert.Equalf(t, tt.want, identityID.Bytes(), "Bytes()") + }) + } +} + +func Test_identityID_Compare(t *testing.T) { + type fields struct { + HashID ids.HashID + } + type args struct { + listable traits.Listable + } + tests := []struct { + name string + fields fields + args args + want int + }{ + {"-ve", fields{testIdentityID.GetHashID()}, args{testIdentityID2}, 1}, + {"-ve with nil immutables mutables", fields{testIdentityID2.GetHashID()}, args{testIdentityID}, -1}, + {"+ve", fields{testIdentityID.GetHashID()}, args{testIdentityID}, 0}, + {"+ve with nil immutables mutables", fields{testIdentityID2.GetHashID()}, args{testIdentityID2}, 0}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + identityID := identityID{ + HashID: tt.fields.HashID, + } + assert.Equalf(t, tt.want, identityID.Compare(tt.args.listable), "Compare(%v)", tt.args.listable) + }) + } +} + +func Test_identityID_GetHashID(t *testing.T) { + type fields struct { + HashID ids.HashID + } + tests := []struct { + name string + fields fields + want ids.HashID + }{ + {"+ve", fields{GenerateHashID(testClassificationID.Bytes(), testImmutables.GenerateHashID().Bytes())}, GenerateHashID(testClassificationID.Bytes(), testImmutables.GenerateHashID().Bytes())}, + {"+ve with nil mutable immutables", fields{testIdentityID2.GetHashID()}, testIdentityID2.GetHashID()}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + identityID := identityID{ + HashID: tt.fields.HashID, + } + assert.Equalf(t, tt.want, identityID.GetHashID(), "GetHashID()") + }) + } +} + +func Test_identityID_String(t *testing.T) { + type fields struct { + HashID ids.HashID + } + tests := []struct { + name string + fields fields + want string + }{ + {"+ve", fields{testIdentityID.GetHashID()}, testIdentityID.GetHashID().String()}, + {"+ve with nil mutable immutables", fields{testIdentityID2.GetHashID()}, testIdentityID2.GetHashID().String()}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + identityID := identityID{ + HashID: tt.fields.HashID, + } + assert.Equalf(t, tt.want, identityID.String(), "String()") + }) + } +} diff --git a/schema/ids/base/maintainerID_test.go b/schema/ids/base/maintainerID_test.go new file mode 100644 index 000000000..2e37b8472 --- /dev/null +++ b/schema/ids/base/maintainerID_test.go @@ -0,0 +1,141 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "fmt" + "github.com/AssetMantle/modules/schema/ids" + "github.com/AssetMantle/modules/schema/qualified" + "github.com/AssetMantle/modules/schema/traits" + "github.com/stretchr/testify/assert" + "testing" +) + +var ( + testMaintainerID = NewMaintainerID(testClassificationID, testImmutables) + testMaintainerID2 = NewMaintainerID(testClassificationID2, testImmutables2) +) + +func TestNewMaintainerID(t *testing.T) { + type args struct { + classificationID ids.ClassificationID + immutables qualified.Immutables + } + tests := []struct { + name string + args args + want ids.MaintainerID + }{ + {"+ve", args{testClassificationID, testImmutables}, maintainerID{GenerateHashID(testClassificationID.Bytes(), testImmutables.GenerateHashID().Bytes())}}, + {"+ve with PrototypeClassificationID", args{PrototypeClassificationID(), testImmutables}, maintainerID{GenerateHashID(PrototypeClassificationID().Bytes(), testImmutables.GenerateHashID().Bytes())}}, + {"+ve with PrototypeImmutables", args{testClassificationID, testImmutables2}, maintainerID{GenerateHashID(testClassificationID.Bytes(), testImmutables2.GenerateHashID().Bytes())}}, + {"+ve with nil immutables", args{testClassificationID, nil}, maintainerID{GenerateHashID(testClassificationID.Bytes(), nil)}}, //TODO: panics for nil immutables + {"+ve with nil classificationID", args{nil, testImmutables}, maintainerID{GenerateHashID(nil, testImmutables.GenerateHashID().Bytes())}}, //TODO: panics for nil classificationID + {"+ve with both nil", args{}, maintainerID{GenerateHashID(nil, nil)}}, //TODO: panics for nil classificationID and nil immutables + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, NewMaintainerID(tt.args.classificationID, tt.args.immutables), "NewMaintainerID(%v, %v)", tt.args.classificationID, tt.args.immutables) + }) + } +} + +func TestPrototypeMaintainerID(t *testing.T) { + tests := []struct { + name string + want ids.MaintainerID + }{ + {"+ve", maintainerID{PrototypeHashID()}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, PrototypeMaintainerID(), "PrototypeMaintainerID()") + }) + } +} + +func TestReadMaintainerID(t *testing.T) { + type args struct { + maintainerIDString string + } + tests := []struct { + name string + args args + want ids.MaintainerID + wantErr assert.ErrorAssertionFunc + }{ + {"+ve with valid maintainerID", args{testMaintainerID.String()}, testMaintainerID, assert.NoError}, + {"+ve with valid maintainerID with leading and trailing spaces", args{" " + testMaintainerID.String() + " "}, testMaintainerID, assert.NoError}, //TODO: MetaDataError for leading and trailing spaces + {"+ve with empty maintainerID", args{""}, PrototypeMaintainerID(), assert.NoError}, //TODO: need to refactor the test cases + {"+ve with PrototypeMaintainerID", args{PrototypeMaintainerID().String()}, PrototypeMaintainerID(), assert.NoError}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ReadMaintainerID(tt.args.maintainerIDString) + if !tt.wantErr(t, err, fmt.Sprintf("ReadMaintainerID(%v)", tt.args.maintainerIDString)) { + return + } + assert.Equalf(t, tt.want, got, "ReadMaintainerID(%v)", tt.args.maintainerIDString) + }) + } +} + +func Test_maintainerIDFromInterface(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + args args + want maintainerID + shouldPanic bool + }{ + {"+ve with valid maintainerID", args{testMaintainerID}, testMaintainerID.(maintainerID), false}, + {"+ve PrototypeMaintainerID", args{PrototypeMaintainerID()}, PrototypeMaintainerID().(maintainerID), false}, + {"-ve with invalid type", args{testIdentityID}, maintainerID{}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.shouldPanic { + assert.Panicsf(t, func() { maintainerIDFromInterface(tt.args.i) }, "maintainerIDFromInterface(%v)", tt.args.i) + } else { + assert.Equalf(t, tt.want, maintainerIDFromInterface(tt.args.i), "maintainerIDFromInterface(%v)", tt.args.i) + } + + }) + } +} + +func Test_maintainerID_Compare(t *testing.T) { + type fields struct { + HashID ids.HashID + } + type args struct { + listable traits.Listable + } + tests := []struct { + name string + fields fields + args args + want int + shouldPanic bool + }{ + {"+ve with same maintainerID", fields{testMaintainerID.(maintainerID).HashID}, args{testMaintainerID}, 0, false}, + {"+ve with different maintainerID", fields{testMaintainerID.(maintainerID).HashID}, args{testMaintainerID2}, 1, false}, + {"+ve with different type", fields{testMaintainerID.(maintainerID).HashID}, args{testIdentityID}, -1, true}, + {"+ce with nil", fields{testMaintainerID.(maintainerID).HashID}, args{nil}, 1, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + maintainerID := maintainerID{ + HashID: tt.fields.HashID, + } + if tt.shouldPanic { + assert.Panicsf(t, func() { maintainerID.Compare(tt.args.listable) }, "maintainerID.Compare(%v)", tt.args.listable) + } else { + assert.Equalf(t, tt.want, maintainerID.Compare(tt.args.listable), "Compare(%v)", tt.args.listable) + } + }) + } +} diff --git a/schema/ids/base/orderID_test.go b/schema/ids/base/orderID_test.go new file mode 100644 index 000000000..8d6d77db0 --- /dev/null +++ b/schema/ids/base/orderID_test.go @@ -0,0 +1,133 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "fmt" + "github.com/AssetMantle/modules/schema/ids" + "github.com/AssetMantle/modules/schema/qualified" + "github.com/AssetMantle/modules/schema/traits" + "github.com/stretchr/testify/assert" + "testing" +) + +var ( + testOrderID = NewOrderID(testClassificationID, testImmutables) + testOrderID2 = NewOrderID(testClassificationID2, testImmutables2) +) + +func TestNewOrderID(t *testing.T) { + type args struct { + classificationID ids.ClassificationID + immutables qualified.Immutables + } + tests := []struct { + name string + args args + want ids.OrderID + }{ + {"+ve with Prototype ClasificationID", args{testClassificationID2, testImmutables}, orderID{GenerateHashID(testClassificationID2.Bytes(), testImmutables.GenerateHashID().Bytes())}}, + {"+ve", args{testClassificationID, testImmutables}, orderID{GenerateHashID(testClassificationID.Bytes(), testImmutables.GenerateHashID().Bytes())}}, + {"+ve with nil ClassificationID", args{nil, testImmutables}, orderID{GenerateHashID(nil, testImmutables.GenerateHashID().Bytes())}}, //TODO: implement Sanitize() + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, NewOrderID(tt.args.classificationID, tt.args.immutables), "NewOrderID(%v, %v)", tt.args.classificationID, tt.args.immutables) + }) + } +} + +func TestPrototypeOrderID(t *testing.T) { + tests := []struct { + name string + want ids.OrderID + }{ + {"+ve", orderID{GenerateHashID(testClassificationID2.Bytes(), testImmutables2.GenerateHashID().Bytes())}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, PrototypeOrderID(), "PrototypeOrderID()") + }) + } +} + +func TestReadOrderID(t *testing.T) { + type args struct { + orderIDString string + } + tests := []struct { + name string + args args + want ids.OrderID + wantErr assert.ErrorAssertionFunc + }{ + {"+ve", args{testOrderID.String()}, testOrderID, assert.NoError}, + {"+ve with Prototype", args{PrototypeOrderID().String()}, PrototypeOrderID(), assert.NoError}, //TODO: Restructure the logic + {"+ve with empty string", args{""}, nil, assert.Error}, //TODO: Restructure the logic + {"+ve with invalid string", args{"invalid"}, nil, assert.Error}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ReadOrderID(tt.args.orderIDString) + if !tt.wantErr(t, err, fmt.Sprintf("ReadOrderID(%v)", tt.args.orderIDString)) { + return + } + assert.Equalf(t, tt.want, got, "ReadOrderID(%v)", tt.args.orderIDString) + }) + } +} + +func Test_orderIDFromInterface(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + args args + want orderID + shouldPanic bool + }{ + {"+ve", args{testOrderID}, testOrderID.(orderID), false}, + {"+ve with nil", args{nil}, orderID{}, true}, + {"+ve with Prototype", args{PrototypeOrderID()}, PrototypeOrderID().(orderID), false}, + {"+ve with invalid type", args{testClassificationID}, orderID{}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.shouldPanic { + assert.Panicsf(t, func() { orderIDFromInterface(tt.args.i) }, "orderIDFromInterface(%v)", tt.args.i) + } else { + assert.Equalf(t, tt.want, orderIDFromInterface(tt.args.i), "orderIDFromInterface(%v)", tt.args.i) + } + + }) + } +} + +func Test_orderID_Compare(t *testing.T) { + type fields struct { + HashID ids.HashID + } + type args struct { + listable traits.Listable + } + tests := []struct { + name string + fields fields + args args + want int + }{ + {"+ve", fields{testOrderID.(orderID).HashID}, args{testOrderID}, 0}, + {"+ve with Prototype", fields{PrototypeOrderID().(orderID).HashID}, args{PrototypeOrderID()}, 0}, + {"-ve", fields{testOrderID.(orderID).HashID}, args{testOrderID2}, 1}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + orderID := orderID{ + HashID: tt.fields.HashID, + } + assert.Equalf(t, tt.want, orderID.Compare(tt.args.listable), "Compare(%v)", tt.args.listable) + }) + } +} diff --git a/schema/ids/base/ownableID_test.go b/schema/ids/base/ownableID_test.go new file mode 100644 index 000000000..a8ef7e6c9 --- /dev/null +++ b/schema/ids/base/ownableID_test.go @@ -0,0 +1,149 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "fmt" + "github.com/AssetMantle/modules/schema/ids" + "github.com/AssetMantle/modules/schema/traits" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" +) + +var ( + testStringID = NewStringID("ownableID") + testOwnableID = NewOwnableID(testStringID) + testStringIDPrototype = PrototypeStringID() +) + +func TestNewOwnableID(t *testing.T) { + type args struct { + stringID ids.StringID + } + tests := []struct { + name string + args args + want ids.OwnableID + }{ + {"+ve", args{testStringID}, testOwnableID}, + {"+ve with prototype", args{testStringIDPrototype}, testOwnableIDPrototype}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, NewOwnableID(tt.args.stringID), "NewOwnableID(%v)", tt.args.stringID) + }) + } +} + +func TestPrototypeOwnableID(t *testing.T) { + tests := []struct { + name string + want ids.OwnableID + }{ + {"+ve", ownableID{testStringIDPrototype}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, PrototypeOwnableID(), "PrototypeOwnableID()") + }) + } +} + +func TestReadOwnableID(t *testing.T) { + assetID, err := ReadAssetID("") + require.NoError(t, err) + type args struct { + ownableIDString string + } + tests := []struct { + name string + args args + want ids.OwnableID + wantErr assert.ErrorAssertionFunc + }{ + {"+ve", args{"ownableID"}, testOwnableID, assert.NoError}, + {"+ve with prototype", args{""}, assetID, assert.NoError}, + {"-ve with empty string", args{"ownableID"}, testOwnableID, assert.NoError}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ReadOwnableID(tt.args.ownableIDString) + if !tt.wantErr(t, err, fmt.Sprintf("ReadOwnableID(%v)", tt.args.ownableIDString)) { + return + } + assert.Equalf(t, tt.want, got, "ReadOwnableID(%v)", tt.args.ownableIDString) + }) + } +} + +func Test_ownableIDFromInterface(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + args args + want ids.OwnableID + shouldPanic bool + }{ + {"+ve", args{testOwnableID}, testOwnableID, false}, + {"+ve with prototype", args{testOwnableIDPrototype}, testOwnableIDPrototype, false}, + {"+ve Panic case", args{testOwnableIDPrototype}, testOwnableIDPrototype, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, ownableIDFromInterface(tt.args.i), "ownableIDFromInterface(%v)", tt.args.i) + }) + } +} + +func Test_ownableID_Compare(t *testing.T) { + type fields struct { + StringID ids.StringID + } + type args struct { + listable traits.Listable + } + tests := []struct { + name string + fields fields + args args + want int + }{ + {"+ve", fields{testStringID}, args{testOwnableID}, 0}, + {"+ve with prototype", fields{testStringIDPrototype}, args{testOwnableIDPrototype}, 0}, + {"-ve", fields{testStringID}, args{testOwnableIDPrototype}, 1}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ownableID := ownableID{ + StringID: tt.fields.StringID, + } + assert.Equalf(t, tt.want, ownableID.Compare(tt.args.listable), "Compare(%v)", tt.args.listable) + }) + } +} + +func Test_ownableID_IsOwnableID(t *testing.T) { + type fields struct { + StringID ids.StringID + } + tests := []struct { + name string + fields fields + }{ + {"+ve", fields{testStringID}}, + {"+ve with prototype", fields{testStringIDPrototype}}, + {"-ve", fields{testStringIDPrototype}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ownableID := ownableID{ + StringID: tt.fields.StringID, + } + ownableID.IsOwnableID() + }) + } +} diff --git a/schema/ids/base/splitID_test.go b/schema/ids/base/splitID_test.go new file mode 100644 index 000000000..62a0eb10e --- /dev/null +++ b/schema/ids/base/splitID_test.go @@ -0,0 +1,239 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package base + +import ( + "github.com/AssetMantle/modules/schema/ids" + stringUtilities "github.com/AssetMantle/modules/schema/ids/utilities" + "github.com/AssetMantle/modules/schema/traits" + "github.com/stretchr/testify/assert" + "reflect" + "testing" +) + +var ( + testIdentityIDPrototype = PrototypeIdentityID() + testOwnableIDPrototype = PrototypeOwnableID() + testIdentityID, _ = ReadIdentityID("CBepOLnJFnKO9NEyZlSv7r80nKNZFFXRqHfnsObZ_KU=") +) + +func TestNewSplitID(t *testing.T) { + type args struct { + ownerID ids.IdentityID + ownableID ids.OwnableID + } + tests := []struct { + name string + args args + want ids.SplitID + }{ + {"+ve", args{testIdentityID, testOwnableID}, splitID{testIdentityID, testOwnableID}}, + {"+ve test", args{testIdentityIDPrototype, testOwnableIDPrototype}, splitID{testIdentityIDPrototype, testOwnableIDPrototype}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewSplitID(tt.args.ownerID, tt.args.ownableID); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewSplitID() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestPrototypeSplitID(t *testing.T) { + tests := []struct { + name string + want ids.SplitID + }{ + {"+ve", splitID{testIdentityIDPrototype, testOwnableIDPrototype}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := PrototypeSplitID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("PrototypeSplitID() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestReadSplitID(t *testing.T) { + type args struct { + splitIDString string + } + tests := []struct { + name string + args args + want ids.SplitID + wantErr bool + }{ + {"+ve", args{NewSplitID(testIdentityID, testOwnableID).String()}, splitID{testIdentityID, testOwnableID}, false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ReadSplitID(tt.args.splitIDString) + if (err != nil) != tt.wantErr { + t.Errorf("ReadSplitID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("ReadSplitID() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_splitIDFromInterface(t *testing.T) { + type args struct { + i interface{} + } + tests := []struct { + name string + args args + want splitID + shouldPanic bool + }{ + {"+ve for PrototypeSplitID", args{PrototypeSplitID()}, splitID{testIdentityIDPrototype, testOwnableIDPrototype}, false}, + {"+ve", args{splitID{testIdentityID, testOwnableID}}, splitID{testIdentityID, testOwnableID}, false}, + {"-ve for panic case", args{testOwnableID}, splitID{}, true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.shouldPanic { + assert.Panics(t, func() { splitIDFromInterface(tt.args.i) }) + } else if got := splitIDFromInterface(tt.args.i); !reflect.DeepEqual(got, tt.want) { + t.Errorf("splitIDFromInterface() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_splitID_Bytes(t *testing.T) { + type fields struct { + OwnerID ids.IdentityID + OwnableID ids.OwnableID + } + tests := []struct { + name string + fields fields + want []byte + }{ + {"+ve with Prototype", fields{testIdentityIDPrototype, testOwnableID}, append(testIdentityIDPrototype.Bytes(), testOwnableID.Bytes()...)}, + {"+ve", fields{testIdentityID, testOwnableID}, append(testIdentityID.Bytes(), testOwnableID.Bytes()...)}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + splitID := splitID{ + OwnerID: tt.fields.OwnerID, + OwnableID: tt.fields.OwnableID, + } + if got := splitID.Bytes(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("Bytes() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_splitID_Compare(t *testing.T) { + type fields struct { + OwnerID ids.IdentityID + OwnableID ids.OwnableID + } + type args struct { + listable traits.Listable + } + tests := []struct { + name string + fields fields + args args + want int + }{ + {"+ve", fields{testIdentityID, testOwnableID}, args{splitID{testIdentityID, testOwnableID}}, 0}, + {"-ve", fields{testIdentityIDPrototype, testOwnableID}, args{splitID{testIdentityIDPrototype, testOwnableIDPrototype}}, 1}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + splitID := splitID{ + OwnerID: tt.fields.OwnerID, + OwnableID: tt.fields.OwnableID, + } + if got := splitID.Compare(tt.args.listable); got != tt.want { + t.Errorf("Compare() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_splitID_GetOwnableID(t *testing.T) { + type fields struct { + OwnerID ids.IdentityID + OwnableID ids.OwnableID + } + tests := []struct { + name string + fields fields + want ids.ID + }{ + {"+ve", fields{testIdentityID, testOwnableID}, testOwnableID}, + {"+ve", fields{testIdentityIDPrototype, testOwnableID}, testOwnableID}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + splitID := splitID{ + OwnerID: tt.fields.OwnerID, + OwnableID: tt.fields.OwnableID, + } + if got := splitID.GetOwnableID(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetOwnableID() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_splitID_IsSplitID(t *testing.T) { + type fields struct { + OwnerID ids.IdentityID + OwnableID ids.OwnableID + } + tests := []struct { + name string + fields fields + }{ + {"+ve", fields{testIdentityID, testOwnableID}}, + {"+ve", fields{testIdentityIDPrototype, testOwnableIDPrototype}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + splitID := splitID{ + OwnerID: tt.fields.OwnerID, + OwnableID: tt.fields.OwnableID, + } + splitID.IsSplitID() + }) + } +} + +func Test_splitID_String(t *testing.T) { + type fields struct { + OwnerID ids.IdentityID + OwnableID ids.OwnableID + } + tests := []struct { + name string + fields fields + want string + }{ + {"+ve with prototype", fields{testIdentityIDPrototype, testOwnableIDPrototype}, stringUtilities.JoinIDStrings(testIdentityIDPrototype.String(), testOwnableIDPrototype.String())}, + {"+ve", fields{testIdentityID, testOwnableID}, stringUtilities.JoinIDStrings(testIdentityID.String(), testOwnableID.String())}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + splitID := splitID{ + OwnerID: tt.fields.OwnerID, + OwnableID: tt.fields.OwnableID, + } + if got := splitID.String(); got != tt.want { + t.Errorf("String() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/schema/ids/utilities/id_test.go b/schema/ids/utilities/id_test.go new file mode 100644 index 000000000..8bc58282d --- /dev/null +++ b/schema/ids/utilities/id_test.go @@ -0,0 +1,53 @@ +// Copyright [2021] - [2022], AssetMantle Pte. Ltd. and the code contributors +// SPDX-License-Identifier: Apache-2.0 + +package utilities + +import ( + "reflect" + "testing" +) + +func TestJoinIDStrings(t *testing.T) { + type args struct { + idStrings []string + } + tests := []struct { + name string + args args + want string + }{ + {"+ve empty", args{[]string{}}, ""}, + {"+ve single", args{[]string{"a"}}, "a"}, + {"+ve double", args{[]string{"a", "b"}}, "a.b"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := JoinIDStrings(tt.args.idStrings...); got != tt.want { + t.Errorf("JoinIDStrings() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestSplitCompositeIDString(t *testing.T) { + type args struct { + idString string + } + tests := []struct { + name string + args args + want []string + }{ + {"+ve empty", args{""}, []string{""}}, + {"+ve single", args{"a"}, []string{"a"}}, + {"+ve double", args{"a.b"}, []string{"a", "b"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := SplitCompositeIDString(tt.args.idString); !reflect.DeepEqual(got, tt.want) { + t.Errorf("SplitCompositeIDString() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/schema/lists/base/dataList.go b/schema/lists/base/dataList.go index 70926d412..0462fc687 100644 --- a/schema/lists/base/dataList.go +++ b/schema/lists/base/dataList.go @@ -27,16 +27,33 @@ func (dataList dataList) GetList() []data.Data { return DataList } func (dataList dataList) Search(data data.Data) (int, bool) { + if sanitizedList, err := dataList.Sanitize(); err == nil { + dataList.List = NewList(dataToListables(sanitizedList.(lists.DataList).GetList()...)...) + } return dataList.List.Search(data) } func (dataList dataList) Add(data ...data.Data) lists.DataList { + if sanitizedList, err := dataList.Sanitize(); err == nil { + dataList.List = NewList(dataToListables(sanitizedList.(lists.DataList).GetList()...)...) + } dataList.List = dataList.List.Add(dataToListables(data...)...) return dataList } func (dataList dataList) Remove(data ...data.Data) lists.DataList { + if sanitizedList, err := dataList.Sanitize(); err == nil { + dataList.List = NewList(dataToListables(sanitizedList.(lists.DataList).GetList()...)...) + } dataList.List = dataList.List.Remove(dataToListables(data...)...) return dataList } + +func (dataList dataList) Sanitize() (lists.DataList, error) { + if dataList.List == nil { + dataList.List = NewList() + } + return dataList, nil +} + func dataToListables(data ...data.Data) []traits.Listable { listables := make([]traits.Listable, len(data)) diff --git a/schema/lists/base/dataList_test.go b/schema/lists/base/dataList_test.go index 7c76f0501..6085d79f7 100644 --- a/schema/lists/base/dataList_test.go +++ b/schema/lists/base/dataList_test.go @@ -52,6 +52,7 @@ func Test_dataList_Add(t *testing.T) { want lists.DataList }{ {"+ve with no dataList", fields{List: NewList(dataToListables([]data.Data{}...)...)}, args{}, dataList{List: NewList(dataToListables([]data.Data{}...)...)}}, + {"+ve with DataList", fields{List: NewList(dataToListables([]data.Data{NewStringData("Data")}...)...)}, args{[]data.Data{NewStringData("Data1")}}, dataList{List: NewList(dataToListables([]data.Data{NewStringData("Data"), NewStringData("Data1")}...)...)}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -105,6 +106,7 @@ func Test_dataList_Remove(t *testing.T) { }{ {"+ve with empty struct", fields{NewList(dataToListables([]data.Data{}...)...)}, args{}, dataList{List: NewList(dataToListables([]data.Data{}...)...)}}, {"+ve", fields{NewList(dataToListables([]data.Data{NewStringData("Data")}...)...)}, args{[]data.Data{NewStringData("Data")}}, dataList{List: NewList(dataToListables([]data.Data{}...)...)}}, + {"+ve with nil", fields{nil}, args{[]data.Data{NewStringData("Data")}}, dataList{List: NewList(dataToListables([]data.Data{}...)...)}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -134,6 +136,7 @@ func Test_dataList_Search(t *testing.T) { }{ {"+ve with empty struct", fields{NewList(dataToListables([]data.Data{}...)...)}, args{NewStringData("Data")}, 0, false}, // TODO: fix this {"+ve", fields{NewList(dataToListables([]data.Data{NewStringData("Data")}...)...)}, args{NewStringData("Data")}, 0, true}, + {"+ve with nil", fields{nil}, args{NewStringData("Data")}, 0, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -177,6 +180,11 @@ type stringData struct { Value string `json:"value"` } +func (stringData stringData) Sanitize() (data.Data, error) { + //TODO implement me + panic("implement me") +} + var _ data.StringData = (*stringData)(nil) func (stringData stringData) GetID() ids.DataID { diff --git a/schema/lists/base/idList.go b/schema/lists/base/idList.go index eb1d1b153..378b0d8d9 100644 --- a/schema/lists/base/idList.go +++ b/schema/lists/base/idList.go @@ -25,16 +25,33 @@ func (idList idList) GetList() []ids.ID { return returnIDList } func (idList idList) Search(id ids.ID) (index int, found bool) { + if sanitizedList, err := idList.Sanitize(); err == nil { + idList.List = NewList(idsToListables(sanitizedList.(lists.IDList).GetList()...)...) + } return idList.List.Search(id) } func (idList idList) Add(ids ...ids.ID) lists.IDList { + if sanitizedList, err := idList.Sanitize(); err == nil { + idList.List = NewList(idsToListables(sanitizedList.(lists.IDList).GetList()...)...) + } idList.List = idList.List.Add(idsToListables(ids...)...) return idList } func (idList idList) Remove(ids ...ids.ID) lists.IDList { + if sanitizedList, err := idList.Sanitize(); err == nil { + idList.List = NewList(idsToListables(sanitizedList.(lists.IDList).GetList()...)...) + } idList.List = idList.List.Remove(idsToListables(ids...)...) return idList } + +func (idList idList) Sanitize() (lists.IDList, error) { + if idList.List == nil { + idList.List = NewList() + } + return idList, nil +} + func idsToListables(ids ...ids.ID) []traits.Listable { listables := make([]traits.Listable, len(ids)) for i, id := range ids { diff --git a/schema/lists/base/idList_test.go b/schema/lists/base/idList_test.go index 82e3820da..2ab5767c1 100644 --- a/schema/lists/base/idList_test.go +++ b/schema/lists/base/idList_test.go @@ -27,8 +27,9 @@ func Test_idList_Add(t *testing.T) { args args want lists.IDList }{ - {"+ve for nil", fields{NewList()}, args{[]ids.ID{NewStringID("ID")}}, idList{NewList(idsToListables([]ids.ID{NewStringID("ID")}...)...)}}, // TODO: panic for nil - {"+ve", fields{NewList(idsToListables([]ids.ID{NewStringID("ID")}...)...)}, args{[]ids.ID{NewStringID("ID1")}}, idList{NewList(idsToListables([]ids.ID{NewStringID("ID"), NewStringID("ID1")}...)...)}}, // TODO: report + {"+ve for nil", fields{nil}, args{[]ids.ID{NewStringID("ID")}}, idList{NewList(idsToListables([]ids.ID{NewStringID("ID")}...)...)}}, + {"+ve for empty", fields{NewList()}, args{[]ids.ID{NewStringID("ID")}}, idList{NewList(idsToListables([]ids.ID{NewStringID("ID")}...)...)}}, + {"+ve", fields{NewList(idsToListables([]ids.ID{NewStringID("ID")}...)...)}, args{[]ids.ID{NewStringID("ID1")}}, idList{NewList(idsToListables([]ids.ID{NewStringID("ID"), NewStringID("ID1")}...)...)}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -51,7 +52,8 @@ func Test_idList_GetList(t *testing.T) { fields fields want []ids.ID }{ - {"+ve with nil", fields{NewList()}, []ids.ID{}}, + {"+ve with empty List", fields{NewList()}, []ids.ID{}}, + {"+ve with nil List", fields{nil}, []ids.ID{}}, {"+ve", fields{NewList(idsToListables([]ids.ID{NewStringID("Data")}...)...)}, []ids.ID{NewStringID("Data").(ids.ID)}}, } for _, tt := range tests { @@ -81,6 +83,7 @@ func Test_idList_Remove(t *testing.T) { }{ {"-ve with no removal", fields{NewList(idsToListables(NewStringID("ID1"), NewStringID("ID2"), NewStringID("ID3"))...)}, args{}, idList{NewList(idsToListables(NewStringID("ID1"), NewStringID("ID2"), NewStringID("ID3"))...)}}, {"+ve with removal", fields{NewList(idsToListables(NewStringID("ID1"), NewStringID("ID2"), NewStringID("ID3"))...)}, args{[]ids.ID{NewStringID("ID3")}}, idList{NewList(idsToListables(NewStringID("ID1"), NewStringID("ID2"))...)}}, + {"+ve with nil", fields{nil}, args{[]ids.ID{NewStringID("ID")}}, idList{NewList(idsToListables([]ids.ID{}...)...)}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -108,7 +111,8 @@ func Test_idList_Search(t *testing.T) { wantIndex int wantFound bool }{ - {"+ve with nil", fields{NewList(idsToListables([]ids.ID{}...)...)}, args{NewStringID("ID")}, 0, false}, // TODO report issue + {"+ve with Empty List", fields{NewList(idsToListables([]ids.ID{}...)...)}, args{NewStringID("ID")}, 0, false}, + {"+ve with nil", fields{nil}, args{NewStringID("ID")}, 0, false}, {"+ve", fields{NewList(idsToListables([]ids.ID{NewStringID("ID")}...)...)}, args{NewStringID("ID")}, 0, true}, {"-ve with no entry", fields{NewList(idsToListables([]ids.ID{NewStringID("ID")}...)...)}, args{NewStringID("ID1")}, 1, false}, } diff --git a/schema/lists/base/list.go b/schema/lists/base/list.go index 889e448e4..8841eb490 100644 --- a/schema/lists/base/list.go +++ b/schema/lists/base/list.go @@ -4,6 +4,7 @@ package base import ( + "github.com/AssetMantle/modules/schema/errors/constants" "sort" "github.com/AssetMantle/modules/schema/lists" @@ -49,6 +50,9 @@ func (list list) Add(listables ...traits.Listable) lists.List { return updatedList } func (list list) Remove(listables ...traits.Listable) lists.List { + if sanitizedList, err := list.Sanitize(); err != nil { + return sanitizedList + } updatedList := list for _, listable := range listables { @@ -60,6 +64,9 @@ func (list list) Remove(listables ...traits.Listable) lists.List { return updatedList } func (list list) Mutate(listables ...traits.Listable) lists.List { + if sanitizedList, err := list.Sanitize(); err != nil { + return sanitizedList + } // TODO write test updatedList := list @@ -72,6 +79,13 @@ func (list list) Mutate(listables ...traits.Listable) lists.List { return updatedList } +func (list list) Sanitize() (lists.List, error) { + if list == nil { + return NewList([]traits.Listable{}...), constants.MetaDataError + } + return list, nil +} + func NewList(listables ...traits.Listable) lists.List { list := list(listables) sort.Slice(list, func(i, j int) bool { diff --git a/schema/lists/base/list_test.go b/schema/lists/base/list_test.go index 757c0e60c..75462d8e0 100644 --- a/schema/lists/base/list_test.go +++ b/schema/lists/base/list_test.go @@ -7,18 +7,12 @@ import ( "reflect" "testing" - "github.com/stretchr/testify/assert" - - "github.com/AssetMantle/modules/schema/ids/base" "github.com/AssetMantle/modules/schema/lists" baseProperties "github.com/AssetMantle/modules/schema/properties/base" "github.com/AssetMantle/modules/schema/traits" ) func TestNewList(t *testing.T) { - assert.Panics(t, func() { - NewList(base.NewPropertyID(NewStringID("ID"), NewStringID("Data")), NewStringID("ID")) - }) type args struct { listables []traits.Listable } @@ -49,8 +43,9 @@ func Test_list_Add(t *testing.T) { args args want lists.List }{ - {"+ve with nil", list{}, args{[]traits.Listable{}}, list{}}, + {"+ve with Empty List", list{}, args{[]traits.Listable{}}, list{}}, {"+ve", []traits.Listable{}, args{[]traits.Listable{NewStringID("ID")}}, list{NewStringID("ID")}}, + {"+ve with Nil list", nil, args{[]traits.Listable{NewStringID("ID")}}, list{NewStringID("ID")}}, {"+ve", list{NewStringID("ID")}, args{[]traits.Listable{NewStringID("ID1")}}, list{NewStringID("ID"), NewStringID("ID1")}}, } for _, tt := range tests { @@ -91,7 +86,8 @@ func Test_list_Mutate(t *testing.T) { want lists.List }{ {"+ve", []traits.Listable{baseProperties.NewMetaProperty(NewStringID("ID1"), NewStringData("Data1"))}, args{[]traits.Listable{baseProperties.NewMetaProperty(NewStringID("ID1"), NewStringData("Data2"))}}, list{baseProperties.NewMetaProperty(NewStringID("ID1"), NewStringData("Data2"))}}, - {"+ve with nil", list{}, args{}, list{}}, + {"+ve with nil list", nil, args{[]traits.Listable{baseProperties.NewMetaProperty(NewStringID("ID1"), NewStringData("Data2"))}}, list{}}, + {"+ve with Empty List", list{}, args{}, list{}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -112,8 +108,9 @@ func Test_list_Remove(t *testing.T) { args args want lists.List }{ - {"+ve for nil", []traits.Listable{}, args{}, list{}}, + {"+ve for Empty List", []traits.Listable{}, args{}, list{}}, {"+ve", []traits.Listable{NewStringID("ID")}, args{[]traits.Listable{NewStringID("ID2")}}, list{NewStringID("ID")}}, + {"+ve with nil", nil, args{[]traits.Listable{NewStringID("ID2")}}, list{}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -135,7 +132,7 @@ func Test_list_Search(t *testing.T) { want int want1 bool }{ - {"+ve for nil", []traits.Listable{}, args{}, 0, false}, // TODO: panics if list is nil + {"+ve for nil", []traits.Listable{}, args{}, 0, false}, {"+ve", []traits.Listable{NewStringID("ID")}, args{NewStringID("ID")}, 0, true}, } for _, tt := range tests { diff --git a/schema/lists/base/propertyList.go b/schema/lists/base/propertyList.go index 9d45a3870..970a40dfd 100644 --- a/schema/lists/base/propertyList.go +++ b/schema/lists/base/propertyList.go @@ -1,6 +1,7 @@ package base import ( + "github.com/AssetMantle/modules/schema/errors/constants" "github.com/AssetMantle/modules/schema/ids" "github.com/AssetMantle/modules/schema/lists" "github.com/AssetMantle/modules/schema/properties" @@ -15,6 +16,15 @@ type propertyList struct { var _ lists.PropertyList = (*propertyList)(nil) func (propertyList propertyList) GetProperty(propertyID ids.PropertyID) properties.Property { + if sanitizedPropertyList, err := propertyList.Sanitize(); err == nil { + propertyList.List = NewList(propertiesToListables(sanitizedPropertyList.(lists.PropertyList).GetList()...)...) + } + switch propertyID.(type) { + case ids.PropertyID: + propertyID = propertyID.(ids.PropertyID) + default: + panic(constants.MetaDataError) + } if i, found := propertyList.Search(base.NewEmptyMesaPropertyFromID(propertyID)); found { return propertyList.GetList()[i] } @@ -22,6 +32,9 @@ func (propertyList propertyList) GetProperty(propertyID ids.PropertyID) properti return nil } func (propertyList propertyList) GetList() []properties.Property { + if propertyList.List == nil { + propertyList.List = NewList() + } Properties := make([]properties.Property, propertyList.List.Size()) for i, listable := range propertyList.List.Get() { Properties[i] = listable.(properties.Property) @@ -29,6 +42,9 @@ func (propertyList propertyList) GetList() []properties.Property { return Properties } func (propertyList propertyList) GetPropertyIDList() lists.IDList { + if sanitizedPropertyList, err := propertyList.Sanitize(); err == nil { + propertyList.List = NewList(propertiesToListables(sanitizedPropertyList.(lists.PropertyList).GetList()...)...) + } propertyIDList := NewIDList() for _, property := range propertyList.GetList() { propertyIDList = propertyIDList.Add(property.GetID()) @@ -36,18 +52,30 @@ func (propertyList propertyList) GetPropertyIDList() lists.IDList { return propertyIDList } func (propertyList propertyList) Add(properties ...properties.Property) lists.PropertyList { + if sanitizedPropertyList, err := propertyList.Sanitize(); err == nil { + propertyList.List = NewList(propertiesToListables(sanitizedPropertyList.(lists.PropertyList).GetList()...)...) + } propertyList.List = propertyList.List.Add(propertiesToListables(properties...)...) return propertyList } func (propertyList propertyList) Remove(properties ...properties.Property) lists.PropertyList { + if sanitizedPropertyList, err := propertyList.Sanitize(); err == nil { + propertyList.List = NewList(propertiesToListables(sanitizedPropertyList.(lists.PropertyList).GetList()...)...) + } propertyList.List = propertyList.List.Remove(propertiesToListables(properties...)...) return propertyList } func (propertyList propertyList) Mutate(properties ...properties.Property) lists.PropertyList { + if sanitizedPropertyList, err := propertyList.Sanitize(); err == nil { + propertyList.List = NewList(propertiesToListables(sanitizedPropertyList.(lists.PropertyList).GetList()...)...) + } propertyList.List = propertyList.List.Mutate(propertiesToListables(properties...)...) return propertyList } func (propertyList propertyList) ScrubData() lists.PropertyList { + if sanitizedPropertyList, err := propertyList.Sanitize(); err == nil { + propertyList.List = NewList(propertiesToListables(sanitizedPropertyList.(lists.PropertyList).GetList()...)...) + } newPropertyList := NewPropertyList() for _, listable := range propertyList.List.Get() { if property := listable.(properties.Property); property.IsMeta() { @@ -58,6 +86,14 @@ func (propertyList propertyList) ScrubData() lists.PropertyList { } return newPropertyList } + +func (propertyList propertyList) Sanitize() (lists.PropertyList, error) { + if propertyList.List == nil { + propertyList.List = NewList() + } + return propertyList, nil +} + func propertiesToListables(properties ...properties.Property) []traits.Listable { listables := make([]traits.Listable, len(properties)) for i, property := range properties { diff --git a/schema/lists/base/propertyList_test.go b/schema/lists/base/propertyList_test.go index 44b06bfc1..d01143b0c 100644 --- a/schema/lists/base/propertyList_test.go +++ b/schema/lists/base/propertyList_test.go @@ -4,6 +4,7 @@ package base import ( + "github.com/stretchr/testify/assert" "reflect" "testing" @@ -122,22 +123,26 @@ func Test_propertyList_GetProperty(t *testing.T) { propertyID ids.PropertyID } tests := []struct { - name string - fields fields - args args - want properties.Property + name string + fields fields + args args + want properties.Property + shouldPanic bool }{ - {"+ve Meta", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D"))}, baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}, - {"+ve Mesa", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMesaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D"))}, baseProperties.NewMesaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}, - {"-ve", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{propertyID: nil}, baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}, // TODO: panics if propertyID is nil - {"-ve", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewEmptyMetaPropertyFromID(baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D")))}...)...)}, args{baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D"))}, baseProperties.NewEmptyMetaPropertyFromID(baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D")))}, + {"+ve Meta", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D"))}, baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1))), false}, + {"+ve Mesa", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMesaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D"))}, baseProperties.NewMesaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1))), false}, + {"-ve with nil arg", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{propertyID: nil}, baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1))), true}, // TODO: panics if propertyID is nil + {"-ve", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewEmptyMetaPropertyFromID(baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D")))}...)...)}, args{baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D"))}, baseProperties.NewEmptyMetaPropertyFromID(baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D"))), false}, + {"+ve with nil", fields{nil}, args{baseIDs.NewPropertyID(NewStringID("supply"), NewStringID("D"))}, nil, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { propertyList := propertyList{ List: tt.fields.List, } - if got := propertyList.GetProperty(tt.args.propertyID); !reflect.DeepEqual(got, tt.want) { + if tt.shouldPanic { + assert.Panics(t, func() { propertyList.GetProperty(tt.args.propertyID) }) + } else if got := propertyList.GetProperty(tt.args.propertyID); !reflect.DeepEqual(got, tt.want) { t.Errorf("GetProperty() = %v, want %v", got, tt.want) } }) @@ -154,6 +159,7 @@ func Test_propertyList_GetPropertyIDList(t *testing.T) { want lists.IDList }{ {"+ve", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, NewIDList().Add(baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1))).GetID())}, + {"+ve with nil list", fields{nil}, NewIDList()}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -181,7 +187,8 @@ func Test_propertyList_Mutate(t *testing.T) { want lists.PropertyList }{ {"+ve", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{[]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(2)))}}, NewPropertyList([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(2)))}...)}, - // {"+ve", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{[]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewStringData("test"))}}, NewPropertyList([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewStringData("test"))}...)}, //TODO: Should handle error if different property data is tried to mutate + {"+ve with nil", fields{nil}, args{[]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(2)))}}, NewPropertyList([]properties.Property{}...)}, + {"+ve", fields{NewList(propertiesToListables([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)...)}, args{[]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewStringData("test"))}}, NewPropertyList([]properties.Property{baseProperties.NewMetaProperty(NewStringID("supply"), NewDecData(sdkTypes.NewDec(1)))}...)}, //TODO: Should handle error if different property data is tried to mutate } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -246,6 +253,8 @@ func Test_propertyList_ScrubData(t *testing.T) { } } +// Mocks for DecData + type decData struct { Value sdkTypes.Dec `json:"value"` } @@ -292,6 +301,11 @@ func (decData decData) Get() sdkTypes.Dec { return decData.Value } +func (decData decData) Sanitize() (data.Data, error) { + //TODO implement me + panic("implement me") +} + func decDataFromInterface(listable traits.Listable) (decData, error) { switch value := listable.(type) { case decData: diff --git a/schema/lists/dataList.go b/schema/lists/dataList.go index d8b50f793..faba8a6c8 100644 --- a/schema/lists/dataList.go +++ b/schema/lists/dataList.go @@ -13,4 +13,7 @@ type DataList interface { Search(data.Data) (int, bool) Add(...data.Data) DataList Remove(...data.Data) DataList + + // Sanitize dataList + Sanitize() (DataList, error) } diff --git a/schema/lists/idList.go b/schema/lists/idList.go index 15c0d1131..118c9bf38 100644 --- a/schema/lists/idList.go +++ b/schema/lists/idList.go @@ -13,4 +13,7 @@ type IDList interface { Search(ids.ID) (index int, found bool) Add(...ids.ID) IDList Remove(...ids.ID) IDList + + // Sanitize idList + Sanitize() (IDList, error) } diff --git a/schema/lists/list.go b/schema/lists/list.go index 0dd3ca111..73f78e89b 100644 --- a/schema/lists/list.go +++ b/schema/lists/list.go @@ -24,4 +24,7 @@ type List interface { Add(...traits.Listable) List // TODO prevent compare panic Remove(...traits.Listable) List // TODO prevent compare panic Mutate(...traits.Listable) List // TODO prevent compare panic + + // Sanitize List + Sanitize() (List, error) } diff --git a/schema/lists/propertyList.go b/schema/lists/propertyList.go index 8ebc1a918..ca2213e9d 100644 --- a/schema/lists/propertyList.go +++ b/schema/lists/propertyList.go @@ -15,4 +15,7 @@ type PropertyList interface { Mutate(...properties.Property) PropertyList ScrubData() PropertyList + + // Sanitize propertyList + Sanitize() (PropertyList, error) } diff --git a/schema/properties/base/mesaProperty_test.go b/schema/properties/base/mesaProperty_test.go index bbb716b66..0c9a56f02 100644 --- a/schema/properties/base/mesaProperty_test.go +++ b/schema/properties/base/mesaProperty_test.go @@ -330,6 +330,11 @@ type stringData struct { Value string `json:"value"` } +func (stringData stringData) Sanitize() (data.Data, error) { + //TODO implement me + panic("implement me") +} + var _ data.StringData = (*stringData)(nil) func (stringData stringData) GetID() ids.DataID {