storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/erasure-sets_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2017 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  	"path/filepath"
    23  	"testing"
    24  
    25  	"github.com/google/uuid"
    26  )
    27  
    28  var testUUID = uuid.MustParse("f5c58c61-7175-4018-ab5e-a94fe9c2de4e")
    29  
    30  func BenchmarkCrcHash(b *testing.B) {
    31  	cases := []struct {
    32  		key int
    33  	}{
    34  		{16},
    35  		{64},
    36  		{128},
    37  		{256},
    38  		{512},
    39  		{1024},
    40  	}
    41  	for _, testCase := range cases {
    42  		testCase := testCase
    43  		key := randString(testCase.key)
    44  		b.Run("", func(b *testing.B) {
    45  			b.SetBytes(1024)
    46  			b.ReportAllocs()
    47  			b.ResetTimer()
    48  			for i := 0; i < b.N; i++ {
    49  				crcHashMod(key, 16)
    50  			}
    51  		})
    52  	}
    53  }
    54  
    55  func BenchmarkSipHash(b *testing.B) {
    56  	cases := []struct {
    57  		key int
    58  	}{
    59  		{16},
    60  		{64},
    61  		{128},
    62  		{256},
    63  		{512},
    64  		{1024},
    65  	}
    66  	for _, testCase := range cases {
    67  		testCase := testCase
    68  		key := randString(testCase.key)
    69  		b.Run("", func(b *testing.B) {
    70  			b.SetBytes(1024)
    71  			b.ReportAllocs()
    72  			b.ResetTimer()
    73  			for i := 0; i < b.N; i++ {
    74  				sipHashMod(key, 16, testUUID)
    75  			}
    76  		})
    77  	}
    78  }
    79  
    80  // TestSipHashMod - test sip hash.
    81  func TestSipHashMod(t *testing.T) {
    82  	testCases := []struct {
    83  		objectName string
    84  		sipHash    int
    85  	}{
    86  		// cases which should pass the test.
    87  		// passing in valid object name.
    88  		{"object", 37},
    89  		{"The Shining Script <v1>.pdf", 38},
    90  		{"Cost Benefit Analysis (2009-2010).pptx", 59},
    91  		{"117Gn8rfHL2ACARPAhaFd0AGzic9pUbIA/5OCn5A", 35},
    92  		{"SHØRT", 49},
    93  		{"There are far too many object names, and far too few bucket names!", 8},
    94  		{"a/b/c/", 159},
    95  		{"/a/b/c", 96},
    96  		{string([]byte{0xff, 0xfe, 0xfd}), 147},
    97  	}
    98  
    99  	// Tests hashing order to be consistent.
   100  	for i, testCase := range testCases {
   101  		if sipHashElement := hashKey("SIPMOD", testCase.objectName, 200, testUUID); sipHashElement != testCase.sipHash {
   102  			t.Errorf("Test case %d: Expected \"%v\" but failed \"%v\"", i+1, testCase.sipHash, sipHashElement)
   103  		}
   104  	}
   105  
   106  	if sipHashElement := hashKey("SIPMOD", "This will fail", -1, testUUID); sipHashElement != -1 {
   107  		t.Errorf("Test: Expected \"-1\" but got \"%v\"", sipHashElement)
   108  	}
   109  
   110  	if sipHashElement := hashKey("SIPMOD", "This will fail", 0, testUUID); sipHashElement != -1 {
   111  		t.Errorf("Test: Expected \"-1\" but got \"%v\"", sipHashElement)
   112  	}
   113  
   114  	if sipHashElement := hashKey("UNKNOWN", "This will fail", 0, testUUID); sipHashElement != -1 {
   115  		t.Errorf("Test: Expected \"-1\" but got \"%v\"", sipHashElement)
   116  	}
   117  }
   118  
   119  // TestCrcHashMod - test crc hash.
   120  func TestCrcHashMod(t *testing.T) {
   121  	testCases := []struct {
   122  		objectName string
   123  		crcHash    int
   124  	}{
   125  		// cases which should pass the test.
   126  		// passing in valid object name.
   127  		{"object", 28},
   128  		{"The Shining Script <v1>.pdf", 142},
   129  		{"Cost Benefit Analysis (2009-2010).pptx", 133},
   130  		{"117Gn8rfHL2ACARPAhaFd0AGzic9pUbIA/5OCn5A", 185},
   131  		{"SHØRT", 97},
   132  		{"There are far too many object names, and far too few bucket names!", 101},
   133  		{"a/b/c/", 193},
   134  		{"/a/b/c", 116},
   135  		{string([]byte{0xff, 0xfe, 0xfd}), 61},
   136  	}
   137  
   138  	// Tests hashing order to be consistent.
   139  	for i, testCase := range testCases {
   140  		if crcHashElement := hashKey("CRCMOD", testCase.objectName, 200, testUUID); crcHashElement != testCase.crcHash {
   141  			t.Errorf("Test case %d: Expected \"%v\" but failed \"%v\"", i+1, testCase.crcHash, crcHashElement)
   142  		}
   143  	}
   144  
   145  	if crcHashElement := hashKey("CRCMOD", "This will fail", -1, testUUID); crcHashElement != -1 {
   146  		t.Errorf("Test: Expected \"-1\" but got \"%v\"", crcHashElement)
   147  	}
   148  
   149  	if crcHashElement := hashKey("CRCMOD", "This will fail", 0, testUUID); crcHashElement != -1 {
   150  		t.Errorf("Test: Expected \"-1\" but got \"%v\"", crcHashElement)
   151  	}
   152  
   153  	if crcHashElement := hashKey("UNKNOWN", "This will fail", 0, testUUID); crcHashElement != -1 {
   154  		t.Errorf("Test: Expected \"-1\" but got \"%v\"", crcHashElement)
   155  	}
   156  }
   157  
   158  // TestNewErasure - tests initialization of all input disks
   159  // and constructs a valid `Erasure` object
   160  func TestNewErasureSets(t *testing.T) {
   161  	ctx, cancel := context.WithCancel(context.Background())
   162  	defer cancel()
   163  
   164  	var nDisks = 16 // Maximum disks.
   165  	var erasureDisks []string
   166  	for i := 0; i < nDisks; i++ {
   167  		// Do not attempt to create this path, the test validates
   168  		// so that newErasureSets initializes non existing paths
   169  		// and successfully returns initialized object layer.
   170  		disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix())
   171  		erasureDisks = append(erasureDisks, disk)
   172  		defer os.RemoveAll(disk)
   173  	}
   174  
   175  	endpoints := mustGetNewEndpoints(erasureDisks...)
   176  	_, _, err := waitForFormatErasure(true, endpoints, 1, 0, 16, "", "")
   177  	if err != errInvalidArgument {
   178  		t.Fatalf("Expecting error, got %s", err)
   179  	}
   180  
   181  	_, _, err = waitForFormatErasure(true, nil, 1, 1, 16, "", "")
   182  	if err != errInvalidArgument {
   183  		t.Fatalf("Expecting error, got %s", err)
   184  	}
   185  
   186  	// Initializes all erasure disks
   187  	storageDisks, format, err := waitForFormatErasure(true, endpoints, 1, 1, 16, "", "")
   188  	if err != nil {
   189  		t.Fatalf("Unable to format disks for erasure, %s", err)
   190  	}
   191  
   192  	if _, err := newErasureSets(ctx, endpoints, storageDisks, format, ecDrivesNoConfig(16), 0); err != nil {
   193  		t.Fatalf("Unable to initialize erasure")
   194  	}
   195  }
   196  
   197  // TestHashedLayer - tests the hashed layer which will be returned
   198  // consistently for a given object name.
   199  func TestHashedLayer(t *testing.T) {
   200  	// Test distribution with 16 sets.
   201  	var objs [16]*erasureObjects
   202  	for i := range objs {
   203  		objs[i] = &erasureObjects{}
   204  	}
   205  
   206  	sets := &erasureSets{sets: objs[:], distributionAlgo: "CRCMOD"}
   207  
   208  	testCases := []struct {
   209  		objectName  string
   210  		expectedObj *erasureObjects
   211  	}{
   212  		// cases which should pass the test.
   213  		// passing in valid object name.
   214  		{"object", objs[12]},
   215  		{"The Shining Script <v1>.pdf", objs[14]},
   216  		{"Cost Benefit Analysis (2009-2010).pptx", objs[13]},
   217  		{"117Gn8rfHL2ACARPAhaFd0AGzic9pUbIA/5OCn5A", objs[1]},
   218  		{"SHØRT", objs[9]},
   219  		{"There are far too many object names, and far too few bucket names!", objs[13]},
   220  		{"a/b/c/", objs[1]},
   221  		{"/a/b/c", objs[4]},
   222  		{string([]byte{0xff, 0xfe, 0xfd}), objs[13]},
   223  	}
   224  
   225  	// Tests hashing order to be consistent.
   226  	for i, testCase := range testCases {
   227  		gotObj := sets.getHashedSet(testCase.objectName)
   228  		if gotObj != testCase.expectedObj {
   229  			t.Errorf("Test case %d: Expected \"%#v\" but failed \"%#v\"", i+1, testCase.expectedObj, gotObj)
   230  		}
   231  	}
   232  }