@@ -1040,10 +1040,8 @@ function (CommandInterface $cmd) use (&$captured) {
10401040 public function testCallerSuppliedTaggingDoesNotTriggerReplace ()
10411041 {
10421042 // Caller-supplied params['Tagging'] does NOT auto-flip tags_directive.
1043- // With no explicit tags_directive (the default), the resolver stays
1044- // at UNSPECIFIED. No Phase 1 read,
1045- // no Phase 3 PUT. Caller's Tagging rides on CreateMultipartUpload as
1046- // before, preserving legacy initiate-time tagging behavior.
1043+ // Callers who need their Tagging applied must opt in via
1044+ // tags_directive='REPLACE'.
10471045 $ client = $ this ->getTestClient ('s3 ' );
10481046 $ this ->addMockResults ($ client , [
10491047 new Result (['UploadId ' => 'baz ' ]),
@@ -1075,7 +1073,11 @@ function (CommandInterface $cmd) use (&$observed, &$initiate) {
10751073 $ this ->assertNotContains ('GetObjectTagging ' , $ observed );
10761074 $ this ->assertNotContains ('PutObjectTagging ' , $ observed );
10771075 $ this ->assertNotNull ($ initiate );
1078- $ this ->assertSame ('Project=Override&Env=prod ' , $ initiate ['Tagging ' ]);
1076+ $ this ->assertNull (
1077+ $ initiate ['Tagging ' ] ?? null ,
1078+ 'UNSPECIFIED must drop caller-supplied Tagging from '
1079+ . 'CreateMultipartUpload — MPU never carries Tagging on initiate. '
1080+ );
10791081 }
10801082
10811083 public function testAnnotationPutTransientFailureIsRetried ()
@@ -1739,14 +1741,13 @@ function (CommandInterface $cmd) use (&$initiate, &$putTagging) {
17391741 );
17401742 }
17411743
1742- public function testTagsDirectiveUnspecifiedLeavesCallerTaggingOnInitiate ()
1744+ public function testTagsDirectiveUnspecifiedDropsCallerTaggingFromInitiate ()
17431745 {
1744- // When tags_directive resolves to UNSPECIFIED (legacy default with
1745- // no caller --tagging), there is
1746- // no Phase 3 tag write. Caller-supplied params['Tagging'], if any, is
1747- // left on CreateMultipartUpload exactly as before, preserving
1748- // backwards compatibility for callers that relied on the original
1749- // initiate-time tagging behavior.
1746+ // When tags_directive resolves to UNSPECIFIED
1747+ // (the default), there is no Phase 3 tag write AND any caller-supplied
1748+ // params['Tagging'] is dropped from the initiate. Callers who need
1749+ // their Tagging applied to the destination must opt in via
1750+ // tags_directive='REPLACE'.
17501751 $ client = $ this ->getTestClient ('s3 ' );
17511752 $ this ->addMockResults ($ client , [
17521753 new Result (['UploadId ' => 'baz ' ]),
@@ -1772,13 +1773,18 @@ function (CommandInterface $cmd) use (&$initiate, &$observed) {
17721773 'key ' => 'bar ' ,
17731774 'source_metadata ' => $ this ->srcMeta (),
17741775 'tags_directive ' => 'UNSPECIFIED ' ,
1775- 'params ' => ['Tagging ' => 'preserved =yes ' ],
1776+ 'params ' => ['Tagging ' => 'dropped =yes ' ],
17761777 ]);
17771778 $ uploader ->upload ();
17781779
17791780 $ this ->assertNotNull ($ initiate );
1780- $ this ->assertSame ('preserved=yes ' , $ initiate ['Tagging ' ]);
1781- // No Phase 3 tag writes.
1781+ $ this ->assertNull (
1782+ $ initiate ['Tagging ' ] ?? null ,
1783+ 'UNSPECIFIED must drop caller-supplied Tagging from '
1784+ . 'CreateMultipartUpload — MPU never carries Tagging on initiate. '
1785+ );
1786+ // No Phase 1 read, no Phase 3 write.
1787+ $ this ->assertNotContains ('GetObjectTagging ' , $ observed );
17821788 $ this ->assertNotContains ('PutObjectTagging ' , $ observed );
17831789 }
17841790
@@ -2108,7 +2114,7 @@ function (CommandInterface $cmd) use (&$putAnnotCmds) {
21082114 $ this ->assertCount (3 , $ putAnnotCmds );
21092115
21102116 // First attempt: no @http.delay (cold path).
2111- $ this ->assertNull ($ putAnnotCmds [0 ]['@http ' ]['delay ' ] ?? null );
2117+ $ this ->assertEmpty ($ putAnnotCmds [0 ]['@http ' ]['delay ' ] ?? null );
21122118
21132119 // Subsequent retries: @http.delay set to a non-negative integer
21142120 // within the 5000ms ceiling. (Full-jitter formula allows 0 as a
0 commit comments