From 8a57ac0fcfc00d8497cce88e81adc742e2d46673 Mon Sep 17 00:00:00 2001 From: Yuvraj Kolkar Date: Fri, 30 Jan 2026 21:05:58 +0530 Subject: [PATCH 1/2] Migrate Tiredstore Ginkgo/Gomega Signed-off-by: Yuvraj Kolkar --- .../tieredstore/tiered_store_suite_test.go | 29 + pkg/utils/tieredstore/tiered_store_test.go | 742 +++++++++--------- 2 files changed, 417 insertions(+), 354 deletions(-) create mode 100644 pkg/utils/tieredstore/tiered_store_suite_test.go diff --git a/pkg/utils/tieredstore/tiered_store_suite_test.go b/pkg/utils/tieredstore/tiered_store_suite_test.go new file mode 100644 index 00000000000..2d8999db773 --- /dev/null +++ b/pkg/utils/tieredstore/tiered_store_suite_test.go @@ -0,0 +1,29 @@ +/* +Copyright 2023 The Fluid Author. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tieredstore + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestTieredStore(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "TieredStore Suite") +} diff --git a/pkg/utils/tieredstore/tiered_store_test.go b/pkg/utils/tieredstore/tiered_store_test.go index aa18e35f979..bad017035d5 100644 --- a/pkg/utils/tieredstore/tiered_store_test.go +++ b/pkg/utils/tieredstore/tiered_store_test.go @@ -1,4 +1,5 @@ /* +Copyright 2023 The Fluid Author. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,7 +17,8 @@ limitations under the License. package tieredstore import ( - "testing" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" datav1alpha1 "github.com/fluid-cloudnative/fluid/api/v1alpha1" "github.com/fluid-cloudnative/fluid/pkg/common" @@ -24,388 +26,420 @@ import ( "k8s.io/apimachinery/pkg/api/resource" ) -func TestLen(t *testing.T) { - testCases := map[string]sortMediumType{ - "test case 1": []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - common.SSD, - common.HDD, - }, - "test case 2": []common.MediumType{ - common.SSD, - common.HDD, - }, - "test case 3": []common.MediumType{ - common.HDD, - common.SSD, - common.HDD, - }, - } - for k, item := range testCases { - if item.Len() != len(item) { - t.Errorf("%s check failure,want:%v,got:%v", k, len(item), item.Len()) - } - } -} +var _ = Describe("TieredStore", func() { -func TestSwap(t *testing.T) { - testCases := map[string]struct { - sortMedium sortMediumType - i int - j int - }{ - "test case 1": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - }, - i: 2, - j: 1, - }, - "test case 2": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - common.SSD, - }, - i: 1, - j: 3, - }, - "test case 3": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - common.SSD, - common.HDD, - }, - i: 4, - j: 2, - }, - } - for k, item := range testCases { - var temp = make([]common.MediumType, len(item.sortMedium)) - _ = copy(temp, item.sortMedium) - if item.i < item.sortMedium.Len() && item.j < item.sortMedium.Len() { - item.sortMedium.Swap(item.i, item.j) - if temp[item.i] != item.sortMedium[item.j] || temp[item.j] != item.sortMedium[item.i] { - t.Errorf("%s check failure", k) - } - } else { - t.Errorf("%s is not suitable", k) - } - } -} - -func TestLess(t *testing.T) { - testCases := map[string]struct { - sortMedium sortMediumType - i int - j int - want bool - }{ - "test case 1": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - }, - i: 2, - j: 1, - want: false, - }, - "test case 2": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - common.SSD, - }, - i: 1, - j: 3, - want: false, - }, - "test case 3": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - common.SSD, - common.Memory, - }, - i: 4, - j: 2, - want: true, - }, - "test case 4": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.SSD, - common.Memory, - }, - i: 3, - j: 2, - want: true, - }, - } - for k, item := range testCases { - if item.i < item.sortMedium.Len() && item.j < item.sortMedium.Len() { - result := item.sortMedium.Less(item.i, item.j) - if result != item.want { - t.Errorf("%s check failure,want:%t,got:%t", k, item.want, result) - } - } else { - t.Errorf("%s is not suitable", k) - } - - } -} - -func TestMakeMediumTypeSorted(t *testing.T) { - testCases := map[string]struct { - sortMedium sortMediumType - want sortMediumType - }{ - "test case 1": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - }, - want: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - }, - }, - "test case 2": { - sortMedium: []common.MediumType{ - common.SSD, - common.HDD, - common.SSD, - "apple", - "baba", - common.Memory, - }, - want: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - }, - }, - "test case 3": { - sortMedium: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - common.SSD, - common.HDD, - }, - want: []common.MediumType{ - common.Memory, - common.SSD, - common.HDD, - }, - }, - } - for k, item := range testCases { - newMediumTypes := makeMediumTypeSorted(item.sortMedium) - if len(newMediumTypes) >= 2 { - for index := 1; index < len(newMediumTypes); index++ { - if newMediumTypes[index-1] == newMediumTypes[index] { - t.Errorf("%s cannot paas, because of repeat MediumTypes", k) + Describe("sortMediumType", func() { + Context("Len", func() { + It("should return the correct length", func() { + testCases := []struct { + name string + sortMedium sortMediumType + }{ + { + name: "5 elements", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + common.SSD, + common.HDD, + }, + }, + { + name: "2 elements", + sortMedium: []common.MediumType{ + common.SSD, + common.HDD, + }, + }, + { + name: "3 elements", + sortMedium: []common.MediumType{ + common.HDD, + common.SSD, + common.HDD, + }, + }, } - if common.GetDefaultTieredStoreOrder(newMediumTypes[index-1]) > common.GetDefaultTieredStoreOrder(newMediumTypes[index]) { - t.Errorf("%s cannot paas, because of wrong sort result", k) + + for _, tc := range testCases { + Expect(tc.sortMedium.Len()).To(Equal(len(tc.sortMedium)), "test case: %s", tc.name) } - } - } - } -} + }) + }) -func TestGetLevelStorageMap(t *testing.T) { - testCases := map[string]struct { - tieredStore datav1alpha1.TieredStore - want map[common.CacheStoreType]int64 - }{ - "test case 1": { - tieredStore: datav1alpha1.TieredStore{}, - want: map[common.CacheStoreType]int64{}, - }, - "test case 2": { - tieredStore: datav1alpha1.TieredStore{ - Levels: []datav1alpha1.Level{ + Context("Swap", func() { + It("should correctly swap elements", func() { + testCases := []struct { + name string + sortMedium sortMediumType + i int + j int + }{ { - MediumType: common.Memory, - Path: "/path/to/cache1/,/path/to/cache2/", - Quota: resource.NewQuantity(124, resource.BinarySI), + name: "swap indices 2 and 1", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + }, + i: 2, + j: 1, }, - }, - }, - want: map[common.CacheStoreType]int64{ - common.MemoryCacheStore: 124, - }, - }, - "test case 3": { - tieredStore: datav1alpha1.TieredStore{ - Levels: []datav1alpha1.Level{ { - MediumType: common.Memory, - Path: "/path/to/cache1/,/path/to/cache2/", - Quota: resource.NewQuantity(124, resource.BinarySI), + name: "swap indices 1 and 3", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + common.SSD, + }, + i: 1, + j: 3, }, { - Path: "/path/to/cache2/,/path/to/cache3/", - Quota: resource.NewQuantity(125, resource.BinarySI), + name: "swap indices 4 and 2", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + common.SSD, + common.HDD, + }, + i: 4, + j: 2, + }, + } + + for _, tc := range testCases { + temp := make([]common.MediumType, len(tc.sortMedium)) + copy(temp, tc.sortMedium) + + tc.sortMedium.Swap(tc.i, tc.j) + + Expect(tc.sortMedium[tc.i]).To(Equal(temp[tc.j]), "test case: %s", tc.name) + Expect(tc.sortMedium[tc.j]).To(Equal(temp[tc.i]), "test case: %s", tc.name) + } + }) + }) + + Context("Less", func() { + It("should correctly compare elements", func() { + testCases := []struct { + name string + sortMedium sortMediumType + i int + j int + want bool + }{ + { + name: "HDD vs SSD", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + }, + i: 2, + j: 1, + want: false, }, - }, - }, - want: map[common.CacheStoreType]int64{ - common.MemoryCacheStore: 248, - }, - }, - "test case 4": { - tieredStore: datav1alpha1.TieredStore{ - Levels: []datav1alpha1.Level{ { - MediumType: common.Memory, - Path: "/path/to/cache1/,/path/to/cache2/", - Quota: resource.NewQuantity(124, resource.BinarySI), + name: "SSD vs SSD", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + common.SSD, + }, + i: 1, + j: 3, + want: false, }, { - MediumType: common.HDD, - Path: "/path/to/cache3/,/path/to/cache4/", - Quota: resource.NewQuantity(256, resource.BinarySI), + name: "Memory vs HDD", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + common.SSD, + common.Memory, + }, + i: 4, + j: 2, + want: true, }, { - MediumType: common.SSD, - Path: "/path/to/cache5/,/path/to/cache6/", - Quota: resource.NewQuantity(256, resource.BinarySI), + name: "Memory vs SSD", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.SSD, + common.Memory, + }, + i: 3, + j: 2, + want: true, + }, + } + + for _, tc := range testCases { + result := tc.sortMedium.Less(tc.i, tc.j) + Expect(result).To(Equal(tc.want), "test case: %s", tc.name) + } + }) + }) + }) + + Describe("makeMediumTypeSorted", func() { + It("should return sorted and deduplicated medium types", func() { + testCases := []struct { + name string + sortMedium sortMediumType + }{ + { + name: "already sorted", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + }, + }, + { + name: "with duplicates and invalid types", + sortMedium: []common.MediumType{ + common.SSD, + common.HDD, + common.SSD, + "apple", + "baba", + common.Memory, + }, + }, + { + name: "with duplicates", + sortMedium: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + common.SSD, + common.HDD, }, }, - }, - want: map[common.CacheStoreType]int64{ - common.MemoryCacheStore: 124, - common.DiskCacheStore: 512, - }, - }, - } - for k, item := range testCases { - runtimeInfo, err := base.BuildRuntimeInfo( - "name", - "namespace", - "runtimeType", - base.WithTieredStore(item.tieredStore), - ) - if err != nil { - t.Errorf("%s cannot build the runtimeInfo", k) - } - result := GetLevelStorageMap(runtimeInfo) - if len(result) != len(item.want) { - t.Errorf("%s cannot paas, want %v types, get %v types", k, len(item.want), len(result)) - } else { - for index, value := range result { - int64Result, _ := value.AsInt64() - if item.want[index] != int64Result { - t.Errorf("%s cannot paas, want %v, get %v", k, item.want[index], int64Result) + } + + for _, tc := range testCases { + newMediumTypes := makeMediumTypeSorted(tc.sortMedium) + + if len(newMediumTypes) >= 2 { + for index := 1; index < len(newMediumTypes); index++ { + // Check for no duplicates + Expect(newMediumTypes[index]).NotTo(Equal(newMediumTypes[index-1]), + "test case %s: found duplicate MediumTypes", tc.name) + + // Check for correct sort order (should be <= to handle invalid types with same order) + Expect(common.GetDefaultTieredStoreOrder(newMediumTypes[index-1])).To( + BeNumerically("<=", common.GetDefaultTieredStoreOrder(newMediumTypes[index])), + "test case %s: incorrect sort order", tc.name) + } } } - } - } -} + }) + }) -func TestGetTieredLevel(t *testing.T) { - var mockQuota = resource.NewQuantity(124, resource.BinarySI) - testCases := map[string]struct { - tieredStore datav1alpha1.TieredStore - search common.MediumType - want int - }{ - "test case 1": { - tieredStore: datav1alpha1.TieredStore{}, - search: common.Memory, - want: -1, - }, - "test case 2": { - tieredStore: datav1alpha1.TieredStore{ - Levels: []datav1alpha1.Level{ - { - MediumType: common.Memory, - Path: "/path/to/cache1/,/path/to/cache2/", - Quota: mockQuota, + Describe("GetLevelStorageMap", func() { + It("should correctly aggregate storage by cache store type", func() { + testCases := []struct { + name string + tieredStore datav1alpha1.TieredStore + want map[common.CacheStoreType]int64 + }{ + { + name: "empty tiered store", + tieredStore: datav1alpha1.TieredStore{}, + want: map[common.CacheStoreType]int64{}, + }, + { + name: "single memory level", + tieredStore: datav1alpha1.TieredStore{ + Levels: []datav1alpha1.Level{ + { + MediumType: common.Memory, + Path: "/path/to/cache1/,/path/to/cache2/", + Quota: resource.NewQuantity(124, resource.BinarySI), + }, + }, + }, + want: map[common.CacheStoreType]int64{ + common.MemoryCacheStore: 124, }, }, - }, - search: common.Memory, - want: 0, - }, - "test case 3": { - tieredStore: datav1alpha1.TieredStore{ - Levels: []datav1alpha1.Level{ - { - MediumType: common.Memory, - Path: "/path/to/cache1/,/path/to/cache2/", - Quota: mockQuota, + { + name: "multiple memory levels", + tieredStore: datav1alpha1.TieredStore{ + Levels: []datav1alpha1.Level{ + { + MediumType: common.Memory, + Path: "/path/to/cache1/,/path/to/cache2/", + Quota: resource.NewQuantity(124, resource.BinarySI), + }, + { + Path: "/path/to/cache2/,/path/to/cache3/", + Quota: resource.NewQuantity(125, resource.BinarySI), + }, + }, }, - { - MediumType: common.SSD, - Path: "/path/to/cache3/,/path/to/cache4/", - Quota: mockQuota, + want: map[common.CacheStoreType]int64{ + common.MemoryCacheStore: 248, }, }, - }, - search: common.SSD, - want: 1, - }, - "test case 4": { - tieredStore: datav1alpha1.TieredStore{ - Levels: []datav1alpha1.Level{ - { - MediumType: common.Memory, - Path: "/path/to/cache1/,/path/to/cache2/", - Quota: mockQuota, + { + name: "mixed storage types", + tieredStore: datav1alpha1.TieredStore{ + Levels: []datav1alpha1.Level{ + { + MediumType: common.Memory, + Path: "/path/to/cache1/,/path/to/cache2/", + Quota: resource.NewQuantity(124, resource.BinarySI), + }, + { + MediumType: common.HDD, + Path: "/path/to/cache3/,/path/to/cache4/", + Quota: resource.NewQuantity(256, resource.BinarySI), + }, + { + MediumType: common.SSD, + Path: "/path/to/cache5/,/path/to/cache6/", + Quota: resource.NewQuantity(256, resource.BinarySI), + }, + }, }, - { - MediumType: common.Memory, - Path: "/path/to/cache3/,/path/to/cache4/", - Quota: mockQuota, + want: map[common.CacheStoreType]int64{ + common.MemoryCacheStore: 124, + common.DiskCacheStore: 512, }, - { - MediumType: common.SSD, - Path: "/path/to/cache5/,/path/to/cache6/", - Quota: mockQuota, + }, + } + + for _, tc := range testCases { + runtimeInfo, err := base.BuildRuntimeInfo( + "name", + "namespace", + "runtimeType", + base.WithTieredStore(tc.tieredStore), + ) + Expect(err).NotTo(HaveOccurred(), "test case %s: failed to build runtimeInfo", tc.name) + + result := GetLevelStorageMap(runtimeInfo) + Expect(result).To(HaveLen(len(tc.want)), "test case %s: incorrect number of storage types", tc.name) + + for storeType, expectedQuota := range tc.want { + actualQuantity, found := result[storeType] + Expect(found).To(BeTrue(), "test case %s: storage type %v not found", tc.name, storeType) + + actualQuota, ok := actualQuantity.AsInt64() + Expect(ok).To(BeTrue(), "test case %s: failed to convert quantity to int64", tc.name) + Expect(actualQuota).To(Equal(expectedQuota), "test case %s: incorrect quota for %v", tc.name, storeType) + } + } + }) + }) + + Describe("GetTieredLevel", func() { + var mockQuota *resource.Quantity + + BeforeEach(func() { + mockQuota = resource.NewQuantity(124, resource.BinarySI) + }) + + It("should return the correct tier level index", func() { + testCases := []struct { + name string + tieredStore datav1alpha1.TieredStore + search common.MediumType + want int + }{ + { + name: "empty tiered store", + tieredStore: datav1alpha1.TieredStore{}, + search: common.Memory, + want: -1, + }, + { + name: "single level - found", + tieredStore: datav1alpha1.TieredStore{ + Levels: []datav1alpha1.Level{ + { + MediumType: common.Memory, + Path: "/path/to/cache1/,/path/to/cache2/", + Quota: mockQuota, + }, + }, }, - { - MediumType: common.HDD, - Path: "/path/to/cache7/,/path/to/cache8/", - Quota: mockQuota, + search: common.Memory, + want: 0, + }, + { + name: "multiple levels - found at index 1", + tieredStore: datav1alpha1.TieredStore{ + Levels: []datav1alpha1.Level{ + { + MediumType: common.Memory, + Path: "/path/to/cache1/,/path/to/cache2/", + Quota: mockQuota, + }, + { + MediumType: common.SSD, + Path: "/path/to/cache3/,/path/to/cache4/", + Quota: mockQuota, + }, + }, }, + search: common.SSD, + want: 1, }, - }, - search: common.HDD, - want: 2, - }, - } + { + name: "duplicate medium types - returns sorted index", + tieredStore: datav1alpha1.TieredStore{ + Levels: []datav1alpha1.Level{ + { + MediumType: common.Memory, + Path: "/path/to/cache1/,/path/to/cache2/", + Quota: mockQuota, + }, + { + MediumType: common.Memory, + Path: "/path/to/cache3/,/path/to/cache4/", + Quota: mockQuota, + }, + { + MediumType: common.SSD, + Path: "/path/to/cache5/,/path/to/cache6/", + Quota: mockQuota, + }, + { + MediumType: common.HDD, + Path: "/path/to/cache7/,/path/to/cache8/", + Quota: mockQuota, + }, + }, + }, + search: common.HDD, + want: 2, + }, + } - for k, item := range testCases { - runtimeInfo, err := base.BuildRuntimeInfo( - "name", - "namespace", - "runtimeType", - base.WithTieredStore(item.tieredStore), - ) - if err != nil { - t.Errorf("%s cannot build the runtimeInfo", k) - } - result := GetTieredLevel(runtimeInfo, item.search) - if result != item.want { - t.Errorf("%s cannot paas, want %v, get %v", k, item.want, result) - } - } + for _, tc := range testCases { + runtimeInfo, err := base.BuildRuntimeInfo( + "name", + "namespace", + "runtimeType", + base.WithTieredStore(tc.tieredStore), + ) + Expect(err).NotTo(HaveOccurred(), "test case %s: failed to build runtimeInfo", tc.name) -} + result := GetTieredLevel(runtimeInfo, tc.search) + Expect(result).To(Equal(tc.want), "test case %s: incorrect tier level", tc.name) + } + }) + }) +}) From f303f1846218aa5aa5df124e8e494109ddb9482f Mon Sep 17 00:00:00 2001 From: Yuvraj Kolkar Date: Fri, 30 Jan 2026 21:57:10 +0530 Subject: [PATCH 2/2] Resolve review Signed-off-by: Yuvraj Kolkar --- pkg/utils/tieredstore/tiered_store_test.go | 48 ++++++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/pkg/utils/tieredstore/tiered_store_test.go b/pkg/utils/tieredstore/tiered_store_test.go index bad017035d5..3c8384d06b7 100644 --- a/pkg/utils/tieredstore/tiered_store_test.go +++ b/pkg/utils/tieredstore/tiered_store_test.go @@ -195,6 +195,7 @@ var _ = Describe("TieredStore", func() { testCases := []struct { name string sortMedium sortMediumType + expected []common.MediumType }{ { name: "already sorted", @@ -203,24 +204,52 @@ var _ = Describe("TieredStore", func() { common.SSD, common.HDD, }, + expected: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + }, }, { - name: "with duplicates and invalid types", + name: "with duplicates", sortMedium: []common.MediumType{ + common.Memory, common.SSD, common.HDD, common.SSD, - "apple", - "baba", + common.HDD, + }, + expected: []common.MediumType{ common.Memory, + common.SSD, + common.HDD, }, }, { - name: "with duplicates", + name: "unsorted with no duplicates", + sortMedium: []common.MediumType{ + common.HDD, + common.Memory, + common.SSD, + }, + expected: []common.MediumType{ + common.Memory, + common.SSD, + common.HDD, + }, + }, + { + name: "unsorted with duplicates", sortMedium: []common.MediumType{ + common.HDD, + common.SSD, common.Memory, common.SSD, common.HDD, + common.Memory, + }, + expected: []common.MediumType{ + common.Memory, common.SSD, common.HDD, }, @@ -230,6 +259,17 @@ var _ = Describe("TieredStore", func() { for _, tc := range testCases { newMediumTypes := makeMediumTypeSorted(tc.sortMedium) + // Check that the result has the correct length + Expect(newMediumTypes).To(HaveLen(len(tc.expected)), + "test case %s: incorrect length", tc.name) + + // Verify the result contains the correct set of unique elements + for i, expectedType := range tc.expected { + Expect(newMediumTypes[i]).To(Equal(expectedType), + "test case %s: element at index %d should be %v, got %v", + tc.name, i, expectedType, newMediumTypes[i]) + } + if len(newMediumTypes) >= 2 { for index := 1; index < len(newMediumTypes); index++ { // Check for no duplicates