github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/config/storageclass/storage-class_test.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package storageclass 19 20 import ( 21 "errors" 22 "reflect" 23 "testing" 24 ) 25 26 func TestParseStorageClass(t *testing.T) { 27 tests := []struct { 28 storageClassEnv string 29 wantSc StorageClass 30 expectedError error 31 }{ 32 { 33 "EC:3", 34 StorageClass{ 35 Parity: 3, 36 }, 37 nil, 38 }, 39 { 40 "EC:4", 41 StorageClass{ 42 Parity: 4, 43 }, 44 nil, 45 }, 46 { 47 "AB:4", 48 StorageClass{ 49 Parity: 4, 50 }, 51 errors.New("Unsupported scheme AB. Supported scheme is EC"), 52 }, 53 { 54 "EC:4:5", 55 StorageClass{ 56 Parity: 4, 57 }, 58 errors.New("Too many sections in EC:4:5"), 59 }, 60 { 61 "EC:A", 62 StorageClass{ 63 Parity: 4, 64 }, 65 errors.New(`strconv.Atoi: parsing "A": invalid syntax`), 66 }, 67 { 68 "AB", 69 StorageClass{ 70 Parity: 4, 71 }, 72 errors.New("Too few sections in AB"), 73 }, 74 } 75 for i, tt := range tests { 76 gotSc, err := parseStorageClass(tt.storageClassEnv) 77 if err != nil && tt.expectedError == nil { 78 t.Errorf("Test %d, Expected %s, got %s", i+1, tt.expectedError, err) 79 return 80 } 81 if err == nil && tt.expectedError != nil { 82 t.Errorf("Test %d, Expected %s, got %s", i+1, tt.expectedError, err) 83 return 84 } 85 if tt.expectedError == nil && !reflect.DeepEqual(gotSc, tt.wantSc) { 86 t.Errorf("Test %d, Expected %v, got %v", i+1, tt.wantSc, gotSc) 87 return 88 } 89 if tt.expectedError != nil && err.Error() != tt.expectedError.Error() { 90 t.Errorf("Test %d, Expected `%v`, got `%v`", i+1, tt.expectedError, err) 91 } 92 } 93 } 94 95 func TestValidateParity(t *testing.T) { 96 tests := []struct { 97 rrsParity int 98 ssParity int 99 success bool 100 setDriveCount int 101 }{ 102 {2, 4, true, 16}, 103 {3, 3, true, 16}, 104 {0, 0, true, 16}, 105 {1, 4, true, 16}, 106 {0, 4, true, 16}, 107 {7, 6, false, 16}, 108 {9, 0, false, 16}, 109 {9, 9, false, 16}, 110 {2, 9, false, 16}, 111 {9, 2, false, 16}, 112 } 113 for i, tt := range tests { 114 err := validateParity(tt.ssParity, tt.rrsParity, tt.setDriveCount) 115 if err != nil && tt.success { 116 t.Errorf("Test %d, Expected success, got %s", i+1, err) 117 } 118 if err == nil && !tt.success { 119 t.Errorf("Test %d, Expected failure, got success", i+1) 120 } 121 } 122 } 123 124 func TestParityCount(t *testing.T) { 125 tests := []struct { 126 sc string 127 drivesCount int 128 expectedData int 129 expectedParity int 130 }{ 131 {RRS, 16, 14, 2}, 132 {STANDARD, 16, 8, 8}, 133 {"", 16, 8, 8}, 134 {RRS, 16, 9, 7}, 135 {STANDARD, 16, 10, 6}, 136 {"", 16, 9, 7}, 137 } 138 for i, tt := range tests { 139 scfg := Config{ 140 Standard: StorageClass{ 141 Parity: 8, 142 }, 143 RRS: StorageClass{ 144 Parity: 2, 145 }, 146 initialized: true, 147 } 148 // Set env var for test case 4 149 if i+1 == 4 { 150 scfg.RRS.Parity = 7 151 } 152 // Set env var for test case 5 153 if i+1 == 5 { 154 scfg.Standard.Parity = 6 155 } 156 // Set env var for test case 6 157 if i+1 == 6 { 158 scfg.Standard.Parity = 7 159 } 160 parity := scfg.GetParityForSC(tt.sc) 161 if (tt.drivesCount - parity) != tt.expectedData { 162 t.Errorf("Test %d, Expected data drives %d, got %d", i+1, tt.expectedData, tt.drivesCount-parity) 163 continue 164 } 165 if parity != tt.expectedParity { 166 t.Errorf("Test %d, Expected parity drives %d, got %d", i+1, tt.expectedParity, parity) 167 } 168 } 169 } 170 171 // Test IsValid method with valid and invalid inputs 172 func TestIsValidStorageClassKind(t *testing.T) { 173 tests := []struct { 174 sc string 175 want bool 176 }{ 177 {"STANDARD", true}, 178 {"REDUCED_REDUNDANCY", true}, 179 {"", false}, 180 {"INVALID", false}, 181 {"123", false}, 182 {"MINIO_STORAGE_CLASS_RRS", false}, 183 {"MINIO_STORAGE_CLASS_STANDARD", false}, 184 } 185 for i, tt := range tests { 186 if got := IsValid(tt.sc); got != tt.want { 187 t.Errorf("Test %d, Expected Storage Class to be %t, got %t", i+1, tt.want, got) 188 } 189 } 190 }