@@ -10,6 +10,7 @@ import (
10
10
"testing"
11
11
"time"
12
12
13
+ "github.com/aws/aws-sdk-go-v2/aws"
13
14
"github.com/aws/aws-sdk-go-v2/service/s3"
14
15
"github.com/aws/aws-sdk-go-v2/service/s3/types"
15
16
"github.com/hashicorp/terraform-plugin-testing/compare"
@@ -5267,3 +5268,125 @@ resource "aws_s3_bucket" "test" {
5267
5268
}
5268
5269
` , rName )
5269
5270
}
5271
+
5272
+ func TestNormalizeEmptyPrefix (t * testing.T ) {
5273
+ t .Parallel ()
5274
+
5275
+ testCases := []struct {
5276
+ name string
5277
+ input * types.LifecycleRule
5278
+ expected * types.LifecycleRule
5279
+ }{
5280
+ {
5281
+ name : "empty string prefix becomes nil" ,
5282
+ input : & types.LifecycleRule {
5283
+ ID : aws .String ("test-rule" ),
5284
+ Prefix : aws .String ("" ),
5285
+ Status : types .ExpirationStatusEnabled ,
5286
+ },
5287
+ expected : & types.LifecycleRule {
5288
+ ID : aws .String ("test-rule" ),
5289
+ Prefix : nil ,
5290
+ Status : types .ExpirationStatusEnabled ,
5291
+ },
5292
+ },
5293
+ {
5294
+ name : "forward slash prefix becomes nil" ,
5295
+ input : & types.LifecycleRule {
5296
+ ID : aws .String ("test-rule" ),
5297
+ Prefix : aws .String ("/" ),
5298
+ Status : types .ExpirationStatusEnabled ,
5299
+ },
5300
+ expected : & types.LifecycleRule {
5301
+ ID : aws .String ("test-rule" ),
5302
+ Prefix : nil ,
5303
+ Status : types .ExpirationStatusEnabled ,
5304
+ },
5305
+ },
5306
+ {
5307
+ name : "nil prefix remains nil" ,
5308
+ input : & types.LifecycleRule {
5309
+ ID : aws .String ("test-rule" ),
5310
+ Prefix : nil ,
5311
+ Status : types .ExpirationStatusEnabled ,
5312
+ },
5313
+ expected : & types.LifecycleRule {
5314
+ ID : aws .String ("test-rule" ),
5315
+ Prefix : nil ,
5316
+ Status : types .ExpirationStatusEnabled ,
5317
+ },
5318
+ },
5319
+ {
5320
+ name : "non-empty prefix unchanged" ,
5321
+ input : & types.LifecycleRule {
5322
+ ID : aws .String ("test-rule" ),
5323
+ Prefix : aws .String ("logs/" ),
5324
+ Status : types .ExpirationStatusEnabled ,
5325
+ },
5326
+ expected : & types.LifecycleRule {
5327
+ ID : aws .String ("test-rule" ),
5328
+ Prefix : aws .String ("logs/" ),
5329
+ Status : types .ExpirationStatusEnabled ,
5330
+ },
5331
+ },
5332
+ }
5333
+
5334
+ for _ , tc := range testCases {
5335
+ t .Run (tc .name , func (t * testing.T ) {
5336
+ // Simulate what findBucketLifecycleConfiguration does
5337
+ if tc .input .Prefix != nil && (* tc .input .Prefix == "" || * tc .input .Prefix == "/" ) {
5338
+ tc .input .Prefix = nil
5339
+ }
5340
+
5341
+ // Verify normalization
5342
+ if tc .input .Prefix == nil && tc .expected .Prefix != nil {
5343
+ t .Errorf ("Expected non-nil prefix, got nil" )
5344
+ } else if tc .input .Prefix != nil && tc .expected .Prefix == nil {
5345
+ t .Errorf ("Expected nil prefix, got %v" , * tc .input .Prefix )
5346
+ } else if tc .input .Prefix != nil && tc .expected .Prefix != nil && * tc .input .Prefix != * tc .expected .Prefix {
5347
+ t .Errorf ("Expected prefix %v, got %v" , * tc .expected .Prefix , * tc .input .Prefix )
5348
+ }
5349
+ })
5350
+ }
5351
+ }
5352
+
5353
+ func TestExpandNormalizeSymmetry (t * testing.T ) {
5354
+ t .Parallel ()
5355
+
5356
+ testCases := []struct {
5357
+ name string
5358
+ configValue string
5359
+ afterExpand * string
5360
+ afterNormalize * string
5361
+ }{
5362
+ {
5363
+ name : "empty string config" ,
5364
+ configValue : "" ,
5365
+ afterExpand : nil , // fwflex.EmptyStringAsNull converts "" to nil
5366
+ afterNormalize : nil , // normalization keeps nil as nil
5367
+ },
5368
+ {
5369
+ name : "non-empty config" ,
5370
+ configValue : "logs/" ,
5371
+ afterExpand : aws .String ("logs/" ),
5372
+ afterNormalize : aws .String ("logs/" ),
5373
+ },
5374
+ }
5375
+
5376
+ for _ , tc := range testCases {
5377
+ t .Run (tc .name , func (t * testing.T ) {
5378
+ // This test proves the expand->API->normalize cycle is symmetric
5379
+ // 1. Config "" -> expand -> nil (sent to API)
5380
+ // 2. API returns "" (Ceph) or nil (AWS)
5381
+ // 3. normalize -> nil (consistent internal representation)
5382
+
5383
+ if tc .afterExpand == nil && tc .afterNormalize != nil {
5384
+ t .Errorf ("Symmetry broken: expand returned nil but normalize expects %v" , * tc .afterNormalize )
5385
+ } else if tc .afterExpand != nil && tc .afterNormalize == nil {
5386
+ t .Errorf ("Symmetry broken: expand returned %v but normalize expects nil" , * tc .afterExpand )
5387
+ } else if tc .afterExpand != nil && tc .afterNormalize != nil && * tc .afterExpand != * tc .afterNormalize {
5388
+ t .Errorf ("Symmetry broken: expand returned %v but normalize expects %v" , * tc .afterExpand , * tc .afterNormalize )
5389
+ }
5390
+ })
5391
+ }
5392
+ }
0 commit comments