1
0
mirror of https://github.com/minio/minio.git synced 2025-04-01 10:13:42 -04:00
minio/cmd/xl-storage-format-utils_test.go
Krishnan Parthasarathi 3da9ee15d3
Add MaxNoncurrentVersions to NoncurrentExpiration action ()
This unit allows users to limit the maximum number of noncurrent 
versions of an object.

To enable this rule you need the following *ilm.json*
```
cat >> ilm.json <<EOF
{
    "Rules": [
        {
            "ID": "test-max-noncurrent",
            "Status": "Enabled",
            "Filter": {
                "Prefix": "user-uploads/"
            },
            "NoncurrentVersionExpiration": {
                "MaxNoncurrentVersions": 5
            }
        }
    ]
}
EOF
mc ilm import myminio/mybucket < ilm.json
```
2021-11-19 17:54:10 -08:00

206 lines
5.9 KiB
Go

// Copyright (c) 2015-2021 MinIO, Inc.
//
// This file is part of MinIO Object Storage stack
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package cmd
import (
"sort"
"testing"
"time"
"github.com/minio/minio/internal/bucket/lifecycle"
xhttp "github.com/minio/minio/internal/http"
)
func Test_hashDeterministicString(t *testing.T) {
tests := []struct {
name string
arg map[string]string
}{
{
name: "zero",
arg: map[string]string{},
},
{
name: "nil",
arg: nil,
},
{
name: "one",
arg: map[string]string{"key": "value"},
},
{
name: "several",
arg: map[string]string{
xhttp.AmzRestore: "FAILED",
xhttp.ContentMD5: mustGetUUID(),
xhttp.AmzBucketReplicationStatus: "PENDING",
xhttp.ContentType: "application/json",
},
},
{
name: "someempty",
arg: map[string]string{
xhttp.AmzRestore: "",
xhttp.ContentMD5: mustGetUUID(),
xhttp.AmzBucketReplicationStatus: "",
xhttp.ContentType: "application/json",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
const n = 100
want := hashDeterministicString(tt.arg)
m := tt.arg
for i := 0; i < n; i++ {
if got := hashDeterministicString(m); got != want {
t.Errorf("hashDeterministicString() = %v, want %v", got, want)
}
}
// Check casual collisions
if m == nil {
m = make(map[string]string)
}
m["12312312"] = ""
if got := hashDeterministicString(m); got == want {
t.Errorf("hashDeterministicString() = %v, does not want %v", got, want)
}
want = hashDeterministicString(m)
delete(m, "12312312")
m["another"] = ""
if got := hashDeterministicString(m); got == want {
t.Errorf("hashDeterministicString() = %v, does not want %v", got, want)
}
want = hashDeterministicString(m)
m["another"] = "hashDeterministicString"
if got := hashDeterministicString(m); got == want {
t.Errorf("hashDeterministicString() = %v, does not want %v", got, want)
}
want = hashDeterministicString(m)
m["another"] = "hashDeterministicStringhashDeterministicStringhashDeterministicStringhashDeterministicStringhashDeterministicStringhashDeterministicStringhashDeterministicString"
if got := hashDeterministicString(m); got == want {
t.Errorf("hashDeterministicString() = %v, does not want %v", got, want)
}
// Flip key/value
want = hashDeterministicString(m)
delete(m, "another")
m["hashDeterministicStringhashDeterministicStringhashDeterministicStringhashDeterministicStringhashDeterministicStringhashDeterministicStringhashDeterministicString"] = "another"
if got := hashDeterministicString(m); got == want {
t.Errorf("hashDeterministicString() = %v, does not want %v", got, want)
}
})
}
}
func TestGetFileInfoVersions(t *testing.T) {
basefi := FileInfo{
Volume: "volume",
Name: "object-name",
VersionID: "756100c6-b393-4981-928a-d49bbc164741",
IsLatest: true,
Deleted: false,
TransitionStatus: "",
DataDir: "bffea160-ca7f-465f-98bc-9b4f1c3ba1ef",
XLV1: false,
ModTime: time.Now().UTC(),
Size: 0,
Mode: 0,
Metadata: nil,
Parts: nil,
Erasure: ErasureInfo{
Algorithm: ReedSolomon.String(),
DataBlocks: 4,
ParityBlocks: 2,
BlockSize: 10000,
Index: 1,
Distribution: []int{1, 2, 3, 4, 5, 6, 7, 8},
Checksums: []ChecksumInfo{{
PartNumber: 1,
Algorithm: HighwayHash256S,
Hash: nil,
}},
},
MarkDeleted: false,
NumVersions: 1,
SuccessorModTime: time.Time{},
}
xl := xlMetaV2{}
var versions []FileInfo
var freeVersionIDs []string
for i := 0; i < 5; i++ {
fi := basefi
fi.VersionID = mustGetUUID()
fi.DataDir = mustGetUUID()
fi.ModTime = basefi.ModTime.Add(time.Duration(i) * time.Second)
if err := xl.AddVersion(fi); err != nil {
t.Fatalf("%d: Failed to add version %v", i+1, err)
}
if i > 3 {
// Simulate transition of a version
transfi := fi
transfi.TransitionStatus = lifecycle.TransitionComplete
transfi.TransitionTier = "MINIO-TIER"
transfi.TransitionedObjName = mustGetUUID()
xl.DeleteVersion(transfi)
fi.SetTierFreeVersionID(mustGetUUID())
// delete this version leading to a free version
xl.DeleteVersion(fi)
freeVersionIDs = append(freeVersionIDs, fi.TierFreeVersionID())
} else {
versions = append(versions, fi)
}
}
buf, err := xl.AppendTo(nil)
if err != nil {
t.Fatalf("Failed to serialize xlmeta %v", err)
}
fivs, err := getFileInfoVersions(buf, basefi.Volume, basefi.Name)
if err != nil {
t.Fatalf("getFileInfoVersions failed: %v", err)
}
sort.Slice(versions, func(i, j int) bool {
if versions[i].IsLatest {
return true
}
if versions[j].IsLatest {
return false
}
return versions[i].ModTime.After(versions[j].ModTime)
})
for i, fi := range fivs.Versions {
if fi.VersionID != versions[i].VersionID {
t.Fatalf("getFileInfoVersions: versions don't match at %d, version id expected %s but got %s", i, fi.VersionID, versions[i].VersionID)
}
}
for i, free := range fivs.FreeVersions {
if free.VersionID != freeVersionIDs[i] {
t.Fatalf("getFileInfoVersions: free versions don't match at %d, version id expected %s but got %s", i, free.VersionID, freeVersionIDs[i])
}
}
}