storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/format-disk-cache_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2018 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 cmd
    18  
    19  import (
    20  	"context"
    21  	"os"
    22  	"testing"
    23  )
    24  
    25  // TestDiskCacheFormat - tests initFormatCache, formatMetaGetFormatBackendCache, formatCacheGetVersion.
    26  func TestDiskCacheFormat(t *testing.T) {
    27  	ctx := context.Background()
    28  	fsDirs, err := getRandomDisks(1)
    29  	if err != nil {
    30  		t.Fatal(err)
    31  	}
    32  
    33  	_, err = initFormatCache(ctx, fsDirs)
    34  	if err != nil {
    35  		t.Fatal(err)
    36  	}
    37  	// Do the basic sanity checks to check if initFormatCache() did its job.
    38  	cacheFormatPath := pathJoin(fsDirs[0], minioMetaBucket, formatConfigFile)
    39  	f, err := os.OpenFile(cacheFormatPath, os.O_RDWR|os.O_SYNC, 0)
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	defer f.Close()
    44  	version, err := formatCacheGetVersion(f)
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  	if version != formatCacheVersionV2 {
    49  		t.Fatalf(`expected: %s, got: %s`, formatCacheVersionV2, version)
    50  	}
    51  
    52  	// Corrupt the format.json file and test the functions.
    53  	// formatMetaGetFormatBackendFS, formatFSGetVersion, initFormatFS should return errors.
    54  	if err = f.Truncate(0); err != nil {
    55  		t.Fatal(err)
    56  	}
    57  	if _, err = f.WriteString("b"); err != nil {
    58  		t.Fatal(err)
    59  	}
    60  
    61  	if _, _, err = loadAndValidateCacheFormat(context.Background(), fsDirs); err == nil {
    62  		t.Fatal("expected to fail")
    63  	}
    64  
    65  	// With unknown formatMetaV1.Version formatMetaGetFormatCache, initFormatCache should return error.
    66  	if err = f.Truncate(0); err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	// Here we set formatMetaV1.Version to "2"
    70  	if _, err = f.WriteString(`{"version":"2","format":"cache","cache":{"version":"1"}}`); err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	if _, _, err = loadAndValidateCacheFormat(context.Background(), fsDirs); err == nil {
    75  		t.Fatal("expected to fail")
    76  	}
    77  }
    78  
    79  // generates a valid format.json for Cache backend.
    80  func genFormatCacheValid() []*formatCacheV2 {
    81  	disks := make([]string, 8)
    82  	formatConfigs := make([]*formatCacheV2, 8)
    83  	for index := range disks {
    84  		disks[index] = mustGetUUID()
    85  	}
    86  	for index := range disks {
    87  		format := &formatCacheV1{}
    88  		format.Version = formatMetaVersion1
    89  		format.Format = formatCache
    90  		format.Cache.Version = formatCacheVersionV2
    91  		format.Cache.This = disks[index]
    92  		format.Cache.Disks = disks
    93  		formatConfigs[index] = format
    94  	}
    95  	return formatConfigs
    96  }
    97  
    98  // generates a invalid format.json version for Cache backend.
    99  func genFormatCacheInvalidVersion() []*formatCacheV2 {
   100  	disks := make([]string, 8)
   101  	formatConfigs := make([]*formatCacheV2, 8)
   102  	for index := range disks {
   103  		disks[index] = mustGetUUID()
   104  	}
   105  	for index := range disks {
   106  		format := &formatCacheV1{}
   107  		format.Version = formatMetaVersion1
   108  		format.Format = formatCache
   109  		format.Cache.Version = formatCacheVersionV1
   110  		format.Cache.This = disks[index]
   111  		format.Cache.Disks = disks
   112  		formatConfigs[index] = format
   113  	}
   114  	// Corrupt version numbers.
   115  	formatConfigs[0].Version = "2"
   116  	formatConfigs[3].Version = "-1"
   117  	return formatConfigs
   118  }
   119  
   120  // generates a invalid format.json version for Cache backend.
   121  func genFormatCacheInvalidFormat() []*formatCacheV2 {
   122  	disks := make([]string, 8)
   123  	formatConfigs := make([]*formatCacheV2, 8)
   124  	for index := range disks {
   125  		disks[index] = mustGetUUID()
   126  	}
   127  	for index := range disks {
   128  		format := &formatCacheV2{}
   129  		format.Version = formatMetaVersion1
   130  		format.Format = formatCache
   131  		format.Cache.Version = formatCacheVersionV1
   132  		format.Cache.This = disks[index]
   133  		format.Cache.Disks = disks
   134  		formatConfigs[index] = format
   135  	}
   136  	// Corrupt format.
   137  	formatConfigs[0].Format = "cach"
   138  	formatConfigs[3].Format = "cach"
   139  	return formatConfigs
   140  }
   141  
   142  // generates a invalid format.json version for Cache backend.
   143  func genFormatCacheInvalidCacheVersion() []*formatCacheV2 {
   144  	disks := make([]string, 8)
   145  	formatConfigs := make([]*formatCacheV2, 8)
   146  	for index := range disks {
   147  		disks[index] = mustGetUUID()
   148  	}
   149  	for index := range disks {
   150  		format := &formatCacheV2{}
   151  		format.Version = formatMetaVersion1
   152  		format.Format = formatCache
   153  		format.Cache.Version = formatCacheVersionV1
   154  		format.Cache.This = disks[index]
   155  		format.Cache.Disks = disks
   156  		formatConfigs[index] = format
   157  	}
   158  	// Corrupt version numbers.
   159  	formatConfigs[0].Cache.Version = "10"
   160  	formatConfigs[3].Cache.Version = "-1"
   161  	return formatConfigs
   162  }
   163  
   164  // generates a invalid format.json version for Cache backend.
   165  func genFormatCacheInvalidDisksCount() []*formatCacheV2 {
   166  	disks := make([]string, 7)
   167  	formatConfigs := make([]*formatCacheV2, 8)
   168  	for index := range disks {
   169  		disks[index] = mustGetUUID()
   170  	}
   171  	for index := range disks {
   172  		format := &formatCacheV2{}
   173  		format.Version = formatMetaVersion1
   174  		format.Format = formatCache
   175  		format.Cache.Version = formatCacheVersionV2
   176  		format.Cache.This = disks[index]
   177  		format.Cache.Disks = disks
   178  		formatConfigs[index] = format
   179  	}
   180  	return formatConfigs
   181  }
   182  
   183  // generates a invalid format.json Disks for Cache backend.
   184  func genFormatCacheInvalidDisks() []*formatCacheV2 {
   185  	disks := make([]string, 8)
   186  	formatConfigs := make([]*formatCacheV2, 8)
   187  	for index := range disks {
   188  		disks[index] = mustGetUUID()
   189  	}
   190  	for index := range disks {
   191  		format := &formatCacheV1{}
   192  		format.Version = formatMetaVersion1
   193  		format.Format = formatCache
   194  		format.Cache.Version = formatCacheVersionV2
   195  		format.Cache.This = disks[index]
   196  		format.Cache.Disks = disks
   197  		formatConfigs[index] = format
   198  	}
   199  	for index := range disks {
   200  		disks[index] = mustGetUUID()
   201  	}
   202  	// Corrupt Disks entries on disk 6 and disk 8.
   203  	formatConfigs[5].Cache.Disks = disks
   204  	formatConfigs[7].Cache.Disks = disks
   205  	return formatConfigs
   206  }
   207  
   208  // generates a invalid format.json This disk UUID for Cache backend.
   209  func genFormatCacheInvalidThis() []*formatCacheV1 {
   210  	disks := make([]string, 8)
   211  	formatConfigs := make([]*formatCacheV1, 8)
   212  	for index := range disks {
   213  		disks[index] = mustGetUUID()
   214  	}
   215  	for index := range disks {
   216  		format := &formatCacheV1{}
   217  		format.Version = formatMetaVersion1
   218  		format.Format = formatCache
   219  		format.Cache.Version = formatCacheVersionV2
   220  		format.Cache.This = disks[index]
   221  		format.Cache.Disks = disks
   222  		formatConfigs[index] = format
   223  	}
   224  	// Make disk 5 and disk 8 have inconsistent disk uuid's.
   225  	formatConfigs[4].Cache.This = mustGetUUID()
   226  	formatConfigs[7].Cache.This = mustGetUUID()
   227  	return formatConfigs
   228  }
   229  
   230  // generates a invalid format.json Disk UUID in wrong order for Cache backend.
   231  func genFormatCacheInvalidDisksOrder() []*formatCacheV2 {
   232  	disks := make([]string, 8)
   233  	formatConfigs := make([]*formatCacheV2, 8)
   234  	for index := range disks {
   235  		disks[index] = mustGetUUID()
   236  	}
   237  	for index := range disks {
   238  		format := &formatCacheV1{}
   239  		format.Version = formatMetaVersion1
   240  		format.Format = formatCache
   241  		format.Cache.Version = formatCacheVersionV2
   242  		format.Cache.This = disks[index]
   243  		format.Cache.Disks = disks
   244  		formatConfigs[index] = format
   245  	}
   246  	// Re order disks for failure case.
   247  	var disks1 = make([]string, 8)
   248  	copy(disks1, disks)
   249  	disks1[1], disks1[2] = disks[2], disks[1]
   250  	formatConfigs[2].Cache.Disks = disks1
   251  	return formatConfigs
   252  }
   253  
   254  // Wrapper for calling FormatCache tests - validates
   255  //  - valid format
   256  //  - unrecognized version number
   257  //  - unrecognized format tag
   258  //  - unrecognized cache version
   259  //  - wrong number of Disks entries
   260  //  - invalid This uuid
   261  //  - invalid Disks order
   262  func TestFormatCache(t *testing.T) {
   263  	formatInputCases := [][]*formatCacheV1{
   264  		genFormatCacheValid(),
   265  		genFormatCacheInvalidVersion(),
   266  		genFormatCacheInvalidFormat(),
   267  		genFormatCacheInvalidCacheVersion(),
   268  		genFormatCacheInvalidDisksCount(),
   269  		genFormatCacheInvalidDisks(),
   270  		genFormatCacheInvalidThis(),
   271  		genFormatCacheInvalidDisksOrder(),
   272  	}
   273  	testCases := []struct {
   274  		formatConfigs []*formatCacheV1
   275  		shouldPass    bool
   276  	}{
   277  		{
   278  			formatConfigs: formatInputCases[0],
   279  			shouldPass:    true,
   280  		},
   281  		{
   282  			formatConfigs: formatInputCases[1],
   283  			shouldPass:    false,
   284  		},
   285  		{
   286  			formatConfigs: formatInputCases[2],
   287  			shouldPass:    false,
   288  		},
   289  		{
   290  			formatConfigs: formatInputCases[3],
   291  			shouldPass:    false,
   292  		},
   293  		{
   294  			formatConfigs: formatInputCases[4],
   295  			shouldPass:    false,
   296  		},
   297  		{
   298  			formatConfigs: formatInputCases[5],
   299  			shouldPass:    false,
   300  		},
   301  		{
   302  			formatConfigs: formatInputCases[6],
   303  			shouldPass:    false,
   304  		},
   305  		{
   306  			formatConfigs: formatInputCases[7],
   307  			shouldPass:    false,
   308  		},
   309  	}
   310  
   311  	for i, testCase := range testCases {
   312  		err := validateCacheFormats(context.Background(), false, testCase.formatConfigs)
   313  		if err != nil && testCase.shouldPass {
   314  			t.Errorf("Test %d: Expected to pass but failed with %s", i+1, err)
   315  		}
   316  		if err == nil && !testCase.shouldPass {
   317  			t.Errorf("Test %d: Expected to fail but passed instead", i+1)
   318  		}
   319  	}
   320  }