mirror of https://github.com/minio/minio.git
138 lines
3.8 KiB
Go
138 lines
3.8 KiB
Go
|
// Copyright (c) 2015-2023 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 (
|
||
|
"context"
|
||
|
"encoding/xml"
|
||
|
"sync"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/google/uuid"
|
||
|
"github.com/minio/minio/internal/bucket/lifecycle"
|
||
|
"github.com/minio/minio/internal/bucket/versioning"
|
||
|
)
|
||
|
|
||
|
func TestApplyNewerNoncurrentVersionsLimit(t *testing.T) {
|
||
|
objAPI, disks, err := prepareErasure(context.Background(), 8)
|
||
|
if err != nil {
|
||
|
t.Fatalf("Failed to initialize object layer: %v", err)
|
||
|
}
|
||
|
defer removeRoots(disks)
|
||
|
setObjectLayer(objAPI)
|
||
|
globalBucketMetadataSys = NewBucketMetadataSys()
|
||
|
globalBucketObjectLockSys = &BucketObjectLockSys{}
|
||
|
globalBucketVersioningSys = &BucketVersioningSys{}
|
||
|
globalExpiryState = newExpiryState()
|
||
|
var wg sync.WaitGroup
|
||
|
wg.Add(1)
|
||
|
expired := make([]ObjectToDelete, 0, 5)
|
||
|
go func() {
|
||
|
defer wg.Done()
|
||
|
for t := range globalExpiryState.byNewerNoncurrentCh {
|
||
|
expired = append(expired, t.versions...)
|
||
|
}
|
||
|
}()
|
||
|
lc := lifecycle.Lifecycle{
|
||
|
Rules: []lifecycle.Rule{
|
||
|
{
|
||
|
ID: "max-versions",
|
||
|
Status: "Enabled",
|
||
|
NoncurrentVersionExpiration: lifecycle.NoncurrentVersionExpiration{
|
||
|
NewerNoncurrentVersions: 1,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
lcXML, err := xml.Marshal(lc)
|
||
|
if err != nil {
|
||
|
t.Fatalf("Failed to marshal lifecycle config: %v", err)
|
||
|
}
|
||
|
vcfg := versioning.Versioning{
|
||
|
Status: "Enabled",
|
||
|
}
|
||
|
vcfgXML, err := xml.Marshal(vcfg)
|
||
|
if err != nil {
|
||
|
t.Fatalf("Failed to marshal versioning config: %v", err)
|
||
|
}
|
||
|
|
||
|
bucket := "bucket"
|
||
|
obj := "obj-1"
|
||
|
now := time.Now()
|
||
|
meta := BucketMetadata{
|
||
|
Name: bucket,
|
||
|
Created: now,
|
||
|
LifecycleConfigXML: lcXML,
|
||
|
VersioningConfigXML: vcfgXML,
|
||
|
VersioningConfigUpdatedAt: now,
|
||
|
LifecycleConfigUpdatedAt: now,
|
||
|
lifecycleConfig: &lc,
|
||
|
versioningConfig: &vcfg,
|
||
|
}
|
||
|
globalBucketMetadataSys.Set(bucket, meta)
|
||
|
item := scannerItem{
|
||
|
Path: obj,
|
||
|
bucket: bucket,
|
||
|
prefix: "",
|
||
|
objectName: obj,
|
||
|
lifeCycle: &lc,
|
||
|
}
|
||
|
|
||
|
modTime := time.Now()
|
||
|
uuids := make([]uuid.UUID, 5)
|
||
|
for i := range uuids {
|
||
|
uuids[i] = uuid.UUID([16]byte{15: uint8(i + 1)})
|
||
|
}
|
||
|
fivs := make([]FileInfo, 5)
|
||
|
for i := 0; i < 5; i++ {
|
||
|
fivs[i] = FileInfo{
|
||
|
Volume: bucket,
|
||
|
Name: obj,
|
||
|
VersionID: uuids[i].String(),
|
||
|
IsLatest: i == 0,
|
||
|
ModTime: modTime.Add(-1 * time.Duration(i) * time.Minute),
|
||
|
Size: 1 << 10,
|
||
|
NumVersions: 5,
|
||
|
}
|
||
|
}
|
||
|
versioned := vcfg.Status == "Enabled"
|
||
|
wants := make([]ObjectInfo, 2)
|
||
|
for i, fi := range fivs[:2] {
|
||
|
wants[i] = fi.ToObjectInfo(bucket, obj, versioned)
|
||
|
}
|
||
|
gots, err := item.applyNewerNoncurrentVersionLimit(context.TODO(), objAPI, fivs)
|
||
|
if err != nil {
|
||
|
t.Fatalf("Failed with err: %v", err)
|
||
|
}
|
||
|
if len(gots) != len(wants) {
|
||
|
t.Fatalf("Expected %d objects but got %d", len(wants), len(gots))
|
||
|
}
|
||
|
|
||
|
// Close expiry state's channel to inspect object versions enqueued for expiration
|
||
|
close(globalExpiryState.byNewerNoncurrentCh)
|
||
|
wg.Wait()
|
||
|
for _, obj := range expired {
|
||
|
switch obj.ObjectV.VersionID {
|
||
|
case uuids[2].String(), uuids[3].String(), uuids[4].String():
|
||
|
default:
|
||
|
t.Errorf("Unexpected versionID being expired: %#v\n", obj)
|
||
|
}
|
||
|
}
|
||
|
}
|