storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/config/storageclass/storage-class_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2017-2019 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package storageclass
    18  
    19  import (
    20  	"errors"
    21  	"reflect"
    22  	"testing"
    23  )
    24  
    25  func TestParseStorageClass(t *testing.T) {
    26  	tests := []struct {
    27  		storageClassEnv string
    28  		wantSc          StorageClass
    29  		expectedError   error
    30  	}{
    31  		{"EC:3", StorageClass{
    32  			Parity: 3},
    33  			nil},
    34  		{"EC:4", StorageClass{
    35  			Parity: 4},
    36  			nil},
    37  		{"AB:4", StorageClass{
    38  			Parity: 4},
    39  			errors.New("Unsupported scheme AB. Supported scheme is EC")},
    40  		{"EC:4:5", StorageClass{
    41  			Parity: 4},
    42  			errors.New("Too many sections in EC:4:5")},
    43  		{"EC:A", StorageClass{
    44  			Parity: 4},
    45  			errors.New(`strconv.Atoi: parsing "A": invalid syntax`)},
    46  		{"AB", StorageClass{
    47  			Parity: 4},
    48  			errors.New("Too few sections in AB")},
    49  	}
    50  	for i, tt := range tests {
    51  		gotSc, err := parseStorageClass(tt.storageClassEnv)
    52  		if err != nil && tt.expectedError == nil {
    53  			t.Errorf("Test %d, Expected %s, got %s", i+1, tt.expectedError, err)
    54  			return
    55  		}
    56  		if err == nil && tt.expectedError != nil {
    57  			t.Errorf("Test %d, Expected %s, got %s", i+1, tt.expectedError, err)
    58  			return
    59  		}
    60  		if tt.expectedError == nil && !reflect.DeepEqual(gotSc, tt.wantSc) {
    61  			t.Errorf("Test %d, Expected %v, got %v", i+1, tt.wantSc, gotSc)
    62  			return
    63  		}
    64  		if tt.expectedError != nil && err.Error() != tt.expectedError.Error() {
    65  			t.Errorf("Test %d, Expected `%v`, got `%v`", i+1, tt.expectedError, err)
    66  		}
    67  	}
    68  }
    69  
    70  func TestValidateParity(t *testing.T) {
    71  	tests := []struct {
    72  		rrsParity     int
    73  		ssParity      int
    74  		success       bool
    75  		setDriveCount int
    76  	}{
    77  		{2, 4, true, 16},
    78  		{3, 3, true, 16},
    79  		{0, 0, true, 16},
    80  		{1, 4, false, 16},
    81  		{7, 6, false, 16},
    82  		{9, 0, false, 16},
    83  		{9, 9, false, 16},
    84  		{2, 9, false, 16},
    85  		{9, 2, false, 16},
    86  	}
    87  	for i, tt := range tests {
    88  		err := validateParity(tt.ssParity, tt.rrsParity, tt.setDriveCount)
    89  		if err != nil && tt.success {
    90  			t.Errorf("Test %d, Expected success, got %s", i+1, err)
    91  		}
    92  		if err == nil && !tt.success {
    93  			t.Errorf("Test %d, Expected failure, got success", i+1)
    94  		}
    95  	}
    96  }
    97  
    98  func TestParityCount(t *testing.T) {
    99  	tests := []struct {
   100  		sc             string
   101  		disksCount     int
   102  		expectedData   int
   103  		expectedParity int
   104  	}{
   105  		{RRS, 16, 14, 2},
   106  		{STANDARD, 16, 8, 8},
   107  		{"", 16, 8, 8},
   108  		{RRS, 16, 9, 7},
   109  		{STANDARD, 16, 10, 6},
   110  		{"", 16, 9, 7},
   111  	}
   112  	for i, tt := range tests {
   113  		scfg := Config{
   114  			Standard: StorageClass{
   115  				Parity: 8,
   116  			},
   117  			RRS: StorageClass{
   118  				Parity: 0,
   119  			},
   120  		}
   121  		// Set env var for test case 4
   122  		if i+1 == 4 {
   123  			scfg.RRS.Parity = 7
   124  		}
   125  		// Set env var for test case 5
   126  		if i+1 == 5 {
   127  			scfg.Standard.Parity = 6
   128  		}
   129  		// Set env var for test case 6
   130  		if i+1 == 6 {
   131  			scfg.Standard.Parity = 7
   132  		}
   133  		parity := scfg.GetParityForSC(tt.sc)
   134  		if (tt.disksCount - parity) != tt.expectedData {
   135  			t.Errorf("Test %d, Expected data disks %d, got %d", i+1, tt.expectedData, tt.disksCount-parity)
   136  			continue
   137  		}
   138  		if parity != tt.expectedParity {
   139  			t.Errorf("Test %d, Expected parity disks %d, got %d", i+1, tt.expectedParity, parity)
   140  		}
   141  	}
   142  }
   143  
   144  // Test IsValid method with valid and invalid inputs
   145  func TestIsValidStorageClassKind(t *testing.T) {
   146  	tests := []struct {
   147  		sc   string
   148  		want bool
   149  	}{
   150  		{"STANDARD", true},
   151  		{"REDUCED_REDUNDANCY", true},
   152  		{"", false},
   153  		{"INVALID", false},
   154  		{"123", false},
   155  		{"MINIO_STORAGE_CLASS_RRS", false},
   156  		{"MINIO_STORAGE_CLASS_STANDARD", false},
   157  	}
   158  	for i, tt := range tests {
   159  		if got := IsValid(tt.sc); got != tt.want {
   160  			t.Errorf("Test %d, Expected Storage Class to be %t, got %t", i+1, tt.want, got)
   161  		}
   162  	}
   163  }