mirror of
https://github.com/minio/minio.git
synced 2024-12-26 15:15:55 -05:00
bc61417284
it is possible in many screnarios that even if the divisible value is optimal, we may end up with uneven distribution due to number of nodes present in the configuration. added code allow for affinity towards various ellipses to figure out optimal value across ellipses such that we can always reach a symmetric value automatically. Fixes #9416
154 lines
4.5 KiB
Go
154 lines
4.5 KiB
Go
/*
|
|
* MinIO Cloud Storage, (C) 2017 MinIO, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// TestCrcHashMod - test crc hash.
|
|
func TestCrcHashMod(t *testing.T) {
|
|
testCases := []struct {
|
|
objectName string
|
|
crcHash int
|
|
}{
|
|
// cases which should pass the test.
|
|
// passing in valid object name.
|
|
{"object", 12},
|
|
{"The Shining Script <v1>.pdf", 14},
|
|
{"Cost Benefit Analysis (2009-2010).pptx", 13},
|
|
{"117Gn8rfHL2ACARPAhaFd0AGzic9pUbIA/5OCn5A", 1},
|
|
{"SHØRT", 9},
|
|
{"There are far too many object names, and far too few bucket names!", 13},
|
|
{"a/b/c/", 1},
|
|
{"/a/b/c", 4},
|
|
{string([]byte{0xff, 0xfe, 0xfd}), 13},
|
|
}
|
|
|
|
// Tests hashing order to be consistent.
|
|
for i, testCase := range testCases {
|
|
if crcHashElement := hashKey("CRCMOD", testCase.objectName, 16); crcHashElement != testCase.crcHash {
|
|
t.Errorf("Test case %d: Expected \"%v\" but failed \"%v\"", i+1, testCase.crcHash, crcHashElement)
|
|
}
|
|
}
|
|
|
|
if crcHashElement := hashKey("CRCMOD", "This will fail", -1); crcHashElement != -1 {
|
|
t.Errorf("Test: Expected \"-1\" but got \"%v\"", crcHashElement)
|
|
}
|
|
|
|
if crcHashElement := hashKey("CRCMOD", "This will fail", 0); crcHashElement != -1 {
|
|
t.Errorf("Test: Expected \"-1\" but got \"%v\"", crcHashElement)
|
|
}
|
|
|
|
if crcHashElement := hashKey("UNKNOWN", "This will fail", 0); crcHashElement != -1 {
|
|
t.Errorf("Test: Expected \"-1\" but got \"%v\"", crcHashElement)
|
|
}
|
|
}
|
|
|
|
// TestNewXL - tests initialization of all input disks
|
|
// and constructs a valid `XL` object
|
|
func TestNewXLSets(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
var nDisks = 16 // Maximum disks.
|
|
var erasureDisks []string
|
|
for i := 0; i < nDisks; i++ {
|
|
// Do not attempt to create this path, the test validates
|
|
// so that newXLSets initializes non existing paths
|
|
// and successfully returns initialized object layer.
|
|
disk := filepath.Join(globalTestTmpDir, "minio-"+nextSuffix())
|
|
erasureDisks = append(erasureDisks, disk)
|
|
defer os.RemoveAll(disk)
|
|
}
|
|
|
|
endpoints := mustGetNewEndpoints(erasureDisks...)
|
|
_, _, err := waitForFormatXL(true, endpoints, 1, 0, 16, "")
|
|
if err != errInvalidArgument {
|
|
t.Fatalf("Expecting error, got %s", err)
|
|
}
|
|
|
|
_, _, err = waitForFormatXL(true, nil, 1, 1, 16, "")
|
|
if err != errInvalidArgument {
|
|
t.Fatalf("Expecting error, got %s", err)
|
|
}
|
|
|
|
// Initializes all erasure disks
|
|
storageDisks, format, err := waitForFormatXL(true, endpoints, 1, 1, 16, "")
|
|
if err != nil {
|
|
t.Fatalf("Unable to format disks for erasure, %s", err)
|
|
}
|
|
|
|
if _, err := newXLSets(ctx, endpoints, storageDisks, format); err != nil {
|
|
t.Fatalf("Unable to initialize erasure")
|
|
}
|
|
}
|
|
|
|
// TestHashedLayer - tests the hashed layer which will be returned
|
|
// consistently for a given object name.
|
|
func TestHashedLayer(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
var objs []*xlObjects
|
|
|
|
for i := 0; i < 16; i++ {
|
|
obj, fsDirs, err := prepareXL16(ctx)
|
|
if err != nil {
|
|
t.Fatal("Unable to initialize 'XL' object layer.", err)
|
|
}
|
|
|
|
// Remove all dirs.
|
|
for _, dir := range fsDirs {
|
|
defer os.RemoveAll(dir)
|
|
}
|
|
|
|
z := obj.(*xlZones)
|
|
objs = append(objs, z.zones[0].sets[0])
|
|
}
|
|
|
|
sets := &xlSets{sets: objs, distributionAlgo: "CRCMOD"}
|
|
|
|
testCases := []struct {
|
|
objectName string
|
|
expectedObj *xlObjects
|
|
}{
|
|
// cases which should pass the test.
|
|
// passing in valid object name.
|
|
{"object", objs[12]},
|
|
{"The Shining Script <v1>.pdf", objs[14]},
|
|
{"Cost Benefit Analysis (2009-2010).pptx", objs[13]},
|
|
{"117Gn8rfHL2ACARPAhaFd0AGzic9pUbIA/5OCn5A", objs[1]},
|
|
{"SHØRT", objs[9]},
|
|
{"There are far too many object names, and far too few bucket names!", objs[13]},
|
|
{"a/b/c/", objs[1]},
|
|
{"/a/b/c", objs[4]},
|
|
{string([]byte{0xff, 0xfe, 0xfd}), objs[13]},
|
|
}
|
|
|
|
// Tests hashing order to be consistent.
|
|
for i, testCase := range testCases {
|
|
gotObj := sets.getHashedSet(testCase.objectName)
|
|
if gotObj != testCase.expectedObj {
|
|
t.Errorf("Test case %d: Expected \"%#v\" but failed \"%#v\"", i+1, testCase.expectedObj, gotObj)
|
|
}
|
|
}
|
|
}
|