github.com/minio/console@v1.4.1/api/user_buckets_lifecycle_test.go (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 package api 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 "testing" 24 25 "github.com/minio/console/models" 26 "github.com/stretchr/testify/assert" 27 28 bucketApi "github.com/minio/console/api/operations/bucket" 29 "github.com/minio/minio-go/v7/pkg/lifecycle" 30 ) 31 32 // assigning mock at runtime instead of compile time 33 var minioGetLifecycleRulesMock func(ctx context.Context, bucketName string) (lifecycle *lifecycle.Configuration, err error) 34 35 // mock function of getLifecycleRules() 36 func (ac minioClientMock) getLifecycleRules(ctx context.Context, bucketName string) (lifecycle *lifecycle.Configuration, err error) { 37 return minioGetLifecycleRulesMock(ctx, bucketName) 38 } 39 40 // assign mock for set Bucket Lifecycle 41 var minioSetBucketLifecycleMock func(ctx context.Context, bucketName string, config *lifecycle.Configuration) error 42 43 // mock function of setBucketLifecycle() 44 func (ac minioClientMock) setBucketLifecycle(ctx context.Context, bucketName string, config *lifecycle.Configuration) error { 45 return minioSetBucketLifecycleMock(ctx, bucketName, config) 46 } 47 48 func TestGetLifecycleRules(t *testing.T) { 49 assert := assert.New(t) 50 // mock minIO client 51 minClient := minioClientMock{} 52 53 function := "getBucketLifecycle()" 54 bucketName := "testBucket" 55 ctx, cancel := context.WithCancel(context.Background()) 56 defer cancel() 57 58 // Test-1 : getBucketLifecycle() get list of events for a particular bucket only one config 59 // mock lifecycle response from MinIO 60 mockLifecycle := lifecycle.Configuration{ 61 Rules: []lifecycle.Rule{ 62 { 63 ID: "TESTRULE", 64 Expiration: lifecycle.Expiration{Days: 15}, 65 Status: "Enabled", 66 RuleFilter: lifecycle.Filter{Tag: lifecycle.Tag{Key: "tag1", Value: "val1"}, And: lifecycle.And{Prefix: "prefix1"}}, 67 }, 68 }, 69 } 70 71 expectedOutput := models.BucketLifecycleResponse{ 72 Lifecycle: []*models.ObjectBucketLifecycle{ 73 { 74 ID: "TESTRULE", 75 Status: "Enabled", 76 Prefix: "prefix1", 77 Expiration: &models.ExpirationResponse{Days: int64(15)}, 78 Transition: &models.TransitionResponse{}, 79 Tags: []*models.LifecycleTag{{Key: "tag1", Value: "val1"}}, 80 }, 81 }, 82 } 83 84 minioGetLifecycleRulesMock = func(_ context.Context, _ string) (lifecycle *lifecycle.Configuration, err error) { 85 return &mockLifecycle, nil 86 } 87 88 lifeCycleConfigs, err := getBucketLifecycle(ctx, minClient, bucketName) 89 if err != nil { 90 t.Errorf("Failed on %s:, error occurred: %s", function, err.Error()) 91 } 92 // verify length of buckets is correct 93 assert.Equal(len(expectedOutput.Lifecycle), len(lifeCycleConfigs.Lifecycle), fmt.Sprintf("Failed on %s: length of lists is not the same", function)) 94 for i, conf := range lifeCycleConfigs.Lifecycle { 95 assert.Equal(expectedOutput.Lifecycle[i].ID, conf.ID) 96 assert.Equal(expectedOutput.Lifecycle[i].Status, conf.Status) 97 assert.Equal(expectedOutput.Lifecycle[i].Prefix, conf.Prefix) 98 assert.Equal(expectedOutput.Lifecycle[i].Expiration.Days, conf.Expiration.Days) 99 for j, event := range conf.Tags { 100 assert.Equal(expectedOutput.Lifecycle[i].Tags[j], event) 101 } 102 } 103 104 // Test-2 : getBucketLifecycle() get list of events is empty 105 mockLifecycleT2 := lifecycle.Configuration{ 106 Rules: []lifecycle.Rule{}, 107 } 108 109 expectedOutputT2 := models.BucketLifecycleResponse{ 110 Lifecycle: []*models.ObjectBucketLifecycle{}, 111 } 112 113 minioGetLifecycleRulesMock = func(_ context.Context, _ string) (lifecycle *lifecycle.Configuration, err error) { 114 return &mockLifecycleT2, nil 115 } 116 117 lifeCycleConfigsT2, err := getBucketLifecycle(ctx, minClient, bucketName) 118 if err != nil { 119 t.Errorf("Failed on %s:, error occurred: %s", function, err.Error()) 120 } 121 // verify length of buckets is correct 122 assert.Equal(len(expectedOutputT2.Lifecycle), len(lifeCycleConfigsT2.Lifecycle), fmt.Sprintf("Failed on %s: length of lists is not the same", function)) 123 124 // Test-3 : getBucketLifecycle() get list of events returns an error 125 126 minioGetLifecycleRulesMock = func(_ context.Context, _ string) (lifecycle *lifecycle.Configuration, err error) { 127 return nil, errors.New("error returned") 128 } 129 130 _, errT3 := getBucketLifecycle(ctx, minClient, bucketName) 131 132 errorCompare := errors.New("error returned") 133 134 assert.Equal(errorCompare, errT3, fmt.Sprintf("Failed on %s: Invalid error message", function)) 135 136 // verify length of buckets is correct 137 assert.Equal(len(expectedOutputT2.Lifecycle), len(lifeCycleConfigsT2.Lifecycle), fmt.Sprintf("Failed on %s: length of lists is not the same", function)) 138 } 139 140 func TestSetLifecycleRule(t *testing.T) { 141 assert := assert.New(t) 142 // mock minIO client 143 minClient := minioClientMock{} 144 145 function := "addBucketLifecycle()" 146 ctx, cancel := context.WithCancel(context.Background()) 147 defer cancel() 148 149 // Test-1 : addBucketLifecycle() get list of events for a particular bucket only one config 150 // mock create request 151 mockLifecycle := lifecycle.Configuration{ 152 Rules: []lifecycle.Rule{ 153 { 154 ID: "TESTRULE", 155 Expiration: lifecycle.Expiration{Days: 15}, 156 Status: "Enabled", 157 RuleFilter: lifecycle.Filter{Tag: lifecycle.Tag{Key: "tag1", Value: "val1"}, And: lifecycle.And{Prefix: "prefix1"}}, 158 }, 159 }, 160 } 161 162 minioGetLifecycleRulesMock = func(_ context.Context, _ string) (lifecycle *lifecycle.Configuration, err error) { 163 return &mockLifecycle, nil 164 } 165 166 expiryRule := "expiry" 167 168 insertMock := bucketApi.AddBucketLifecycleParams{ 169 BucketName: "testBucket", 170 Body: &models.AddBucketLifecycle{ 171 Type: expiryRule, 172 Disable: false, 173 ExpiredObjectDeleteMarker: false, 174 ExpiryDays: int32(16), 175 NoncurrentversionExpirationDays: 0, 176 NoncurrentversionTransitionDays: 0, 177 NoncurrentversionTransitionStorageClass: "", 178 Prefix: "pref1", 179 StorageClass: "", 180 Tags: "", 181 TransitionDays: 0, 182 }, 183 } 184 185 minioSetBucketLifecycleMock = func(_ context.Context, _ string, _ *lifecycle.Configuration) error { 186 return nil 187 } 188 189 err := addBucketLifecycle(ctx, minClient, insertMock) 190 191 assert.Equal(nil, err, fmt.Sprintf("Failed on %s: Error returned", function)) 192 193 // Test-2 : addBucketLifecycle() returns error 194 195 minioSetBucketLifecycleMock = func(_ context.Context, _ string, _ *lifecycle.Configuration) error { 196 return errors.New("error setting lifecycle") 197 } 198 199 err2 := addBucketLifecycle(ctx, minClient, insertMock) 200 201 assert.Equal(errors.New("error setting lifecycle"), err2, fmt.Sprintf("Failed on %s: Error returned", function)) 202 } 203 204 func TestUpdateLifecycleRule(t *testing.T) { 205 assert := assert.New(t) 206 // mock minIO client 207 minClient := minioClientMock{} 208 209 function := "editBucketLifecycle()" 210 ctx, cancel := context.WithCancel(context.Background()) 211 defer cancel() 212 213 // Test-1 : editBucketLifecycle() get list of events for a particular bucket only one config (get lifecycle mock) 214 // mock create request 215 mockLifecycle := lifecycle.Configuration{ 216 Rules: []lifecycle.Rule{ 217 { 218 ID: "TESTRULE", 219 Expiration: lifecycle.Expiration{Days: 15}, 220 Status: "Enabled", 221 RuleFilter: lifecycle.Filter{Tag: lifecycle.Tag{Key: "tag1", Value: "val1"}, And: lifecycle.And{Prefix: "prefix1"}}, 222 }, 223 }, 224 } 225 226 minioGetLifecycleRulesMock = func(_ context.Context, _ string) (lifecycle *lifecycle.Configuration, err error) { 227 return &mockLifecycle, nil 228 } 229 230 // Test-2 : editBucketLifecycle() Update lifecycle rule 231 232 expiryRule := "expiry" 233 234 editMock := bucketApi.UpdateBucketLifecycleParams{ 235 BucketName: "testBucket", 236 Body: &models.UpdateBucketLifecycle{ 237 Type: &expiryRule, 238 Disable: false, 239 ExpiredObjectDeleteMarker: false, 240 ExpiryDays: int32(16), 241 NoncurrentversionExpirationDays: 0, 242 NoncurrentversionTransitionDays: 0, 243 NoncurrentversionTransitionStorageClass: "", 244 Prefix: "pref1", 245 StorageClass: "", 246 Tags: "", 247 TransitionDays: 0, 248 }, 249 LifecycleID: "TESTRULE", 250 } 251 252 minioSetBucketLifecycleMock = func(_ context.Context, _ string, _ *lifecycle.Configuration) error { 253 return nil 254 } 255 256 err := editBucketLifecycle(ctx, minClient, editMock) 257 258 assert.Equal(nil, err, fmt.Sprintf("Failed on %s: Error returned", function)) 259 260 // Test-2a : editBucketLifecycle() Update lifecycle rule 261 262 transitionRule := "transition" 263 264 editMock = bucketApi.UpdateBucketLifecycleParams{ 265 BucketName: "testBucket", 266 Body: &models.UpdateBucketLifecycle{ 267 Type: &transitionRule, 268 Disable: false, 269 ExpiredObjectDeleteMarker: false, 270 NoncurrentversionTransitionDays: 5, 271 Prefix: "pref1", 272 StorageClass: "TEST", 273 NoncurrentversionTransitionStorageClass: "TESTNC", 274 Tags: "", 275 TransitionDays: int32(16), 276 }, 277 LifecycleID: "TESTRULE", 278 } 279 280 minioSetBucketLifecycleMock = func(_ context.Context, _ string, _ *lifecycle.Configuration) error { 281 return nil 282 } 283 284 err = editBucketLifecycle(ctx, minClient, editMock) 285 286 assert.Equal(nil, err, fmt.Sprintf("Failed on %s: Error returned", function)) 287 288 // Test-3 : editBucketLifecycle() returns error 289 290 minioSetBucketLifecycleMock = func(_ context.Context, _ string, _ *lifecycle.Configuration) error { 291 return errors.New("error setting lifecycle") 292 } 293 294 err2 := editBucketLifecycle(ctx, minClient, editMock) 295 296 assert.Equal(errors.New("error setting lifecycle"), err2, fmt.Sprintf("Failed on %s: Error returned", function)) 297 } 298 299 func TestDeleteLifecycleRule(t *testing.T) { 300 assert := assert.New(t) 301 // mock minIO client 302 minClient := minioClientMock{} 303 304 function := "deleteBucketLifecycle()" 305 ctx, cancel := context.WithCancel(context.Background()) 306 defer cancel() 307 308 minioSetBucketLifecycleMock = func(_ context.Context, _ string, _ *lifecycle.Configuration) error { 309 return nil 310 } 311 312 // Test-1 : deleteBucketLifecycle() get list of events for a particular bucket only one config (get lifecycle mock) 313 // mock create request 314 mockLifecycle := lifecycle.Configuration{ 315 Rules: []lifecycle.Rule{ 316 { 317 ID: "TESTRULE", 318 Expiration: lifecycle.Expiration{Days: 15}, 319 Status: "Enabled", 320 RuleFilter: lifecycle.Filter{Tag: lifecycle.Tag{Key: "tag1", Value: "val1"}, And: lifecycle.And{Prefix: "prefix1"}}, 321 }, 322 { 323 ID: "TESTRULE2", 324 Transition: lifecycle.Transition{Days: 10, StorageClass: "TESTSTCLASS"}, 325 Status: "Enabled", 326 RuleFilter: lifecycle.Filter{Tag: lifecycle.Tag{Key: "tag1", Value: "val1"}, And: lifecycle.And{Prefix: "prefix1"}}, 327 }, 328 }, 329 } 330 331 minioGetLifecycleRulesMock = func(_ context.Context, _ string) (lifecycle *lifecycle.Configuration, err error) { 332 return &mockLifecycle, nil 333 } 334 335 // Test-2 : deleteBucketLifecycle() try to delete an available rule 336 337 availableParams := bucketApi.DeleteBucketLifecycleRuleParams{ 338 LifecycleID: "TESTRULE2", 339 BucketName: "testBucket", 340 } 341 342 err := deleteBucketLifecycle(ctx, minClient, availableParams) 343 344 assert.Equal(nil, err, fmt.Sprintf("Failed on %s: Error returned", function)) 345 346 // Test-3 : deleteBucketLifecycle() returns error trying to delete a non available rule 347 348 nonAvailableParams := bucketApi.DeleteBucketLifecycleRuleParams{ 349 LifecycleID: "INVALIDTESTRULE", 350 BucketName: "testBucket", 351 } 352 353 err2 := deleteBucketLifecycle(ctx, minClient, nonAvailableParams) 354 355 assert.Equal(fmt.Errorf("lifecycle rule for id '%s' doesn't exist", nonAvailableParams.LifecycleID), err2, fmt.Sprintf("Failed on %s: Error returned", function)) 356 357 // Test-4 : deleteBucketLifecycle() returns error trying to delete a rule when no rules are available 358 359 mockLifecycle2 := lifecycle.Configuration{ 360 Rules: []lifecycle.Rule{}, 361 } 362 363 minioGetLifecycleRulesMock = func(_ context.Context, _ string) (lifecycle *lifecycle.Configuration, err error) { 364 return &mockLifecycle2, nil 365 } 366 367 err3 := deleteBucketLifecycle(ctx, minClient, nonAvailableParams) 368 369 assert.Equal(errors.New("no rules available to delete"), err3, fmt.Sprintf("Failed on %s: Error returned", function)) 370 }