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)
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |