package kubecost import ( "reflect" "testing" "time" "golang.org/x/exp/slices" ) func TestDiff(t *testing.T) { start := time.Now().AddDate(0, 0, -1) end := time.Now() window1 := NewWindow(&start, &end) node1 := NewNode("node1", "cluster1", "123abc", start, end, window1) node2 := NewNode("node2", "cluster1", "123abc", start, end, window1) node3 := NewNode("node3", "cluster1", "123abc", start, end, window1) node4 := NewNode("node4", "cluster1", "123abc", start, end, window1) disk1 := NewDisk("disk1", "cluster1", "123abc", start, end, window1) disk2 := NewDisk("disk2", "cluster1", "123abc", start, end, window1) cases := map[string]struct { inputAssetsBefore []Asset inputAssetsAfter []Asset expected []Diff[Asset] }{ "added node": { inputAssetsBefore: []Asset{node1, node2}, inputAssetsAfter: []Asset{node1, node2, node3}, expected: []Diff[Asset]{{node3, DiffAdded}}, }, "multiple adds": { inputAssetsBefore: []Asset{node1, node2}, inputAssetsAfter: []Asset{node1, node2, node3, node4}, expected: []Diff[Asset]{{node3, DiffAdded}, {node4, DiffAdded}}, }, "removed node": { inputAssetsBefore: []Asset{node1, node2}, inputAssetsAfter: []Asset{node2}, expected: []Diff[Asset]{{node1, DiffRemoved}}, }, "multiple removes": { inputAssetsBefore: []Asset{node1, node2, node3}, inputAssetsAfter: []Asset{node2}, expected: []Diff[Asset]{{node1, DiffRemoved}, {node3, DiffRemoved}}, }, "remove all": { inputAssetsBefore: []Asset{node1, node2}, inputAssetsAfter: []Asset{}, expected: []Diff[Asset]{{node1, DiffRemoved}, {node2, DiffRemoved}}, }, "add and remove": { inputAssetsBefore: []Asset{node1, node2}, inputAssetsAfter: []Asset{node2, node3}, expected: []Diff[Asset]{{node1, DiffRemoved}, {node3, DiffAdded}}, }, "no change": { inputAssetsBefore: []Asset{node1, node2}, inputAssetsAfter: []Asset{node1, node2}, expected: []Diff[Asset]{}, }, "order switch": { inputAssetsBefore: []Asset{node2, node1}, inputAssetsAfter: []Asset{node1, node2}, expected: []Diff[Asset]{}, }, "disk add": { inputAssetsBefore: []Asset{disk1, node1}, inputAssetsAfter: []Asset{disk1, node1, disk2}, expected: []Diff[Asset]{{disk2, DiffAdded}}, }, "disk and node add": { inputAssetsBefore: []Asset{disk1, node1}, inputAssetsAfter: []Asset{disk1, node1, disk2, node2}, expected: []Diff[Asset]{{disk2, DiffAdded}, {node2, DiffAdded}}, }, "disk and node removed": { inputAssetsBefore: []Asset{disk1, node1, disk2, node2}, inputAssetsAfter: []Asset{disk2, node2}, expected: []Diff[Asset]{{disk1, DiffRemoved}, {node1, DiffRemoved}}, }, } for name, tc := range cases { t.Run(name, func(t *testing.T) { as1 := NewAssetSet(start, end, tc.inputAssetsBefore...) as2 := NewAssetSet(start, end, tc.inputAssetsAfter...) result := DiffAsset(as1.Clone(), as2.Clone()) slices.SortFunc(result, func(a, b Diff[Asset]) bool { return a.Entity.Properties().Name < b.Entity.Properties().Name }) slices.SortFunc(tc.expected, func(a, b Diff[Asset]) bool { return a.Entity.Properties().Name < b.Entity.Properties().Name }) if !reflect.DeepEqual(result, tc.expected) { t.Fatalf("expected %+v; got %+v", tc.expected, result) } }) } }