storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/xl-storage-format-v2_test.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2021 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  	"bytes"
    21  	"testing"
    22  	"time"
    23  )
    24  
    25  func TestXLV2FormatData(t *testing.T) {
    26  	failOnErr := func(err error) {
    27  		t.Helper()
    28  		if err != nil {
    29  			t.Fatal(err)
    30  		}
    31  	}
    32  	data := []byte("some object data")
    33  	data2 := []byte("some other object data")
    34  
    35  	xl := xlMetaV2{}
    36  	fi := FileInfo{
    37  		Volume:           "volume",
    38  		Name:             "object-name",
    39  		VersionID:        "756100c6-b393-4981-928a-d49bbc164741",
    40  		IsLatest:         true,
    41  		Deleted:          false,
    42  		TransitionStatus: "",
    43  		DataDir:          "bffea160-ca7f-465f-98bc-9b4f1c3ba1ef",
    44  		XLV1:             false,
    45  		ModTime:          time.Now(),
    46  		Size:             0,
    47  		Mode:             0,
    48  		Metadata:         nil,
    49  		Parts:            nil,
    50  		Erasure: ErasureInfo{
    51  			Algorithm:    ReedSolomon.String(),
    52  			DataBlocks:   4,
    53  			ParityBlocks: 2,
    54  			BlockSize:    10000,
    55  			Index:        1,
    56  			Distribution: []int{1, 2, 3, 4, 5, 6, 7, 8},
    57  			Checksums: []ChecksumInfo{{
    58  				PartNumber: 1,
    59  				Algorithm:  HighwayHash256S,
    60  				Hash:       nil,
    61  			}},
    62  		},
    63  		MarkDeleted:                   false,
    64  		DeleteMarkerReplicationStatus: "",
    65  		VersionPurgeStatus:            "",
    66  		Data:                          data,
    67  		NumVersions:                   1,
    68  		SuccessorModTime:              time.Time{},
    69  	}
    70  
    71  	failOnErr(xl.AddVersion(fi))
    72  
    73  	fi.VersionID = mustGetUUID()
    74  	fi.DataDir = mustGetUUID()
    75  	fi.Data = data2
    76  	failOnErr(xl.AddVersion(fi))
    77  
    78  	serialized, err := xl.AppendTo(nil)
    79  	failOnErr(err)
    80  	// Roundtrip data
    81  	var xl2 xlMetaV2
    82  	failOnErr(xl2.Load(serialized))
    83  
    84  	// We should have one data entry
    85  	list, err := xl2.data.list()
    86  	failOnErr(err)
    87  	if len(list) != 2 {
    88  		t.Fatalf("want 1 entry, got %d", len(list))
    89  	}
    90  
    91  	if !bytes.Equal(xl2.data.find("756100c6-b393-4981-928a-d49bbc164741"), data) {
    92  		t.Fatal("Find data returned", xl2.data.find("756100c6-b393-4981-928a-d49bbc164741"))
    93  	}
    94  	if !bytes.Equal(xl2.data.find(fi.VersionID), data2) {
    95  		t.Fatal("Find data returned", xl2.data.find(fi.VersionID))
    96  	}
    97  
    98  	// Remove entry
    99  	xl2.data.remove(fi.VersionID)
   100  	failOnErr(xl2.data.validate())
   101  	if xl2.data.find(fi.VersionID) != nil {
   102  		t.Fatal("Data was not removed:", xl2.data.find(fi.VersionID))
   103  	}
   104  	if xl2.data.entries() != 1 {
   105  		t.Fatal("want 1 entry, got", xl2.data.entries())
   106  	}
   107  	// Re-add
   108  	xl2.data.replace(fi.VersionID, fi.Data)
   109  	failOnErr(xl2.data.validate())
   110  	if xl2.data.entries() != 2 {
   111  		t.Fatal("want 2 entries, got", xl2.data.entries())
   112  	}
   113  
   114  	// Replace entry
   115  	xl2.data.replace("756100c6-b393-4981-928a-d49bbc164741", data2)
   116  	failOnErr(xl2.data.validate())
   117  	if xl2.data.entries() != 2 {
   118  		t.Fatal("want 2 entries, got", xl2.data.entries())
   119  	}
   120  	if !bytes.Equal(xl2.data.find("756100c6-b393-4981-928a-d49bbc164741"), data2) {
   121  		t.Fatal("Find data returned", xl2.data.find("756100c6-b393-4981-928a-d49bbc164741"))
   122  	}
   123  
   124  	if !xl2.data.rename("756100c6-b393-4981-928a-d49bbc164741", "new-key") {
   125  		t.Fatal("old key was not found")
   126  	}
   127  	failOnErr(xl2.data.validate())
   128  	if !bytes.Equal(xl2.data.find("new-key"), data2) {
   129  		t.Fatal("Find data returned", xl2.data.find("756100c6-b393-4981-928a-d49bbc164741"))
   130  	}
   131  	if xl2.data.entries() != 2 {
   132  		t.Fatal("want 2 entries, got", xl2.data.entries())
   133  	}
   134  	if !bytes.Equal(xl2.data.find(fi.VersionID), data2) {
   135  		t.Fatal("Find data returned", xl2.data.find(fi.DataDir))
   136  	}
   137  
   138  	// Test trimmed
   139  	xl2 = xlMetaV2{}
   140  	trimmed := xlMetaV2TrimData(serialized)
   141  	failOnErr(xl2.Load(trimmed))
   142  	if len(xl2.data) != 0 {
   143  		t.Fatal("data, was not trimmed, bytes left:", len(xl2.data))
   144  	}
   145  	// Corrupt metadata, last 5 bytes is the checksum, so go a bit further back.
   146  	trimmed[len(trimmed)-10] += 10
   147  	if err := xl2.Load(trimmed); err == nil {
   148  		t.Fatal("metadata corruption not detected")
   149  	}
   150  }