@@ -4603,6 +4603,78 @@ func TestIntegration_SoftDelete(t *testing.T) {
46034603 })
46044604}
46054605
4606+ func TestIntegration_ObjectMove (t * testing.T ) {
4607+ multiTransportTest (skipJSONReads (context .Background (), "no reads in test" ), t , func (t * testing.T , ctx context.Context , _ , prefix string , client * Client ) {
4608+ h := testHelper {t }
4609+ srcObj := "move-src-obj"
4610+ dstObj := "move-dst-obj"
4611+
4612+ // Create bucket with HNS enabled
4613+ bkt := client .Bucket (prefix + uidSpace .New ())
4614+ attrs := & BucketAttrs {
4615+ HierarchicalNamespace : & HierarchicalNamespace {Enabled : true },
4616+ UniformBucketLevelAccess : UniformBucketLevelAccess {Enabled : true },
4617+ SoftDeletePolicy : & SoftDeletePolicy {RetentionDuration : 0 },
4618+ }
4619+ if err := bkt .Create (ctx , testutil .ProjID (), attrs ); err != nil {
4620+ t .Fatalf ("error creating bucket with soft delete policy set: %v" , err )
4621+ }
4622+ t .Cleanup (func () { h .mustDeleteBucket (bkt ) })
4623+
4624+ // Create source object
4625+ obj := bkt .Object (srcObj )
4626+ w := obj .NewWriter (ctx )
4627+ h .mustWrite (w , randomContents ())
4628+ t .Cleanup (func () { h .mustDeleteObject (bkt .Object (dstObj )) })
4629+
4630+ // Move object
4631+ objAttrs , err := obj .Move (ctx , MoveObjectDestination {Object : dstObj })
4632+ if err != nil {
4633+ t .Fatalf ("ObjectHandle.Move: %v" , err )
4634+ }
4635+ // Check attrs are populated.
4636+ if objAttrs == nil || objAttrs .Name == "" {
4637+ t .Errorf ("wanted object attrs to be populated; got %+v" , objAttrs )
4638+ }
4639+ // Check source object is no longer present.
4640+ if _ , err := obj .Attrs (ctx ); ! errors .Is (err , ErrObjectNotExist ) {
4641+ t .Errorf ("source object: got err %v, want ErrObjectNotExist" , err )
4642+ }
4643+
4644+ // Test that source and destination preconditions are applied appropriately.
4645+ srcObj2 := "move-src-obj2"
4646+ dstObj2 := "move-dst-obj2"
4647+
4648+ obj2 := bkt .Object (srcObj2 )
4649+ w2 := obj2 .NewWriter (ctx )
4650+ h .mustWrite (w2 , randomContents ())
4651+ t .Cleanup (func () { h .mustDeleteObject (bkt .Object (dstObj2 )) })
4652+
4653+ // Bad source generation should cause 412.
4654+ _ , err = obj2 .If (Conditions {
4655+ GenerationMatch : 123 ,
4656+ }).Move (ctx , MoveObjectDestination {Object : dstObj2 })
4657+ if err == nil || ! (status .Code (err ) == codes .FailedPrecondition || extractErrCode (err ) == http .StatusPreconditionFailed ) {
4658+ t .Errorf ("ObjectHandle.Move: got err %v, want failed precondition (412)" , err )
4659+ }
4660+
4661+ // Bad dest generation should also cause 412.
4662+ _ , err = obj2 .Move (ctx , MoveObjectDestination {Object : dstObj2 , Conditions : & Conditions {GenerationMatch : 123 }})
4663+ if err == nil || ! (status .Code (err ) == codes .FailedPrecondition || extractErrCode (err ) == http .StatusPreconditionFailed ) {
4664+ t .Errorf ("ObjectHandle.Move: got err %v, want failed precondition (412)" , err )
4665+ }
4666+
4667+ // Correctly applied preconditions should work.
4668+ _ , err = obj2 .If (Conditions {
4669+ GenerationMatch : w2 .Attrs ().Generation ,
4670+ MetagenerationMatch : w2 .Attrs ().Metageneration ,
4671+ }).Move (ctx , MoveObjectDestination {Object : dstObj2 , Conditions : & Conditions {DoesNotExist : true }})
4672+ if err != nil {
4673+ t .Fatalf ("ObjectHandle.Move: %v" , err )
4674+ }
4675+ })
4676+ }
4677+
46064678func TestIntegration_KMS (t * testing.T ) {
46074679 multiTransportTest (context .Background (), t , func (t * testing.T , ctx context.Context , bucket , prefix string , client * Client ) {
46084680 h := testHelper {t }
0 commit comments