mirror of
https://github.com/minio/minio.git
synced 2025-11-09 21:49:46 -05:00
simplify storage class validation (#5470)
Check if the storage class is set in an non XL setup instead of relying on `globalEndpoints` value. Also converge the checks for both SS and RRS parity configuration. This PR also removes redundant `tt.name` in all test cases, since each testcase doesn't need to be numbered explicitly they are numbered implicitly.
This commit is contained in:
committed by
Nitish Tiwari
parent
033cfb5cef
commit
3316dbc037
@@ -29,125 +29,93 @@ func TestParseStorageClass(t *testing.T) {
|
||||
|
||||
func testParseStorageClass(obj ObjectLayer, instanceType string, t TestErrHandler) {
|
||||
tests := []struct {
|
||||
name int
|
||||
storageClassEnv string
|
||||
wantSc storageClass
|
||||
expectedError error
|
||||
}{
|
||||
{1, "EC:3", storageClass{
|
||||
{"EC:3", storageClass{
|
||||
Scheme: "EC",
|
||||
Parity: 3},
|
||||
nil},
|
||||
{2, "EC:4", storageClass{
|
||||
{"EC:4", storageClass{
|
||||
Scheme: "EC",
|
||||
Parity: 4},
|
||||
nil},
|
||||
{3, "AB:4", storageClass{
|
||||
{"AB:4", storageClass{
|
||||
Scheme: "EC",
|
||||
Parity: 4},
|
||||
errors.New("Unsupported scheme AB. Supported scheme is EC")},
|
||||
{4, "EC:4:5", storageClass{
|
||||
{"EC:4:5", storageClass{
|
||||
Scheme: "EC",
|
||||
Parity: 4},
|
||||
errors.New("Too many sections in EC:4:5")},
|
||||
{5, "AB", storageClass{
|
||||
{"AB", storageClass{
|
||||
Scheme: "EC",
|
||||
Parity: 4},
|
||||
errors.New("Too few sections in AB")},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
for i, tt := range tests {
|
||||
gotSc, err := parseStorageClass(tt.storageClassEnv)
|
||||
if err != nil && tt.expectedError == nil {
|
||||
t.Errorf("Test %d, Expected %s, got %s", tt.name, tt.expectedError, err)
|
||||
t.Errorf("Test %d, Expected %s, got %s", i+1, tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
if err == nil && tt.expectedError != nil {
|
||||
t.Errorf("Test %d, Expected %s, got %s", tt.name, tt.expectedError, err)
|
||||
t.Errorf("Test %d, Expected %s, got %s", i+1, tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
if tt.expectedError == nil && !reflect.DeepEqual(gotSc, tt.wantSc) {
|
||||
t.Errorf("Test %d, Expected %v, got %v", tt.name, tt.wantSc, gotSc)
|
||||
t.Errorf("Test %d, Expected %v, got %v", i+1, tt.wantSc, gotSc)
|
||||
return
|
||||
}
|
||||
if tt.expectedError != nil && !reflect.DeepEqual(err, tt.expectedError) {
|
||||
t.Errorf("Test %d, Expected %v, got %v", tt.name, tt.expectedError, err)
|
||||
t.Errorf("Test %d, Expected %v, got %v", i+1, tt.expectedError, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRRSParity(t *testing.T) {
|
||||
ExecObjectLayerTestWithDirs(t, testValidateRRSParity)
|
||||
func TestValidateParity(t *testing.T) {
|
||||
ExecObjectLayerTestWithDirs(t, testValidateParity)
|
||||
}
|
||||
|
||||
func testValidateRRSParity(obj ObjectLayer, instanceType string, dirs []string, t TestErrHandler) {
|
||||
func testValidateParity(obj ObjectLayer, instanceType string, dirs []string, t TestErrHandler) {
|
||||
// Reset global storage class flags
|
||||
resetGlobalStorageEnvs()
|
||||
|
||||
// Set globalEndpoints for a single node XL setup.
|
||||
endpoints := globalEndpoints
|
||||
defer func() {
|
||||
globalEndpoints = endpoints
|
||||
}()
|
||||
|
||||
isXL := globalIsXL
|
||||
defer func() {
|
||||
globalIsXL = isXL
|
||||
}()
|
||||
|
||||
globalIsXL = true
|
||||
globalEndpoints = mustGetNewEndpointList(dirs...)
|
||||
|
||||
tests := []struct {
|
||||
name int
|
||||
rrsParity int
|
||||
ssParity int
|
||||
expectedError error
|
||||
rrsParity int
|
||||
ssParity int
|
||||
success bool
|
||||
}{
|
||||
{1, 2, 4, nil},
|
||||
{2, 1, 4, errors.New("Reduced redundancy storage class parity should be greater than or equal to 2")},
|
||||
{3, 7, 6, errors.New("Reduced redundancy storage class parity disks should be less than 6")},
|
||||
{4, 9, 0, errors.New("Reduced redundancy storage class parity disks should be less than 8")},
|
||||
{5, 3, 3, errors.New("Reduced redundancy storage class parity disks should be less than 3")},
|
||||
{2, 4, true},
|
||||
{3, 3, true},
|
||||
{1, 4, false},
|
||||
{7, 6, false},
|
||||
{9, 0, false},
|
||||
{9, 9, false},
|
||||
{2, 9, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
err := validateRRSParity(tt.rrsParity, tt.ssParity)
|
||||
if err != nil && tt.expectedError == nil {
|
||||
t.Errorf("Test %d, Expected %s, got %s", tt.name, tt.expectedError, err)
|
||||
return
|
||||
for i, tt := range tests {
|
||||
err := validateParity(tt.ssParity, tt.rrsParity)
|
||||
if err != nil && tt.success {
|
||||
t.Errorf("Test %d, Expected success, got %s", i+1, err)
|
||||
}
|
||||
if err == nil && tt.expectedError != nil {
|
||||
t.Errorf("Test %d, Expected %s, got %s", tt.name, tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
if tt.expectedError != nil && !reflect.DeepEqual(err, tt.expectedError) {
|
||||
t.Errorf("Test %d, Expected %v, got %v", tt.name, tt.expectedError, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateSSParity(t *testing.T) {
|
||||
ExecObjectLayerTestWithDirs(t, testValidateSSParity)
|
||||
}
|
||||
|
||||
func testValidateSSParity(obj ObjectLayer, instanceType string, dirs []string, t TestErrHandler) {
|
||||
// Reset global storage class flags
|
||||
resetGlobalStorageEnvs()
|
||||
// Set globalEndpoints for a single node XL setup.
|
||||
globalEndpoints = mustGetNewEndpointList(dirs...)
|
||||
|
||||
tests := []struct {
|
||||
name int
|
||||
ssParity int
|
||||
rrsParity int
|
||||
expectedError error
|
||||
}{
|
||||
{1, 4, 2, nil},
|
||||
{2, 6, 5, nil},
|
||||
{3, 1, 0, errors.New("Standard storage class parity disks should be greater than or equal to 2")},
|
||||
{4, 4, 6, errors.New("Standard storage class parity disks should be greater than 6")},
|
||||
{5, 9, 0, errors.New("Standard storage class parity disks should be less than or equal to 8")},
|
||||
{6, 3, 3, errors.New("Standard storage class parity disks should be greater than 3")},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
err := validateSSParity(tt.ssParity, tt.rrsParity)
|
||||
if err != nil && tt.expectedError == nil {
|
||||
t.Errorf("Test %d, Expected %s, got %s", tt.name, tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
if err == nil && tt.expectedError != nil {
|
||||
t.Errorf("Test %d, Expected %s, got %s", tt.name, tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
if tt.expectedError != nil && !reflect.DeepEqual(err, tt.expectedError) {
|
||||
t.Errorf("Test %d, Expected %v, got %v", tt.name, tt.expectedError, err)
|
||||
if err == nil && !tt.success {
|
||||
t.Errorf("Test %d, Expected failure, got success", i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -162,39 +130,38 @@ func testGetRedundancyCount(obj ObjectLayer, instanceType string, dirs []string,
|
||||
xl := obj.(*xlObjects)
|
||||
|
||||
tests := []struct {
|
||||
name int
|
||||
sc string
|
||||
disks []StorageAPI
|
||||
expectedData int
|
||||
expectedParity int
|
||||
}{
|
||||
{1, reducedRedundancyStorageClass, xl.storageDisks, 14, 2},
|
||||
{2, standardStorageClass, xl.storageDisks, 8, 8},
|
||||
{3, "", xl.storageDisks, 8, 8},
|
||||
{4, reducedRedundancyStorageClass, xl.storageDisks, 9, 7},
|
||||
{5, standardStorageClass, xl.storageDisks, 10, 6},
|
||||
{6, "", xl.storageDisks, 9, 7},
|
||||
{reducedRedundancyStorageClass, xl.storageDisks, 14, 2},
|
||||
{standardStorageClass, xl.storageDisks, 8, 8},
|
||||
{"", xl.storageDisks, 8, 8},
|
||||
{reducedRedundancyStorageClass, xl.storageDisks, 9, 7},
|
||||
{standardStorageClass, xl.storageDisks, 10, 6},
|
||||
{"", xl.storageDisks, 9, 7},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
for i, tt := range tests {
|
||||
// Set env var for test case 4
|
||||
if tt.name == 4 {
|
||||
if i+1 == 4 {
|
||||
globalRRStorageClass.Parity = 7
|
||||
}
|
||||
// Set env var for test case 5
|
||||
if tt.name == 5 {
|
||||
if i+1 == 5 {
|
||||
globalStandardStorageClass.Parity = 6
|
||||
}
|
||||
// Set env var for test case 6
|
||||
if tt.name == 6 {
|
||||
if i+1 == 6 {
|
||||
globalStandardStorageClass.Parity = 7
|
||||
}
|
||||
data, parity := getRedundancyCount(tt.sc, len(tt.disks))
|
||||
if data != tt.expectedData {
|
||||
t.Errorf("Test %d, Expected data disks %d, got %d", tt.name, tt.expectedData, data)
|
||||
t.Errorf("Test %d, Expected data disks %d, got %d", i+1, tt.expectedData, data)
|
||||
return
|
||||
}
|
||||
if parity != tt.expectedParity {
|
||||
t.Errorf("Test %d, Expected parity disks %d, got %d", tt.name, tt.expectedParity, parity)
|
||||
t.Errorf("Test %d, Expected parity disks %d, got %d", i+1, tt.expectedParity, parity)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -322,38 +289,36 @@ func testObjectQuorumFromMeta(obj ObjectLayer, instanceType string, dirs []strin
|
||||
parts7, errs7 := readAllXLMetadata(xlDisks, bucket, object7)
|
||||
|
||||
tests := []struct {
|
||||
name int
|
||||
xl xlObjects
|
||||
parts []xlMetaV1
|
||||
errs []error
|
||||
expectedReadQuorum int
|
||||
expectedWriteQuorum int
|
||||
expectedError error
|
||||
}{
|
||||
{1, *xl, parts1, errs1, 8, 9, nil},
|
||||
{2, *xl, parts2, errs2, 14, 15, nil},
|
||||
{3, *xl, parts3, errs3, 8, 9, nil},
|
||||
{4, *xl, parts4, errs4, 10, 11, nil},
|
||||
{5, *xl, parts5, errs5, 14, 15, nil},
|
||||
{6, *xl, parts6, errs6, 8, 9, nil},
|
||||
{7, *xl, parts7, errs7, 14, 15, nil},
|
||||
{parts1, errs1, 8, 9, nil},
|
||||
{parts2, errs2, 14, 15, nil},
|
||||
{parts3, errs3, 8, 9, nil},
|
||||
{parts4, errs4, 10, 11, nil},
|
||||
{parts5, errs5, 14, 15, nil},
|
||||
{parts6, errs6, 8, 9, nil},
|
||||
{parts7, errs7, 14, 15, nil},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
actualReadQuorum, actualWriteQuorum, err := objectQuorumFromMeta(tt.xl, tt.parts, tt.errs)
|
||||
for i, tt := range tests {
|
||||
actualReadQuorum, actualWriteQuorum, err := objectQuorumFromMeta(*xl, tt.parts, tt.errs)
|
||||
if tt.expectedError != nil && err == nil {
|
||||
t.Errorf("Test %d, Expected %s, got %s", tt.name, tt.expectedError, err)
|
||||
t.Errorf("Test %d, Expected %s, got %s", i+1, tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
if tt.expectedError == nil && err != nil {
|
||||
t.Errorf("Test %d, Expected %s, got %s", tt.name, tt.expectedError, err)
|
||||
t.Errorf("Test %d, Expected %s, got %s", i+1, tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
if tt.expectedReadQuorum != actualReadQuorum {
|
||||
t.Errorf("Test %d, Expected Read Quorum %d, got %d", tt.name, tt.expectedReadQuorum, actualReadQuorum)
|
||||
t.Errorf("Test %d, Expected Read Quorum %d, got %d", i+1, tt.expectedReadQuorum, actualReadQuorum)
|
||||
return
|
||||
}
|
||||
if tt.expectedWriteQuorum != actualWriteQuorum {
|
||||
t.Errorf("Test %d, Expected Write Quorum %d, got %d", tt.name, tt.expectedWriteQuorum, actualWriteQuorum)
|
||||
t.Errorf("Test %d, Expected Write Quorum %d, got %d", i+1, tt.expectedWriteQuorum, actualWriteQuorum)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -362,21 +327,20 @@ func testObjectQuorumFromMeta(obj ObjectLayer, instanceType string, dirs []strin
|
||||
// Test isValidStorageClassMeta method with valid and invalid inputs
|
||||
func TestIsValidStorageClassMeta(t *testing.T) {
|
||||
tests := []struct {
|
||||
name int
|
||||
sc string
|
||||
want bool
|
||||
}{
|
||||
{1, "STANDARD", true},
|
||||
{2, "REDUCED_REDUNDANCY", true},
|
||||
{3, "", false},
|
||||
{4, "INVALID", false},
|
||||
{5, "123", false},
|
||||
{6, "MINIO_STORAGE_CLASS_RRS", false},
|
||||
{7, "MINIO_STORAGE_CLASS_STANDARD", false},
|
||||
{"STANDARD", true},
|
||||
{"REDUCED_REDUNDANCY", true},
|
||||
{"", false},
|
||||
{"INVALID", false},
|
||||
{"123", false},
|
||||
{"MINIO_STORAGE_CLASS_RRS", false},
|
||||
{"MINIO_STORAGE_CLASS_STANDARD", false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
for i, tt := range tests {
|
||||
if got := isValidStorageClassMeta(tt.sc); got != tt.want {
|
||||
t.Errorf("Test %d, Expected Storage Class to be %t, got %t", tt.name, tt.want, got)
|
||||
t.Errorf("Test %d, Expected Storage Class to be %t, got %t", i+1, tt.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user