From e6cb5068a8adf327e1da222644bc43691f008183 Mon Sep 17 00:00:00 2001 From: Tip ten Brink <75669206+tiptenbrink@users.noreply.github.com> Date: Sat, 3 Oct 2026 12:56:23 +0200 Subject: [PATCH 1/3] Test the copy semantics a client decides from the documentation. 15 cases, verified live: an S3 REPLACE replaces content properties with metadata, and with none clears metadata or tags; UploadPartCopy reports a failed source condition as 412; Copy Blob ignores content properties, which Put Blob From URL honors; a From URL source that is missing is 404 CannotVerifyCopySource. Co-Authored-By: Claude Opus 5.5 (1M context) --- cases/operations.json | 6602 ++++++++++++++++++++++++++++------------- 1 file changed, 4574 insertions(+), 2028 deletions(-) diff --git a/cases/operations.json b/cases/operations.json index abb7476..a8c1eec 100644 --- a/cases/operations.json +++ b/cases/operations.json @@ -32,6 +32,7 @@ "operations/azure-hns/commit-with-tier": "Commit a block list into an access tier, named in x-ms-access-tier", "operations/azure-hns/copy": "Copy an object to another key in the same container", "operations/azure-hns/copy-across-containers": "Copy a blob from another container of the same account, which x-ms-copy-source names in its URL", + "operations/azure-hns/copy-content-properties": "Copy a blob with a content type, which Copy Blob ignores: the copy keeps the source's content properties. A client may send it, or refuse or decline the parameter", "operations/azure-hns/copy-if-none-match-exists": "Report a copy with If-None-Match: * onto a blob that exists as a failed condition on the destination", "operations/azure-hns/copy-missing-source": "Refuse a copy whose source does not exist", "operations/azure-hns/copy-pending": "Report a copy that Azure answers as pending with its copy ID, so that a caller can follow it with a HEAD or abort it", @@ -41,6 +42,7 @@ "operations/azure-hns/copy-source-if-unmodified-since-failed": "Report a copy whose source changed after the time in x-ms-source-if-unmodified-since as a failed condition, 412 SourceConditionNotMet", "operations/azure-hns/copy-source-key-encoded": "Copy from a key with a space, +, %, é, ? and #. The x-ms-copy-source URL percent-encodes every byte of the key outside letters, digits, -._~ and /", "operations/azure-hns/copy-sync": "Copy a blob with Copy Blob From URL, x-ms-requires-sync: true, which answers once the copy is done. The source must be readable by URL: by a SAS, or by a bearer token in x-ms-copy-source-authorization", + "operations/azure-hns/copy-sync-missing-source": "Report a Copy Blob From URL whose source does not exist as an error. Azure answers 404 CannotVerifyCopySource, a code of its own, not BlobNotFound", "operations/azure-hns/copy-tier": "Copy a blob into another access tier, named in x-ms-access-tier", "operations/azure-hns/create-append": "Create an empty append blob", "operations/azure-hns/create-page": "Create a page blob of 1,024 bytes, which an HNS account does not support", @@ -223,6 +225,8 @@ "operations/azure-hns/put-created-key-trailing-slash": "put created, with the key \"trailing-slash/\"", "operations/azure-hns/put-first-version": "put first version", "operations/azure-hns/put-from-url": "Write a block blob from the bytes at a URL with Put Blob From URL: a PUT with x-ms-blob-type: BlockBlob, x-ms-copy-source and no body, which answers once it is written", + "operations/azure-hns/put-from-url-content-properties": "Write a block blob from a URL with content properties of its own, sent as x-ms-blob-content-type and x-ms-blob-cache-control. Put Blob From URL stores them in place of the source's", + "operations/azure-hns/put-from-url-missing-source": "Report a Put Blob From URL whose source does not exist as an error. Azure answers 404 CannotVerifyCopySource, a code of its own, not BlobNotFound", "operations/azure-hns/put-if-match-current": "put if match current", "operations/azure-hns/put-if-none-match-missing": "put if none match missing", "operations/azure-hns/put-if-unmodified-since-past": "Refuse a write with 412 when the object changed after If-Unmodified-Since", @@ -319,6 +323,7 @@ "operations/azure/commit-with-tier": "Commit a block list into an access tier, named in x-ms-access-tier", "operations/azure/copy": "Copy an object to another key in the same container", "operations/azure/copy-across-containers": "Copy a blob from another container of the same account, which x-ms-copy-source names in its URL", + "operations/azure/copy-content-properties": "Copy a blob with a content type, which Copy Blob ignores: the copy keeps the source's content properties. A client may send it, or refuse or decline the parameter", "operations/azure/copy-if-none-match-exists": "Report a copy with If-None-Match: * onto a blob that exists as a failed condition on the destination", "operations/azure/copy-missing-source": "Refuse a copy whose source does not exist", "operations/azure/copy-pending": "Report a copy that Azure answers as pending with its copy ID, so that a caller can follow it with a HEAD or abort it", @@ -329,6 +334,7 @@ "operations/azure/copy-source-key-encoded": "Copy from a key with a space, +, %, é, ? and #. The x-ms-copy-source URL percent-encodes every byte of the key outside letters, digits, -._~ and /", "operations/azure/copy-source-version": "Copy an earlier version of a blob, named by versionid in the x-ms-copy-source URL", "operations/azure/copy-sync": "Copy a blob with Copy Blob From URL, x-ms-requires-sync: true, which answers once the copy is done. The source must be readable by URL: by a SAS, or by a bearer token in x-ms-copy-source-authorization", + "operations/azure/copy-sync-missing-source": "Report a Copy Blob From URL whose source does not exist as an error. Azure answers 404 CannotVerifyCopySource, a code of its own, not BlobNotFound", "operations/azure/copy-tier": "Copy a blob into another access tier, named in x-ms-access-tier", "operations/azure/create-append": "Create an empty append blob", "operations/azure/create-page": "Create a page blob of 1,024 bytes", @@ -512,6 +518,8 @@ "operations/azure/put-created-key-trailing-slash": "put created, with the key \"trailing-slash/\"", "operations/azure/put-first-version": "put first version", "operations/azure/put-from-url": "Write a block blob from the bytes at a URL with Put Blob From URL: a PUT with x-ms-blob-type: BlockBlob, x-ms-copy-source and no body, which answers once it is written", + "operations/azure/put-from-url-content-properties": "Write a block blob from a URL with content properties of its own, sent as x-ms-blob-content-type and x-ms-blob-cache-control. Put Blob From URL stores them in place of the source's", + "operations/azure/put-from-url-missing-source": "Report a Put Blob From URL whose source does not exist as an error. Azure answers 404 CannotVerifyCopySource, a code of its own, not BlobNotFound", "operations/azure/put-if-match-current": "put if match current", "operations/azure/put-if-none-match-missing": "put if none match missing", "operations/azure/put-if-unmodified-since-past": "Refuse a write with 412 when the object changed after If-Unmodified-Since", @@ -617,10 +625,12 @@ "operations/s3-express/complete-multipart-200-error": "complete multipart 200 error", "operations/s3-express/copy": "Copy an object to another key in the same bucket", "operations/s3-express/copy-200-internal-error": "Report a copy answered 200 with an InternalError in the body as an error, never as a success. A client may retry up to 5 times first, and need not retry", + "operations/s3-express/copy-clear-metadata": "Copy an object with no metadata in place of the source's: x-amz-metadata-directive: REPLACE with no x-amz-meta- header. A client API that cannot say no metadata may refuse or decline the call", "operations/s3-express/copy-missing-source": "Refuse a copy whose source does not exist", "operations/s3-express/copy-onto-itself": "Copy an object onto itself without changing it. A directory bucket accepts it, where a general-purpose bucket answers 400 InvalidRequest", "operations/s3-express/copy-onto-itself-replace-metadata": "Copy an object onto itself to replace its metadata, which S3 accepts with x-amz-metadata-directive: REPLACE", "operations/s3-express/copy-replace-metadata": "Copy an object with new metadata and a new content type. S3 keeps the source's unless x-amz-metadata-directive is REPLACE, so a client that sets either must send it", + "operations/s3-express/copy-replace-metadata-only": "Copy an object with new metadata and no content type. x-amz-metadata-directive: REPLACE replaces the content properties too: S3 gives the copy binary/octet-stream, not the source's content type, unless the caller names one", "operations/s3-express/copy-source-if-match": "Copy an object only if the source still has this ETag, named in x-amz-copy-source-if-match", "operations/s3-express/copy-source-if-match-failed": "Report a copy whose source does not have the ETag in x-amz-copy-source-if-match as a failed condition. S3 answers 412 PreconditionFailed and writes nothing", "operations/s3-express/copy-source-if-modified-since": "Copy an object only if the source changed after a time, named in x-amz-copy-source-if-modified-since as an HTTP date", @@ -792,6 +802,7 @@ "operations/s3-express/stage-copy-200-internal-error": "Report a part copy answered 200 with an InternalError in the body as an error, never as a success. A client may retry up to 5 times first, and need not retry", "operations/s3-express/stage-copy-range": "Copy bytes 0 to 2 of an object into a part, named in x-amz-copy-source-range with an inclusive end, as bytes=0-2", "operations/s3-express/stage-copy-range-beyond-source": "Copy a part whose range ends past the source. A directory bucket accepts it, where a general-purpose bucket answers 400 InvalidArgument", + "operations/s3-express/stage-copy-source-if-match-failed": "Report a part copy whose source does not have the ETag in x-amz-copy-source-if-match as a failed condition, 412 PreconditionFailed, of kind precondition", "operations/s3-express/stage-empty-part": "Stage an empty part, which S3 takes", "operations/s3-express/stage-key-double-slash": "stage, with the key \"double//slash.txt\"", "operations/s3-express/stage-key-hash": "stage, with the key \"hash#tag.txt\"", @@ -843,10 +854,13 @@ "operations/s3/copy": "Copy an object to another key in the same bucket", "operations/s3/copy-200-internal-error": "Report a copy answered 200 with an InternalError in the body as an error, never as a success. A client may retry up to 5 times first, and need not retry", "operations/s3/copy-across-buckets": "Copy an object from another bucket, which x-amz-copy-source names before the key", + "operations/s3/copy-clear-metadata": "Copy an object with no metadata in place of the source's: x-amz-metadata-directive: REPLACE with no x-amz-meta- header. A client API that cannot say no metadata may refuse or decline the call", + "operations/s3/copy-clear-tags": "Copy an object with no tags in place of the source's: x-amz-tagging-directive: REPLACE with an empty or no x-amz-tagging. A client API that cannot say no tags may refuse or decline the call", "operations/s3/copy-missing-source": "Refuse a copy whose source does not exist", "operations/s3/copy-onto-itself": "Report a copy of an object onto itself that changes nothing as an error. S3 answers 400 InvalidRequest", "operations/s3/copy-onto-itself-replace-metadata": "Copy an object onto itself to replace its metadata, which S3 accepts with x-amz-metadata-directive: REPLACE", "operations/s3/copy-replace-metadata": "Copy an object with new metadata and a new content type. S3 keeps the source's unless x-amz-metadata-directive is REPLACE, so a client that sets either must send it", + "operations/s3/copy-replace-metadata-only": "Copy an object with new metadata and no content type. x-amz-metadata-directive: REPLACE replaces the content properties too: S3 gives the copy binary/octet-stream, not the source's content type, unless the caller names one", "operations/s3/copy-replace-tags": "Copy an object with new tags. S3 copies the source's tags unless x-amz-tagging-directive is REPLACE, so a client that sets tags must send it", "operations/s3/copy-source-if-match": "Copy an object only if the source still has this ETag, named in x-amz-copy-source-if-match", "operations/s3/copy-source-if-match-failed": "Report a copy whose source does not have the ETag in x-amz-copy-source-if-match as a failed condition. S3 answers 412 PreconditionFailed and writes nothing", @@ -1053,6 +1067,7 @@ "operations/s3/stage-copy-200-internal-error": "Report a part copy answered 200 with an InternalError in the body as an error, never as a success. A client may retry up to 5 times first, and need not retry", "operations/s3/stage-copy-range": "Copy bytes 0 to 2 of an object into a part, named in x-amz-copy-source-range with an inclusive end, as bytes=0-2", "operations/s3/stage-copy-range-beyond-source": "Report a part copy whose range ends past the source as an error. S3 answers 400 InvalidArgument", + "operations/s3/stage-copy-source-if-match-failed": "Report a part copy whose source does not have the ETag in x-amz-copy-source-if-match as a failed condition, 412 PreconditionFailed, of kind precondition", "operations/s3/stage-empty-part": "Stage an empty part, which S3 takes", "operations/s3/stage-key-double-slash": "stage, with the key \"double//slash.txt\"", "operations/s3/stage-key-hash": "stage, with the key \"hash#tag.txt\"", @@ -34670,19 +34685,18 @@ "refusal": null }, { - "id": "operations/azure/copy-pending", + "id": "operations/azure/copy-sync-missing-source", "profile": "azure", "lane": "core", - "purpose": "Report a copy that Azure answers as pending with its copy ID, so that a caller can follow it with a HEAD or abort it", + "purpose": "Report a Copy Blob From URL whose source does not exist as an error. Azure answers 404 CannotVerifyCopySource, a code of its own, not BlobNotFound", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/copy-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url" ], - "origin": "transient", - "derived_from": "operations/azure/copy", "call": { "key": "object-tests/copy/target.txt", "op": "copy", - "source_key": "object-tests/copy/source.txt" + "source_key": "object-tests/copy/absent.txt", + "sync": true }, "exchanges": [ { @@ -34718,25 +34732,34 @@ "optional": false, "rule": { "is": "matches", - "pattern": "https?://[^/]+/fixture/object-tests/copy/source\\.txt" + "pattern": "https?://[^/]+/fixture/object-tests/copy/absent\\.txt" + } + }, + { + "at": "/headers/x-ms-requires-sync", + "optional": false, + "rule": { + "is": "equal", + "value": "true" } } ], - "allow_headers": [], + "allow_headers": [ + "x-ms-copy-source-authorization" + ], "allow_query": [], "response": { - "status": 202, + "status": 404, "headers": { + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-copy-id": "fixture-copy-id", - "x-ms-copy-status": "pending" + "x-ms-error-code": "CannotVerifyCopySource" }, "body": { - "encoding": "empty" + "encoding": "utf8", + "data": "CannotVerifyCopySourceFixture error" } } } @@ -34749,39 +34772,41 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/copy_status", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "pending" + "value": 404 } }, { - "at": "/value/copy_id", + "at": "/code", "optional": false, "rule": { "is": "equal", - "value": "fixture-copy-id" + "value": "CannotVerifyCopySource" } } ], "refusal": null }, { - "id": "operations/azure/put-from-url", + "id": "operations/azure/copy-pending", "profile": "azure", "lane": "core", - "purpose": "Write a block blob from the bytes at a URL with Put Blob From URL: a PUT with x-ms-blob-type: BlockBlob, x-ms-copy-source and no body, which answers once it is written", + "purpose": "Report a copy that Azure answers as pending with its copy ID, so that a caller can follow it with a HEAD or abort it", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob-from-url" + "https://learn.microsoft.com/en-us/rest/api/storageservices/copy-blob" ], + "origin": "transient", + "derived_from": "operations/azure/copy", "call": { "key": "object-tests/copy/target.txt", - "op": "azure.put_from_url", + "op": "copy", "source_key": "object-tests/copy/source.txt" }, "exchanges": [ @@ -34820,30 +34845,20 @@ "is": "matches", "pattern": "https?://[^/]+/fixture/object-tests/copy/source\\.txt" } - }, - { - "at": "/headers/x-ms-blob-type", - "optional": false, - "rule": { - "is": "equal", - "value": "BlockBlob" - } } ], - "allow_headers": [ - "x-ms-copy-source-authorization", - "x-ms-copy-source-blob-properties" - ], + "allow_headers": [], "allow_query": [], "response": { - "status": 201, + "status": 202, "headers": { "date": { "from": "now" }, "etag": "\"fixture-etag\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-request-server-encrypted": "true" + "x-ms-copy-id": "fixture-copy-id", + "x-ms-copy-status": "pending" }, "body": { "encoding": "empty" @@ -34863,30 +34878,37 @@ } }, { - "at": "/value/etag", + "at": "/value/copy_status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": "pending" + } + }, + { + "at": "/value/copy_id", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-copy-id" } } ], "refusal": null }, { - "id": "operations/azure/abort-copy", + "id": "operations/azure/copy-content-properties", "profile": "azure", "lane": "core", - "purpose": "Abort a pending copy by its copy ID, with x-ms-copy-action: abort", + "purpose": "Copy a blob with a content type, which Copy Blob ignores: the copy keeps the source's content properties. A client may send it, or refuse or decline the parameter", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/copy-blob" ], - "origin": "transient", - "derived_from": "operations/azure/abort-copy-finished", "call": { - "copy_id": "fixture-copy-id", + "content_type": "text/plain", "key": "object-tests/copy/target.txt", - "op": "azure.abort_copy" + "op": "copy", + "source_key": "object-tests/copy/source.txt" }, "exchanges": [ { @@ -34918,38 +34940,34 @@ } }, { - "at": "/query/comp", - "optional": false, - "rule": { - "is": "equal", - "value": "copy" - } - }, - { - "at": "/query/copyid", + "at": "/headers/x-ms-copy-source", "optional": false, "rule": { - "is": "equal", - "value": "fixture-copy-id" + "is": "matches", + "pattern": "https?://[^/]+/fixture/object-tests/copy/source\\.txt" } }, { - "at": "/headers/x-ms-copy-action", + "at": "/headers/x-ms-blob-content-type", "optional": false, "rule": { "is": "equal", - "value": "abort" + "value": "text/plain" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 204, + "status": 202, "headers": { "date": { "from": "now" - } + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-copy-id": "fixture-copy-id", + "x-ms-copy-status": "success" }, "body": { "encoding": "empty" @@ -34967,22 +34985,56 @@ "is": "equal", "value": "ok" } + }, + { + "at": "/value/copy_status", + "optional": false, + "rule": { + "is": "equal", + "value": "success" + } } ], - "refusal": null + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "content_type" + } + } + ], + "decline_permitted": true }, { - "id": "operations/azure/abort-copy-finished", + "id": "operations/azure/put-from-url", "profile": "azure", "lane": "core", - "purpose": "Report an abort of a copy that has finished as an error, 409 NoPendingCopyOperation", + "purpose": "Write a block blob from the bytes at a URL with Put Blob From URL: a PUT with x-ms-blob-type: BlockBlob, x-ms-copy-source and no body, which answers once it is written", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob-from-url" ], "call": { - "copy_id": "fixture-copy-id", "key": "object-tests/copy/target.txt", - "op": "azure.abort_copy" + "op": "azure.put_from_url", + "source_key": "object-tests/copy/source.txt" }, "exchanges": [ { @@ -35014,44 +35066,39 @@ } }, { - "at": "/query/comp", - "optional": false, - "rule": { - "is": "equal", - "value": "copy" - } - }, - { - "at": "/query/copyid", + "at": "/headers/x-ms-copy-source", "optional": false, "rule": { - "is": "equal", - "value": "fixture-copy-id" + "is": "matches", + "pattern": "https?://[^/]+/fixture/object-tests/copy/source\\.txt" } }, { - "at": "/headers/x-ms-copy-action", + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "abort" + "value": "BlockBlob" } } ], - "allow_headers": [], + "allow_headers": [ + "x-ms-copy-source-authorization", + "x-ms-copy-source-blob-properties" + ], "allow_query": [], "response": { - "status": 409, + "status": 201, "headers": { - "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "NoPendingCopyOperation" + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-request-server-encrypted": "true" }, "body": { - "encoding": "utf8", - "data": "NoPendingCopyOperationFixture error" + "encoding": "empty" } } } @@ -35064,39 +35111,34 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 409 + "value": "ok" } }, { - "at": "/code", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": "NoPendingCopyOperation" + "value": "\"fixture-etag\"" } } ], "refusal": null }, { - "id": "operations/azure/get-page-ranges", + "id": "operations/azure/put-from-url-content-properties", "profile": "azure", "lane": "core", - "purpose": "List the written ranges of a page blob", + "purpose": "Write a block blob from a URL with content properties of its own, sent as x-ms-blob-content-type and x-ms-blob-cache-control. Put Blob From URL stores them in place of the source's", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/get-page-ranges" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob-from-url" ], "call": { - "key": "object-tests/pages/object.vhd", - "op": "azure.get_page_ranges" + "cache_control": "max-age=3600", + "content_type": "text/plain", + "key": "object-tests/copy/target.txt", + "op": "azure.put_from_url", + "source_key": "object-tests/copy/source.txt" }, "exchanges": [ { @@ -35108,7 +35150,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -35116,7 +35158,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -35128,32 +35170,56 @@ } }, { - "at": "/query/comp", + "at": "/headers/x-ms-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "https?://[^/]+/fixture/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "pagelist" + "value": "BlockBlob" + } + }, + { + "at": "/headers/x-ms-blob-content-type", + "optional": false, + "rule": { + "is": "equal", + "value": "text/plain" + } + }, + { + "at": "/headers/x-ms-blob-cache-control", + "optional": false, + "rule": { + "is": "equal", + "value": "max-age=3600" } } ], - "allow_headers": [], + "allow_headers": [ + "x-ms-copy-source-authorization", + "x-ms-copy-source-blob-properties" + ], "allow_query": [], "response": { - "status": 200, + "status": 201, "headers": { - "content-type": "application/xml", "date": { "from": "now" }, "etag": "\"fixture-etag\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-blob-content-length": "1024" + "x-ms-request-server-encrypted": "true" }, "body": { - "encoding": "utf8", - "data": "0511" - }, - "framing": "chunked" + "encoding": "empty" + } } } ] @@ -35169,34 +35235,28 @@ } }, { - "at": "/value/ranges", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": [ - { - "end": 512, - "start": 0 - } - ] + "value": "\"fixture-etag\"" } } ], "refusal": null }, { - "id": "operations/azure/upload-pages-unaligned", + "id": "operations/azure/put-from-url-missing-source", "profile": "azure", "lane": "core", - "purpose": "Refuse a page write that does not start on a 512-byte boundary", + "purpose": "Report a Put Blob From URL whose source does not exist as an error. Azure answers 404 CannotVerifyCopySource, a code of its own, not BlobNotFound", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-page" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob-from-url" ], "call": { - "body_base64": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=", - "key": "object-tests/pages/object.vhd", - "offset": 1, - "op": "azure.upload_pages" + "key": "object-tests/copy/target.txt", + "op": "azure.put_from_url", + "source_key": "object-tests/copy/absent.txt" }, "exchanges": [ { @@ -35216,7 +35276,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -35224,48 +35284,43 @@ "optional": false, "rule": { "is": "equal", - "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" - } - }, - { - "at": "/query/comp", - "optional": false, - "rule": { - "is": "equal", - "value": "page" + "value": "" } }, { - "at": "/headers/x-ms-page-write", + "at": "/headers/x-ms-copy-source", "optional": false, "rule": { - "is": "equal", - "value": "update" + "is": "matches", + "pattern": "https?://[^/]+/fixture/object-tests/copy/absent\\.txt" } }, { - "at": "/headers/x-ms-range", + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "bytes=1-512" + "value": "BlockBlob" } } ], - "allow_headers": [], + "allow_headers": [ + "x-ms-copy-source-authorization", + "x-ms-copy-source-blob-properties" + ], "allow_query": [], "response": { - "status": 400, + "status": 404, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "InvalidHeaderValue" + "x-ms-error-code": "CannotVerifyCopySource" }, "body": { "encoding": "utf8", - "data": "InvalidHeaderValueFixture error" + "data": "CannotVerifyCopySourceFixture error" } } } @@ -35286,7 +35341,7 @@ "optional": false, "rule": { "is": "equal", - "value": 400 + "value": 404 } }, { @@ -35294,25 +35349,26 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidHeaderValue" + "value": "CannotVerifyCopySource" } } ], "refusal": null }, { - "id": "operations/azure/upload-pages", + "id": "operations/azure/abort-copy", "profile": "azure", "lane": "core", - "purpose": "Write the first page of a page blob", + "purpose": "Abort a pending copy by its copy ID, with x-ms-copy-action: abort", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-page" + "https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob" ], + "origin": "transient", + "derived_from": "operations/azure/abort-copy-finished", "call": { - "body_base64": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=", - "key": "object-tests/pages/object.vhd", - "offset": 0, - "op": "azure.upload_pages" + "copy_id": "fixture-copy-id", + "key": "object-tests/copy/target.txt", + "op": "azure.abort_copy" }, "exchanges": [ { @@ -35332,7 +35388,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -35340,7 +35396,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" + "value": "" } }, { @@ -35348,38 +35404,34 @@ "optional": false, "rule": { "is": "equal", - "value": "page" + "value": "copy" } }, { - "at": "/headers/x-ms-page-write", + "at": "/query/copyid", "optional": false, "rule": { "is": "equal", - "value": "update" + "value": "fixture-copy-id" } }, { - "at": "/headers/x-ms-range", + "at": "/headers/x-ms-copy-action", "optional": false, "rule": { "is": "equal", - "value": "bytes=0-511" + "value": "abort" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 201, + "status": 204, "headers": { "date": { "from": "now" - }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-blob-sequence-number": "0", - "x-ms-request-server-encrypted": "true" + } }, "body": { "encoding": "empty" @@ -35402,17 +35454,17 @@ "refusal": null }, { - "id": "operations/azure/create-page", + "id": "operations/azure/abort-copy-finished", "profile": "azure", "lane": "core", - "purpose": "Create a page blob of 1,024 bytes", + "purpose": "Report an abort of a copy that has finished as an error, 409 NoPendingCopyOperation", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob" ], "call": { - "key": "object-tests/pages/object.vhd", - "op": "azure.create_page", - "size": 1024 + "copy_id": "fixture-copy-id", + "key": "object-tests/copy/target.txt", + "op": "azure.abort_copy" }, "exchanges": [ { @@ -35432,7 +35484,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -35444,36 +35496,44 @@ } }, { - "at": "/headers/x-ms-blob-type", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "PageBlob" + "value": "copy" } }, { - "at": "/headers/x-ms-blob-content-length", + "at": "/query/copyid", "optional": false, "rule": { "is": "equal", - "value": "1024" + "value": "fixture-copy-id" + } + }, + { + "at": "/headers/x-ms-copy-action", + "optional": false, + "rule": { + "is": "equal", + "value": "abort" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 201, + "status": 409, "headers": { + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-request-server-encrypted": "true" + "x-ms-error-code": "NoPendingCopyOperation" }, "body": { - "encoding": "empty" + "encoding": "utf8", + "data": "NoPendingCopyOperationFixture error" } } } @@ -35486,24 +35546,39 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 409 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "NoPendingCopyOperation" } } ], "refusal": null }, { - "id": "operations/azure/append-block-to-block-blob", + "id": "operations/azure/get-page-ranges", "profile": "azure", "lane": "core", - "purpose": "Refuse an append to a block blob", + "purpose": "List the written ranges of a page blob", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" + "https://learn.microsoft.com/en-us/rest/api/storageservices/get-page-ranges" ], "call": { - "body_base64": "c2Vjb25k", - "key": "object-tests/append/object.log", - "op": "azure.append_block" + "key": "object-tests/pages/object.vhd", + "op": "azure.get_page_ranges" }, "exchanges": [ { @@ -35515,7 +35590,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -35523,7 +35598,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -35531,7 +35606,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "" } }, { @@ -35539,25 +35614,28 @@ "optional": false, "rule": { "is": "equal", - "value": "appendblock" + "value": "pagelist" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 409, + "status": 200, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "InvalidBlobType" + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-blob-content-length": "1024" }, "body": { "encoding": "utf8", - "data": "InvalidBlobTypeFixture error" - } + "data": "0511" + }, + "framing": "chunked" } } ] @@ -35569,41 +35647,38 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 409 + "value": "ok" } }, { - "at": "/code", + "at": "/value/ranges", "optional": false, "rule": { "is": "equal", - "value": "InvalidBlobType" + "value": [ + { + "end": 512, + "start": 0 + } + ] } } ], "refusal": null }, { - "id": "operations/azure/append-block-at-wrong-position", + "id": "operations/azure/upload-pages-unaligned", "profile": "azure", "lane": "core", - "purpose": "Refuse an append whose position condition does not match the blob length", + "purpose": "Refuse a page write that does not start on a 512-byte boundary", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-page" ], "call": { - "append_position": 0, - "body_base64": "c2Vjb25k", - "key": "object-tests/append/object.log", - "op": "azure.append_block" + "body_base64": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=", + "key": "object-tests/pages/object.vhd", + "offset": 1, + "op": "azure.upload_pages" }, "exchanges": [ { @@ -35623,7 +35698,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -35631,7 +35706,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" } }, { @@ -35639,32 +35714,40 @@ "optional": false, "rule": { "is": "equal", - "value": "appendblock" + "value": "page" } }, { - "at": "/headers/x-ms-blob-condition-appendpos", + "at": "/headers/x-ms-page-write", "optional": false, "rule": { "is": "equal", - "value": "0" + "value": "update" + } + }, + { + "at": "/headers/x-ms-range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes=1-512" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 412, + "status": 400, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "AppendPositionConditionNotMet" + "x-ms-error-code": "InvalidHeaderValue" }, "body": { "encoding": "utf8", - "data": "AppendPositionConditionNotMetFixture error" + "data": "InvalidHeaderValueFixture error" } } } @@ -35685,7 +35768,7 @@ "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 400 } }, { @@ -35693,24 +35776,25 @@ "optional": false, "rule": { "is": "equal", - "value": "AppendPositionConditionNotMet" + "value": "InvalidHeaderValue" } } ], "refusal": null }, { - "id": "operations/azure/append-block", + "id": "operations/azure/upload-pages", "profile": "azure", "lane": "core", - "purpose": "Append a block to an append blob and report its offset", + "purpose": "Write the first page of a page blob", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-page" ], "call": { - "body_base64": "c2Vjb25k", - "key": "object-tests/append/object.log", - "op": "azure.append_block" + "body_base64": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=", + "key": "object-tests/pages/object.vhd", + "offset": 0, + "op": "azure.upload_pages" }, "exchanges": [ { @@ -35730,7 +35814,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -35738,7 +35822,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" } }, { @@ -35746,7 +35830,23 @@ "optional": false, "rule": { "is": "equal", - "value": "appendblock" + "value": "page" + } + }, + { + "at": "/headers/x-ms-page-write", + "optional": false, + "rule": { + "is": "equal", + "value": "update" + } + }, + { + "at": "/headers/x-ms-range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes=0-511" } } ], @@ -35760,8 +35860,7 @@ }, "etag": "\"fixture-etag\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-blob-append-offset": "5", - "x-ms-blob-committed-block-count": "2", + "x-ms-blob-sequence-number": "0", "x-ms-request-server-encrypted": "true" }, "body": { @@ -35780,37 +35879,22 @@ "is": "equal", "value": "ok" } - }, - { - "at": "/value/append_offset", - "optional": false, - "rule": { - "is": "equal", - "value": 5 - } - }, - { - "at": "/value/committed_block_count", - "optional": false, - "rule": { - "is": "equal", - "value": 2 - } } ], "refusal": null }, { - "id": "operations/azure/create-append", + "id": "operations/azure/create-page", "profile": "azure", "lane": "core", - "purpose": "Create an empty append blob", + "purpose": "Create a page blob of 1,024 bytes", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" ], "call": { - "key": "object-tests/append/object.log", - "op": "azure.create_append" + "key": "object-tests/pages/object.vhd", + "op": "azure.create_page", + "size": 1024 }, "exchanges": [ { @@ -35830,7 +35914,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -35846,7 +35930,15 @@ "optional": false, "rule": { "is": "equal", - "value": "AppendBlob" + "value": "PageBlob" + } + }, + { + "at": "/headers/x-ms-blob-content-length", + "optional": false, + "rule": { + "is": "equal", + "value": "1024" } } ], @@ -35883,18 +35975,17 @@ "refusal": null }, { - "id": "operations/azure/put-leased-if-match-without-lease-id", + "id": "operations/azure/append-block-to-block-blob", "profile": "azure", "lane": "core", - "purpose": "Refuse a write to a leased object whose If-Match holds but that names no lease ID", + "purpose": "Refuse an append to a block blob", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" ], "call": { "body_base64": "c2Vjb25k", - "if_match": "\"fixture-etag\"", - "key": "object-tests/leases/object.txt", - "op": "put" + "key": "object-tests/append/object.log", + "op": "azure.append_block" }, "exchanges": [ { @@ -35914,7 +36005,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -35926,36 +36017,28 @@ } }, { - "at": "/headers/x-ms-blob-type", - "optional": false, - "rule": { - "is": "equal", - "value": "BlockBlob" - } - }, - { - "at": "/headers/if-match", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": "appendblock" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 412, + "status": 409, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "LeaseIdMissing" + "x-ms-error-code": "InvalidBlobType" }, "body": { "encoding": "utf8", - "data": "LeaseIdMissingFixture error" + "data": "InvalidBlobTypeFixture error" } } } @@ -35976,7 +36059,7 @@ "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 409 } }, { @@ -35984,25 +36067,25 @@ "optional": false, "rule": { "is": "equal", - "value": "LeaseIdMissing" + "value": "InvalidBlobType" } } ], "refusal": null }, { - "id": "operations/azure/put-leased-with-lease-id", + "id": "operations/azure/append-block-at-wrong-position", "profile": "azure", "lane": "core", - "purpose": "Write to a leased object with its lease ID", + "purpose": "Refuse an append whose position condition does not match the blob length", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" ], "call": { + "append_position": 0, "body_base64": "c2Vjb25k", - "key": "object-tests/leases/object.txt", - "lease_id": "11111111-2222-3333-4444-555555555555", - "op": "put" + "key": "object-tests/append/object.log", + "op": "azure.append_block" }, "exchanges": [ { @@ -36022,7 +36105,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -36034,36 +36117,36 @@ } }, { - "at": "/headers/x-ms-blob-type", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "BlockBlob" + "value": "appendblock" } }, { - "at": "/headers/x-ms-lease-id", + "at": "/headers/x-ms-blob-condition-appendpos", "optional": false, "rule": { "is": "equal", - "value": "11111111-2222-3333-4444-555555555555" + "value": "0" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 201, + "status": 412, "headers": { + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-request-server-encrypted": "true" + "x-ms-error-code": "AppendPositionConditionNotMet" }, "body": { - "encoding": "empty" + "encoding": "utf8", + "data": "AppendPositionConditionNotMetFixture error" } } } @@ -36076,24 +36159,40 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 412 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "AppendPositionConditionNotMet" } } ], "refusal": null }, { - "id": "operations/azure/put-leased-without-lease-id", + "id": "operations/azure/append-block", "profile": "azure", "lane": "core", - "purpose": "Refuse a write to a leased object that names no lease ID", + "purpose": "Append a block to an append blob and report its offset", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" ], "call": { "body_base64": "c2Vjb25k", - "key": "object-tests/leases/object.txt", - "op": "put" + "key": "object-tests/append/object.log", + "op": "azure.append_block" }, "exchanges": [ { @@ -36113,7 +36212,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -36125,28 +36224,30 @@ } }, { - "at": "/headers/x-ms-blob-type", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "BlockBlob" + "value": "appendblock" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 412, + "status": 201, "headers": { - "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "LeaseIdMissing" + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-blob-append-offset": "5", + "x-ms-blob-committed-block-count": "2", + "x-ms-request-server-encrypted": "true" }, "body": { - "encoding": "utf8", - "data": "LeaseIdMissingFixture error" + "encoding": "empty" } } } @@ -36159,41 +36260,39 @@ "optional": false, "rule": { "is": "equal", - "value": "error" + "value": "ok" } }, { - "at": "/status", + "at": "/value/append_offset", "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 5 } }, { - "at": "/code", + "at": "/value/committed_block_count", "optional": false, "rule": { "is": "equal", - "value": "LeaseIdMissing" + "value": 2 } } ], "refusal": null }, { - "id": "operations/azure/lease-break", + "id": "operations/azure/create-append", "profile": "azure", "lane": "core", - "purpose": "Break a lease at once", + "purpose": "Create an empty append blob", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" ], "call": { - "action": "break", - "break_period": 0, - "key": "object-tests/leases/object.txt", - "op": "azure.lease" + "key": "object-tests/append/object.log", + "op": "azure.create_append" }, "exchanges": [ { @@ -36213,7 +36312,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -36225,41 +36324,424 @@ } }, { - "at": "/query/comp", - "optional": false, - "rule": { - "is": "equal", - "value": "lease" - } - }, - { - "at": "/headers/x-ms-lease-action", - "optional": false, - "rule": { - "is": "equal", - "value": "break" - } - }, - { - "at": "/headers/x-ms-lease-break-period", + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "0" + "value": "AppendBlob" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 202, + "status": 201, "headers": { "date": { "from": "now" }, "etag": "\"fixture-etag\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-lease-time": "0" + "x-ms-request-server-encrypted": "true" + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/put-leased-if-match-without-lease-id", + "profile": "azure", + "lane": "core", + "purpose": "Refuse a write to a leased object whose If-Match holds but that names no lease ID", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + ], + "call": { + "body_base64": "c2Vjb25k", + "if_match": "\"fixture-etag\"", + "key": "object-tests/leases/object.txt", + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/leases/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "c2Vjb25k" + } + }, + { + "at": "/headers/x-ms-blob-type", + "optional": false, + "rule": { + "is": "equal", + "value": "BlockBlob" + } + }, + { + "at": "/headers/if-match", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-etag\"" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 412, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "LeaseIdMissing" + }, + "body": { + "encoding": "utf8", + "data": "LeaseIdMissingFixture error" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 412 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "LeaseIdMissing" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/put-leased-with-lease-id", + "profile": "azure", + "lane": "core", + "purpose": "Write to a leased object with its lease ID", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + ], + "call": { + "body_base64": "c2Vjb25k", + "key": "object-tests/leases/object.txt", + "lease_id": "11111111-2222-3333-4444-555555555555", + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/leases/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "c2Vjb25k" + } + }, + { + "at": "/headers/x-ms-blob-type", + "optional": false, + "rule": { + "is": "equal", + "value": "BlockBlob" + } + }, + { + "at": "/headers/x-ms-lease-id", + "optional": false, + "rule": { + "is": "equal", + "value": "11111111-2222-3333-4444-555555555555" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 201, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-request-server-encrypted": "true" + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/put-leased-without-lease-id", + "profile": "azure", + "lane": "core", + "purpose": "Refuse a write to a leased object that names no lease ID", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + ], + "call": { + "body_base64": "c2Vjb25k", + "key": "object-tests/leases/object.txt", + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/leases/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "c2Vjb25k" + } + }, + { + "at": "/headers/x-ms-blob-type", + "optional": false, + "rule": { + "is": "equal", + "value": "BlockBlob" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 412, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "LeaseIdMissing" + }, + "body": { + "encoding": "utf8", + "data": "LeaseIdMissingFixture error" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 412 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "LeaseIdMissing" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/lease-break", + "profile": "azure", + "lane": "core", + "purpose": "Break a lease at once", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + ], + "call": { + "action": "break", + "break_period": 0, + "key": "object-tests/leases/object.txt", + "op": "azure.lease" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/leases/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "lease" + } + }, + { + "at": "/headers/x-ms-lease-action", + "optional": false, + "rule": { + "is": "equal", + "value": "break" + } + }, + { + "at": "/headers/x-ms-lease-break-period", + "optional": false, + "rule": { + "is": "equal", + "value": "0" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-lease-time": "0" }, "body": { "encoding": "empty" @@ -82810,6 +83292,116 @@ ], "refusal": null }, + { + "id": "operations/azure-hns/copy-sync-missing-source", + "profile": "azure-hns", + "lane": "core", + "purpose": "Report a Copy Blob From URL whose source does not exist as an error. Azure answers 404 CannotVerifyCopySource, a code of its own, not BlobNotFound", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url" + ], + "call": { + "key": "object-tests/copy/target.txt", + "op": "copy", + "source_key": "object-tests/copy/absent.txt", + "sync": true + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/copy/target.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-ms-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "https?://[^/]+/fixture/object-tests/copy/absent\\.txt" + } + }, + { + "at": "/headers/x-ms-requires-sync", + "optional": false, + "rule": { + "is": "equal", + "value": "true" + } + } + ], + "allow_headers": [ + "x-ms-copy-source-authorization" + ], + "allow_query": [], + "response": { + "status": 404, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "CannotVerifyCopySource" + }, + "body": { + "encoding": "utf8", + "data": "CannotVerifyCopySourceFixture error" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 404 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "CannotVerifyCopySource" + } + } + ], + "refusal": null + }, { "id": "operations/azure-hns/copy-pending", "profile": "azure-hns", @@ -82913,16 +83505,17 @@ "refusal": null }, { - "id": "operations/azure-hns/put-from-url", + "id": "operations/azure-hns/copy-content-properties", "profile": "azure-hns", "lane": "core", - "purpose": "Write a block blob from the bytes at a URL with Put Blob From URL: a PUT with x-ms-blob-type: BlockBlob, x-ms-copy-source and no body, which answers once it is written", + "purpose": "Copy a blob with a content type, which Copy Blob ignores: the copy keeps the source's content properties. A client may send it, or refuse or decline the parameter", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob-from-url" + "https://learn.microsoft.com/en-us/rest/api/storageservices/copy-blob" ], "call": { + "content_type": "text/plain", "key": "object-tests/copy/target.txt", - "op": "azure.put_from_url", + "op": "copy", "source_key": "object-tests/copy/source.txt" }, "exchanges": [ @@ -82963,28 +83556,26 @@ } }, { - "at": "/headers/x-ms-blob-type", + "at": "/headers/x-ms-blob-content-type", "optional": false, "rule": { "is": "equal", - "value": "BlockBlob" + "value": "text/plain" } } ], - "allow_headers": [ - "x-ms-copy-source-authorization", - "x-ms-copy-source-blob-properties" - ], + "allow_headers": [], "allow_query": [], "response": { - "status": 201, + "status": 202, "headers": { "date": { "from": "now" }, "etag": "\"fixture-etag\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-request-server-encrypted": "true" + "x-ms-copy-id": "fixture-copy-id", + "x-ms-copy-status": "success" }, "body": { "encoding": "empty" @@ -83004,30 +83595,54 @@ } }, { - "at": "/value/etag", + "at": "/value/copy_status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": "success" } } ], - "refusal": null + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "content_type" + } + } + ], + "decline_permitted": true }, { - "id": "operations/azure-hns/abort-copy", + "id": "operations/azure-hns/put-from-url", "profile": "azure-hns", "lane": "core", - "purpose": "Abort a pending copy by its copy ID, with x-ms-copy-action: abort", + "purpose": "Write a block blob from the bytes at a URL with Put Blob From URL: a PUT with x-ms-blob-type: BlockBlob, x-ms-copy-source and no body, which answers once it is written", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob-from-url" ], - "origin": "transient", - "derived_from": "operations/azure-hns/abort-copy-finished", "call": { - "copy_id": "fixture-copy-id", "key": "object-tests/copy/target.txt", - "op": "azure.abort_copy" + "op": "azure.put_from_url", + "source_key": "object-tests/copy/source.txt" }, "exchanges": [ { @@ -83059,38 +83674,36 @@ } }, { - "at": "/query/comp", - "optional": false, - "rule": { - "is": "equal", - "value": "copy" - } - }, - { - "at": "/query/copyid", + "at": "/headers/x-ms-copy-source", "optional": false, "rule": { - "is": "equal", - "value": "fixture-copy-id" + "is": "matches", + "pattern": "https?://[^/]+/fixture/object-tests/copy/source\\.txt" } }, { - "at": "/headers/x-ms-copy-action", + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "abort" + "value": "BlockBlob" } } ], - "allow_headers": [], + "allow_headers": [ + "x-ms-copy-source-authorization", + "x-ms-copy-source-blob-properties" + ], "allow_query": [], "response": { - "status": 204, + "status": 201, "headers": { "date": { "from": "now" - } + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-request-server-encrypted": "true" }, "body": { "encoding": "empty" @@ -83108,22 +83721,32 @@ "is": "equal", "value": "ok" } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-etag\"" + } } ], "refusal": null }, { - "id": "operations/azure-hns/abort-copy-finished", + "id": "operations/azure-hns/put-from-url-content-properties", "profile": "azure-hns", "lane": "core", - "purpose": "Report an abort of a copy that has finished as an error, 409 NoPendingCopyOperation", + "purpose": "Write a block blob from a URL with content properties of its own, sent as x-ms-blob-content-type and x-ms-blob-cache-control. Put Blob From URL stores them in place of the source's", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob-from-url" ], "call": { - "copy_id": "fixture-copy-id", + "cache_control": "max-age=3600", + "content_type": "text/plain", "key": "object-tests/copy/target.txt", - "op": "azure.abort_copy" + "op": "azure.put_from_url", + "source_key": "object-tests/copy/source.txt" }, "exchanges": [ { @@ -83155,44 +83778,55 @@ } }, { - "at": "/query/comp", + "at": "/headers/x-ms-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "https?://[^/]+/fixture/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "copy" + "value": "BlockBlob" } }, { - "at": "/query/copyid", + "at": "/headers/x-ms-blob-content-type", "optional": false, "rule": { "is": "equal", - "value": "fixture-copy-id" + "value": "text/plain" } }, { - "at": "/headers/x-ms-copy-action", + "at": "/headers/x-ms-blob-cache-control", "optional": false, "rule": { "is": "equal", - "value": "abort" + "value": "max-age=3600" } } ], - "allow_headers": [], + "allow_headers": [ + "x-ms-copy-source-authorization", + "x-ms-copy-source-blob-properties" + ], "allow_query": [], "response": { - "status": 409, + "status": 201, "headers": { - "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "NoPendingCopyOperation" + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-request-server-encrypted": "true" }, "body": { - "encoding": "utf8", - "data": "NoPendingCopyOperationFixture error" + "encoding": "empty" } } } @@ -83205,39 +83839,32 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 409 + "value": "ok" } }, { - "at": "/code", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": "NoPendingCopyOperation" + "value": "\"fixture-etag\"" } } ], "refusal": null }, { - "id": "operations/azure-hns/get-page-ranges", + "id": "operations/azure-hns/put-from-url-missing-source", "profile": "azure-hns", "lane": "core", - "purpose": "List the written ranges of a page blob, which an HNS account does not support", + "purpose": "Report a Put Blob From URL whose source does not exist as an error. Azure answers 404 CannotVerifyCopySource, a code of its own, not BlobNotFound", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/get-page-ranges" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob-from-url" ], "call": { - "key": "object-tests/pages/object.vhd", - "op": "azure.get_page_ranges" + "key": "object-tests/copy/target.txt", + "op": "azure.put_from_url", + "source_key": "object-tests/copy/absent.txt" }, "exchanges": [ { @@ -83249,7 +83876,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -83257,7 +83884,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -83269,28 +83896,39 @@ } }, { - "at": "/query/comp", + "at": "/headers/x-ms-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "https?://[^/]+/fixture/object-tests/copy/absent\\.txt" + } + }, + { + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "pagelist" + "value": "BlockBlob" } } ], - "allow_headers": [], + "allow_headers": [ + "x-ms-copy-source-authorization", + "x-ms-copy-source-blob-properties" + ], "allow_query": [], "response": { - "status": 409, + "status": 404, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "FeatureNotYetSupportedForHierarchicalNamespaceAccounts" + "x-ms-error-code": "CannotVerifyCopySource" }, "body": { "encoding": "utf8", - "data": "FeatureNotYetSupportedForHierarchicalNamespaceAccountsFixture error" + "data": "CannotVerifyCopySourceFixture error" } } } @@ -83311,7 +83949,7 @@ "optional": false, "rule": { "is": "equal", - "value": 409 + "value": 404 } }, { @@ -83319,25 +83957,26 @@ "optional": false, "rule": { "is": "equal", - "value": "FeatureNotYetSupportedForHierarchicalNamespaceAccounts" + "value": "CannotVerifyCopySource" } } ], "refusal": null }, { - "id": "operations/azure-hns/upload-pages-unaligned", + "id": "operations/azure-hns/abort-copy", "profile": "azure-hns", "lane": "core", - "purpose": "Refuse a page write that does not start on a 512-byte boundary, which an HNS account does not support", + "purpose": "Abort a pending copy by its copy ID, with x-ms-copy-action: abort", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-page" + "https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob" ], + "origin": "transient", + "derived_from": "operations/azure-hns/abort-copy-finished", "call": { - "body_base64": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=", - "key": "object-tests/pages/object.vhd", - "offset": 1, - "op": "azure.upload_pages" + "copy_id": "fixture-copy-id", + "key": "object-tests/copy/target.txt", + "op": "azure.abort_copy" }, "exchanges": [ { @@ -83357,7 +83996,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -83365,7 +84004,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" + "value": "" } }, { @@ -83373,40 +84012,37 @@ "optional": false, "rule": { "is": "equal", - "value": "page" + "value": "copy" } }, { - "at": "/headers/x-ms-page-write", + "at": "/query/copyid", "optional": false, "rule": { "is": "equal", - "value": "update" + "value": "fixture-copy-id" } }, { - "at": "/headers/x-ms-range", + "at": "/headers/x-ms-copy-action", "optional": false, "rule": { "is": "equal", - "value": "bytes=1-512" + "value": "abort" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 400, + "status": 204, "headers": { - "content-type": "application/xml", "date": { "from": "now" - }, - "x-ms-error-code": "InvalidHeaderValue" + } }, "body": { - "encoding": "utf8", - "data": "InvalidHeaderValueFixture error" + "encoding": "empty" } } } @@ -83419,41 +84055,24 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": false, - "rule": { - "is": "equal", - "value": "InvalidHeaderValue" + "value": "ok" } } ], "refusal": null }, { - "id": "operations/azure-hns/upload-pages", + "id": "operations/azure-hns/abort-copy-finished", "profile": "azure-hns", "lane": "core", - "purpose": "Write the first page of a page blob, which an HNS account does not support", + "purpose": "Report an abort of a copy that has finished as an error, 409 NoPendingCopyOperation", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-page" + "https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-blob" ], "call": { - "body_base64": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=", - "key": "object-tests/pages/object.vhd", - "offset": 0, - "op": "azure.upload_pages" + "copy_id": "fixture-copy-id", + "key": "object-tests/copy/target.txt", + "op": "azure.abort_copy" }, "exchanges": [ { @@ -83473,7 +84092,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -83481,7 +84100,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" + "value": "" } }, { @@ -83489,23 +84108,23 @@ "optional": false, "rule": { "is": "equal", - "value": "page" + "value": "copy" } }, { - "at": "/headers/x-ms-page-write", + "at": "/query/copyid", "optional": false, "rule": { "is": "equal", - "value": "update" + "value": "fixture-copy-id" } }, { - "at": "/headers/x-ms-range", + "at": "/headers/x-ms-copy-action", "optional": false, "rule": { "is": "equal", - "value": "bytes=0-511" + "value": "abort" } } ], @@ -83518,11 +84137,11 @@ "date": { "from": "now" }, - "x-ms-error-code": "FeatureNotYetSupportedForHierarchicalNamespaceAccounts" + "x-ms-error-code": "NoPendingCopyOperation" }, "body": { "encoding": "utf8", - "data": "FeatureNotYetSupportedForHierarchicalNamespaceAccountsFixture error" + "data": "NoPendingCopyOperationFixture error" } } } @@ -83551,24 +84170,23 @@ "optional": false, "rule": { "is": "equal", - "value": "FeatureNotYetSupportedForHierarchicalNamespaceAccounts" + "value": "NoPendingCopyOperation" } } ], "refusal": null }, { - "id": "operations/azure-hns/create-page", + "id": "operations/azure-hns/get-page-ranges", "profile": "azure-hns", "lane": "core", - "purpose": "Create a page blob of 1,024 bytes, which an HNS account does not support", + "purpose": "List the written ranges of a page blob, which an HNS account does not support", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/get-page-ranges" ], "call": { "key": "object-tests/pages/object.vhd", - "op": "azure.create_page", - "size": 1024 + "op": "azure.get_page_ranges" }, "exchanges": [ { @@ -83580,7 +84198,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -83600,19 +84218,11 @@ } }, { - "at": "/headers/x-ms-blob-type", - "optional": false, - "rule": { - "is": "equal", - "value": "PageBlob" - } - }, - { - "at": "/headers/x-ms-blob-content-length", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "1024" + "value": "pagelist" } } ], @@ -83665,17 +84275,18 @@ "refusal": null }, { - "id": "operations/azure-hns/append-block-to-block-blob", + "id": "operations/azure-hns/upload-pages-unaligned", "profile": "azure-hns", "lane": "core", - "purpose": "Refuse an append to a block blob", + "purpose": "Refuse a page write that does not start on a 512-byte boundary, which an HNS account does not support", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-page" ], "call": { - "body_base64": "c2Vjb25k", - "key": "object-tests/append/object.log", - "op": "azure.append_block" + "body_base64": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=", + "key": "object-tests/pages/object.vhd", + "offset": 1, + "op": "azure.upload_pages" }, "exchanges": [ { @@ -83695,7 +84306,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -83703,7 +84314,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" } }, { @@ -83711,24 +84322,40 @@ "optional": false, "rule": { "is": "equal", - "value": "appendblock" + "value": "page" + } + }, + { + "at": "/headers/x-ms-page-write", + "optional": false, + "rule": { + "is": "equal", + "value": "update" + } + }, + { + "at": "/headers/x-ms-range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes=1-512" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 409, + "status": 400, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "InvalidBlobType" + "x-ms-error-code": "InvalidHeaderValue" }, "body": { "encoding": "utf8", - "data": "InvalidBlobTypeFixture error" + "data": "InvalidHeaderValueFixture error" } } } @@ -83749,7 +84376,7 @@ "optional": false, "rule": { "is": "equal", - "value": 409 + "value": 400 } }, { @@ -83757,25 +84384,25 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidBlobType" + "value": "InvalidHeaderValue" } } ], "refusal": null }, { - "id": "operations/azure-hns/append-block-at-wrong-position", + "id": "operations/azure-hns/upload-pages", "profile": "azure-hns", "lane": "core", - "purpose": "Refuse an append whose position condition does not match the blob length", + "purpose": "Write the first page of a page blob, which an HNS account does not support", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-page" ], "call": { - "append_position": 0, - "body_base64": "c2Vjb25k", - "key": "object-tests/append/object.log", - "op": "azure.append_block" + "body_base64": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=", + "key": "object-tests/pages/object.vhd", + "offset": 0, + "op": "azure.upload_pages" }, "exchanges": [ { @@ -83795,7 +84422,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -83803,7 +84430,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" } }, { @@ -83811,32 +84438,40 @@ "optional": false, "rule": { "is": "equal", - "value": "appendblock" + "value": "page" } }, { - "at": "/headers/x-ms-blob-condition-appendpos", + "at": "/headers/x-ms-page-write", "optional": false, "rule": { "is": "equal", - "value": "0" + "value": "update" + } + }, + { + "at": "/headers/x-ms-range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes=0-511" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 412, + "status": 409, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "AppendPositionConditionNotMet" + "x-ms-error-code": "FeatureNotYetSupportedForHierarchicalNamespaceAccounts" }, "body": { "encoding": "utf8", - "data": "AppendPositionConditionNotMetFixture error" + "data": "FeatureNotYetSupportedForHierarchicalNamespaceAccountsFixture error" } } } @@ -83857,7 +84492,7 @@ "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 409 } }, { @@ -83865,24 +84500,24 @@ "optional": false, "rule": { "is": "equal", - "value": "AppendPositionConditionNotMet" + "value": "FeatureNotYetSupportedForHierarchicalNamespaceAccounts" } } ], "refusal": null }, { - "id": "operations/azure-hns/append-block", + "id": "operations/azure-hns/create-page", "profile": "azure-hns", "lane": "core", - "purpose": "Append a block to an append blob and report its offset", + "purpose": "Create a page blob of 1,024 bytes, which an HNS account does not support", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" ], "call": { - "body_base64": "c2Vjb25k", - "key": "object-tests/append/object.log", - "op": "azure.append_block" + "key": "object-tests/pages/object.vhd", + "op": "azure.create_page", + "size": 1024 }, "exchanges": [ { @@ -83902,7 +84537,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -83910,34 +84545,40 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "" } }, { - "at": "/query/comp", + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "appendblock" + "value": "PageBlob" + } + }, + { + "at": "/headers/x-ms-blob-content-length", + "optional": false, + "rule": { + "is": "equal", + "value": "1024" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 201, + "status": 409, "headers": { + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-blob-append-offset": "5", - "x-ms-blob-committed-block-count": "2", - "x-ms-request-server-encrypted": "true" + "x-ms-error-code": "FeatureNotYetSupportedForHierarchicalNamespaceAccounts" }, "body": { - "encoding": "empty" + "encoding": "utf8", + "data": "FeatureNotYetSupportedForHierarchicalNamespaceAccountsFixture error" } } } @@ -83950,39 +84591,40 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/append_offset", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": 5 + "value": 409 } }, { - "at": "/value/committed_block_count", + "at": "/code", "optional": false, "rule": { "is": "equal", - "value": 2 + "value": "FeatureNotYetSupportedForHierarchicalNamespaceAccounts" } } ], "refusal": null }, { - "id": "operations/azure-hns/create-append", + "id": "operations/azure-hns/append-block-to-block-blob", "profile": "azure-hns", "lane": "core", - "purpose": "Create an empty append blob", + "purpose": "Refuse an append to a block blob", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" ], "call": { + "body_base64": "c2Vjb25k", "key": "object-tests/append/object.log", - "op": "azure.create_append" + "op": "azure.append_block" }, "exchanges": [ { @@ -84010,32 +84652,32 @@ "optional": false, "rule": { "is": "equal", - "value": "" + "value": "c2Vjb25k" } }, { - "at": "/headers/x-ms-blob-type", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "AppendBlob" + "value": "appendblock" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 201, + "status": 409, "headers": { + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-request-server-encrypted": "true" + "x-ms-error-code": "InvalidBlobType" }, "body": { - "encoding": "empty" + "encoding": "utf8", + "data": "InvalidBlobTypeFixture error" } } } @@ -84048,25 +84690,41 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 409 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidBlobType" } } ], "refusal": null }, { - "id": "operations/azure-hns/put-leased-if-match-without-lease-id", + "id": "operations/azure-hns/append-block-at-wrong-position", "profile": "azure-hns", "lane": "core", - "purpose": "Refuse a write to a leased object whose If-Match holds but that names no lease ID", + "purpose": "Refuse an append whose position condition does not match the blob length", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" ], "call": { + "append_position": 0, "body_base64": "c2Vjb25k", - "if_match": "\"fixture-etag\"", - "key": "object-tests/leases/object.txt", - "op": "put" + "key": "object-tests/append/object.log", + "op": "azure.append_block" }, "exchanges": [ { @@ -84086,7 +84744,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -84098,19 +84756,19 @@ } }, { - "at": "/headers/x-ms-blob-type", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "BlockBlob" + "value": "appendblock" } }, { - "at": "/headers/if-match", + "at": "/headers/x-ms-blob-condition-appendpos", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": "0" } } ], @@ -84123,11 +84781,11 @@ "date": { "from": "now" }, - "x-ms-error-code": "LeaseIdMissing" + "x-ms-error-code": "AppendPositionConditionNotMet" }, "body": { "encoding": "utf8", - "data": "LeaseIdMissingFixture error" + "data": "AppendPositionConditionNotMetFixture error" } } } @@ -84156,25 +84814,24 @@ "optional": false, "rule": { "is": "equal", - "value": "LeaseIdMissing" + "value": "AppendPositionConditionNotMet" } } ], "refusal": null }, { - "id": "operations/azure-hns/put-leased-with-lease-id", + "id": "operations/azure-hns/append-block", "profile": "azure-hns", "lane": "core", - "purpose": "Write to a leased object with its lease ID", + "purpose": "Append a block to an append blob and report its offset", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/append-block" ], "call": { "body_base64": "c2Vjb25k", - "key": "object-tests/leases/object.txt", - "lease_id": "11111111-2222-3333-4444-555555555555", - "op": "put" + "key": "object-tests/append/object.log", + "op": "azure.append_block" }, "exchanges": [ { @@ -84194,7 +84851,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -84206,19 +84863,11 @@ } }, { - "at": "/headers/x-ms-blob-type", - "optional": false, - "rule": { - "is": "equal", - "value": "BlockBlob" - } - }, - { - "at": "/headers/x-ms-lease-id", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "11111111-2222-3333-4444-555555555555" + "value": "appendblock" } } ], @@ -84232,6 +84881,8 @@ }, "etag": "\"fixture-etag\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-blob-append-offset": "5", + "x-ms-blob-committed-block-count": "2", "x-ms-request-server-encrypted": "true" }, "body": { @@ -84250,22 +84901,37 @@ "is": "equal", "value": "ok" } + }, + { + "at": "/value/append_offset", + "optional": false, + "rule": { + "is": "equal", + "value": 5 + } + }, + { + "at": "/value/committed_block_count", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } } ], "refusal": null }, { - "id": "operations/azure-hns/put-leased-without-lease-id", + "id": "operations/azure-hns/create-append", "profile": "azure-hns", "lane": "core", - "purpose": "Refuse a write to a leased object that names no lease ID", + "purpose": "Create an empty append blob", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" ], "call": { - "body_base64": "c2Vjb25k", - "key": "object-tests/leases/object.txt", - "op": "put" + "key": "object-tests/append/object.log", + "op": "azure.create_append" }, "exchanges": [ { @@ -84285,7 +84951,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -84293,7 +84959,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "" } }, { @@ -84301,24 +84967,24 @@ "optional": false, "rule": { "is": "equal", - "value": "BlockBlob" + "value": "AppendBlob" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 412, + "status": 201, "headers": { - "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "LeaseIdMissing" + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-request-server-encrypted": "true" }, "body": { - "encoding": "utf8", - "data": "LeaseIdMissingFixture error" + "encoding": "empty" } } } @@ -84331,41 +84997,324 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 412 - } - }, - { - "at": "/code", - "optional": false, - "rule": { - "is": "equal", - "value": "LeaseIdMissing" + "value": "ok" } } ], "refusal": null }, { - "id": "operations/azure-hns/lease-break", + "id": "operations/azure-hns/put-leased-if-match-without-lease-id", "profile": "azure-hns", "lane": "core", - "purpose": "Break a lease at once", + "purpose": "Refuse a write to a leased object whose If-Match holds but that names no lease ID", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" ], "call": { - "action": "break", - "break_period": 0, + "body_base64": "c2Vjb25k", + "if_match": "\"fixture-etag\"", "key": "object-tests/leases/object.txt", - "op": "azure.lease" + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/leases/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "c2Vjb25k" + } + }, + { + "at": "/headers/x-ms-blob-type", + "optional": false, + "rule": { + "is": "equal", + "value": "BlockBlob" + } + }, + { + "at": "/headers/if-match", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-etag\"" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 412, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "LeaseIdMissing" + }, + "body": { + "encoding": "utf8", + "data": "LeaseIdMissingFixture error" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 412 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "LeaseIdMissing" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure-hns/put-leased-with-lease-id", + "profile": "azure-hns", + "lane": "core", + "purpose": "Write to a leased object with its lease ID", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + ], + "call": { + "body_base64": "c2Vjb25k", + "key": "object-tests/leases/object.txt", + "lease_id": "11111111-2222-3333-4444-555555555555", + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/leases/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "c2Vjb25k" + } + }, + { + "at": "/headers/x-ms-blob-type", + "optional": false, + "rule": { + "is": "equal", + "value": "BlockBlob" + } + }, + { + "at": "/headers/x-ms-lease-id", + "optional": false, + "rule": { + "is": "equal", + "value": "11111111-2222-3333-4444-555555555555" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 201, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-request-server-encrypted": "true" + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure-hns/put-leased-without-lease-id", + "profile": "azure-hns", + "lane": "core", + "purpose": "Refuse a write to a leased object that names no lease ID", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + ], + "call": { + "body_base64": "c2Vjb25k", + "key": "object-tests/leases/object.txt", + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/leases/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "c2Vjb25k" + } + }, + { + "at": "/headers/x-ms-blob-type", + "optional": false, + "rule": { + "is": "equal", + "value": "BlockBlob" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 412, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "LeaseIdMissing" + }, + "body": { + "encoding": "utf8", + "data": "LeaseIdMissingFixture error" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 412 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "LeaseIdMissing" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure-hns/lease-break", + "profile": "azure-hns", + "lane": "core", + "purpose": "Break a lease at once", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/lease-blob" + ], + "call": { + "action": "break", + "break_period": 0, + "key": "object-tests/leases/object.txt", + "op": "azure.lease" }, "exchanges": [ { @@ -129151,20 +130100,20 @@ "refusal": null }, { - "id": "operations/s3/copy-replace-tags", + "id": "operations/s3/copy-replace-metadata-only", "profile": "s3", "lane": "core", - "purpose": "Copy an object with new tags. S3 copies the source's tags unless x-amz-tagging-directive is REPLACE, so a client that sets tags must send it", + "purpose": "Copy an object with new metadata and no content type. x-amz-metadata-directive: REPLACE replaces the content properties too: S3 gives the copy binary/octet-stream, not the source's content type, unless the caller names one", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", + "metadata": { + "colour": "blue" + }, "op": "copy", - "source_key": "object-tests/copy/source.txt", - "tags": { - "project": "copied" - } + "source_key": "object-tests/copy/source.txt" }, "exchanges": [ { @@ -129204,7 +130153,7 @@ } }, { - "at": "/headers/x-amz-tagging-directive", + "at": "/headers/x-amz-metadata-directive", "optional": false, "rule": { "is": "equal", @@ -129212,11 +130161,11 @@ } }, { - "at": "/headers/x-amz-tagging", + "at": "/headers/x-amz-meta-colour", "optional": false, "rule": { "is": "equal", - "value": "project=copied" + "value": "blue" } } ], @@ -129303,7 +130252,7 @@ } }, { - "at": "/headers/x-amz-tagging-directive", + "at": "/headers/x-amz-metadata-directive", "optional": false, "rule": { "is": "equal", @@ -129311,11 +130260,11 @@ } }, { - "at": "/headers/x-amz-tagging", + "at": "/headers/x-amz-meta-colour", "optional": false, "rule": { "is": "equal", - "value": "project=copied" + "value": "blue" } } ], @@ -129375,18 +130324,18 @@ "refusal": null }, { - "id": "operations/s3/copy-storage-class", + "id": "operations/s3/copy-clear-metadata", "profile": "s3", "lane": "core", - "purpose": "Copy an object into another storage class, named in x-amz-storage-class", + "purpose": "Copy an object with no metadata in place of the source's: x-amz-metadata-directive: REPLACE with no x-amz-meta- header. A client API that cannot say no metadata may refuse or decline the call", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", + "metadata": {}, "op": "copy", - "source_key": "object-tests/copy/source.txt", - "storage_class": "STANDARD_IA" + "source_key": "object-tests/copy/source.txt" }, "exchanges": [ { @@ -129426,11 +130375,11 @@ } }, { - "at": "/headers/x-amz-storage-class", + "at": "/headers/x-amz-metadata-directive", "optional": false, "rule": { "is": "equal", - "value": "STANDARD_IA" + "value": "REPLACE" } } ], @@ -129517,11 +130466,11 @@ } }, { - "at": "/headers/x-amz-storage-class", + "at": "/headers/x-amz-metadata-directive", "optional": false, "rule": { "is": "equal", - "value": "STANDARD_IA" + "value": "REPLACE" } } ], @@ -129578,21 +130527,49 @@ } } ], - "refusal": null + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "metadata" + } + } + ], + "decline_permitted": true }, { - "id": "operations/s3/copy-source-if-match", + "id": "operations/s3/copy-replace-tags", "profile": "s3", "lane": "core", - "purpose": "Copy an object only if the source still has this ETag, named in x-amz-copy-source-if-match", + "purpose": "Copy an object with new tags. S3 copies the source's tags unless x-amz-tagging-directive is REPLACE, so a client that sets tags must send it", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", "op": "copy", - "source_if_match": "\"fixture-etag\"", - "source_key": "object-tests/copy/source.txt" + "source_key": "object-tests/copy/source.txt", + "tags": { + "project": "copied" + } }, "exchanges": [ { @@ -129632,11 +130609,19 @@ } }, { - "at": "/headers/x-amz-copy-source-if-match", + "at": "/headers/x-amz-tagging-directive", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "project=copied" } } ], @@ -129723,11 +130708,19 @@ } }, { - "at": "/headers/x-amz-copy-source-if-match", + "at": "/headers/x-amz-tagging-directive", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "project=copied" } } ], @@ -129787,18 +130780,18 @@ "refusal": null }, { - "id": "operations/s3/copy-source-if-match-failed", + "id": "operations/s3/copy-clear-tags", "profile": "s3", "lane": "core", - "purpose": "Report a copy whose source does not have the ETag in x-amz-copy-source-if-match as a failed condition. S3 answers 412 PreconditionFailed and writes nothing", + "purpose": "Copy an object with no tags in place of the source's: x-amz-tagging-directive: REPLACE with an empty or no x-amz-tagging. A client API that cannot say no tags may refuse or decline the call", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", "op": "copy", - "source_if_match": "\"fixture-0123456789ab\"", - "source_key": "object-tests/copy/source.txt" + "source_key": "object-tests/copy/source.txt", + "tags": {} }, "exchanges": [ { @@ -129838,11 +130831,19 @@ } }, { - "at": "/headers/x-amz-copy-source-if-match", + "at": "/headers/x-amz-tagging-directive", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-0123456789ab\"" + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-tagging", + "optional": true, + "rule": { + "is": "equal", + "value": "" } } ], @@ -129851,7 +130852,7 @@ ], "allow_query": [], "response": { - "status": 412, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -129860,9 +130861,8 @@ }, "body": { "encoding": "utf8", - "data": "\nPreconditionFailedFixture error" - }, - "framing": "chunked" + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } } }, { @@ -129930,11 +130930,19 @@ } }, { - "at": "/headers/x-amz-copy-source-if-match", + "at": "/headers/x-amz-tagging-directive", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-0123456789ab\"" + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-tagging", + "optional": true, + "rule": { + "is": "equal", + "value": "" } } ], @@ -129943,7 +130951,7 @@ ], "allow_query": [], "response": { - "status": 412, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -129952,9 +130960,8 @@ }, "body": { "encoding": "utf8", - "data": "\nPreconditionFailedFixture error" - }, - "framing": "chunked" + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } } } ] @@ -129988,41 +130995,51 @@ "optional": false, "rule": { "is": "equal", - "value": "error" + "value": "ok" } - }, + } + ], + "refusal": [ { - "at": "/status", + "at": "/outcome", "optional": false, "rule": { "is": "equal", - "value": 412 + "value": "refused" } }, { - "at": "/code", + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", "optional": false, "rule": { "is": "equal", - "value": "PreconditionFailed" + "value": "tags" } } ], - "refusal": null + "decline_permitted": true }, { - "id": "operations/s3/copy-source-if-none-match-failed", + "id": "operations/s3/copy-storage-class", "profile": "s3", "lane": "core", - "purpose": "Report a copy whose source has the ETag in x-amz-copy-source-if-none-match as a failed condition. A copy answers 412 PreconditionFailed where a read answers 304", + "purpose": "Copy an object into another storage class, named in x-amz-storage-class", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", "op": "copy", - "source_if_none_match": "\"fixture-etag\"", - "source_key": "object-tests/copy/source.txt" + "source_key": "object-tests/copy/source.txt", + "storage_class": "STANDARD_IA" }, "exchanges": [ { @@ -130062,11 +131079,11 @@ } }, { - "at": "/headers/x-amz-copy-source-if-none-match", + "at": "/headers/x-amz-storage-class", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": "STANDARD_IA" } } ], @@ -130075,7 +131092,7 @@ ], "allow_query": [], "response": { - "status": 412, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -130084,9 +131101,8 @@ }, "body": { "encoding": "utf8", - "data": "\nPreconditionFailedFixture error" - }, - "framing": "chunked" + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } } }, { @@ -130154,11 +131170,11 @@ } }, { - "at": "/headers/x-amz-copy-source-if-none-match", + "at": "/headers/x-amz-storage-class", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": "STANDARD_IA" } } ], @@ -130167,7 +131183,7 @@ ], "allow_query": [], "response": { - "status": 412, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -130176,9 +131192,8 @@ }, "body": { "encoding": "utf8", - "data": "\nPreconditionFailedFixture error" - }, - "framing": "chunked" + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } } } ] @@ -130212,40 +131227,24 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 412 - } - }, - { - "at": "/code", - "optional": false, - "rule": { - "is": "equal", - "value": "PreconditionFailed" + "value": "ok" } } ], "refusal": null }, { - "id": "operations/s3/copy-source-if-modified-since", + "id": "operations/s3/copy-source-if-match", "profile": "s3", "lane": "core", - "purpose": "Copy an object only if the source changed after a time, named in x-amz-copy-source-if-modified-since as an HTTP date", + "purpose": "Copy an object only if the source still has this ETag, named in x-amz-copy-source-if-match", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", "op": "copy", - "source_if_modified_since": "Mon, 01 Jan 2024 00:00:00 GMT", + "source_if_match": "\"fixture-etag\"", "source_key": "object-tests/copy/source.txt" }, "exchanges": [ @@ -130286,11 +131285,11 @@ } }, { - "at": "/headers/x-amz-copy-source-if-modified-since", + "at": "/headers/x-amz-copy-source-if-match", "optional": false, "rule": { "is": "equal", - "value": "Mon, 01 Jan 2024 00:00:00 GMT" + "value": "\"fixture-etag\"" } } ], @@ -130377,11 +131376,11 @@ } }, { - "at": "/headers/x-amz-copy-source-if-modified-since", + "at": "/headers/x-amz-copy-source-if-match", "optional": false, "rule": { "is": "equal", - "value": "Mon, 01 Jan 2024 00:00:00 GMT" + "value": "\"fixture-etag\"" } } ], @@ -130441,17 +131440,17 @@ "refusal": null }, { - "id": "operations/s3/copy-source-if-unmodified-since-failed", + "id": "operations/s3/copy-source-if-match-failed", "profile": "s3", "lane": "core", - "purpose": "Report a copy whose source changed after the time in x-amz-copy-source-if-unmodified-since as a failed condition, 412 PreconditionFailed", + "purpose": "Report a copy whose source does not have the ETag in x-amz-copy-source-if-match as a failed condition. S3 answers 412 PreconditionFailed and writes nothing", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", "op": "copy", - "source_if_unmodified_since": "Mon, 01 Jan 2024 00:00:00 GMT", + "source_if_match": "\"fixture-0123456789ab\"", "source_key": "object-tests/copy/source.txt" }, "exchanges": [ @@ -130492,11 +131491,11 @@ } }, { - "at": "/headers/x-amz-copy-source-if-unmodified-since", + "at": "/headers/x-amz-copy-source-if-match", "optional": false, "rule": { "is": "equal", - "value": "Mon, 01 Jan 2024 00:00:00 GMT" + "value": "\"fixture-0123456789ab\"" } } ], @@ -130584,11 +131583,11 @@ } }, { - "at": "/headers/x-amz-copy-source-if-unmodified-since", + "at": "/headers/x-amz-copy-source-if-match", "optional": false, "rule": { "is": "equal", - "value": "Mon, 01 Jan 2024 00:00:00 GMT" + "value": "\"fixture-0123456789ab\"" } } ], @@ -130665,17 +131664,17 @@ "refusal": null }, { - "id": "operations/s3/copy-across-buckets", + "id": "operations/s3/copy-source-if-none-match-failed", "profile": "s3", "lane": "core", - "purpose": "Copy an object from another bucket, which x-amz-copy-source names before the key", + "purpose": "Report a copy whose source has the ETag in x-amz-copy-source-if-none-match as a failed condition. A copy answers 412 PreconditionFailed where a read answers 304", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", "op": "copy", - "source_bucket": "source", + "source_if_none_match": "\"fixture-etag\"", "source_key": "object-tests/copy/source.txt" }, "exchanges": [ @@ -130712,7 +131711,15 @@ "optional": false, "rule": { "is": "matches", - "pattern": "/?source/object-tests/copy/source\\.txt" + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-amz-copy-source-if-none-match", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-etag\"" } } ], @@ -130721,7 +131728,7 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 412, "headers": { "content-type": "application/xml", "date": { @@ -130730,8 +131737,9 @@ }, "body": { "encoding": "utf8", - "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" - } + "data": "\nPreconditionFailedFixture error" + }, + "framing": "chunked" } }, { @@ -130795,7 +131803,15 @@ "optional": false, "rule": { "is": "matches", - "pattern": "/?source/object-tests/copy/source\\.txt" + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-amz-copy-source-if-none-match", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-etag\"" } } ], @@ -130804,7 +131820,7 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 412, "headers": { "content-type": "application/xml", "date": { @@ -130813,8 +131829,9 @@ }, "body": { "encoding": "utf8", - "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" - } + "data": "\nPreconditionFailedFixture error" + }, + "framing": "chunked" } } ] @@ -130848,24 +131865,41 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 412 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "PreconditionFailed" } } ], "refusal": null }, { - "id": "operations/s3/copy-source-key-encoded", + "id": "operations/s3/copy-source-if-modified-since", "profile": "s3", "lane": "core", - "purpose": "Copy from a key with a space, +, %, é, ? and #. x-amz-copy-source percent-encodes every byte of the key outside letters, digits, -._~ and /", + "purpose": "Copy an object only if the source changed after a time, named in x-amz-copy-source-if-modified-since as an HTTP date", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { "key": "object-tests/copy/target.txt", "op": "copy", - "source_key": "object-tests/copy/a b+c%é?#.txt" + "source_if_modified_since": "Mon, 01 Jan 2024 00:00:00 GMT", + "source_key": "object-tests/copy/source.txt" }, "exchanges": [ { @@ -130901,7 +131935,15 @@ "optional": false, "rule": { "is": "matches", - "pattern": "/?fixture[^/]*/object-tests/copy/a%20b%2[Bb]c%25%[Cc]3%[Aa]9%3[Ff]%23\\.txt" + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-amz-copy-source-if-modified-since", + "optional": false, + "rule": { + "is": "equal", + "value": "Mon, 01 Jan 2024 00:00:00 GMT" } } ], @@ -130938,7 +131980,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/copy/a b+c%é?#.txt" + "value": "/object-tests/copy/source.txt" } }, { @@ -130984,7 +132026,15 @@ "optional": false, "rule": { "is": "matches", - "pattern": "/?fixture[^/]*/object-tests/copy/a%20b%2[Bb]c%25%[Cc]3%[Aa]9%3[Ff]%23\\.txt" + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-amz-copy-source-if-modified-since", + "optional": false, + "rule": { + "is": "equal", + "value": "Mon, 01 Jan 2024 00:00:00 GMT" } } ], @@ -131044,16 +132094,17 @@ "refusal": null }, { - "id": "operations/s3/copy-onto-itself", + "id": "operations/s3/copy-source-if-unmodified-since-failed", "profile": "s3", "lane": "core", - "purpose": "Report a copy of an object onto itself that changes nothing as an error. S3 answers 400 InvalidRequest", + "purpose": "Report a copy whose source changed after the time in x-amz-copy-source-if-unmodified-since as a failed condition, 412 PreconditionFailed", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { - "key": "object-tests/copy/source.txt", + "key": "object-tests/copy/target.txt", "op": "copy", + "source_if_unmodified_since": "Mon, 01 Jan 2024 00:00:00 GMT", "source_key": "object-tests/copy/source.txt" }, "exchanges": [ @@ -131074,7 +132125,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/copy/source.txt" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -131092,6 +132143,14 @@ "is": "matches", "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } + }, + { + "at": "/headers/x-amz-copy-source-if-unmodified-since", + "optional": false, + "rule": { + "is": "equal", + "value": "Mon, 01 Jan 2024 00:00:00 GMT" + } } ], "allow_headers": [ @@ -131099,7 +132158,7 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 412, "headers": { "content-type": "application/xml", "date": { @@ -131108,7 +132167,7 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidRequestFixture error" + "data": "\nPreconditionFailedFixture error" }, "framing": "chunked" } @@ -131158,7 +132217,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/copy/source.txt" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -131176,6 +132235,14 @@ "is": "matches", "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } + }, + { + "at": "/headers/x-amz-copy-source-if-unmodified-since", + "optional": false, + "rule": { + "is": "equal", + "value": "Mon, 01 Jan 2024 00:00:00 GMT" + } } ], "allow_headers": [ @@ -131183,7 +132250,7 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 412, "headers": { "content-type": "application/xml", "date": { @@ -131192,7 +132259,7 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidRequestFixture error" + "data": "\nPreconditionFailedFixture error" }, "framing": "chunked" } @@ -131236,7 +132303,7 @@ "optional": false, "rule": { "is": "equal", - "value": 400 + "value": 412 } }, { @@ -131244,26 +132311,24 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidRequest" + "value": "PreconditionFailed" } } ], "refusal": null }, { - "id": "operations/s3/copy-onto-itself-replace-metadata", + "id": "operations/s3/copy-across-buckets", "profile": "s3", "lane": "core", - "purpose": "Copy an object onto itself to replace its metadata, which S3 accepts with x-amz-metadata-directive: REPLACE", + "purpose": "Copy an object from another bucket, which x-amz-copy-source names before the key", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { - "key": "object-tests/copy/source.txt", - "metadata": { - "colour": "blue" - }, + "key": "object-tests/copy/target.txt", "op": "copy", + "source_bucket": "source", "source_key": "object-tests/copy/source.txt" }, "exchanges": [ @@ -131284,7 +132349,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/copy/source.txt" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -131300,23 +132365,7 @@ "optional": false, "rule": { "is": "matches", - "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" - } - }, - { - "at": "/headers/x-amz-metadata-directive", - "optional": false, - "rule": { - "is": "equal", - "value": "REPLACE" - } - }, - { - "at": "/headers/x-amz-meta-colour", - "optional": false, - "rule": { - "is": "equal", - "value": "blue" + "pattern": "/?source/object-tests/copy/source\\.txt" } } ], @@ -131383,7 +132432,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/copy/source.txt" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -131399,23 +132448,7 @@ "optional": false, "rule": { "is": "matches", - "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" - } - }, - { - "at": "/headers/x-amz-metadata-directive", - "optional": false, - "rule": { - "is": "equal", - "value": "REPLACE" - } - }, - { - "at": "/headers/x-amz-meta-colour", - "optional": false, - "rule": { - "is": "equal", - "value": "blue" + "pattern": "/?source/object-tests/copy/source\\.txt" } } ], @@ -131475,18 +132508,17 @@ "refusal": null }, { - "id": "operations/s3/put-with-unknown-storage-class", + "id": "operations/s3/copy-source-key-encoded", "profile": "s3", "lane": "core", - "purpose": "Refuse a storage class that S3 does not have", + "purpose": "Copy from a key with a space, +, %, é, ? and #. x-amz-copy-source percent-encodes every byte of the key outside letters, digits, -._~ and /", "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" ], "call": { - "body_base64": "Zmlyc3Q=", - "key": "object-tests/classes/object.txt", - "op": "put", - "storage_class": "WARM" + "key": "object-tests/copy/target.txt", + "op": "copy", + "source_key": "object-tests/copy/a b+c%é?#.txt" }, "exchanges": [ { @@ -131506,7 +132538,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/classes/object.txt" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -131514,15 +132546,15 @@ "optional": false, "rule": { "is": "equal", - "value": "Zmlyc3Q=" + "value": "" } }, { - "at": "/headers/x-amz-storage-class", + "at": "/headers/x-amz-copy-source", "optional": false, "rule": { - "is": "equal", - "value": "WARM" + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/a%20b%2[Bb]c%25%[Cc]3%[Aa]9%3[Ff]%23\\.txt" } } ], @@ -131531,7 +132563,7 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -131540,59 +132572,10 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidStorageClassFixture error" - }, - "framing": "chunked" + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } } - } - ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": false, - "rule": { - "is": "equal", - "value": "InvalidStorageClass" - } - } - ], - "refusal": null - }, - { - "id": "operations/s3/put-with-storage-class", - "profile": "s3", - "lane": "core", - "purpose": "Write an object into the STANDARD_IA storage class", - "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" - ], - "call": { - "body_base64": "Zmlyc3Q=", - "key": "object-tests/classes/object.txt", - "op": "put", - "storage_class": "STANDARD_IA" - }, - "exchanges": [ - { - "alternatives": [ + }, { "request": [ { @@ -131600,7 +132583,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "HEAD" } }, { @@ -131608,7 +132591,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/classes/object.txt" + "value": "/object-tests/copy/a b+c%é?#.txt" } }, { @@ -131616,16 +132599,686 @@ "optional": false, "rule": { "is": "equal", - "value": "Zmlyc3Q=" + "value": "" } - }, + } + ], + "then": [ { - "at": "/headers/x-amz-storage-class", - "optional": false, - "rule": { - "is": "equal", - "value": "STANDARD_IA" - } + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/copy/target.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/a%20b%2[Bb]c%25%[Cc]3%[Aa]9%3[Ff]%23\\.txt" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } + } + } + ] + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-length": "5", + "date": { + "from": "now" + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/copy-onto-itself", + "profile": "s3", + "lane": "core", + "purpose": "Report a copy of an object onto itself that changes nothing as an error. S3 answers 400 InvalidRequest", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" + ], + "call": { + "key": "object-tests/copy/source.txt", + "op": "copy", + "source_key": "object-tests/copy/source.txt" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/copy/source.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidRequestFixture error" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "HEAD" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/copy/source.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "then": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/copy/source.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidRequestFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-length": "5", + "date": { + "from": "now" + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidRequest" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/copy-onto-itself-replace-metadata", + "profile": "s3", + "lane": "core", + "purpose": "Copy an object onto itself to replace its metadata, which S3 accepts with x-amz-metadata-directive: REPLACE", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" + ], + "call": { + "key": "object-tests/copy/source.txt", + "metadata": { + "colour": "blue" + }, + "op": "copy", + "source_key": "object-tests/copy/source.txt" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/copy/source.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-amz-metadata-directive", + "optional": false, + "rule": { + "is": "equal", + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-meta-colour", + "optional": false, + "rule": { + "is": "equal", + "value": "blue" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "HEAD" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/copy/source.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "then": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/copy/source.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-amz-metadata-directive", + "optional": false, + "rule": { + "is": "equal", + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-meta-colour", + "optional": false, + "rule": { + "is": "equal", + "value": "blue" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } + } + } + ] + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-length": "5", + "date": { + "from": "now" + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-with-unknown-storage-class", + "profile": "s3", + "lane": "core", + "purpose": "Refuse a storage class that S3 does not have", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Zmlyc3Q=", + "key": "object-tests/classes/object.txt", + "op": "put", + "storage_class": "WARM" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/classes/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "Zmlyc3Q=" + } + }, + { + "at": "/headers/x-amz-storage-class", + "optional": false, + "rule": { + "is": "equal", + "value": "WARM" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidStorageClassFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidStorageClass" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-with-storage-class", + "profile": "s3", + "lane": "core", + "purpose": "Write an object into the STANDARD_IA storage class", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Zmlyc3Q=", + "key": "object-tests/classes/object.txt", + "op": "put", + "storage_class": "STANDARD_IA" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/classes/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "Zmlyc3Q=" + } + }, + { + "at": "/headers/x-amz-storage-class", + "optional": false, + "rule": { + "is": "equal", + "value": "STANDARD_IA" + } } ], "allow_headers": [ @@ -137519,7 +139172,448 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/metadata/empty-value.txt" + "value": "/fixture/object-tests/metadata/empty-value.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "MQ==" + } + }, + { + "at": "/headers/x-amz-meta-empty", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-6c30b210f0a8\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-6c30b210f0a8\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-metadata-hyphen-name", + "profile": "s3", + "lane": "core", + "purpose": "put metadata hyphen name", + "sources": [ + "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + ], + "call": { + "body_base64": "MQ==", + "key": "object-tests/metadata/hyphen-name.txt", + "metadata": { + "not-valid": "1" + }, + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/metadata/hyphen-name.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "MQ==" + } + }, + { + "at": "/headers/x-amz-meta-not-valid", + "optional": false, + "rule": { + "is": "equal", + "value": "1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-6c30b210f0a8\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-6c30b210f0a8\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-metadata-names-differ-in-case", + "profile": "s3", + "lane": "core", + "purpose": "S3 matches a metadata name without case. A general-purpose bucket merges two names that differ only in case into one pair, dup: one,two, which does not read back as sent, so refuse the call.", + "sources": [ + "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + ], + "call": { + "body_base64": "MQ==", + "key": "object-tests/metadata/names-differ-in-case.txt", + "metadata": { + "DUP": "two", + "dup": "one" + }, + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/metadata/names-differ-in-case.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "MQ==" + } + }, + { + "at": "/headers/x-amz-meta-dup", + "optional": false, + "rule": { + "is": "one_of", + "values": [ + [ + "one", + "two" + ], + [ + "two", + "one" + ] + ] + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-6c30b210f0a8\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + } + ], + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "metadata" + } + } + ] + }, + { + "id": "operations/s3/put-metadata-punctuation-name", + "profile": "s3", + "lane": "core", + "purpose": "S3 stores a name that holds any character of an HTTP token, and one that starts with a digit.", + "sources": [ + "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + ], + "call": { + "body_base64": "MQ==", + "key": "object-tests/metadata/punctuation-name.txt", + "metadata": { + "1a!#$%&'*+.^_`|~b": "1" + }, + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/metadata/punctuation-name.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "MQ==" + } + }, + { + "at": "/headers/x-amz-meta-1a!#$%&'*+.^_`|~0b", + "optional": false, + "rule": { + "is": "equal", + "value": "1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-6c30b210f0a8\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-6c30b210f0a8\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-metadata-replaced", + "profile": "s3", + "lane": "core", + "purpose": "put metadata replaced", + "sources": [ + "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + ], + "call": { + "body_base64": "Mg==", + "key": "object-tests/metadata/replaced.txt", + "op": "put" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/metadata/replaced.txt" } }, { @@ -137527,15 +139621,7 @@ "optional": false, "rule": { "is": "equal", - "value": "MQ==" - } - }, - { - "at": "/headers/x-amz-meta-empty", - "optional": false, - "rule": { - "is": "equal", - "value": "" + "value": "Mg==" } } ], @@ -137549,7 +139635,7 @@ "date": { "from": "now" }, - "etag": "\"fixture-6c30b210f0a8\"", + "etag": "\"fixture-ea4c238956b1\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { @@ -137575,7 +139661,7 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-6c30b210f0a8\"" + "value": "\"fixture-ea4c238956b1\"" } }, { @@ -137593,18 +139679,19 @@ "refusal": null }, { - "id": "operations/s3/put-metadata-hyphen-name", + "id": "operations/s3/put-metadata", "profile": "s3", "lane": "core", - "purpose": "put metadata hyphen name", + "purpose": "put metadata", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "MQ==", - "key": "object-tests/metadata/hyphen-name.txt", + "key": "object-tests/metadata/object.txt", "metadata": { - "not-valid": "1" + "name": "value", + "second": "2" }, "op": "put" }, @@ -137626,7 +139713,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/metadata/hyphen-name.txt" + "value": "/fixture/object-tests/metadata/object.txt" } }, { @@ -137638,11 +139725,19 @@ } }, { - "at": "/headers/x-amz-meta-not-valid", + "at": "/headers/x-amz-meta-name", "optional": false, "rule": { "is": "equal", - "value": "1" + "value": "value" + } + }, + { + "at": "/headers/x-amz-meta-second", + "optional": false, + "rule": { + "is": "equal", + "value": "2" } } ], @@ -137700,20 +139795,16 @@ "refusal": null }, { - "id": "operations/s3/put-metadata-names-differ-in-case", + "id": "operations/s3/put-overwrite", "profile": "s3", "lane": "core", - "purpose": "S3 matches a metadata name without case. A general-purpose bucket merges two names that differ only in case into one pair, dup: one,two, which does not read back as sent, so refuse the call.", + "purpose": "put overwrite", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "MQ==", - "key": "object-tests/metadata/names-differ-in-case.txt", - "metadata": { - "DUP": "two", - "dup": "one" - }, + "body_base64": "b3ZlcndyaXR0ZW4=", + "key": "object-tests/write/object.txt", "op": "put" }, "exchanges": [ @@ -137734,7 +139825,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/metadata/names-differ-in-case.txt" + "value": "/fixture/object-tests/write/object.txt" } }, { @@ -137742,24 +139833,7 @@ "optional": false, "rule": { "is": "equal", - "value": "MQ==" - } - }, - { - "at": "/headers/x-amz-meta-dup", - "optional": false, - "rule": { - "is": "one_of", - "values": [ - [ - "one", - "two" - ], - [ - "two", - "one" - ] - ] + "value": "b3ZlcndyaXR0ZW4=" } } ], @@ -137773,7 +139847,7 @@ "date": { "from": "now" }, - "etag": "\"fixture-6c30b210f0a8\"", + "etag": "\"fixture-a62b555324ac\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { @@ -137791,51 +139865,43 @@ "optional": false, "rule": { "is": "equal", - "value": "refused" - } - } - ], - "refusal": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "refused" + "value": "ok" } }, { - "at": "/kind", + "at": "/value/etag", "optional": false, "rule": { - "is": "matches", - "pattern": ".+" + "is": "equal", + "value": "\"fixture-a62b555324ac\"" } }, { - "at": "/parameter", - "optional": false, + "at": "/value/version", + "optional": true, "rule": { - "is": "equal", - "value": "metadata" + "is": "one_of", + "values": [ + null, + "" + ] } } - ] + ], + "refusal": null }, { - "id": "operations/s3/put-metadata-punctuation-name", + "id": "operations/s3/put-precondition-failed", "profile": "s3", "lane": "core", - "purpose": "S3 stores a name that holds any character of an HTTP token, and one that starts with a digit.", + "purpose": "put precondition failed", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "MQ==", - "key": "object-tests/metadata/punctuation-name.txt", - "metadata": { - "1a!#$%&'*+.^_`|~b": "1" - }, + "body_base64": "YW5vdGhlciBvYmplY3Q=", + "if_match": "\"fixture-db71b2c0257c\"", + "key": "object-tests/write/object.txt", "op": "put" }, "exchanges": [ @@ -137856,7 +139922,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/metadata/punctuation-name.txt" + "value": "/fixture/object-tests/write/object.txt" } }, { @@ -137864,15 +139930,15 @@ "optional": false, "rule": { "is": "equal", - "value": "MQ==" + "value": "YW5vdGhlciBvYmplY3Q=" } }, { - "at": "/headers/x-amz-meta-1a!#$%&'*+.^_`|~0b", + "at": "/headers/if-match", "optional": false, "rule": { "is": "equal", - "value": "1" + "value": "\"fixture-db71b2c0257c\"" } } ], @@ -137881,18 +139947,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 412, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-6c30b210f0a8\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nPreconditionFailedFixture error" + }, + "framing": "chunked" } } ] @@ -137904,42 +139970,39 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/etag", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-6c30b210f0a8\"" + "value": 412 } }, { - "at": "/value/version", - "optional": true, + "at": "/code", + "optional": false, "rule": { - "is": "one_of", - "values": [ - null, - "" - ] + "is": "equal", + "value": "PreconditionFailed" } } ], "refusal": null }, { - "id": "operations/s3/put-metadata-replaced", + "id": "operations/s3/put-unauthenticated", "profile": "s3", "lane": "core", - "purpose": "put metadata replaced", + "purpose": "Report the service authorization error for this operation; signature acceptance is tested separately.", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "Mg==", - "key": "object-tests/metadata/replaced.txt", + "body_base64": "bm90aGluZyBpcyBzdG9yZWQ=", + "key": "object-tests/write/object.txt", "op": "put" }, "exchanges": [ @@ -137960,7 +140023,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/metadata/replaced.txt" + "value": "/fixture/object-tests/write/object.txt" } }, { @@ -137968,7 +140031,7 @@ "optional": false, "rule": { "is": "equal", - "value": "Mg==" + "value": "bm90aGluZyBpcyBzdG9yZWQ=" } } ], @@ -137977,18 +140040,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 403, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-ea4c238956b1\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nInvalidAccessKeyIdFixture error" + }, + "framing": "chunked" } } ] @@ -138000,47 +140063,42 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/etag", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-ea4c238956b1\"" + "value": 403 } }, { - "at": "/value/version", - "optional": true, + "at": "/code", + "optional": false, "rule": { - "is": "one_of", - "values": [ - null, - "" - ] + "is": "equal", + "value": "InvalidAccessKeyId" } } ], "refusal": null }, { - "id": "operations/s3/put-metadata", + "id": "operations/s3/stage-after-abort", "profile": "s3", "lane": "core", - "purpose": "put metadata", + "purpose": "stage after abort", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "MQ==", - "key": "object-tests/metadata/object.txt", - "metadata": { - "name": "value", - "second": "2" - }, - "op": "put" + "body_base64": "eA==", + "key": "object-tests/multipart/aborted.bin", + "op": "s3.upload_part", + "part_number": 2, + "upload_id": "fixture-upload+/f85cf0cd3a3f=" }, "exchanges": [ { @@ -138060,7 +140118,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/metadata/object.txt" + "value": "/fixture/object-tests/multipart/aborted.bin" } }, { @@ -138068,23 +140126,23 @@ "optional": false, "rule": { "is": "equal", - "value": "MQ==" + "value": "eA==" } }, { - "at": "/headers/x-amz-meta-name", + "at": "/query/partNumber", "optional": false, "rule": { "is": "equal", - "value": "value" + "value": "2" } }, { - "at": "/headers/x-amz-meta-second", + "at": "/query/uploadId", "optional": false, "rule": { "is": "equal", - "value": "2" + "value": "fixture-upload+/f85cf0cd3a3f=" } } ], @@ -138093,18 +140151,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 404, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-6c30b210f0a8\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nNoSuchUploadFixture error" + }, + "framing": "chunked" } } ] @@ -138116,43 +140174,42 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/etag", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-6c30b210f0a8\"" + "value": 404 } }, { - "at": "/value/version", - "optional": true, + "at": "/code", + "optional": false, "rule": { - "is": "one_of", - "values": [ - null, - "" - ] + "is": "equal", + "value": "NoSuchUpload" } } ], "refusal": null }, { - "id": "operations/s3/put-overwrite", + "id": "operations/s3/stage-last", "profile": "s3", "lane": "core", - "purpose": "put overwrite", + "purpose": "stage last", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "b3ZlcndyaXR0ZW4=", - "key": "object-tests/write/object.txt", - "op": "put" + "body_base64": "c2Vjb25k", + "key": "object-tests/multipart/object.bin", + "op": "s3.upload_part", + "part_number": 2, + "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ { @@ -138172,7 +140229,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/write/object.txt" + "value": "/fixture/object-tests/multipart/object.bin" } }, { @@ -138180,7 +140237,23 @@ "optional": false, "rule": { "is": "equal", - "value": "b3ZlcndyaXR0ZW4=" + "value": "c2Vjb25k" + } + }, + { + "at": "/query/partNumber", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/query/uploadId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-upload+/276ca18046f9=" } } ], @@ -138194,7 +140267,7 @@ "date": { "from": "now" }, - "etag": "\"fixture-a62b555324ac\"", + "etag": "\"fixture-32b70ae425ac\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { @@ -138220,36 +140293,26 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-a62b555324ac\"" - } - }, - { - "at": "/value/version", - "optional": true, - "rule": { - "is": "one_of", - "values": [ - null, - "" - ] + "value": "\"fixture-32b70ae425ac\"" } } ], "refusal": null }, { - "id": "operations/s3/put-precondition-failed", + "id": "operations/s3/stage-part-10000", "profile": "s3", "lane": "core", - "purpose": "put precondition failed", + "purpose": "Part numbers run from 1 to 10,000. Stage part 10,000; only 0 and 10,001 may be refused.", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "YW5vdGhlciBvYmplY3Q=", - "if_match": "\"fixture-db71b2c0257c\"", - "key": "object-tests/write/object.txt", - "op": "put" + "body_base64": "c2Vjb25k", + "key": "object-tests/multipart/object.bin", + "op": "s3.upload_part", + "part_number": 10000, + "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ { @@ -138269,7 +140332,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/write/object.txt" + "value": "/fixture/object-tests/multipart/object.bin" } }, { @@ -138277,15 +140340,23 @@ "optional": false, "rule": { "is": "equal", - "value": "YW5vdGhlciBvYmplY3Q=" + "value": "c2Vjb25k" } }, { - "at": "/headers/if-match", + "at": "/query/partNumber", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-db71b2c0257c\"" + "value": "10000" + } + }, + { + "at": "/query/uploadId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-upload+/276ca18046f9=" } } ], @@ -138294,18 +140365,18 @@ ], "allow_query": [], "response": { - "status": 412, + "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" - } + }, + "etag": "\"fixture-32b70ae425ac\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { - "encoding": "utf8", - "data": "\nPreconditionFailedFixture error" - }, - "framing": "chunked" + "encoding": "base64", + "data": "" + } } } ] @@ -138317,40 +140388,34 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 412 + "value": "ok" } }, { - "at": "/code", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": "PreconditionFailed" + "value": "\"fixture-32b70ae425ac\"" } } ], "refusal": null }, { - "id": "operations/s3/put-unauthenticated", + "id": "operations/s3/stage-part-10001", "profile": "s3", "lane": "core", - "purpose": "Report the service authorization error for this operation; signature acceptance is tested separately.", + "purpose": "stage part 10001", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "bm90aGluZyBpcyBzdG9yZWQ=", - "key": "object-tests/write/object.txt", - "op": "put" + "body_base64": "eA==", + "key": "object-tests/multipart/object.bin", + "op": "s3.upload_part", + "part_number": 10001, + "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ { @@ -138370,7 +140435,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/write/object.txt" + "value": "/fixture/object-tests/multipart/object.bin" } }, { @@ -138378,7 +140443,23 @@ "optional": false, "rule": { "is": "equal", - "value": "bm90aGluZyBpcyBzdG9yZWQ=" + "value": "eA==" + } + }, + { + "at": "/query/partNumber", + "optional": false, + "rule": { + "is": "equal", + "value": "10001" + } + }, + { + "at": "/query/uploadId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-upload+/276ca18046f9=" } } ], @@ -138387,7 +140468,7 @@ ], "allow_query": [], "response": { - "status": 403, + "status": 400, "headers": { "content-type": "application/xml", "date": { @@ -138396,7 +140477,7 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidAccessKeyIdFixture error" + "data": "\nInvalidArgumentFixture error" }, "framing": "chunked" } @@ -138418,7 +140499,7 @@ "optional": false, "rule": { "is": "equal", - "value": 403 + "value": 400 } }, { @@ -138426,26 +140507,67 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidAccessKeyId" + "value": "InvalidArgument" } } ], - "refusal": null + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "part_number" + } + }, + { + "at": "/status", + "optional": true, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "InvalidArgument" + } + } + ] }, { - "id": "operations/s3/stage-after-abort", + "id": "operations/s3/stage-part-zero", "profile": "s3", "lane": "core", - "purpose": "stage after abort", + "purpose": "stage part zero", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "eA==", - "key": "object-tests/multipart/aborted.bin", + "key": "object-tests/multipart/object.bin", "op": "s3.upload_part", - "part_number": 2, - "upload_id": "fixture-upload+/f85cf0cd3a3f=" + "part_number": 0, + "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ { @@ -138465,7 +140587,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/multipart/aborted.bin" + "value": "/fixture/object-tests/multipart/object.bin" } }, { @@ -138481,7 +140603,7 @@ "optional": false, "rule": { "is": "equal", - "value": "2" + "value": "0" } }, { @@ -138489,7 +140611,7 @@ "optional": false, "rule": { "is": "equal", - "value": "fixture-upload+/f85cf0cd3a3f=" + "value": "fixture-upload+/276ca18046f9=" } } ], @@ -138498,7 +140620,7 @@ ], "allow_query": [], "response": { - "status": 404, + "status": 400, "headers": { "content-type": "application/xml", "date": { @@ -138507,7 +140629,7 @@ }, "body": { "encoding": "utf8", - "data": "\nNoSuchUploadFixture error" + "data": "\nInvalidArgumentFixture error" }, "framing": "chunked" } @@ -138529,7 +140651,7 @@ "optional": false, "rule": { "is": "equal", - "value": 404 + "value": 400 } }, { @@ -138537,26 +140659,67 @@ "optional": false, "rule": { "is": "equal", - "value": "NoSuchUpload" + "value": "InvalidArgument" } } ], - "refusal": null + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "part_number" + } + }, + { + "at": "/status", + "optional": true, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "InvalidArgument" + } + } + ] }, { - "id": "operations/s3/stage-last", + "id": "operations/s3/stage-unknown-upload", "profile": "s3", "lane": "core", - "purpose": "stage last", + "purpose": "stage unknown upload", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "c2Vjb25k", + "body_base64": "eA==", "key": "object-tests/multipart/object.bin", "op": "s3.upload_part", - "part_number": 2, - "upload_id": "fixture-upload+/276ca18046f9=" + "part_number": 1, + "upload_id": "fixture-upload+/4d0d5ccc4993=" }, "exchanges": [ { @@ -138584,7 +140747,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "eA==" } }, { @@ -138592,7 +140755,7 @@ "optional": false, "rule": { "is": "equal", - "value": "2" + "value": "1" } }, { @@ -138600,7 +140763,7 @@ "optional": false, "rule": { "is": "equal", - "value": "fixture-upload+/276ca18046f9=" + "value": "fixture-upload+/4d0d5ccc4993=" } } ], @@ -138609,18 +140772,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 404, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-32b70ae425ac\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nNoSuchUploadFixture error" + }, + "framing": "chunked" } } ] @@ -138632,33 +140795,41 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/etag", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-32b70ae425ac\"" + "value": 404 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "NoSuchUpload" } } ], "refusal": null }, { - "id": "operations/s3/stage-part-10000", + "id": "operations/s3/stage", "profile": "s3", "lane": "core", - "purpose": "Part numbers run from 1 to 10,000. Stage part 10,000; only 0 and 10,001 may be refused.", + "purpose": "stage", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "c2Vjb25k", + "body_base64": "cGFydA==", "key": "object-tests/multipart/object.bin", "op": "s3.upload_part", - "part_number": 10000, + "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ @@ -138687,7 +140858,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cGFydA==" } }, { @@ -138695,7 +140866,7 @@ "optional": false, "rule": { "is": "equal", - "value": "10000" + "value": "1" } }, { @@ -138717,7 +140888,7 @@ "date": { "from": "now" }, - "etag": "\"fixture-32b70ae425ac\"", + "etag": "\"fixture-6d60d5bbaa47\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { @@ -138743,25 +140914,25 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-32b70ae425ac\"" + "value": "\"fixture-6d60d5bbaa47\"" } } ], "refusal": null }, { - "id": "operations/s3/stage-part-10001", + "id": "operations/s3/stage-key-question", "profile": "s3", "lane": "core", - "purpose": "stage part 10001", + "purpose": "stage, with the key \"question?mark.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "eA==", - "key": "object-tests/multipart/object.bin", + "body_base64": "cGFydA==", + "key": "object-tests/keys/question?mark.txt", "op": "s3.upload_part", - "part_number": 10001, + "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ @@ -138782,7 +140953,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/multipart/object.bin" + "value": "/fixture/object-tests/keys/question?mark.txt" } }, { @@ -138790,7 +140961,7 @@ "optional": false, "rule": { "is": "equal", - "value": "eA==" + "value": "cGFydA==" } }, { @@ -138798,7 +140969,7 @@ "optional": false, "rule": { "is": "equal", - "value": "10001" + "value": "1" } }, { @@ -138815,18 +140986,18 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" - } + }, + "etag": "\"fixture-6d60d5bbaa47\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { - "encoding": "utf8", - "data": "\nInvalidArgumentFixture error" - }, - "framing": "chunked" + "encoding": "base64", + "data": "" + } } } ] @@ -138838,82 +141009,33 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 400 + "value": "ok" } }, { - "at": "/code", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": "InvalidArgument" + "value": "\"fixture-6d60d5bbaa47\"" } } ], - "refusal": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "refused" - } - }, - { - "at": "/kind", - "optional": false, - "rule": { - "is": "matches", - "pattern": ".+" - } - }, - { - "at": "/parameter", - "optional": false, - "rule": { - "is": "equal", - "value": "part_number" - } - }, - { - "at": "/status", - "optional": true, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": true, - "rule": { - "is": "equal", - "value": "InvalidArgument" - } - } - ] + "refusal": null }, { - "id": "operations/s3/stage-part-zero", + "id": "operations/s3/stage-key-hash", "profile": "s3", "lane": "core", - "purpose": "stage part zero", + "purpose": "stage, with the key \"hash#tag.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "eA==", - "key": "object-tests/multipart/object.bin", + "body_base64": "cGFydA==", + "key": "object-tests/keys/hash#tag.txt", "op": "s3.upload_part", - "part_number": 0, + "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ @@ -138934,7 +141056,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/multipart/object.bin" + "value": "/fixture/object-tests/keys/hash#tag.txt" } }, { @@ -138942,7 +141064,7 @@ "optional": false, "rule": { "is": "equal", - "value": "eA==" + "value": "cGFydA==" } }, { @@ -138950,7 +141072,7 @@ "optional": false, "rule": { "is": "equal", - "value": "0" + "value": "1" } }, { @@ -138967,18 +141089,18 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" - } + }, + "etag": "\"fixture-6d60d5bbaa47\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { - "encoding": "utf8", - "data": "\nInvalidArgumentFixture error" - }, - "framing": "chunked" + "encoding": "base64", + "data": "" + } } } ] @@ -138990,83 +141112,34 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 400 + "value": "ok" } }, { - "at": "/code", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": "InvalidArgument" + "value": "\"fixture-6d60d5bbaa47\"" } } ], - "refusal": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "refused" - } - }, - { - "at": "/kind", - "optional": false, - "rule": { - "is": "matches", - "pattern": ".+" - } - }, - { - "at": "/parameter", - "optional": false, - "rule": { - "is": "equal", - "value": "part_number" - } - }, - { - "at": "/status", - "optional": true, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": true, - "rule": { - "is": "equal", - "value": "InvalidArgument" - } - } - ] + "refusal": null }, { - "id": "operations/s3/stage-unknown-upload", + "id": "operations/s3/stage-key-percent", "profile": "s3", "lane": "core", - "purpose": "stage unknown upload", + "purpose": "stage, with the key \"percent%20.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "eA==", - "key": "object-tests/multipart/object.bin", + "body_base64": "cGFydA==", + "key": "object-tests/keys/percent%20.txt", "op": "s3.upload_part", "part_number": 1, - "upload_id": "fixture-upload+/4d0d5ccc4993=" + "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ { @@ -139086,7 +141159,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/multipart/object.bin" + "value": "/fixture/object-tests/keys/percent%20.txt" } }, { @@ -139094,7 +141167,7 @@ "optional": false, "rule": { "is": "equal", - "value": "eA==" + "value": "cGFydA==" } }, { @@ -139110,7 +141183,7 @@ "optional": false, "rule": { "is": "equal", - "value": "fixture-upload+/4d0d5ccc4993=" + "value": "fixture-upload+/276ca18046f9=" } } ], @@ -139119,18 +141192,18 @@ ], "allow_query": [], "response": { - "status": 404, + "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" - } + }, + "etag": "\"fixture-6d60d5bbaa47\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { - "encoding": "utf8", - "data": "\nNoSuchUploadFixture error" - }, - "framing": "chunked" + "encoding": "base64", + "data": "" + } } } ] @@ -139142,39 +141215,31 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 404 + "value": "ok" } }, { - "at": "/code", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": "NoSuchUpload" + "value": "\"fixture-6d60d5bbaa47\"" } } ], "refusal": null }, { - "id": "operations/s3/stage", + "id": "operations/s3/stage-key-plus", "profile": "s3", "lane": "core", - "purpose": "stage", + "purpose": "stage, with the key \"plus+plus.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/multipart/object.bin", + "key": "object-tests/keys/plus+plus.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" @@ -139197,7 +141262,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/multipart/object.bin" + "value": "/fixture/object-tests/keys/plus+plus.txt" } }, { @@ -139268,16 +141333,16 @@ "refusal": null }, { - "id": "operations/s3/stage-key-question", + "id": "operations/s3/stage-key-space", "profile": "s3", "lane": "core", - "purpose": "stage, with the key \"question?mark.txt\"", + "purpose": "stage, with the key \"space name.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/question?mark.txt", + "key": "object-tests/keys/space name.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" @@ -139300,7 +141365,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/keys/question?mark.txt" + "value": "/fixture/object-tests/keys/space name.txt" } }, { @@ -139371,16 +141436,16 @@ "refusal": null }, { - "id": "operations/s3/stage-key-hash", + "id": "operations/s3/stage-key-non-ascii", "profile": "s3", "lane": "core", - "purpose": "stage, with the key \"hash#tag.txt\"", + "purpose": "stage, with the key \"café/雪.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/hash#tag.txt", + "key": "object-tests/keys/café/雪.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" @@ -139403,7 +141468,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/keys/hash#tag.txt" + "value": "/fixture/object-tests/keys/café/雪.txt" } }, { @@ -139474,16 +141539,16 @@ "refusal": null }, { - "id": "operations/s3/stage-key-percent", + "id": "operations/s3/stage-key-double-slash", "profile": "s3", "lane": "core", - "purpose": "stage, with the key \"percent%20.txt\"", + "purpose": "stage, with the key \"double//slash.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/percent%20.txt", + "key": "object-tests/keys/double//slash.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" @@ -139506,7 +141571,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/keys/percent%20.txt" + "value": "/fixture/object-tests/keys/double//slash.txt" } }, { @@ -139577,16 +141642,16 @@ "refusal": null }, { - "id": "operations/s3/stage-key-plus", + "id": "operations/s3/stage-key-trailing-slash", "profile": "s3", "lane": "core", - "purpose": "stage, with the key \"plus+plus.txt\"", + "purpose": "stage, with the key \"trailing-slash/\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/plus+plus.txt", + "key": "object-tests/keys/trailing-slash/", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" @@ -139609,7 +141674,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/keys/plus+plus.txt" + "value": "/fixture/object-tests/keys/trailing-slash/" } }, { @@ -139680,16 +141745,16 @@ "refusal": null }, { - "id": "operations/s3/stage-key-space", + "id": "operations/s3/stage-empty-part", "profile": "s3", "lane": "core", - "purpose": "stage, with the key \"space name.txt\"", + "purpose": "Stage an empty part, which S3 takes", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "cGFydA==", - "key": "object-tests/keys/space name.txt", + "body_base64": "", + "key": "object-tests/multipart/object.bin", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/276ca18046f9=" @@ -139712,7 +141777,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/keys/space name.txt" + "value": "/fixture/object-tests/multipart/object.bin" } }, { @@ -139720,7 +141785,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cGFydA==" + "value": "" } }, { @@ -139783,18 +141848,18 @@ "refusal": null }, { - "id": "operations/s3/stage-key-non-ascii", + "id": "operations/s3/stage-copy", "profile": "s3", "lane": "core", - "purpose": "stage, with the key \"café/雪.txt\"", + "purpose": "Copy a whole object into a part of a multipart upload, with UploadPartCopy", "sources": [ - "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" ], "call": { - "body_base64": "cGFydA==", - "key": "object-tests/keys/café/雪.txt", - "op": "s3.upload_part", + "key": "object-tests/multipart/object.bin", + "op": "s3.upload_part_copy", "part_number": 1, + "source_key": "object-tests/copy/source.txt", "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ @@ -139815,7 +141880,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/keys/café/雪.txt" + "value": "/fixture/object-tests/multipart/object.bin" } }, { @@ -139823,7 +141888,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cGFydA==" + "value": "" } }, { @@ -139841,108 +141906,13 @@ "is": "equal", "value": "fixture-upload+/276ca18046f9=" } - } - ], - "allow_headers": [ - "content-type" - ], - "allow_query": [], - "response": { - "status": 200, - "headers": { - "date": { - "from": "now" - }, - "etag": "\"fixture-6d60d5bbaa47\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" - }, - "body": { - "encoding": "base64", - "data": "" - } - } - } - ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "ok" - } - }, - { - "at": "/value/etag", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-6d60d5bbaa47\"" - } - } - ], - "refusal": null - }, - { - "id": "operations/s3/stage-key-double-slash", - "profile": "s3", - "lane": "core", - "purpose": "stage, with the key \"double//slash.txt\"", - "sources": [ - "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" - ], - "call": { - "body_base64": "cGFydA==", - "key": "object-tests/keys/double//slash.txt", - "op": "s3.upload_part", - "part_number": 1, - "upload_id": "fixture-upload+/276ca18046f9=" - }, - "exchanges": [ - { - "alternatives": [ - { - "request": [ - { - "at": "/method", - "optional": false, - "rule": { - "is": "equal", - "value": "PUT" - } }, { - "at": "/path", - "optional": false, - "rule": { - "is": "equal", - "value": "/fixture/object-tests/keys/double//slash.txt" - } - }, - { - "at": "/body_base64", - "optional": false, - "rule": { - "is": "equal", - "value": "cGFydA==" - } - }, - { - "at": "/query/partNumber", - "optional": false, - "rule": { - "is": "equal", - "value": "1" - } - }, - { - "at": "/query/uploadId", + "at": "/headers/x-amz-copy-source", "optional": false, "rule": { - "is": "equal", - "value": "fixture-upload+/276ca18046f9=" + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } } ], @@ -139953,118 +141923,14 @@ "response": { "status": 200, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-6d60d5bbaa47\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" - }, - "body": { - "encoding": "base64", - "data": "" - } - } - } - ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "ok" - } - }, - { - "at": "/value/etag", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-6d60d5bbaa47\"" - } - } - ], - "refusal": null - }, - { - "id": "operations/s3/stage-key-trailing-slash", - "profile": "s3", - "lane": "core", - "purpose": "stage, with the key \"trailing-slash/\"", - "sources": [ - "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" - ], - "call": { - "body_base64": "cGFydA==", - "key": "object-tests/keys/trailing-slash/", - "op": "s3.upload_part", - "part_number": 1, - "upload_id": "fixture-upload+/276ca18046f9=" - }, - "exchanges": [ - { - "alternatives": [ - { - "request": [ - { - "at": "/method", - "optional": false, - "rule": { - "is": "equal", - "value": "PUT" - } - }, - { - "at": "/path", - "optional": false, - "rule": { - "is": "equal", - "value": "/fixture/object-tests/keys/trailing-slash/" } }, - { - "at": "/body_base64", - "optional": false, - "rule": { - "is": "equal", - "value": "cGFydA==" - } - }, - { - "at": "/query/partNumber", - "optional": false, - "rule": { - "is": "equal", - "value": "1" - } - }, - { - "at": "/query/uploadId", - "optional": false, - "rule": { - "is": "equal", - "value": "fixture-upload+/276ca18046f9=" - } - } - ], - "allow_headers": [ - "content-type" - ], - "allow_query": [], - "response": { - "status": 200, - "headers": { - "date": { - "from": "now" - }, - "etag": "\"fixture-6d60d5bbaa47\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" - }, "body": { - "encoding": "base64", - "data": "" + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" } } } @@ -140085,25 +141951,29 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-6d60d5bbaa47\"" + "value": "\"fixture-etag\"" } } ], "refusal": null }, { - "id": "operations/s3/stage-empty-part", + "id": "operations/s3/stage-copy-range", "profile": "s3", "lane": "core", - "purpose": "Stage an empty part, which S3 takes", + "purpose": "Copy bytes 0 to 2 of an object into a part, named in x-amz-copy-source-range with an inclusive end, as bytes=0-2", "sources": [ - "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" ], "call": { - "body_base64": "", "key": "object-tests/multipart/object.bin", - "op": "s3.upload_part", + "op": "s3.upload_part_copy", "part_number": 1, + "source_key": "object-tests/copy/source.txt", + "source_range": { + "end": 3, + "start": 0 + }, "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ @@ -140150,116 +142020,21 @@ "is": "equal", "value": "fixture-upload+/276ca18046f9=" } - } - ], - "allow_headers": [ - "content-type" - ], - "allow_query": [], - "response": { - "status": 200, - "headers": { - "date": { - "from": "now" - }, - "etag": "\"fixture-6d60d5bbaa47\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" - }, - "body": { - "encoding": "base64", - "data": "" - } - } - } - ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "ok" - } - }, - { - "at": "/value/etag", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-6d60d5bbaa47\"" - } - } - ], - "refusal": null - }, - { - "id": "operations/s3/stage-copy", - "profile": "s3", - "lane": "core", - "purpose": "Copy a whole object into a part of a multipart upload, with UploadPartCopy", - "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" - ], - "call": { - "key": "object-tests/multipart/object.bin", - "op": "s3.upload_part_copy", - "part_number": 1, - "source_key": "object-tests/copy/source.txt", - "upload_id": "fixture-upload+/276ca18046f9=" - }, - "exchanges": [ - { - "alternatives": [ - { - "request": [ - { - "at": "/method", - "optional": false, - "rule": { - "is": "equal", - "value": "PUT" - } - }, - { - "at": "/path", - "optional": false, - "rule": { - "is": "equal", - "value": "/fixture/object-tests/multipart/object.bin" - } - }, - { - "at": "/body_base64", - "optional": false, - "rule": { - "is": "equal", - "value": "" - } }, { - "at": "/query/partNumber", + "at": "/headers/x-amz-copy-source", "optional": false, "rule": { - "is": "equal", - "value": "1" + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } }, { - "at": "/query/uploadId", + "at": "/headers/x-amz-copy-source-range", "optional": false, "rule": { "is": "equal", - "value": "fixture-upload+/276ca18046f9=" - } - }, - { - "at": "/headers/x-amz-copy-source", - "optional": false, - "rule": { - "is": "matches", - "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + "value": "bytes=0-2" } } ], @@ -140305,10 +142080,10 @@ "refusal": null }, { - "id": "operations/s3/stage-copy-range", + "id": "operations/s3/stage-copy-range-beyond-source", "profile": "s3", "lane": "core", - "purpose": "Copy bytes 0 to 2 of an object into a part, named in x-amz-copy-source-range with an inclusive end, as bytes=0-2", + "purpose": "Report a part copy whose range ends past the source as an error. S3 answers 400 InvalidArgument", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" ], @@ -140318,7 +142093,7 @@ "part_number": 1, "source_key": "object-tests/copy/source.txt", "source_range": { - "end": 3, + "end": 10, "start": 0 }, "upload_id": "fixture-upload+/276ca18046f9=" @@ -140381,7 +142156,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=0-2" + "value": "bytes=0-9" } } ], @@ -140390,7 +142165,7 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 400, "headers": { "content-type": "application/xml", "date": { @@ -140399,8 +142174,9 @@ }, "body": { "encoding": "utf8", - "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" - } + "data": "\nInvalidArgumentFixture error" + }, + "framing": "chunked" } } ] @@ -140412,37 +142188,44 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/etag", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-etag\"" + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidArgument" } } ], "refusal": null }, { - "id": "operations/s3/stage-copy-range-beyond-source", + "id": "operations/s3/stage-copy-200-internal-error", "profile": "s3", "lane": "core", - "purpose": "Report a part copy whose range ends past the source as an error. S3 answers 400 InvalidArgument", + "purpose": "Report a part copy answered 200 with an InternalError in the body as an error, never as a success. A client may retry up to 5 times first, and need not retry", "sources": [ + "https://repost.aws/knowledge-center/s3-resolve-200-internalerror", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" ], + "origin": "transient", + "derived_from": "operations/s3/stage-copy", "call": { "key": "object-tests/multipart/object.bin", "op": "s3.upload_part_copy", "part_number": 1, "source_key": "object-tests/copy/source.txt", - "source_range": { - "end": 10, - "start": 0 - }, "upload_id": "fixture-upload+/276ca18046f9=" }, "exchanges": [ @@ -140497,14 +142280,6 @@ "is": "matches", "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } - }, - { - "at": "/headers/x-amz-copy-source-range", - "optional": false, - "rule": { - "is": "equal", - "value": "bytes=0-9" - } } ], "allow_headers": [ @@ -140512,7 +142287,7 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -140521,61 +142296,13 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidArgumentFixture error" + "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" }, "framing": "chunked" } } ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "error" - } }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": false, - "rule": { - "is": "equal", - "value": "InvalidArgument" - } - } - ], - "refusal": null - }, - { - "id": "operations/s3/stage-copy-200-internal-error", - "profile": "s3", - "lane": "core", - "purpose": "Report a part copy answered 200 with an InternalError in the body as an error, never as a success. A client may retry up to 5 times first, and need not retry", - "sources": [ - "https://repost.aws/knowledge-center/s3-resolve-200-internalerror", - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" - ], - "origin": "transient", - "derived_from": "operations/s3/stage-copy", - "call": { - "key": "object-tests/multipart/object.bin", - "op": "s3.upload_part_copy", - "part_number": 1, - "source_key": "object-tests/copy/source.txt", - "upload_id": "fixture-upload+/276ca18046f9=" - }, - "exchanges": [ { "alternatives": [ { @@ -140648,7 +142375,8 @@ "framing": "chunked" } } - ] + ], + "optional": true }, { "alternatives": [ @@ -140949,7 +142677,45 @@ } ], "optional": true + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InternalError" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/stage-copy-source-if-match-failed", + "profile": "s3", + "lane": "core", + "purpose": "Report a part copy whose source does not have the ETag in x-amz-copy-source-if-match as a failed condition, 412 PreconditionFailed, of kind precondition", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" + ], + "call": { + "key": "object-tests/multipart/object.bin", + "op": "s3.upload_part_copy", + "part_number": 1, + "source_if_match": "\"fixture-0123456789ab\"", + "source_key": "object-tests/copy/source.txt", + "upload_id": "fixture-upload+/276ca18046f9=" + }, + "exchanges": [ { "alternatives": [ { @@ -141001,6 +142767,14 @@ "is": "matches", "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } + }, + { + "at": "/headers/x-amz-copy-source-if-match", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-0123456789ab\"" + } } ], "allow_headers": [ @@ -141008,7 +142782,7 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 412, "headers": { "content-type": "application/xml", "date": { @@ -141017,13 +142791,12 @@ }, "body": { "encoding": "utf8", - "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" + "data": "\nPreconditionFailedFixture error" }, "framing": "chunked" } } - ], - "optional": true + ] } ], "expect": [ @@ -141035,12 +142808,28 @@ "value": "error" } }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 412 + } + }, { "at": "/code", "optional": false, "rule": { "is": "equal", - "value": "InternalError" + "value": "PreconditionFailed" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "equal", + "value": "precondition" } } ], @@ -194161,22 +195950,610 @@ "is": "equal", "value": "REPLACE" } - }, - { - "at": "/headers/x-amz-meta-colour", - "optional": false, - "rule": { - "is": "equal", - "value": "blue" - } - }, - { - "at": "/headers/content-type", - "optional": false, - "rule": { - "is": "equal", - "value": "text/plain" - } + }, + { + "at": "/headers/x-amz-meta-colour", + "optional": false, + "rule": { + "is": "equal", + "value": "blue" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "equal", + "value": "text/plain" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "HEAD" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/copy/source.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + } + ], + "then": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/copy/target.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + }, + { + "at": "/headers/x-amz-metadata-directive", + "optional": false, + "rule": { + "is": "equal", + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-meta-colour", + "optional": false, + "rule": { + "is": "equal", + "value": "blue" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "equal", + "value": "text/plain" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + }, + "framing": "chunked" + } + } + ] + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-length": "5", + "date": { + "from": "now" + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3-express/copy-replace-metadata-only", + "profile": "s3-express", + "lane": "core", + "purpose": "Copy an object with new metadata and no content type. x-amz-metadata-directive: REPLACE replaces the content properties too: S3 gives the copy binary/octet-stream, not the source's content type, unless the caller names one", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" + ], + "call": { + "key": "object-tests/copy/target.txt", + "metadata": { + "colour": "blue" + }, + "op": "copy", + "source_key": "object-tests/copy/source.txt" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/copy/target.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + }, + { + "at": "/headers/x-amz-metadata-directive", + "optional": false, + "rule": { + "is": "equal", + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-meta-colour", + "optional": false, + "rule": { + "is": "equal", + "value": "blue" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "HEAD" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/copy/source.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + } + ], + "then": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/copy/target.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + }, + { + "at": "/headers/x-amz-metadata-directive", + "optional": false, + "rule": { + "is": "equal", + "value": "REPLACE" + } + }, + { + "at": "/headers/x-amz-meta-colour", + "optional": false, + "rule": { + "is": "equal", + "value": "blue" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + }, + "framing": "chunked" + } + } + ] + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-length": "5", + "date": { + "from": "now" + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3-express/copy-clear-metadata", + "profile": "s3-express", + "lane": "core", + "purpose": "Copy an object with no metadata in place of the source's: x-amz-metadata-directive: REPLACE with no x-amz-meta- header. A client API that cannot say no metadata may refuse or decline the call", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" + ], + "call": { + "key": "object-tests/copy/target.txt", + "metadata": {}, + "op": "copy", + "source_key": "object-tests/copy/source.txt" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/copy/target.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + }, + { + "at": "/headers/x-amz-metadata-directive", + "optional": false, + "rule": { + "is": "equal", + "value": "REPLACE" + } } ], "allow_headers": [ @@ -194315,22 +196692,6 @@ "is": "equal", "value": "REPLACE" } - }, - { - "at": "/headers/x-amz-meta-colour", - "optional": false, - "rule": { - "is": "equal", - "value": "blue" - } - }, - { - "at": "/headers/content-type", - "optional": false, - "rule": { - "is": "equal", - "value": "text/plain" - } } ], "allow_headers": [ @@ -194387,7 +196748,33 @@ } } ], - "refusal": null + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "metadata" + } + } + ], + "decline_permitted": true }, { "id": "operations/s3-express/copy-source-if-match", @@ -207487,16 +209874,225 @@ ], "allow_query": [], "response": { - "status": 404, + "status": 404, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nNoSuchUploadFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 404 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "NoSuchUpload" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3-express/stage", + "profile": "s3-express", + "lane": "core", + "purpose": "stage", + "sources": [ + "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + ], + "call": { + "body_base64": "cGFydA==", + "key": "object-tests/multipart/object.bin", + "op": "s3.upload_part", + "part_number": 1, + "upload_id": "fixture-upload+/c60fb1e2e00d=" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/" + } + }, + { + "at": "/query/session", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml" + }, + "body": { + "encoding": "utf8", + "data": "\nfixture-session-tokenfixture-secret-keyfixture-access-keySESSION_EXPIRATION" + }, + "body_time": { + "text": "SESSION_EXPIRATION", + "offset_seconds": 300 + } + } + } + ] + }, + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/object-tests/multipart/object.bin" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "cGFydA==" + } + }, + { + "at": "/query/partNumber", + "optional": false, + "rule": { + "is": "equal", + "value": "1" + } + }, + { + "at": "/query/uploadId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-upload+/c60fb1e2e00d=" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-session-token" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=fixture-access-key/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" - } + }, + "etag": "\"fixture-9aff617fcdf8\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { - "encoding": "utf8", - "data": "\nNoSuchUploadFixture error" + "encoding": "base64", + "data": "" }, "framing": "chunked" } @@ -207510,39 +210106,31 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 404 + "value": "ok" } }, { - "at": "/code", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": "NoSuchUpload" + "value": "\"fixture-9aff617fcdf8\"" } } ], "refusal": null }, { - "id": "operations/s3-express/stage", + "id": "operations/s3-express/stage-key-question", "profile": "s3-express", "lane": "core", - "purpose": "stage", + "purpose": "stage, with the key \"question?mark.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/multipart/object.bin", + "key": "object-tests/keys/question?mark.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -207638,7 +210226,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/multipart/object.bin" + "value": "/object-tests/keys/question?mark.txt" } }, { @@ -207734,16 +210322,16 @@ "refusal": null }, { - "id": "operations/s3-express/stage-key-question", + "id": "operations/s3-express/stage-key-hash", "profile": "s3-express", "lane": "core", - "purpose": "stage, with the key \"question?mark.txt\"", + "purpose": "stage, with the key \"hash#tag.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/question?mark.txt", + "key": "object-tests/keys/hash#tag.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -207839,7 +210427,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/question?mark.txt" + "value": "/object-tests/keys/hash#tag.txt" } }, { @@ -207935,16 +210523,16 @@ "refusal": null }, { - "id": "operations/s3-express/stage-key-hash", + "id": "operations/s3-express/stage-key-percent", "profile": "s3-express", "lane": "core", - "purpose": "stage, with the key \"hash#tag.txt\"", + "purpose": "stage, with the key \"percent%20.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/hash#tag.txt", + "key": "object-tests/keys/percent%20.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -208040,7 +210628,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/hash#tag.txt" + "value": "/object-tests/keys/percent%20.txt" } }, { @@ -208136,16 +210724,16 @@ "refusal": null }, { - "id": "operations/s3-express/stage-key-percent", + "id": "operations/s3-express/stage-key-plus", "profile": "s3-express", "lane": "core", - "purpose": "stage, with the key \"percent%20.txt\"", + "purpose": "stage, with the key \"plus+plus.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/percent%20.txt", + "key": "object-tests/keys/plus+plus.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -208241,7 +210829,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/percent%20.txt" + "value": "/object-tests/keys/plus+plus.txt" } }, { @@ -208337,16 +210925,16 @@ "refusal": null }, { - "id": "operations/s3-express/stage-key-plus", + "id": "operations/s3-express/stage-key-space", "profile": "s3-express", "lane": "core", - "purpose": "stage, with the key \"plus+plus.txt\"", + "purpose": "stage, with the key \"space name.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/plus+plus.txt", + "key": "object-tests/keys/space name.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -208442,7 +211030,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/plus+plus.txt" + "value": "/object-tests/keys/space name.txt" } }, { @@ -208538,16 +211126,16 @@ "refusal": null }, { - "id": "operations/s3-express/stage-key-space", + "id": "operations/s3-express/stage-key-non-ascii", "profile": "s3-express", "lane": "core", - "purpose": "stage, with the key \"space name.txt\"", + "purpose": "stage, with the key \"café/雪.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/space name.txt", + "key": "object-tests/keys/café/雪.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -208643,7 +211231,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/space name.txt" + "value": "/object-tests/keys/café/雪.txt" } }, { @@ -208739,16 +211327,16 @@ "refusal": null }, { - "id": "operations/s3-express/stage-key-non-ascii", + "id": "operations/s3-express/stage-key-double-slash", "profile": "s3-express", "lane": "core", - "purpose": "stage, with the key \"café/雪.txt\"", + "purpose": "stage, with the key \"double//slash.txt\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/café/雪.txt", + "key": "object-tests/keys/double//slash.txt", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -208844,7 +211432,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/café/雪.txt" + "value": "/object-tests/keys/double//slash.txt" } }, { @@ -208940,16 +211528,16 @@ "refusal": null }, { - "id": "operations/s3-express/stage-key-double-slash", + "id": "operations/s3-express/stage-key-trailing-slash", "profile": "s3-express", "lane": "core", - "purpose": "stage, with the key \"double//slash.txt\"", + "purpose": "stage, with the key \"trailing-slash/\"", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { "body_base64": "cGFydA==", - "key": "object-tests/keys/double//slash.txt", + "key": "object-tests/keys/trailing-slash/", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -209045,7 +211633,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/double//slash.txt" + "value": "/object-tests/keys/trailing-slash/" } }, { @@ -209141,16 +211729,16 @@ "refusal": null }, { - "id": "operations/s3-express/stage-key-trailing-slash", + "id": "operations/s3-express/stage-empty-part", "profile": "s3-express", "lane": "core", - "purpose": "stage, with the key \"trailing-slash/\"", + "purpose": "Stage an empty part, which S3 takes", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "body_base64": "cGFydA==", - "key": "object-tests/keys/trailing-slash/", + "body_base64": "", + "key": "object-tests/multipart/object.bin", "op": "s3.upload_part", "part_number": 1, "upload_id": "fixture-upload+/c60fb1e2e00d=" @@ -209246,7 +211834,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/trailing-slash/" + "value": "/object-tests/multipart/object.bin" } }, { @@ -209254,7 +211842,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cGFydA==" + "value": "" } }, { @@ -209342,18 +211930,18 @@ "refusal": null }, { - "id": "operations/s3-express/stage-empty-part", + "id": "operations/s3-express/stage-copy", "profile": "s3-express", "lane": "core", - "purpose": "Stage an empty part, which S3 takes", + "purpose": "Copy a whole object into a part of a multipart upload, with UploadPartCopy", "sources": [ - "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" ], "call": { - "body_base64": "", "key": "object-tests/multipart/object.bin", - "op": "s3.upload_part", + "op": "s3.upload_part_copy", "part_number": 1, + "source_key": "object-tests/copy/source.txt", "upload_id": "fixture-upload+/c60fb1e2e00d=" }, "exchanges": [ @@ -209366,7 +211954,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -209374,17 +211962,33 @@ "optional": false, "rule": { "is": "equal", - "value": "/" + "value": "/object-tests/multipart/object.bin" } }, { - "at": "/query/session", + "at": "/body_base64", "optional": false, "rule": { "is": "equal", "value": "" } }, + { + "at": "/query/partNumber", + "optional": false, + "rule": { + "is": "equal", + "value": "1" + } + }, + { + "at": "/query/uploadId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-upload+/c60fb1e2e00d=" + } + }, { "at": "/headers/host", "optional": false, @@ -209393,6 +211997,13 @@ "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" } }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + }, { "at": "/headers/authorization", "optional": false, @@ -209402,10 +212013,11 @@ } }, { - "at": "/headers/x-amz-s3session-token", + "at": "/headers/x-amz-copy-source", "optional": false, "rule": { - "is": "absent" + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } } ], @@ -209416,20 +212028,61 @@ "response": { "status": 200, "headers": { - "content-type": "application/xml" + "content-type": "application/xml", + "date": { + "from": "now" + } }, "body": { "encoding": "utf8", - "data": "\nfixture-session-tokenfixture-secret-keyfixture-access-keySESSION_EXPIRATION" + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" }, - "body_time": { - "text": "SESSION_EXPIRATION", - "offset_seconds": 300 - } + "framing": "chunked" } } ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-etag\"" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3-express/stage-copy-range", + "profile": "s3-express", + "lane": "core", + "purpose": "Copy bytes 0 to 2 of an object into a part, named in x-amz-copy-source-range with an inclusive end, as bytes=0-2", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" + ], + "call": { + "key": "object-tests/multipart/object.bin", + "op": "s3.upload_part_copy", + "part_number": 1, + "source_key": "object-tests/copy/source.txt", + "source_range": { + "end": 3, + "start": 0 }, + "upload_id": "fixture-upload+/c60fb1e2e00d=" + }, + "exchanges": [ { "alternatives": [ { @@ -209486,8 +212139,7 @@ "at": "/headers/x-amz-s3session-token", "optional": false, "rule": { - "is": "equal", - "value": "fixture-session-token" + "is": "absent" } }, { @@ -209495,7 +212147,23 @@ "optional": false, "rule": { "is": "matches", - "pattern": "AWS4-HMAC-SHA256 Credential=fixture-access-key/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-copy-source", + "optional": false, + "rule": { + "is": "matches", + "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + } + }, + { + "at": "/headers/x-amz-copy-source-range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes=0-2" } } ], @@ -209506,15 +212174,14 @@ "response": { "status": 200, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-9aff617fcdf8\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + } }, "body": { - "encoding": "base64", - "data": "" + "encoding": "utf8", + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" }, "framing": "chunked" } @@ -209536,17 +212203,17 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-9aff617fcdf8\"" + "value": "\"fixture-etag\"" } } ], "refusal": null }, { - "id": "operations/s3-express/stage-copy", + "id": "operations/s3-express/stage-copy-range-beyond-source", "profile": "s3-express", "lane": "core", - "purpose": "Copy a whole object into a part of a multipart upload, with UploadPartCopy", + "purpose": "Copy a part whose range ends past the source. A directory bucket accepts it, where a general-purpose bucket answers 400 InvalidArgument", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" ], @@ -209555,6 +212222,10 @@ "op": "s3.upload_part_copy", "part_number": 1, "source_key": "object-tests/copy/source.txt", + "source_range": { + "end": 10, + "start": 0 + }, "upload_id": "fixture-upload+/c60fb1e2e00d=" }, "exchanges": [ @@ -209632,6 +212303,14 @@ "is": "matches", "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } + }, + { + "at": "/headers/x-amz-copy-source-range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes=0-9" + } } ], "allow_headers": [ @@ -209677,22 +212356,21 @@ "refusal": null }, { - "id": "operations/s3-express/stage-copy-range", + "id": "operations/s3-express/stage-copy-200-internal-error", "profile": "s3-express", "lane": "core", - "purpose": "Copy bytes 0 to 2 of an object into a part, named in x-amz-copy-source-range with an inclusive end, as bytes=0-2", + "purpose": "Report a part copy answered 200 with an InternalError in the body as an error, never as a success. A client may retry up to 5 times first, and need not retry", "sources": [ + "https://repost.aws/knowledge-center/s3-resolve-200-internalerror", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" ], + "origin": "transient", + "derived_from": "operations/s3-express/stage-copy", "call": { "key": "object-tests/multipart/object.bin", "op": "s3.upload_part_copy", "part_number": 1, "source_key": "object-tests/copy/source.txt", - "source_range": { - "end": 3, - "start": 0 - }, "upload_id": "fixture-upload+/c60fb1e2e00d=" }, "exchanges": [ @@ -209770,14 +212448,6 @@ "is": "matches", "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } - }, - { - "at": "/headers/x-amz-copy-source-range", - "optional": false, - "rule": { - "is": "equal", - "value": "bytes=0-2" - } } ], "allow_headers": [ @@ -209794,54 +212464,13 @@ }, "body": { "encoding": "utf8", - "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" }, "framing": "chunked" } } ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "ok" - } - }, - { - "at": "/value/etag", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-etag\"" - } - } - ], - "refusal": null - }, - { - "id": "operations/s3-express/stage-copy-range-beyond-source", - "profile": "s3-express", - "lane": "core", - "purpose": "Copy a part whose range ends past the source. A directory bucket accepts it, where a general-purpose bucket answers 400 InvalidArgument", - "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" - ], - "call": { - "key": "object-tests/multipart/object.bin", - "op": "s3.upload_part_copy", - "part_number": 1, - "source_key": "object-tests/copy/source.txt", - "source_range": { - "end": 10, - "start": 0 }, - "upload_id": "fixture-upload+/c60fb1e2e00d=" - }, - "exchanges": [ { "alternatives": [ { @@ -209916,14 +212545,6 @@ "is": "matches", "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } - }, - { - "at": "/headers/x-amz-copy-source-range", - "optional": false, - "rule": { - "is": "equal", - "value": "bytes=0-9" - } } ], "allow_headers": [ @@ -209940,53 +212561,14 @@ }, "body": { "encoding": "utf8", - "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" }, "framing": "chunked" } } - ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "ok" - } + ], + "optional": true }, - { - "at": "/value/etag", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-etag\"" - } - } - ], - "refusal": null - }, - { - "id": "operations/s3-express/stage-copy-200-internal-error", - "profile": "s3-express", - "lane": "core", - "purpose": "Report a part copy answered 200 with an InternalError in the body as an error, never as a success. A client may retry up to 5 times first, and need not retry", - "sources": [ - "https://repost.aws/knowledge-center/s3-resolve-200-internalerror", - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" - ], - "origin": "transient", - "derived_from": "operations/s3-express/stage-copy", - "call": { - "key": "object-tests/multipart/object.bin", - "op": "s3.upload_part_copy", - "part_number": 1, - "source_key": "object-tests/copy/source.txt", - "upload_id": "fixture-upload+/c60fb1e2e00d=" - }, - "exchanges": [ { "alternatives": [ { @@ -210082,7 +212664,8 @@ "framing": "chunked" } } - ] + ], + "optional": true }, { "alternatives": [ @@ -210377,7 +212960,45 @@ } ], "optional": true + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InternalError" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3-express/stage-copy-source-if-match-failed", + "profile": "s3-express", + "lane": "core", + "purpose": "Report a part copy whose source does not have the ETag in x-amz-copy-source-if-match as a failed condition, 412 PreconditionFailed, of kind precondition", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html" + ], + "call": { + "key": "object-tests/multipart/object.bin", + "op": "s3.upload_part_copy", + "part_number": 1, + "source_if_match": "\"fixture-0123456789ab\"", + "source_key": "object-tests/copy/source.txt", + "upload_id": "fixture-upload+/c60fb1e2e00d=" + }, + "exchanges": [ { "alternatives": [ { @@ -210452,103 +213073,13 @@ "is": "matches", "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" } - } - ], - "allow_headers": [ - "content-type" - ], - "allow_query": [], - "response": { - "status": 200, - "headers": { - "content-type": "application/xml", - "date": { - "from": "now" - } - }, - "body": { - "encoding": "utf8", - "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" - }, - "framing": "chunked" - } - } - ], - "optional": true - }, - { - "alternatives": [ - { - "request": [ - { - "at": "/method", - "optional": false, - "rule": { - "is": "equal", - "value": "PUT" - } - }, - { - "at": "/path", - "optional": false, - "rule": { - "is": "equal", - "value": "/object-tests/multipart/object.bin" - } - }, - { - "at": "/body_base64", - "optional": false, - "rule": { - "is": "equal", - "value": "" - } - }, - { - "at": "/query/partNumber", - "optional": false, - "rule": { - "is": "equal", - "value": "1" - } }, { - "at": "/query/uploadId", - "optional": false, - "rule": { - "is": "equal", - "value": "fixture-upload+/c60fb1e2e00d=" - } - }, - { - "at": "/headers/host", + "at": "/headers/x-amz-copy-source-if-match", "optional": false, "rule": { "is": "equal", - "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" - } - }, - { - "at": "/headers/x-amz-s3session-token", - "optional": false, - "rule": { - "is": "absent" - } - }, - { - "at": "/headers/authorization", - "optional": false, - "rule": { - "is": "matches", - "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" - } - }, - { - "at": "/headers/x-amz-copy-source", - "optional": false, - "rule": { - "is": "matches", - "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + "value": "\"fixture-0123456789ab\"" } } ], @@ -210557,7 +213088,7 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 412, "headers": { "content-type": "application/xml", "date": { @@ -210566,13 +213097,12 @@ }, "body": { "encoding": "utf8", - "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" + "data": "\nPreconditionFailedFixture error" }, "framing": "chunked" } } - ], - "optional": true + ] } ], "expect": [ @@ -210584,12 +213114,28 @@ "value": "error" } }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 412 + } + }, { "at": "/code", "optional": false, "rule": { "is": "equal", - "value": "InternalError" + "value": "PreconditionFailed" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "equal", + "value": "precondition" } } ], From b307703ff961a46b01f4e721bef83aa1cb2ec60a Mon Sep 17 00:00:00 2001 From: Tip ten Brink <75669206+tiptenbrink@users.noreply.github.com> Date: Sat, 3 Oct 2026 13:33:24 +0200 Subject: [PATCH 2/3] Test version tags, batch versions, version listings and restores. Batch deletes, ListObjectVersions and restore get new call and result fields, and blob_batch compares each subrequest's query. Co-Authored-By: Claude Opus 5.5 (1M context) --- REFERENCE.md | 2 + cases/operations.json | 9198 ++++++++++++++++++++++++++++++++++++----- src/model.rs | 4 +- src/request_rules.rs | 61 +- 4 files changed, 8263 insertions(+), 1002 deletions(-) diff --git a/REFERENCE.md b/REFERENCE.md index b467181..094c194 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -33,6 +33,8 @@ Leave out a result property the client does not expose, and name it in `unsuppor Keys are unescaped, bodies base64, ranges an offset and an exclusive end. A `checksum` without `value_base64` is for the client to compute. Tags are an object, or a list of `{"key", "value"}` pairs where a key may repeat. `content_range` reports a served range as `bytes FIRST-LAST/SIZE`. +A `delete_many` key is a name or `{"key", "version"}`, on Azure also `{"key", "snapshot"}`. A result reports each key as the call named it. Where an S3 answer names a version or a delete marker, the key is an object with `version`, `delete_marker` and `delete_marker_version`. A version listing pages by `continuation_token` and `version_marker`, and returns `next_version_marker`. A `restore` reports `state` `started` for a 202 and `readable` for a 200, and a read reports `x-amz-restore` or `x-ms-archive-status` as `restore_status`. + ## Cases [model.rs](src/model.rs) defines the format. diff --git a/cases/operations.json b/cases/operations.json index a8c1eec..7ddd19c 100644 --- a/cases/operations.json +++ b/cases/operations.json @@ -138,6 +138,7 @@ "operations/azure-hns/get-suffix": "get suffix", "operations/azure-hns/get-suffix-longer-than-object": "get suffix longer than object", "operations/azure-hns/get-tags": "Read the tags of an object, which an HNS account does not support", + "operations/azure-hns/get-tags-version": "Send a tag call on a version to an HNS account, which refuses it as it refuses the blob's", "operations/azure-hns/get-unauthenticated": "Report the service authorization error for this operation; signature acceptance is tested separately.", "operations/azure-hns/get-unknown-snapshot": "get unknown snapshot", "operations/azure-hns/get-unknown-version": "get unknown version", @@ -258,6 +259,7 @@ "operations/azure-hns/put-with-tags": "Write an object with tags, which an HNS account does not support", "operations/azure-hns/put-with-tier": "Write an object straight into the Cool access tier", "operations/azure-hns/set-tags": "Replace the tags of an object, which an HNS account does not support", + "operations/azure-hns/set-tags-version": "Send a tag call on a version to an HNS account, which refuses it as it refuses the blob's", "operations/azure-hns/set-tier-cool": "Move an object to the Cool access tier", "operations/azure-hns/set-tier-unknown": "Refuse an access tier the service does not have", "operations/azure-hns/snapshot": "snapshot", @@ -358,10 +360,13 @@ "operations/azure/delete-many-257": "Report a batch of 257 deletions, one more than Azure takes, as an error. Azure answers 202 with one part and no Content-ID, 400 ExceedsMaxBatchRequestCount, for the whole batch, not one part per deletion. A client may refuse it before sending", "operations/azure/delete-many-answers-out-of-order": "Match each part of a batch answer to its deletion by Content-ID, which links them, not by position. Azure has answered every recorded batch in order, up to 256 parts; this answer is written by hand", "operations/azure/delete-many-container-missing": "Report a batch in a missing container, which Azure answers 202 with 404 ContainerNotFound for each deletion, as that error for each key and none deleted, or as one error of kind container_not_found", + "operations/azure/delete-many-current-version": "Delete the current version of a key by its versionid in a batch, which Azure refuses with 403 OperationNotAllowedOnRootBlob", "operations/azure/delete-many-denied": "Report each deletion of a batch that Azure refuses inside its 202 answer, here every one with 403 AuthorizationPermissionMismatch, as that key's error, not as deleted", "operations/azure/delete-many-lf-line-endings": "Read a batch answer whose lines end in LF alone correctly, or report it as an error, but never half-read it. Azure has not been seen to send it: HTTP and multipart require CRLF. This answer is the recorded one with every CR removed", "operations/azure/delete-many-server-busy": "Report a batch that Azure answers as a whole with 503 ServerBusy as an error, never as deleted keys. A client may retry up to five times first", + "operations/azure/delete-many-snapshot": "Delete a snapshot of a key in a batch, named by snapshot in its subrequest's query, which leaves the blob", "operations/azure/delete-many-unauthenticated": "Report a batch whose token Azure does not accept as one error for the whole batch, as Azure answers it, not as an answer per key", + "operations/azure/delete-many-version": "Delete a previous version of one key and another key whole in one batch, the version named by versionid in its subrequest's query, which this account refuses for the version alone", "operations/azure/delete-many-without-content-id": "Report a batch answer whose parts carry no Content-ID as an error. Without one, only the order of the parts would link a result to its key, and a guess could report one key deleted when another failed. Azure echoes the Content-ID of every subrequest; this answer is the recorded one with them removed", "operations/azure/delete-missing": "delete missing. A client reports it as not_found: the object is absent", "operations/azure/delete-precondition-failed": "delete precondition failed", @@ -376,6 +381,7 @@ "operations/azure/delete-versioned-object": "delete versioned object", "operations/azure/delete-with-snapshots": "delete with snapshots", "operations/azure/get-after-snapshots-deleted": "get after snapshots deleted", + "operations/azure/get-archived": "Get an archived blob, which Azure refuses with 409 BlobArchived", "operations/azure/get-body-cut-short": "Report a body that ends before its Content-Length as an error, or resume it, but never return the short body", "operations/azure/get-committed": "get committed", "operations/azure/get-committed-nothing": "get committed nothing", @@ -431,6 +437,8 @@ "operations/azure/get-suffix-longer-than-object": "get suffix longer than object", "operations/azure/get-tags": "Read the tags of an object", "operations/azure/get-tags-none": "Report no blob index tags for a blob without any, which Azure answers with an empty TagSet", + "operations/azure/get-tags-snapshot": "Get the blob index tags of a snapshot, named by snapshot in the query, which keeps the tags the blob had", + "operations/azure/get-tags-version": "Get the blob index tags of a previous version, named by versionid in the query", "operations/azure/get-unauthenticated": "Report the service authorization error for this operation; signature acceptance is tested separately.", "operations/azure/get-unknown-snapshot": "get unknown snapshot", "operations/azure/get-unknown-version": "get unknown version", @@ -456,6 +464,7 @@ "operations/azure/head-metadata": "head metadata", "operations/azure/head-missing": "head missing. A client reports it as not_found: the object is absent", "operations/azure/head-previous-version": "head previous version", + "operations/azure/head-rehydrating": "Report the x-ms-archive-status header of a rehydrating blob as its restore status", "operations/azure/head-snapshot": "head snapshot", "operations/azure/head-written-with-crc64": "head written with crc64", "operations/azure/head-written-with-md5": "head written with md5", @@ -552,6 +561,10 @@ "operations/azure/put-with-tags-duplicate-key": "Report a write whose x-ms-tags names one key twice as an error. A client may refuse it, or report it unsupported where its API cannot repeat a key", "operations/azure/put-with-tags-special-characters": "Write a blob with an index tag that holds a space and each of + - = . _ : /, percent-encoded in x-ms-tags", "operations/azure/put-with-tier": "Write an object straight into the Cool access tier", + "operations/azure/restore": "Start rehydrating an archived blob to Hot at Standard priority, which Azure accepts with 202", + "operations/azure/restore-high-priority": "Start rehydrating an archived blob to Cool at High priority", + "operations/azure/restore-not-archived": "Restore a blob that is online already, which Azure answers with 200 as a readable blob", + "operations/azure/restore-while-rehydrating": "Rehydrate a blob to another tier while it rehydrates", "operations/azure/set-tags": "Replace the tags of an object", "operations/azure/set-tags-10-tags": "Set 10 tags, the most an object takes", "operations/azure/set-tags-11-tags": "Report 11 tags, one more than an object takes, as an error. A client may refuse them", @@ -559,9 +572,11 @@ "operations/azure/set-tags-invalid-character": "Report a blob index tag key with @, which Azure does not allow, as an error. A client may refuse it", "operations/azure/set-tags-key-128": "Set a tag whose key has 128 characters, the longest a key may be", "operations/azure/set-tags-key-129": "Report a tag key of 129 characters, one more than a key may have, as an error. A client may refuse it", + "operations/azure/set-tags-snapshot": "Set the blob index tags of a snapshot, named by snapshot in the query, which leaves the blob's tags alone", "operations/azure/set-tags-special-characters": "Set a blob index tag with a space and each of + - = . _ : /, which Azure allows, escaped as XML text", "operations/azure/set-tags-value-256": "Set a tag whose value has 256 characters, the longest a value may be", "operations/azure/set-tags-value-257": "Report a tag value of 257 characters, one more than a value may have, as an error. A client may refuse it", + "operations/azure/set-tags-version": "Set blob index tags on a previous version, named by versionid in the query", "operations/azure/set-tier-cool": "Move an object to the Cool access tier", "operations/azure/set-tier-rehydrate": "Report a tier change that Azure accepts with 202, as it does when an archived blob starts to rehydrate, as a success", "operations/azure/set-tier-unknown": "Refuse an access tier the service does not have", @@ -743,6 +758,7 @@ "operations/s3-express/list-service-unavailable": "Report a 503 ServiceUnavailable answer as an error, after at most 5 retries", "operations/s3-express/list-start-after": "Report the NotSupported error that a directory bucket answers to start-after", "operations/s3-express/list-truncated-without-token": "Report an error when a truncated page carries no continuation token; do not stop early or list from the start again", + "operations/s3-express/list-versions": "Send ListObjectVersions to a directory bucket, which keeps no versions", "operations/s3-express/list-xml-escaped": "Read XML character references in listed names, such as & and <, or ask for encoding-type=url and decode the names", "operations/s3-express/put-computing-crc32": "Compute the CRC32 checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-crc32 or in a trailer of an aws-chunked body", "operations/s3-express/put-computing-crc32c": "Compute the CRC32C checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-crc32c or in a trailer of an aws-chunked body", @@ -884,11 +900,16 @@ "operations/s3/delete-many": "Delete several objects in one request and report each result", "operations/s3/delete-many-1000": "Delete 1,000 keys in one DeleteObjects request, the most S3 takes", "operations/s3/delete-many-1001": "Report a DeleteObjects request of 1,001 keys, one more than S3 takes, as an error. A client may refuse it before sending", + "operations/s3/delete-many-delete-marker": "Delete a delete marker by its version in a batch, which makes the version before it current again", + "operations/s3/delete-many-deleted-version": "Delete a version that was already deleted in a batch", "operations/s3/delete-many-errors": "Report each key that S3 lists as an Error in a DeleteObjects answer, here AccessDenied, as that key's error, and the others as deleted", + "operations/s3/delete-many-plain-key-versioned": "Delete a key without a version in a versioned bucket, which S3 answers with the delete marker it made and that marker's version", + "operations/s3/delete-many-versions": "Delete two versions of one key in one batch, each named by the VersionId of its Object, which removes the key without a delete marker", "operations/s3/delete-missing": "delete missing", "operations/s3/delete-precondition-failed": "delete precondition failed", "operations/s3/delete-slow-down": "Report a 503 SlowDown answer as an error, after at most 5 retries", "operations/s3/delete-unauthenticated": "Report the service authorization error for this operation; signature acceptance is tested separately.", + "operations/s3/get-archived": "Get a GLACIER object that was not restored, which S3 refuses with 403 InvalidObjectState", "operations/s3/get-before-commit": "get before commit", "operations/s3/get-body-cut-short": "Report a body that ends before its Content-Length as an error, or resume it, but never return the short body", "operations/s3/get-bucket-missing": "get bucket missing. A client reports it as container_not_found: the bucket or container is absent, not the object", @@ -938,7 +959,10 @@ "operations/s3/get-suffix": "get suffix", "operations/s3/get-suffix-longer-than-object": "get suffix longer than object", "operations/s3/get-tagging": "Read the tags of an object", + "operations/s3/get-tagging-deleted-version": "Send a tag call on a version that was deleted", + "operations/s3/get-tagging-malformed-version": "Send a tag call on a version ID that S3 could never have given, which it answers as an invalid argument", "operations/s3/get-tagging-none": "Report no tags for an object without any, which S3 answers with an empty TagSet", + "operations/s3/get-tagging-version": "Get the tags of a previous version, named by versionId in the query", "operations/s3/get-temporary-redirect": "Report a 307 TemporaryRedirect as an error", "operations/s3/get-unauthenticated": "Report the service authorization error for this operation; signature acceptance is tested separately.", "operations/s3/get-version": "get version", @@ -960,6 +984,7 @@ "operations/s3/head-key-trailing-slash": "head, with the key \"trailing-slash/\"", "operations/s3/head-metadata": "head metadata", "operations/s3/head-missing": "Report a HEAD answered 404 as not_found or missing. Its answer has no body, so it cannot say whether the object or the bucket is absent", + "operations/s3/head-restoring": "Report the x-amz-restore header of an object whose restore runs as its restore status", "operations/s3/head-storage-class": "Read the storage class of an object", "operations/s3/list-all-empty": "Report an empty bucket as an empty listing", "operations/s3/list-all-pages": "Follow each page's continuation token until a page is not truncated", @@ -991,6 +1016,13 @@ "operations/s3/list-start-after-delimited": "Send a start-after that names no key; it skips the keys and common prefixes up to it", "operations/s3/list-truncated-without-token": "Report an error when a truncated page carries no continuation token; do not stop early or list from the start again", "operations/s3/list-unauthenticated": "Report the service authorization error for this operation; signature acceptance is tested separately.", + "operations/s3/list-versions": "List every version of each key, newest first, with the current one marked IsLatest", + "operations/s3/list-versions-delete-marker": "List a deleted key's delete marker as its current entry, before the version it hides", + "operations/s3/list-versions-delimited": "List versions with a delimiter, which rolls the versions under a deeper prefix into one common prefix", + "operations/s3/list-versions-encoded-key": "List the versions of a key with a space and a non-ASCII letter, which an encoded listing sends encoded", + "operations/s3/list-versions-first-page": "List the first page of versions, which names the key and version to continue from", + "operations/s3/list-versions-next-page": "List the next page of versions from a key marker and a version marker", + "operations/s3/list-versions-unversioned": "List the versions in a bucket that was never versioned, where each key has one version named null", "operations/s3/list-xml-escaped": "Read XML character references in listed names, such as & and <, or ask for encoding-type=url and decode the names", "operations/s3/put-bucket-missing": "put bucket missing. A client reports it as container_not_found: the bucket or container is absent, not the object", "operations/s3/put-computing-crc32": "Compute the CRC32 checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-crc32 or in a trailer of an aws-chunked body", @@ -1041,13 +1073,16 @@ "operations/s3/put-tagging": "Replace the tags of an object", "operations/s3/put-tagging-10-tags": "Set 10 tags, the most an object takes", "operations/s3/put-tagging-11-tags": "Report 11 tags, one more than an object takes, as an error. A client may refuse them", + "operations/s3/put-tagging-deleted-version": "Send a tag call on a version that was deleted", "operations/s3/put-tagging-duplicate-key": "Report a tag set that names one key twice as an error. A client may refuse it, or report it unsupported where its API cannot repeat a key", "operations/s3/put-tagging-invalid-character": "Report a tag key with !, which S3 does not allow, as an error. A client may refuse it", "operations/s3/put-tagging-key-128": "Set a tag whose key has 128 characters, the longest a key may be", "operations/s3/put-tagging-key-129": "Report a tag key of 129 characters, one more than a key may have, as an error. A client may refuse it", + "operations/s3/put-tagging-malformed-version": "Send a tag call on a version ID that S3 could never have given, which it answers as an invalid argument", "operations/s3/put-tagging-special-characters": "Set a tag with a space and each of + - = . _ : / @, which S3 allows, escaped as XML text", "operations/s3/put-tagging-value-256": "Set a tag whose value has 256 characters, the longest a value may be", "operations/s3/put-tagging-value-257": "Report a tag value of 257 characters, one more than a value may have, as an error. A client may refuse it", + "operations/s3/put-tagging-version": "Set the tags of a previous version, named by versionId in the query", "operations/s3/put-two-checksums": "Report S3's refusal of a write with two additional checksums; S3 keeps one checksum per object and answers 400 InvalidRequest to more than one x-amz-checksum- header", "operations/s3/put-unauthenticated": "Report the service authorization error for this operation; signature acceptance is tested separately.", "operations/s3/put-with-crc32": "Send an additional checksum in its x-amz-checksum- header; S3 stores it as the object's one checksum, in place of the CRC64NVME it adds to a write without one", @@ -1061,6 +1096,12 @@ "operations/s3/put-with-tags-duplicate-key": "Report a write whose x-amz-tagging names one key twice as an error. A client may refuse it, or report it unsupported where its API cannot repeat a key", "operations/s3/put-with-tags-special-characters": "Write an object with a tag that holds a space and each of + - = . _ : / @, percent-encoded in x-amz-tagging, so that S3 reads + as a plus and not a space", "operations/s3/put-with-unknown-storage-class": "Refuse a storage class that S3 does not have", + "operations/s3/restore": "Start restoring a GLACIER object for one day at the Standard tier, which S3 accepts with 202", + "operations/s3/restore-expedited": "Start restoring a GLACIER object at the Expedited tier, which a high priority names", + "operations/s3/restore-in-progress": "Restore an object a second time while the first restore runs, which S3 refuses with 409 RestoreAlreadyInProgress", + "operations/s3/restore-not-archived": "Restore a STANDARD object, which S3 refuses with 403 InvalidObjectState", + "operations/s3/restore-version": "Restore a previous version that is archived, named by versionId in the query", + "operations/s3/restore-without-days": "Restore a GLACIER object without Days, which only an Intelligent-Tiering archive may leave out", "operations/s3/stage": "stage", "operations/s3/stage-after-abort": "stage after abort", "operations/s3/stage-copy": "Copy a whole object into a part of a multipart upload, with UploadPartCopy", @@ -10534,6 +10575,413 @@ ], "refusal": null }, + { + "id": "operations/azure/delete-many-version", + "profile": "azure", + "lane": "core", + "purpose": "Delete a previous version of one key and another key whole in one batch, the version named by versionid in its subrequest's query, which this account refuses for the version alone", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/blob-batch" + ], + "call": { + "keys": [ + "object-tests/batch/b.txt", + { + "key": "object-tests/batch/a.txt", + "version": "2024-01-01T00:00:00.0000000Z" + } + ], + "op": "delete_many" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "POST" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "matches", + "pattern": "multipart/mixed; boundary=batch_[0-9A-Za-z-]+" + } + }, + { + "at": "/query/restype", + "optional": false, + "rule": { + "is": "equal", + "value": "container" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "batch" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "blob_batch", + "subrequests": [ + { + "method": "DELETE", + "path": "/fixture/object-tests/batch/b.txt" + }, + { + "method": "DELETE", + "path": "/fixture/object-tests/batch/a.txt", + "query": { + "versionid": "2024-01-01T00:00:00.0000000Z" + } + } + ] + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "content-type": "multipart/mixed; boundary=batchresponse_fixture", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "--batchresponse_fixture\r\nContent-Type: application/http\r\nContent-ID: 0\r\n\r\nHTTP/1.1 202 Accepted\r\nx-ms-request-id: fixture-0\r\nx-ms-delete-type-permanent: true\r\nx-ms-version: 2023-11-03\r\nServer: Windows-Azure-Blob/1.0\r\n\r\n--batchresponse_fixture\r\nContent-Type: application/http\r\nContent-ID: 1\r\n\r\nHTTP/1.1 403 This operation is not permitted on an automatic snapshot.\r\nx-ms-request-id: fixture-1\r\nx-ms-error-code: OperationNotAllowedOnAutomaticSnapshot\r\nx-ms-version: 2023-11-03\r\nContent-Length: 136\r\nContent-Type: application/xml\r\nServer: Windows-Azure-Blob/1.0\r\n\r\nOperationNotAllowedOnAutomaticSnapshotFixture error\r\n--batchresponse_fixture--" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/deleted", + "optional": false, + "rule": { + "is": "equal", + "value": [ + "object-tests/batch/b.txt" + ] + } + }, + { + "at": "/value/errors", + "optional": false, + "rule": { + "is": "equal", + "value": [ + { + "code": "OperationNotAllowedOnAutomaticSnapshot", + "key": "object-tests/batch/a.txt", + "status": 403, + "version": "2024-01-01T00:00:00.0000000Z" + } + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/delete-many-current-version", + "profile": "azure", + "lane": "core", + "purpose": "Delete the current version of a key by its versionid in a batch, which Azure refuses with 403 OperationNotAllowedOnRootBlob", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/blob-batch" + ], + "call": { + "keys": [ + { + "key": "object-tests/batch/a.txt", + "version": "2024-01-02T00:00:00.0000000Z" + } + ], + "op": "delete_many" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "POST" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "matches", + "pattern": "multipart/mixed; boundary=batch_[0-9A-Za-z-]+" + } + }, + { + "at": "/query/restype", + "optional": false, + "rule": { + "is": "equal", + "value": "container" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "batch" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "blob_batch", + "subrequests": [ + { + "method": "DELETE", + "path": "/fixture/object-tests/batch/a.txt", + "query": { + "versionid": "2024-01-02T00:00:00.0000000Z" + } + } + ] + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "content-type": "multipart/mixed; boundary=batchresponse_fixture", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "--batchresponse_fixture\r\nContent-Type: application/http\r\nContent-ID: 0\r\n\r\nHTTP/1.1 403 This operation is not permitted on a root blob.\r\nx-ms-request-id: fixture-0\r\nx-ms-error-code: OperationNotAllowedOnRootBlob\r\nx-ms-version: 2023-11-03\r\nContent-Length: 127\r\nContent-Type: application/xml\r\nServer: Windows-Azure-Blob/1.0\r\n\r\nOperationNotAllowedOnRootBlobFixture error\r\n--batchresponse_fixture--" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/deleted", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + }, + { + "at": "/value/errors", + "optional": false, + "rule": { + "is": "equal", + "value": [ + { + "code": "OperationNotAllowedOnRootBlob", + "key": "object-tests/batch/a.txt", + "status": 403, + "version": "2024-01-02T00:00:00.0000000Z" + } + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/delete-many-snapshot", + "profile": "azure", + "lane": "core", + "purpose": "Delete a snapshot of a key in a batch, named by snapshot in its subrequest's query, which leaves the blob", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/blob-batch" + ], + "call": { + "keys": [ + { + "key": "object-tests/batch/a.txt", + "snapshot": "2024-01-03T00:00:00.0000000Z" + } + ], + "op": "delete_many" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "POST" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "matches", + "pattern": "multipart/mixed; boundary=batch_[0-9A-Za-z-]+" + } + }, + { + "at": "/query/restype", + "optional": false, + "rule": { + "is": "equal", + "value": "container" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "batch" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "blob_batch", + "subrequests": [ + { + "method": "DELETE", + "path": "/fixture/object-tests/batch/a.txt", + "query": { + "snapshot": "2024-01-03T00:00:00.0000000Z" + } + } + ] + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "content-type": "multipart/mixed; boundary=batchresponse_fixture", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "--batchresponse_fixture\r\nContent-Type: application/http\r\nContent-ID: 0\r\n\r\nHTTP/1.1 202 Accepted\r\nx-ms-request-id: fixture-0\r\nx-ms-delete-type-permanent: true\r\nx-ms-version: 2023-11-03\r\nServer: Windows-Azure-Blob/1.0\r\n\r\n--batchresponse_fixture--" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/deleted", + "optional": false, + "rule": { + "is": "equal", + "value": [ + { + "key": "object-tests/batch/a.txt", + "snapshot": "2024-01-03T00:00:00.0000000Z" + } + ] + } + }, + { + "at": "/value/errors", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + } + ], + "refusal": null + }, { "id": "operations/azure/delete-leased-if-match-without-lease-id", "profile": "azure", @@ -15877,16 +16325,15 @@ "refusal": null }, { - "id": "operations/azure/get-not-modified", + "id": "operations/azure/get-archived", "profile": "azure", "lane": "core", - "purpose": "get not modified", + "purpose": "Get an archived blob, which Azure refuses with 409 BlobArchived", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], "call": { - "if_none_match": "\"fixture-16c44f0af72d\"", - "key": "object-tests/read/object.txt", + "key": "object-tests/archive/object.txt", "op": "get" }, "exchanges": [ @@ -15907,7 +16354,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/read/object.txt" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -15917,29 +16364,22 @@ "is": "equal", "value": "" } - }, - { - "at": "/headers/if-none-match", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-16c44f0af72d\"" - } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 304, + "status": 409, "headers": { + "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "ConditionNotMet" + "x-ms-error-code": "BlobArchived" }, "body": { - "encoding": "base64", - "data": "" + "encoding": "utf8", + "data": "BlobArchivedFixture error" } } } @@ -15960,7 +16400,7 @@ "optional": false, "rule": { "is": "equal", - "value": 304 + "value": 409 } }, { @@ -15968,22 +16408,22 @@ "optional": false, "rule": { "is": "equal", - "value": "ConditionNotMet" + "value": "BlobArchived" } } ], "refusal": null }, { - "id": "operations/azure/get-precondition-failed", + "id": "operations/azure/get-not-modified", "profile": "azure", "lane": "core", - "purpose": "get precondition failed", + "purpose": "get not modified", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], "call": { - "if_match": "\"fixture-088e5dc109cf\"", + "if_none_match": "\"fixture-16c44f0af72d\"", "key": "object-tests/read/object.txt", "op": "get" }, @@ -16017,28 +16457,27 @@ } }, { - "at": "/headers/if-match", + "at": "/headers/if-none-match", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-088e5dc109cf\"" + "value": "\"fixture-16c44f0af72d\"" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 412, + "status": 304, "headers": { - "content-type": "application/xml", "date": { "from": "now" }, "x-ms-error-code": "ConditionNotMet" }, "body": { - "encoding": "utf8", - "data": "ConditionNotMetFixture error" + "encoding": "base64", + "data": "" } } } @@ -16059,7 +16498,7 @@ "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 304 } }, { @@ -16074,17 +16513,17 @@ "refusal": null }, { - "id": "operations/azure/get-previous-version-of-deleted-object", + "id": "operations/azure/get-precondition-failed", "profile": "azure", "lane": "core", - "purpose": "get previous version of deleted object", + "purpose": "get precondition failed", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], "call": { - "key": "object-tests/versions-mtydohr2/deleted.txt", - "op": "get", - "version": "2024-01-01T00:00:00.0160641Z" + "if_match": "\"fixture-088e5dc109cf\"", + "key": "object-tests/read/object.txt", + "op": "get" }, "exchanges": [ { @@ -16104,7 +16543,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/versions-mtydohr2/deleted.txt" + "value": "/fixture/object-tests/read/object.txt" } }, { @@ -16116,34 +16555,28 @@ } }, { - "at": "/query/versionid", + "at": "/headers/if-match", "optional": false, "rule": { "is": "equal", - "value": "2024-01-01T00:00:00.0160641Z" + "value": "\"fixture-088e5dc109cf\"" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 200, + "status": 412, "headers": { - "content-md5": "ASCk+RlqX5659SPzH5FNpw==", - "content-type": "application/octet-stream", + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-3f26f9cf7bbe\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-blob-type": "BlockBlob", - "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-server-encrypted": "true", - "x-ms-version-id": "2024-01-01T00:00:00.0160641Z" + "x-ms-error-code": "ConditionNotMet" }, "body": { - "encoding": "base64", - "data": "ZzE=" + "encoding": "utf8", + "data": "ConditionNotMetFixture error" } } } @@ -16156,72 +16589,40 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" - } - }, - { - "at": "/value/etag", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-3f26f9cf7bbe\"" - } - }, - { - "at": "/value/size", - "optional": false, - "rule": { - "is": "equal", - "value": 2 - } - }, - { - "at": "/value/content_type", - "optional": false, - "rule": { - "is": "equal", - "value": "application/octet-stream" - } - }, - { - "at": "/value/content_md5_base64", - "optional": false, - "rule": { - "is": "equal", - "value": "ASCk+RlqX5659SPzH5FNpw==" + "value": "error" } }, { - "at": "/value/version", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "2024-01-01T00:00:00.0160641Z" + "value": 412 } }, { - "at": "/value/body_base64", + "at": "/code", "optional": false, "rule": { "is": "equal", - "value": "ZzE=" + "value": "ConditionNotMet" } } ], "refusal": null }, { - "id": "operations/azure/get-previous-version", + "id": "operations/azure/get-previous-version-of-deleted-object", "profile": "azure", "lane": "core", - "purpose": "get previous version", + "purpose": "get previous version of deleted object", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], "call": { - "key": "object-tests/versions-mtydohr2/object.txt", + "key": "object-tests/versions-mtydohr2/deleted.txt", "op": "get", - "version": "2024-01-01T00:00:00.2318906Z" + "version": "2024-01-01T00:00:00.0160641Z" }, "exchanges": [ { @@ -16241,7 +16642,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/versions-mtydohr2/object.txt" + "value": "/fixture/object-tests/versions-mtydohr2/deleted.txt" } }, { @@ -16257,7 +16658,7 @@ "optional": false, "rule": { "is": "equal", - "value": "2024-01-01T00:00:00.2318906Z" + "value": "2024-01-01T00:00:00.0160641Z" } } ], @@ -16266,21 +16667,21 @@ "response": { "status": 200, "headers": { - "content-md5": "ZlTHNMyrj0QP8IJetEPcfw==", + "content-md5": "ASCk+RlqX5659SPzH5FNpw==", "content-type": "application/octet-stream", "date": { "from": "now" }, - "etag": "\"fixture-5769a0807b46\"", + "etag": "\"fixture-3f26f9cf7bbe\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", "x-ms-blob-type": "BlockBlob", "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", "x-ms-server-encrypted": "true", - "x-ms-version-id": "2024-01-01T00:00:00.2318906Z" + "x-ms-version-id": "2024-01-01T00:00:00.0160641Z" }, "body": { "encoding": "base64", - "data": "djE=" + "data": "ZzE=" } } } @@ -16301,7 +16702,7 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-5769a0807b46\"" + "value": "\"fixture-3f26f9cf7bbe\"" } }, { @@ -16325,7 +16726,7 @@ "optional": false, "rule": { "is": "equal", - "value": "ZlTHNMyrj0QP8IJetEPcfw==" + "value": "ASCk+RlqX5659SPzH5FNpw==" } }, { @@ -16333,7 +16734,7 @@ "optional": false, "rule": { "is": "equal", - "value": "2024-01-01T00:00:00.2318906Z" + "value": "2024-01-01T00:00:00.0160641Z" } }, { @@ -16341,27 +16742,24 @@ "optional": false, "rule": { "is": "equal", - "value": "djE=" + "value": "ZzE=" } } ], "refusal": null }, { - "id": "operations/azure/get-range-inverted", + "id": "operations/azure/get-previous-version", "profile": "azure", "lane": "core", - "purpose": "get range inverted", + "purpose": "get previous version", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], "call": { - "key": "object-tests/read/object.txt", + "key": "object-tests/versions-mtydohr2/object.txt", "op": "get", - "range": { - "end": 2, - "start": 6 - } + "version": "2024-01-01T00:00:00.2318906Z" }, "exchanges": [ { @@ -16381,67 +16779,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/read/object.txt" - } - }, - { - "at": "/body_base64", - "optional": false, - "rule": { - "is": "equal", - "value": "" - } - }, - { - "at": "/headers/range", - "optional": false, - "rule": { - "is": "equal", - "value": "bytes=6-1" - } - } - ], - "allow_headers": [], - "allow_query": [], - "response": { - "status": 200, - "headers": { - "content-md5": "H1VC0PNTmj+yaCRN4U931g==", - "content-type": "application/octet-stream", - "date": { - "from": "now" - }, - "etag": "\"fixture-16c44f0af72d\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-blob-type": "BlockBlob", - "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-lease-state": "available", - "x-ms-lease-status": "unlocked", - "x-ms-server-encrypted": "true", - "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" - }, - "body": { - "encoding": "base64", - "data": "MDEyMzQ1Njc4OS1vYmplY3QtdGVzdHMtb2JqZWN0" - } - } - }, - { - "request": [ - { - "at": "/method", - "optional": false, - "rule": { - "is": "equal", - "value": "GET" - } - }, - { - "at": "/path", - "optional": false, - "rule": { - "is": "equal", - "value": "/fixture/object-tests/read/object.txt" + "value": "/fixture/object-tests/versions-mtydohr2/object.txt" } }, { @@ -16453,11 +16791,11 @@ } }, { - "at": "/headers/x-ms-range", + "at": "/query/versionid", "optional": false, "rule": { "is": "equal", - "value": "bytes=6-1" + "value": "2024-01-01T00:00:00.2318906Z" } } ], @@ -16466,23 +16804,21 @@ "response": { "status": 200, "headers": { - "content-md5": "H1VC0PNTmj+yaCRN4U931g==", + "content-md5": "ZlTHNMyrj0QP8IJetEPcfw==", "content-type": "application/octet-stream", "date": { "from": "now" }, - "etag": "\"fixture-16c44f0af72d\"", + "etag": "\"fixture-5769a0807b46\"", "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", "x-ms-blob-type": "BlockBlob", "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-lease-state": "available", - "x-ms-lease-status": "unlocked", "x-ms-server-encrypted": "true", - "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" + "x-ms-version-id": "2024-01-01T00:00:00.2318906Z" }, "body": { "encoding": "base64", - "data": "MDEyMzQ1Njc4OS1vYmplY3QtdGVzdHMtb2JqZWN0" + "data": "djE=" } } } @@ -16503,7 +16839,7 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-16c44f0af72d\"" + "value": "\"fixture-5769a0807b46\"" } }, { @@ -16511,7 +16847,7 @@ "optional": false, "rule": { "is": "equal", - "value": 30 + "value": 2 } }, { @@ -16527,7 +16863,7 @@ "optional": false, "rule": { "is": "equal", - "value": "H1VC0PNTmj+yaCRN4U931g==" + "value": "ZlTHNMyrj0QP8IJetEPcfw==" } }, { @@ -16535,7 +16871,7 @@ "optional": false, "rule": { "is": "equal", - "value": "2024-01-01T00:00:00.7556278Z" + "value": "2024-01-01T00:00:00.2318906Z" } }, { @@ -16543,43 +16879,17 @@ "optional": false, "rule": { "is": "equal", - "value": "MDEyMzQ1Njc4OS1vYmplY3QtdGVzdHMtb2JqZWN0" - } - } - ], - "refusal": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "refused" - } - }, - { - "at": "/kind", - "optional": false, - "rule": { - "is": "matches", - "pattern": ".+" - } - }, - { - "at": "/parameter", - "optional": false, - "rule": { - "is": "equal", - "value": "range" + "value": "djE=" } } ], - "decline_permitted": true + "refusal": null }, { - "id": "operations/azure/get-range-empty", + "id": "operations/azure/get-range-inverted", "profile": "azure", "lane": "core", - "purpose": "Read a range of no bytes, whose start equals its end. HTTP has no form for it: bytes=5-4 is inverted, and the service ignores it and sends the whole object. A client may refuse it instead", + "purpose": "get range inverted", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], @@ -16587,8 +16897,8 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "end": 5, - "start": 5 + "end": 2, + "start": 6 } }, "exchanges": [ @@ -16625,7 +16935,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=5-4" + "value": "bytes=6-1" } } ], @@ -16685,7 +16995,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=5-4" + "value": "bytes=6-1" } } ], @@ -16804,10 +17114,10 @@ "decline_permitted": true }, { - "id": "operations/azure/get-range-not-satisfiable", + "id": "operations/azure/get-range-empty", "profile": "azure", "lane": "core", - "purpose": "get range not satisfiable", + "purpose": "Read a range of no bytes, whose start equals its end. HTTP has no form for it: bytes=5-4 is inverted, and the service ignores it and sends the whole object. A client may refuse it instead", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], @@ -16815,7 +17125,8 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "start": 40 + "end": 5, + "start": 5 } }, "exchanges": [ @@ -16852,25 +17163,32 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=40-" + "value": "bytes=5-4" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 416, + "status": 200, "headers": { - "content-range": "bytes */30", - "content-type": "application/xml", + "content-md5": "H1VC0PNTmj+yaCRN4U931g==", + "content-type": "application/octet-stream", "date": { "from": "now" }, - "x-ms-error-code": "InvalidRange" + "etag": "\"fixture-16c44f0af72d\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-blob-type": "BlockBlob", + "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-lease-state": "available", + "x-ms-lease-status": "unlocked", + "x-ms-server-encrypted": "true", + "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" }, "body": { - "encoding": "utf8", - "data": "InvalidRangeFixture error" + "encoding": "base64", + "data": "MDEyMzQ1Njc4OS1vYmplY3QtdGVzdHMtb2JqZWN0" } } }, @@ -16905,25 +17223,32 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=40-" + "value": "bytes=5-4" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 416, + "status": 200, "headers": { - "content-range": "bytes */30", - "content-type": "application/xml", + "content-md5": "H1VC0PNTmj+yaCRN4U931g==", + "content-type": "application/octet-stream", "date": { "from": "now" }, - "x-ms-error-code": "InvalidRange" + "etag": "\"fixture-16c44f0af72d\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-blob-type": "BlockBlob", + "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-lease-state": "available", + "x-ms-lease-status": "unlocked", + "x-ms-server-encrypted": "true", + "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" }, "body": { - "encoding": "utf8", - "data": "InvalidRangeFixture error" + "encoding": "base64", + "data": "MDEyMzQ1Njc4OS1vYmplY3QtdGVzdHMtb2JqZWN0" } } } @@ -16936,33 +17261,91 @@ "optional": false, "rule": { "is": "equal", - "value": "error" + "value": "ok" } }, { - "at": "/status", + "at": "/value/etag", "optional": false, "rule": { "is": "equal", - "value": 416 + "value": "\"fixture-16c44f0af72d\"" } }, { - "at": "/code", + "at": "/value/size", "optional": false, "rule": { "is": "equal", - "value": "InvalidRange" + "value": 30 + } + }, + { + "at": "/value/content_type", + "optional": false, + "rule": { + "is": "equal", + "value": "application/octet-stream" + } + }, + { + "at": "/value/content_md5_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "H1VC0PNTmj+yaCRN4U931g==" + } + }, + { + "at": "/value/version", + "optional": false, + "rule": { + "is": "equal", + "value": "2024-01-01T00:00:00.7556278Z" + } + }, + { + "at": "/value/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "MDEyMzQ1Njc4OS1vYmplY3QtdGVzdHMtb2JqZWN0" } } ], - "refusal": null + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "range" + } + } + ], + "decline_permitted": true }, { - "id": "operations/azure/get-range-past-the-end", + "id": "operations/azure/get-range-not-satisfiable", "profile": "azure", "lane": "core", - "purpose": "Read a range that ends past the object, which the service clips to the object's end. Report the window it served from Content-Range, bytes 28-29/30, so that the caller sees the range was clipped", + "purpose": "get range not satisfiable", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], @@ -16970,8 +17353,7 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "end": 64, - "start": 28 + "start": 40 } }, "exchanges": [ @@ -17008,32 +17390,25 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=28-63" + "value": "bytes=40-" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 206, + "status": 416, "headers": { - "content-range": "bytes 28-29/30", - "content-type": "application/octet-stream", + "content-range": "bytes */30", + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-16c44f0af72d\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-blob-type": "BlockBlob", - "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-lease-state": "available", - "x-ms-lease-status": "unlocked", - "x-ms-server-encrypted": "true", - "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" + "x-ms-error-code": "InvalidRange" }, "body": { - "encoding": "base64", - "data": "Y3Q=" + "encoding": "utf8", + "data": "InvalidRangeFixture error" } } }, @@ -17068,32 +17443,25 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=28-63" + "value": "bytes=40-" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 206, + "status": 416, "headers": { - "content-range": "bytes 28-29/30", - "content-type": "application/octet-stream", + "content-range": "bytes */30", + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-16c44f0af72d\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-blob-type": "BlockBlob", - "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-lease-state": "available", - "x-ms-lease-status": "unlocked", - "x-ms-server-encrypted": "true", - "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" + "x-ms-error-code": "InvalidRange" }, "body": { - "encoding": "base64", - "data": "Y3Q=" + "encoding": "utf8", + "data": "InvalidRangeFixture error" } } } @@ -17106,65 +17474,33 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" - } - }, - { - "at": "/value/etag", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-16c44f0af72d\"" - } - }, - { - "at": "/value/size", - "optional": false, - "rule": { - "is": "equal", - "value": 2 - } - }, - { - "at": "/value/content_type", - "optional": false, - "rule": { - "is": "equal", - "value": "application/octet-stream" - } - }, - { - "at": "/value/version", - "optional": false, - "rule": { - "is": "equal", - "value": "2024-01-01T00:00:00.7556278Z" + "value": "error" } }, { - "at": "/value/body_base64", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "Y3Q=" + "value": 416 } }, { - "at": "/value/content_range", + "at": "/code", "optional": false, "rule": { "is": "equal", - "value": "bytes 28-29/30" + "value": "InvalidRange" } } ], "refusal": null }, { - "id": "operations/azure/get-range-single-byte", + "id": "operations/azure/get-range-past-the-end", "profile": "azure", "lane": "core", - "purpose": "get range single byte", + "purpose": "Read a range that ends past the object, which the service clips to the object's end. Report the window it served from Content-Range, bytes 28-29/30, so that the caller sees the range was clipped", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], @@ -17172,8 +17508,8 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "end": 1, - "start": 0 + "end": 64, + "start": 28 } }, "exchanges": [ @@ -17210,7 +17546,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=0-0" + "value": "bytes=28-63" } } ], @@ -17219,7 +17555,7 @@ "response": { "status": 206, "headers": { - "content-range": "bytes 0-0/30", + "content-range": "bytes 28-29/30", "content-type": "application/octet-stream", "date": { "from": "now" @@ -17235,7 +17571,7 @@ }, "body": { "encoding": "base64", - "data": "MA==" + "data": "Y3Q=" } } }, @@ -17270,7 +17606,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=0-0" + "value": "bytes=28-63" } } ], @@ -17279,7 +17615,7 @@ "response": { "status": 206, "headers": { - "content-range": "bytes 0-0/30", + "content-range": "bytes 28-29/30", "content-type": "application/octet-stream", "date": { "from": "now" @@ -17295,7 +17631,7 @@ }, "body": { "encoding": "base64", - "data": "MA==" + "data": "Y3Q=" } } } @@ -17324,7 +17660,7 @@ "optional": false, "rule": { "is": "equal", - "value": 1 + "value": 2 } }, { @@ -17348,17 +17684,25 @@ "optional": false, "rule": { "is": "equal", - "value": "MA==" + "value": "Y3Q=" + } + }, + { + "at": "/value/content_range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes 28-29/30" } } ], "refusal": null }, { - "id": "operations/azure/get-range", + "id": "operations/azure/get-range-single-byte", "profile": "azure", "lane": "core", - "purpose": "get range", + "purpose": "get range single byte", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], @@ -17366,8 +17710,8 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "end": 6, - "start": 2 + "end": 1, + "start": 0 } }, "exchanges": [ @@ -17404,7 +17748,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=2-5" + "value": "bytes=0-0" } } ], @@ -17413,7 +17757,7 @@ "response": { "status": 206, "headers": { - "content-range": "bytes 2-5/30", + "content-range": "bytes 0-0/30", "content-type": "application/octet-stream", "date": { "from": "now" @@ -17429,7 +17773,201 @@ }, "body": { "encoding": "base64", - "data": "MjM0NQ==" + "data": "MA==" + } + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/read/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-ms-range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes=0-0" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 206, + "headers": { + "content-range": "bytes 0-0/30", + "content-type": "application/octet-stream", + "date": { + "from": "now" + }, + "etag": "\"fixture-16c44f0af72d\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-blob-type": "BlockBlob", + "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-lease-state": "available", + "x-ms-lease-status": "unlocked", + "x-ms-server-encrypted": "true", + "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" + }, + "body": { + "encoding": "base64", + "data": "MA==" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-16c44f0af72d\"" + } + }, + { + "at": "/value/size", + "optional": false, + "rule": { + "is": "equal", + "value": 1 + } + }, + { + "at": "/value/content_type", + "optional": false, + "rule": { + "is": "equal", + "value": "application/octet-stream" + } + }, + { + "at": "/value/version", + "optional": false, + "rule": { + "is": "equal", + "value": "2024-01-01T00:00:00.7556278Z" + } + }, + { + "at": "/value/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "MA==" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/get-range", + "profile": "azure", + "lane": "core", + "purpose": "get range", + "sources": [ + "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" + ], + "call": { + "key": "object-tests/read/object.txt", + "op": "get", + "range": { + "end": 6, + "start": 2 + } + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/read/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/range", + "optional": false, + "rule": { + "is": "equal", + "value": "bytes=2-5" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 206, + "headers": { + "content-range": "bytes 2-5/30", + "content-type": "application/octet-stream", + "date": { + "from": "now" + }, + "etag": "\"fixture-16c44f0af72d\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-blob-type": "BlockBlob", + "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-lease-state": "available", + "x-ms-lease-status": "unlocked", + "x-ms-server-encrypted": "true", + "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" + }, + "body": { + "encoding": "base64", + "data": "MjM0NQ==" } } }, @@ -23146,16 +23684,16 @@ "refusal": null }, { - "id": "operations/azure/list-after-delete-with-versions", + "id": "operations/azure/head-rehydrating", "profile": "azure", "lane": "core", - "purpose": "list after delete with versions", + "purpose": "Report the x-ms-archive-status header of a rehydrating blob as its restore status", "sources": [ - "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" + "https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob-properties" ], "call": { - "op": "list_page", - "prefix": "object-tests/versions-mtydohr2/deleted.txt" + "key": "object-tests/archive/object.txt", + "op": "head" }, "exchanges": [ { @@ -23167,7 +23705,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "HEAD" } }, { @@ -23175,7 +23713,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -23185,13 +23723,132 @@ "is": "equal", "value": "" } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-length": "30", + "content-md5": "H1VC0PNTmj+yaCRN4U931g==", + "content-type": "application/octet-stream", + "date": { + "from": "now" + }, + "etag": "\"fixture-16c44f0af72d\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-access-tier": "Archive", + "x-ms-archive-status": "rehydrate-pending-to-hot", + "x-ms-blob-type": "BlockBlob", + "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-lease-state": "available", + "x-ms-lease-status": "unlocked", + "x-ms-server-encrypted": "true", + "x-ms-version-id": "2024-01-01T00:00:00.7556278Z" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-16c44f0af72d\"" + } + }, + { + "at": "/value/size", + "optional": false, + "rule": { + "is": "equal", + "value": 30 + } + }, + { + "at": "/value/content_type", + "optional": false, + "rule": { + "is": "equal", + "value": "application/octet-stream" + } + }, + { + "at": "/value/content_md5_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "H1VC0PNTmj+yaCRN4U931g==" + } + }, + { + "at": "/value/restore_status", + "optional": false, + "rule": { + "is": "equal", + "value": "rehydrate-pending-to-hot" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/restore-not-archived", + "profile": "azure", + "lane": "core", + "purpose": "Restore a blob that is online already, which Azure answers with 200 as a readable blob", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier" + ], + "call": { + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "standard", + "tier": "Hot" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } }, { - "at": "/query/restype", + "at": "/path", "optional": false, "rule": { "is": "equal", - "value": "container" + "value": "/fixture/object-tests/archive/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" } }, { @@ -23199,15 +23856,23 @@ "optional": false, "rule": { "is": "equal", - "value": "list" + "value": "tier" } }, { - "at": "/query/prefix", + "at": "/headers/x-ms-access-tier", "optional": false, "rule": { "is": "equal", - "value": "object-tests/versions-mtydohr2/deleted.txt" + "value": "Hot" + } + }, + { + "at": "/headers/x-ms-rehydrate-priority", + "optional": false, + "rule": { + "is": "equal", + "value": "Standard" } } ], @@ -23216,18 +23881,13 @@ "response": { "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" - }, - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT" + } }, "body": { - "encoding": "utf8", - "data": "object-tests/versions-mtydohr2/deleted.txt" - }, - "framing": "chunked" + "encoding": "empty" + } } } ] @@ -23243,44 +23903,29 @@ } }, { - "at": "/value/entries", - "optional": false, - "rule": { - "is": "array_length", - "value": 0 - } - }, - { - "at": "/value/prefixes", - "optional": false, - "rule": { - "is": "array_length", - "value": 0 - } - }, - { - "at": "/value/continuation_token", + "at": "/value/state", "optional": false, "rule": { "is": "equal", - "value": "" + "value": "readable" } } ], "refusal": null }, { - "id": "operations/azure/list-bad-marker", + "id": "operations/azure/restore-while-rehydrating", "profile": "azure", "lane": "core", - "purpose": "list bad marker", + "purpose": "Rehydrate a blob to another tier while it rehydrates", "sources": [ - "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier" ], "call": { - "continuation_token": "fixture-marker+/1d52c72a655f=", - "op": "list_page", - "prefix": "object-tests/board/" + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "standard", + "tier": "Cool" }, "exchanges": [ { @@ -23292,7 +23937,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -23300,7 +23945,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -23311,53 +23956,502 @@ "value": "" } }, - { - "at": "/query/restype", - "optional": false, - "rule": { - "is": "equal", - "value": "container" - } - }, { "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "list" + "value": "tier" } }, { - "at": "/query/prefix", + "at": "/headers/x-ms-access-tier", "optional": false, "rule": { "is": "equal", - "value": "object-tests/board/" + "value": "Cool" } }, { - "at": "/query/marker", + "at": "/headers/x-ms-rehydrate-priority", "optional": false, "rule": { "is": "equal", - "value": "fixture-marker+/1d52c72a655f=" + "value": "Standard" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 400, + "status": 409, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "InvalidQueryParameterValue" + "x-ms-error-code": "BlobBeingRehydrated" }, "body": { "encoding": "utf8", - "data": "InvalidQueryParameterValueFixture error" + "data": "BlobBeingRehydratedFixture error" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 409 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "BlobBeingRehydrated" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/restore-high-priority", + "profile": "azure", + "lane": "core", + "purpose": "Start rehydrating an archived blob to Cool at High priority", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier" + ], + "call": { + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "high", + "tier": "Cool" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/archive/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "tier" + } + }, + { + "at": "/headers/x-ms-access-tier", + "optional": false, + "rule": { + "is": "equal", + "value": "Cool" + } + }, + { + "at": "/headers/x-ms-rehydrate-priority", + "optional": false, + "rule": { + "is": "equal", + "value": "High" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/state", + "optional": false, + "rule": { + "is": "equal", + "value": "started" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/restore", + "profile": "azure", + "lane": "core", + "purpose": "Start rehydrating an archived blob to Hot at Standard priority, which Azure accepts with 202", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier" + ], + "call": { + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "standard", + "tier": "Hot" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/archive/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "tier" + } + }, + { + "at": "/headers/x-ms-access-tier", + "optional": false, + "rule": { + "is": "equal", + "value": "Hot" + } + }, + { + "at": "/headers/x-ms-rehydrate-priority", + "optional": false, + "rule": { + "is": "equal", + "value": "Standard" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/state", + "optional": false, + "rule": { + "is": "equal", + "value": "started" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/list-after-delete-with-versions", + "profile": "azure", + "lane": "core", + "purpose": "list after delete with versions", + "sources": [ + "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" + ], + "call": { + "op": "list_page", + "prefix": "object-tests/versions-mtydohr2/deleted.txt" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/restype", + "optional": false, + "rule": { + "is": "equal", + "value": "container" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "list" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions-mtydohr2/deleted.txt" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-creation-time": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "object-tests/versions-mtydohr2/deleted.txt" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/entries", + "optional": false, + "rule": { + "is": "array_length", + "value": 0 + } + }, + { + "at": "/value/prefixes", + "optional": false, + "rule": { + "is": "array_length", + "value": 0 + } + }, + { + "at": "/value/continuation_token", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/list-bad-marker", + "profile": "azure", + "lane": "core", + "purpose": "list bad marker", + "sources": [ + "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" + ], + "call": { + "continuation_token": "fixture-marker+/1d52c72a655f=", + "op": "list_page", + "prefix": "object-tests/board/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/restype", + "optional": false, + "rule": { + "is": "equal", + "value": "container" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "list" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/board/" + } + }, + { + "at": "/query/marker", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-marker+/1d52c72a655f=" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "InvalidQueryParameterValue" + }, + "body": { + "encoding": "utf8", + "data": "InvalidQueryParameterValueFixture error" } } } @@ -37635,19 +38729,17 @@ "refusal": null }, { - "id": "operations/azure/set-tags", + "id": "operations/azure/get-tags-version", "profile": "azure", "lane": "core", - "purpose": "Replace the tags of an object", + "purpose": "Get the blob index tags of a previous version, named by versionid in the query", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" + "https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob-tags" ], "call": { "key": "object-tests/tags/object.txt", - "op": "azure.set_tags", - "tags": { - "project": "object-tests" - } + "op": "azure.get_tags", + "version": "2024-01-01T00:00:00.0000000Z" }, "exchanges": [ { @@ -37659,7 +38751,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -37671,11 +38763,11 @@ } }, { - "at": "/body_text", + "at": "/body_base64", "optional": false, "rule": { - "is": "xml", - "value": "projectobject-tests" + "is": "equal", + "value": "" } }, { @@ -37687,28 +38779,27 @@ } }, { - "at": "/headers/content-type", + "at": "/query/versionid", "optional": false, "rule": { - "is": "one_of", - "values": [ - "application/xml", - "application/xml; charset=UTF-8" - ] + "is": "equal", + "value": "2024-01-01T00:00:00.0000000Z" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 204, + "status": 200, "headers": { + "content-type": "application/xml", "date": { "from": "now" } }, "body": { - "encoding": "empty" + "encoding": "utf8", + "data": "projectobject-tests" } } } @@ -37723,33 +38814,32 @@ "is": "equal", "value": "ok" } + }, + { + "at": "/value/tags", + "optional": false, + "rule": { + "is": "equal", + "value": { + "project": "object-tests" + } + } } ], "refusal": null }, { - "id": "operations/azure/set-tags-10-tags", + "id": "operations/azure/get-tags-snapshot", "profile": "azure", "lane": "core", - "purpose": "Set 10 tags, the most an object takes", + "purpose": "Get the blob index tags of a snapshot, named by snapshot in the query, which keeps the tags the blob had", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" + "https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob-tags" ], "call": { "key": "object-tests/tags/object.txt", - "op": "azure.set_tags", - "tags": { - "tag00": "value0", - "tag01": "value1", - "tag02": "value2", - "tag03": "value3", - "tag04": "value4", - "tag05": "value5", - "tag06": "value6", - "tag07": "value7", - "tag08": "value8", - "tag09": "value9" - } + "op": "azure.get_tags", + "snapshot": "2024-01-01T00:00:00.0000000Z" }, "exchanges": [ { @@ -37761,7 +38851,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -37773,11 +38863,11 @@ } }, { - "at": "/body_text", + "at": "/body_base64", "optional": false, "rule": { - "is": "xml", - "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9" + "is": "equal", + "value": "" } }, { @@ -37789,28 +38879,27 @@ } }, { - "at": "/headers/content-type", + "at": "/query/snapshot", "optional": false, "rule": { - "is": "one_of", - "values": [ - "application/xml", - "application/xml; charset=UTF-8" - ] + "is": "equal", + "value": "2024-01-01T00:00:00.0000000Z" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 204, + "status": 200, "headers": { + "content-type": "application/xml", "date": { "from": "now" } }, "body": { - "encoding": "empty" + "encoding": "utf8", + "data": "projectobject-tests" } } } @@ -37825,15 +38914,25 @@ "is": "equal", "value": "ok" } + }, + { + "at": "/value/tags", + "optional": false, + "rule": { + "is": "equal", + "value": { + "project": "object-tests" + } + } } ], "refusal": null }, { - "id": "operations/azure/set-tags-11-tags", + "id": "operations/azure/set-tags", "profile": "azure", "lane": "core", - "purpose": "Report 11 tags, one more than an object takes, as an error. A client may refuse them", + "purpose": "Replace the tags of an object", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], @@ -37841,17 +38940,7 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "tag00": "value0", - "tag01": "value1", - "tag02": "value2", - "tag03": "value3", - "tag04": "value4", - "tag05": "value5", - "tag06": "value6", - "tag07": "value7", - "tag08": "value8", - "tag09": "value9", - "tag10": "value10" + "project": "object-tests" } }, "exchanges": [ @@ -37880,7 +38969,7 @@ "optional": false, "rule": { "is": "xml", - "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9tag10value10" + "value": "projectobject-tests" } }, { @@ -37906,17 +38995,14 @@ "allow_headers": [], "allow_query": [], "response": { - "status": 400, + "status": 204, "headers": { - "content-type": "application/xml", "date": { "from": "now" - }, - "x-ms-error-code": "TagsTooLarge" + } }, "body": { - "encoding": "utf8", - "data": "TagsTooLargeFixture error" + "encoding": "empty" } } } @@ -37929,74 +39015,17 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": false, - "rule": { - "is": "equal", - "value": "TagsTooLarge" + "value": "ok" } } ], - "refusal": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "refused" - } - }, - { - "at": "/kind", - "optional": false, - "rule": { - "is": "matches", - "pattern": ".+" - } - }, - { - "at": "/parameter", - "optional": false, - "rule": { - "is": "equal", - "value": "tags" - } - }, - { - "at": "/status", - "optional": true, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": true, - "rule": { - "is": "equal", - "value": "TagsTooLarge" - } - } - ] + "refusal": null }, { - "id": "operations/azure/set-tags-key-128", + "id": "operations/azure/set-tags-10-tags", "profile": "azure", "lane": "core", - "purpose": "Set a tag whose key has 128 characters, the longest a key may be", + "purpose": "Set 10 tags, the most an object takes", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], @@ -38004,7 +39033,16 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" + "tag00": "value0", + "tag01": "value1", + "tag02": "value2", + "tag03": "value3", + "tag04": "value4", + "tag05": "value5", + "tag06": "value6", + "tag07": "value7", + "tag08": "value8", + "tag09": "value9" } }, "exchanges": [ @@ -38033,7 +39071,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9" } }, { @@ -38086,10 +39124,10 @@ "refusal": null }, { - "id": "operations/azure/set-tags-key-129", + "id": "operations/azure/set-tags-11-tags", "profile": "azure", "lane": "core", - "purpose": "Report a tag key of 129 characters, one more than a key may have, as an error. A client may refuse it", + "purpose": "Report 11 tags, one more than an object takes, as an error. A client may refuse them", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], @@ -38097,7 +39135,17 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" + "tag00": "value0", + "tag01": "value1", + "tag02": "value2", + "tag03": "value3", + "tag04": "value4", + "tag05": "value5", + "tag06": "value6", + "tag07": "value7", + "tag08": "value8", + "tag09": "value9", + "tag10": "value10" } }, "exchanges": [ @@ -38126,7 +39174,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9tag10value10" } }, { @@ -38239,10 +39287,10 @@ ] }, { - "id": "operations/azure/set-tags-value-256", + "id": "operations/azure/set-tags-key-128", "profile": "azure", "lane": "core", - "purpose": "Set a tag whose value has 256 characters, the longest a value may be", + "purpose": "Set a tag whose key has 128 characters, the longest a key may be", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], @@ -38250,7 +39298,7 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" } }, "exchanges": [ @@ -38279,7 +39327,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" } }, { @@ -38332,10 +39380,10 @@ "refusal": null }, { - "id": "operations/azure/set-tags-value-257", + "id": "operations/azure/set-tags-key-129", "profile": "azure", "lane": "core", - "purpose": "Report a tag value of 257 characters, one more than a value may have, as an error. A client may refuse it", + "purpose": "Report a tag key of 129 characters, one more than a key may have, as an error. A client may refuse it", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], @@ -38343,7 +39391,7 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" } }, "exchanges": [ @@ -38372,7 +39420,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" } }, { @@ -38485,10 +39533,10 @@ ] }, { - "id": "operations/azure/set-tags-special-characters", + "id": "operations/azure/set-tags-value-256", "profile": "azure", "lane": "core", - "purpose": "Set a blob index tag with a space and each of + - = . _ : /, which Azure allows, escaped as XML text", + "purpose": "Set a tag whose value has 256 characters, the longest a value may be", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], @@ -38496,7 +39544,7 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "a b+c-d=e.f_g:h/i": "k l+m-n=o.p_q:r/s" + "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, "exchanges": [ @@ -38525,7 +39573,7 @@ "optional": false, "rule": { "is": "xml", - "value": "a b+c-d=e.f_g:h/ik l+m-n=o.p_q:r/s" + "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, { @@ -38578,10 +39626,10 @@ "refusal": null }, { - "id": "operations/azure/set-tags-invalid-character", + "id": "operations/azure/set-tags-value-257", "profile": "azure", "lane": "core", - "purpose": "Report a blob index tag key with @, which Azure does not allow, as an error. A client may refuse it", + "purpose": "Report a tag value of 257 characters, one more than a value may have, as an error. A client may refuse it", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], @@ -38589,7 +39637,7 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "a@b": "c" + "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, "exchanges": [ @@ -38618,7 +39666,7 @@ "optional": false, "rule": { "is": "xml", - "value": "a@bc" + "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, { @@ -38650,11 +39698,11 @@ "date": { "from": "now" }, - "x-ms-error-code": "InvalidTag" + "x-ms-error-code": "TagsTooLarge" }, "body": { "encoding": "utf8", - "data": "InvalidTagFixture error" + "data": "TagsTooLargeFixture error" } } } @@ -38683,7 +39731,7 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidTag" + "value": "TagsTooLarge" } } ], @@ -38725,32 +39773,278 @@ "optional": true, "rule": { "is": "equal", - "value": "InvalidTag" + "value": "TagsTooLarge" } } ] }, { - "id": "operations/azure/set-tags-duplicate-key", + "id": "operations/azure/set-tags-special-characters", "profile": "azure", "lane": "core", - "purpose": "Report blob index tags that name one key twice as an error. A client may refuse them, or report them unsupported where its API cannot repeat a key", + "purpose": "Set a blob index tag with a space and each of + - = . _ : /, which Azure allows, escaped as XML text", "sources": [ "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], "call": { "key": "object-tests/tags/object.txt", "op": "azure.set_tags", - "tags": [ - { - "key": "project", - "value": "a" - }, - { - "key": "project", - "value": "b" - } - ] + "tags": { + "a b+c-d=e.f_g:h/i": "k l+m-n=o.p_q:r/s" + } + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "a b+c-d=e.f_g:h/ik l+m-n=o.p_q:r/s" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "tags" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "one_of", + "values": [ + "application/xml", + "application/xml; charset=UTF-8" + ] + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 204, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/set-tags-invalid-character", + "profile": "azure", + "lane": "core", + "purpose": "Report a blob index tag key with @, which Azure does not allow, as an error. A client may refuse it", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "azure.set_tags", + "tags": { + "a@b": "c" + } + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "a@bc" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "tags" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "one_of", + "values": [ + "application/xml", + "application/xml; charset=UTF-8" + ] + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "InvalidTag" + }, + "body": { + "encoding": "utf8", + "data": "InvalidTagFixture error" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidTag" + } + } + ], + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "tags" + } + }, + { + "at": "/status", + "optional": true, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "InvalidTag" + } + } + ] + }, + { + "id": "operations/azure/set-tags-duplicate-key", + "profile": "azure", + "lane": "core", + "purpose": "Report blob index tags that name one key twice as an error. A client may refuse them, or report them unsupported where its API cannot repeat a key", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "azure.set_tags", + "tags": [ + { + "key": "project", + "value": "a" + }, + { + "key": "project", + "value": "b" + } + ] }, "exchanges": [ { @@ -38891,6 +40185,210 @@ ], "decline_permitted": true }, + { + "id": "operations/azure/set-tags-version", + "profile": "azure", + "lane": "core", + "purpose": "Set blob index tags on a previous version, named by versionid in the query", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "azure.set_tags", + "tags": { + "project": "object-tests" + }, + "version": "2024-01-01T00:00:00.0000000Z" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "projectobject-tests" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "tags" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "one_of", + "values": [ + "application/xml", + "application/xml; charset=UTF-8" + ] + } + }, + { + "at": "/query/versionid", + "optional": false, + "rule": { + "is": "equal", + "value": "2024-01-01T00:00:00.0000000Z" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 204, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/set-tags-snapshot", + "profile": "azure", + "lane": "core", + "purpose": "Set the blob index tags of a snapshot, named by snapshot in the query, which leaves the blob's tags alone", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "azure.set_tags", + "snapshot": "2024-01-01T00:00:00.0000000Z", + "tags": { + "project": "object-tests" + } + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "projectobject-tests" + } + }, + { + "at": "/query/comp", + "optional": false, + "rule": { + "is": "equal", + "value": "tags" + } + }, + { + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "one_of", + "values": [ + "application/xml", + "application/xml; charset=UTF-8" + ] + } + }, + { + "at": "/query/snapshot", + "optional": false, + "rule": { + "is": "equal", + "value": "2024-01-01T00:00:00.0000000Z" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 204, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, { "id": "operations/azure/put-with-tier", "profile": "azure", @@ -85952,19 +87450,17 @@ "refusal": null }, { - "id": "operations/azure-hns/set-tags", + "id": "operations/azure-hns/get-tags-version", "profile": "azure-hns", "lane": "core", - "purpose": "Replace the tags of an object, which an HNS account does not support", + "purpose": "Send a tag call on a version to an HNS account, which refuses it as it refuses the blob's", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" + "https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob-tags" ], "call": { "key": "object-tests/tags/object.txt", - "op": "azure.set_tags", - "tags": { - "project": "object-tests" - } + "op": "azure.get_tags", + "version": "2024-01-01T00:00:00.0000000Z" }, "exchanges": [ { @@ -85976,7 +87472,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -85988,11 +87484,11 @@ } }, { - "at": "/body_text", + "at": "/body_base64", "optional": false, "rule": { - "is": "xml", - "value": "projectobject-tests" + "is": "equal", + "value": "" } }, { @@ -86004,14 +87500,11 @@ } }, { - "at": "/headers/content-type", + "at": "/query/versionid", "optional": false, "rule": { - "is": "one_of", - "values": [ - "application/xml", - "application/xml; charset=UTF-8" - ] + "is": "equal", + "value": "2024-01-01T00:00:00.0000000Z" } } ], @@ -86024,11 +87517,11 @@ "date": { "from": "now" }, - "x-ms-error-code": "BlobApiNotYetSupportedForHierarchicalNamespaceAccounts" + "x-ms-error-code": "InvalidQueryParameterValue" }, "body": { "encoding": "utf8", - "data": "BlobApiNotYetSupportedForHierarchicalNamespaceAccountsFixture error" + "data": "InvalidQueryParameterValueFixture error" } } } @@ -86057,25 +87550,26 @@ "optional": false, "rule": { "is": "equal", - "value": "BlobApiNotYetSupportedForHierarchicalNamespaceAccounts" + "value": "InvalidQueryParameterValue" } } ], "refusal": null }, { - "id": "operations/azure-hns/put-with-tier", + "id": "operations/azure-hns/set-tags", "profile": "azure-hns", "lane": "core", - "purpose": "Write an object straight into the Cool access tier", + "purpose": "Replace the tags of an object, which an HNS account does not support", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], "call": { - "body_base64": "Zmlyc3Q=", - "key": "object-tests/tiers/object.txt", - "op": "put", - "tier": "Cool" + "key": "object-tests/tags/object.txt", + "op": "azure.set_tags", + "tags": { + "project": "object-tests" + } }, "exchanges": [ { @@ -86095,48 +87589,51 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/tiers/object.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { - "at": "/body_base64", + "at": "/body_text", "optional": false, "rule": { - "is": "equal", - "value": "Zmlyc3Q=" + "is": "xml", + "value": "projectobject-tests" } }, { - "at": "/headers/x-ms-blob-type", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "BlockBlob" + "value": "tags" } }, { - "at": "/headers/x-ms-access-tier", + "at": "/headers/content-type", "optional": false, "rule": { - "is": "equal", - "value": "Cool" + "is": "one_of", + "values": [ + "application/xml", + "application/xml; charset=UTF-8" + ] } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 201, + "status": 400, "headers": { + "content-type": "application/xml", "date": { "from": "now" }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", - "x-ms-request-server-encrypted": "true" + "x-ms-error-code": "BlobApiNotYetSupportedForHierarchicalNamespaceAccounts" }, "body": { - "encoding": "empty" + "encoding": "utf8", + "data": "BlobApiNotYetSupportedForHierarchicalNamespaceAccountsFixture error" } } } @@ -86149,24 +87646,43 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "BlobApiNotYetSupportedForHierarchicalNamespaceAccounts" } } ], "refusal": null }, { - "id": "operations/azure-hns/set-tier-unknown", + "id": "operations/azure-hns/set-tags-version", "profile": "azure-hns", "lane": "core", - "purpose": "Refuse an access tier the service does not have", + "purpose": "Send a tag call on a version to an HNS account, which refuses it as it refuses the blob's", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier" + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tags" ], "call": { - "key": "object-tests/tiers/object.txt", - "op": "azure.set_tier", - "tier": "Warm" + "key": "object-tests/tags/object.txt", + "op": "azure.set_tags", + "tags": { + "project": "object-tests" + }, + "version": "2024-01-01T00:00:00.0000000Z" }, "exchanges": [ { @@ -86186,15 +87702,15 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/tiers/object.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { - "at": "/body_base64", + "at": "/body_text", "optional": false, "rule": { - "is": "equal", - "value": "" + "is": "xml", + "value": "projectobject-tests" } }, { @@ -86202,15 +87718,26 @@ "optional": false, "rule": { "is": "equal", - "value": "tier" + "value": "tags" } }, { - "at": "/headers/x-ms-access-tier", + "at": "/headers/content-type", + "optional": false, + "rule": { + "is": "one_of", + "values": [ + "application/xml", + "application/xml; charset=UTF-8" + ] + } + }, + { + "at": "/query/versionid", "optional": false, "rule": { "is": "equal", - "value": "Warm" + "value": "2024-01-01T00:00:00.0000000Z" } } ], @@ -86223,11 +87750,11 @@ "date": { "from": "now" }, - "x-ms-error-code": "InvalidHeaderValue" + "x-ms-error-code": "BlobApiNotYetSupportedForHierarchicalNamespaceAccounts" }, "body": { "encoding": "utf8", - "data": "InvalidHeaderValueFixture error" + "data": "BlobApiNotYetSupportedForHierarchicalNamespaceAccountsFixture error" } } } @@ -86256,23 +87783,24 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidHeaderValue" + "value": "BlobApiNotYetSupportedForHierarchicalNamespaceAccounts" } } ], "refusal": null }, { - "id": "operations/azure-hns/set-tier-cool", + "id": "operations/azure-hns/put-with-tier", "profile": "azure-hns", "lane": "core", - "purpose": "Move an object to the Cool access tier", + "purpose": "Write an object straight into the Cool access tier", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier" + "https://learn.microsoft.com/en-us/rest/api/storageservices/put-blob" ], "call": { + "body_base64": "Zmlyc3Q=", "key": "object-tests/tiers/object.txt", - "op": "azure.set_tier", + "op": "put", "tier": "Cool" }, "exchanges": [ @@ -86301,15 +87829,15 @@ "optional": false, "rule": { "is": "equal", - "value": "" + "value": "Zmlyc3Q=" } }, { - "at": "/query/comp", + "at": "/headers/x-ms-blob-type", "optional": false, "rule": { "is": "equal", - "value": "tier" + "value": "BlockBlob" } }, { @@ -86324,11 +87852,14 @@ "allow_headers": [], "allow_query": [], "response": { - "status": 200, + "status": 201, "headers": { "date": { "from": "now" - } + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-ms-request-server-encrypted": "true" }, "body": { "encoding": "empty" @@ -86351,19 +87882,17 @@ "refusal": null }, { - "id": "operations/azure-hns/put-internal-error", + "id": "operations/azure-hns/set-tier-unknown", "profile": "azure-hns", "lane": "core", - "purpose": "Report a 500 InternalError answer as an error, after at most 5 retries", + "purpose": "Refuse an access tier the service does not have", "sources": [ - "https://learn.microsoft.com/en-us/rest/api/storageservices/common-rest-api-error-codes", - "https://learn.microsoft.com/en-us/rest/api/storageservices/blob-service-error-codes" + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier" ], - "origin": "transient", "call": { - "body_base64": "MDEyMzQ1Njc4OQ==", - "key": "object-tests/write/object.txt", - "op": "put" + "key": "object-tests/tiers/object.txt", + "op": "azure.set_tier", + "tier": "Warm" }, "exchanges": [ { @@ -86383,7 +87912,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/write/object.txt" + "value": "/fixture/object-tests/tiers/object.txt" } }, { @@ -86391,39 +87920,88 @@ "optional": false, "rule": { "is": "equal", - "value": "MDEyMzQ1Njc4OQ==" + "value": "" } }, { - "at": "/headers/x-ms-blob-type", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "BlockBlob" + "value": "tier" + } + }, + { + "at": "/headers/x-ms-access-tier", + "optional": false, + "rule": { + "is": "equal", + "value": "Warm" } } ], - "allow_headers": [ - "content-type" - ], + "allow_headers": [], "allow_query": [], "response": { - "status": 500, + "status": 400, "headers": { "content-type": "application/xml", "date": { "from": "now" }, - "x-ms-error-code": "InternalError" + "x-ms-error-code": "InvalidHeaderValue" }, "body": { "encoding": "utf8", - "data": "InternalErrorThe server encountered an internal error. Please retry the request." + "data": "InvalidHeaderValueFixture error" } } } ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidHeaderValue" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure-hns/set-tier-cool", + "profile": "azure-hns", + "lane": "core", + "purpose": "Move an object to the Cool access tier", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/set-blob-tier" + ], + "call": { + "key": "object-tests/tiers/object.txt", + "op": "azure.set_tier", + "tier": "Cool" + }, + "exchanges": [ { "alternatives": [ { @@ -86441,7 +88019,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/write/object.txt" + "value": "/fixture/object-tests/tiers/object.txt" } }, { @@ -86449,40 +88027,71 @@ "optional": false, "rule": { "is": "equal", - "value": "MDEyMzQ1Njc4OQ==" + "value": "" } }, { - "at": "/headers/x-ms-blob-type", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "BlockBlob" + "value": "tier" + } + }, + { + "at": "/headers/x-ms-access-tier", + "optional": false, + "rule": { + "is": "equal", + "value": "Cool" } } ], - "allow_headers": [ - "content-type" - ], + "allow_headers": [], "allow_query": [], "response": { - "status": 500, + "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" - }, - "x-ms-error-code": "InternalError" + } }, "body": { - "encoding": "utf8", - "data": "InternalErrorThe server encountered an internal error. Please retry the request." + "encoding": "empty" } } } - ], - "optional": true - }, + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure-hns/put-internal-error", + "profile": "azure-hns", + "lane": "core", + "purpose": "Report a 500 InternalError answer as an error, after at most 5 retries", + "sources": [ + "https://learn.microsoft.com/en-us/rest/api/storageservices/common-rest-api-error-codes", + "https://learn.microsoft.com/en-us/rest/api/storageservices/blob-service-error-codes" + ], + "origin": "transient", + "call": { + "body_base64": "MDEyMzQ1Njc4OQ==", + "key": "object-tests/write/object.txt", + "op": "put" + }, + "exchanges": [ { "alternatives": [ { @@ -86539,8 +88148,125 @@ } } } - ], - "optional": true + ] + }, + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/write/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "MDEyMzQ1Njc4OQ==" + } + }, + { + "at": "/headers/x-ms-blob-type", + "optional": false, + "rule": { + "is": "equal", + "value": "BlockBlob" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 500, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "InternalError" + }, + "body": { + "encoding": "utf8", + "data": "InternalErrorThe server encountered an internal error. Please retry the request." + } + } + } + ], + "optional": true + }, + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/write/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "MDEyMzQ1Njc4OQ==" + } + }, + { + "at": "/headers/x-ms-blob-type", + "optional": false, + "rule": { + "is": "equal", + "value": "BlockBlob" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 500, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "InternalError" + }, + "body": { + "encoding": "utf8", + "data": "InternalErrorThe server encountered an internal error. Please retry the request." + } + } + } + ], + "optional": true }, { "alternatives": [ @@ -103035,17 +104761,25 @@ ] }, { - "id": "operations/s3/delete-slow-down", + "id": "operations/s3/delete-many-versions", "profile": "s3", "lane": "core", - "purpose": "Report a 503 SlowDown answer as an error, after at most 5 retries", + "purpose": "Delete two versions of one key in one batch, each named by the VersionId of its Object, which removes the key without a delete marker", "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html" ], - "origin": "transient", "call": { - "key": "object-tests/remove/present.txt", - "op": "delete" + "keys": [ + { + "key": "object-tests/batch/a.txt", + "version": "fixture-version-1" + }, + { + "key": "object-tests/batch/a.txt", + "version": "fixture-version-2" + } + ], + "op": "delete_many" }, "exchanges": [ { @@ -103057,7 +104791,7 @@ "optional": false, "rule": { "is": "equal", - "value": "DELETE" + "value": "POST" } }, { @@ -103065,16 +104799,41 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/remove/present.txt" + "value": "/fixture" } }, { - "at": "/body_base64", + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "object-tests/batch/a.txtfixture-version-1object-tests/batch/a.txtfixture-version-2" + } + }, + { + "at": "/query/delete", "optional": false, "rule": { "is": "equal", "value": "" } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } } ], "allow_headers": [ @@ -103082,7 +104841,7 @@ ], "allow_query": [], "response": { - "status": 503, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -103091,13 +104850,66 @@ }, "body": { "encoding": "utf8", - "data": "\nSlowDownPlease reduce your request rate.fixture" + "data": "\nobject-tests/batch/a.txtfixture-version-1object-tests/batch/a.txtfixture-version-2" }, "framing": "chunked" } } ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } }, + { + "at": "/value/deleted", + "optional": false, + "rule": { + "is": "equal", + "value": [ + { + "key": "object-tests/batch/a.txt", + "version": "fixture-version-1" + }, + { + "key": "object-tests/batch/a.txt", + "version": "fixture-version-2" + } + ] + } + }, + { + "at": "/value/errors", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/delete-many-plain-key-versioned", + "profile": "s3", + "lane": "core", + "purpose": "Delete a key without a version in a versioned bucket, which S3 answers with the delete marker it made and that marker's version", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html" + ], + "call": { + "keys": [ + "object-tests/batch/a.txt" + ], + "op": "delete_many" + }, + "exchanges": [ { "alternatives": [ { @@ -103107,7 +104919,7 @@ "optional": false, "rule": { "is": "equal", - "value": "DELETE" + "value": "POST" } }, { @@ -103115,16 +104927,41 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/remove/present.txt" + "value": "/fixture" } }, { - "at": "/body_base64", + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "object-tests/batch/a.txt" + } + }, + { + "at": "/query/delete", "optional": false, "rule": { "is": "equal", "value": "" } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } } ], "allow_headers": [ @@ -103132,7 +104969,7 @@ ], "allow_query": [], "response": { - "status": 503, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -103141,14 +104978,66 @@ }, "body": { "encoding": "utf8", - "data": "\nSlowDownPlease reduce your request rate.fixture" + "data": "\nobject-tests/batch/a.txttruefixture-marker-1" }, "framing": "chunked" } } - ], - "optional": true + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/deleted", + "optional": false, + "rule": { + "is": "equal", + "value": [ + { + "delete_marker": true, + "delete_marker_version": "fixture-marker-1", + "key": "object-tests/batch/a.txt" + } + ] + } }, + { + "at": "/value/errors", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/delete-many-delete-marker", + "profile": "s3", + "lane": "core", + "purpose": "Delete a delete marker by its version in a batch, which makes the version before it current again", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html" + ], + "call": { + "keys": [ + { + "key": "object-tests/batch/a.txt", + "version": "fixture-marker-1" + } + ], + "op": "delete_many" + }, + "exchanges": [ { "alternatives": [ { @@ -103158,7 +105047,7 @@ "optional": false, "rule": { "is": "equal", - "value": "DELETE" + "value": "POST" } }, { @@ -103166,16 +105055,41 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/remove/present.txt" + "value": "/fixture" } }, { - "at": "/body_base64", + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "object-tests/batch/a.txtfixture-marker-1" + } + }, + { + "at": "/query/delete", "optional": false, "rule": { "is": "equal", "value": "" } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } } ], "allow_headers": [ @@ -103183,7 +105097,7 @@ ], "allow_query": [], "response": { - "status": 503, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -103192,14 +105106,67 @@ }, "body": { "encoding": "utf8", - "data": "\nSlowDownPlease reduce your request rate.fixture" + "data": "\nobject-tests/batch/a.txtfixture-marker-1truefixture-marker-1" }, "framing": "chunked" } } - ], - "optional": true + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/deleted", + "optional": false, + "rule": { + "is": "equal", + "value": [ + { + "delete_marker": true, + "delete_marker_version": "fixture-marker-1", + "key": "object-tests/batch/a.txt", + "version": "fixture-marker-1" + } + ] + } }, + { + "at": "/value/errors", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/delete-many-deleted-version", + "profile": "s3", + "lane": "core", + "purpose": "Delete a version that was already deleted in a batch", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html" + ], + "call": { + "keys": [ + { + "key": "object-tests/batch/a.txt", + "version": "fixture-version-1" + } + ], + "op": "delete_many" + }, + "exchanges": [ { "alternatives": [ { @@ -103209,7 +105176,7 @@ "optional": false, "rule": { "is": "equal", - "value": "DELETE" + "value": "POST" } }, { @@ -103217,16 +105184,41 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/remove/present.txt" + "value": "/fixture" } }, { - "at": "/body_base64", + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "object-tests/batch/a.txtfixture-version-1" + } + }, + { + "at": "/query/delete", "optional": false, "rule": { "is": "equal", "value": "" } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } } ], "allow_headers": [ @@ -103234,7 +105226,7 @@ ], "allow_query": [], "response": { - "status": 503, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -103243,13 +105235,263 @@ }, "body": { "encoding": "utf8", - "data": "\nSlowDownPlease reduce your request rate.fixture" + "data": "\nobject-tests/batch/a.txtfixture-version-1" }, "framing": "chunked" } } - ], - "optional": true + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/deleted", + "optional": false, + "rule": { + "is": "equal", + "value": [ + { + "key": "object-tests/batch/a.txt", + "version": "fixture-version-1" + } + ] + } + }, + { + "at": "/value/errors", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/delete-slow-down", + "profile": "s3", + "lane": "core", + "purpose": "Report a 503 SlowDown answer as an error, after at most 5 retries", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html" + ], + "origin": "transient", + "call": { + "key": "object-tests/remove/present.txt", + "op": "delete" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "DELETE" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/remove/present.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 503, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nSlowDownPlease reduce your request rate.fixture" + }, + "framing": "chunked" + } + } + ] + }, + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "DELETE" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/remove/present.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 503, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nSlowDownPlease reduce your request rate.fixture" + }, + "framing": "chunked" + } + } + ], + "optional": true + }, + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "DELETE" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/remove/present.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 503, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nSlowDownPlease reduce your request rate.fixture" + }, + "framing": "chunked" + } + } + ], + "optional": true + }, + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "DELETE" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/remove/present.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 503, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nSlowDownPlease reduce your request rate.fixture" + }, + "framing": "chunked" + } + } + ], + "optional": true }, { "alternatives": [ @@ -108520,16 +110762,15 @@ "refusal": null }, { - "id": "operations/s3/get-not-modified", + "id": "operations/s3/get-archived", "profile": "s3", "lane": "core", - "purpose": "get not modified", + "purpose": "Get a GLACIER object that was not restored, which S3 refuses with 403 InvalidObjectState", "sources": [ - "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html" ], "call": { - "if_none_match": "\"fixture-ad03f2ab332a\"", - "key": "object-tests/read/object.txt", + "key": "object-tests/archive/object.txt", "op": "get" }, "exchanges": [ @@ -108550,7 +110791,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/read/object.txt" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -108560,14 +110801,6 @@ "is": "equal", "value": "" } - }, - { - "at": "/headers/if-none-match", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-ad03f2ab332a\"" - } } ], "allow_headers": [ @@ -108575,17 +110808,18 @@ ], "allow_query": [], "response": { - "status": 304, + "status": 403, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-ad03f2ab332a\"" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nInvalidObjectStateFixture error" + }, + "framing": "chunked" } }, { @@ -108603,7 +110837,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/read/object.txt" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -108614,14 +110848,6 @@ "value": "" } }, - { - "at": "/headers/if-none-match", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-ad03f2ab332a\"" - } - }, { "at": "/headers/range", "optional": false, @@ -108636,17 +110862,18 @@ ], "allow_query": [], "response": { - "status": 304, + "status": 403, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-ad03f2ab332a\"" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nInvalidObjectStateFixture error" + }, + "framing": "chunked" } } ] @@ -108666,22 +110893,183 @@ "optional": false, "rule": { "is": "equal", - "value": 304 + "value": 403 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidObjectState" } } ], "refusal": null }, { - "id": "operations/s3/get-precondition-failed", + "id": "operations/s3/get-not-modified", "profile": "s3", "lane": "core", - "purpose": "get precondition failed", + "purpose": "get not modified", "sources": [ "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" ], "call": { - "if_match": "\"fixture-db71b2c0257c\"", + "if_none_match": "\"fixture-ad03f2ab332a\"", + "key": "object-tests/read/object.txt", + "op": "get" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/read/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/if-none-match", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-ad03f2ab332a\"" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 304, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-ad03f2ab332a\"" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/read/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/if-none-match", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-ad03f2ab332a\"" + } + }, + { + "at": "/headers/range", + "optional": false, + "rule": { + "is": "matches", + "pattern": "bytes=0-[1-9][0-9]{2,}" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 304, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-ad03f2ab332a\"" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 304 + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/get-precondition-failed", + "profile": "s3", + "lane": "core", + "purpose": "get precondition failed", + "sources": [ + "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + ], + "call": { + "if_match": "\"fixture-db71b2c0257c\"", "key": "object-tests/read/object.txt", "op": "get" }, @@ -115867,17 +118255,16 @@ "refusal": null }, { - "id": "operations/s3/list-bad-marker", + "id": "operations/s3/head-restoring", "profile": "s3", "lane": "core", - "purpose": "Report S3's 400 InvalidArgument for a continuation token it did not issue", + "purpose": "Report the x-amz-restore header of an object whose restore runs as its restore status", "sources": [ - "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html" ], "call": { - "continuation_token": "fixture-marker+/ce6f21ae951d=", - "op": "list_page", - "prefix": "object-tests/board/" + "key": "object-tests/archive/object.txt", + "op": "head" }, "exchanges": [ { @@ -115889,7 +118276,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "HEAD" } }, { @@ -115897,7 +118284,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -115907,49 +118294,154 @@ "is": "equal", "value": "" } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-length": "30", + "content-type": "binary/octet-stream", + "date": { + "from": "now" + }, + "etag": "\"fixture-ad03f2ab332a\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT", + "x-amz-restore": "ongoing-request=\"true\"", + "x-amz-storage-class": "GLACIER" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-ad03f2ab332a\"" + } + }, + { + "at": "/value/size", + "optional": false, + "rule": { + "is": "equal", + "value": 30 + } + }, + { + "at": "/value/content_type", + "optional": false, + "rule": { + "is": "equal", + "value": "binary/octet-stream" + } + }, + { + "at": "/value/restore_status", + "optional": false, + "rule": { + "is": "equal", + "value": "ongoing-request=\"true\"" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/restore-version", + "profile": "s3", + "lane": "core", + "purpose": "Restore a previous version that is archived, named by versionId in the query", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html" + ], + "call": { + "days": 1, + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "standard", + "version": "fixture-version-1" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "POST" + } }, { - "at": "/query/list-type", + "at": "/path", "optional": false, "rule": { "is": "equal", - "value": "2" + "value": "/fixture/object-tests/archive/object.txt" } }, { - "at": "/query/prefix", + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "1Standard" + } + }, + { + "at": "/query/restore", "optional": false, "rule": { "is": "equal", - "value": "object-tests/board/" + "value": "" } }, { - "at": "/query/continuation-token", + "at": "/query/versionId", "optional": false, "rule": { "is": "equal", - "value": "fixture-marker+/ce6f21ae951d=" + "value": "fixture-version-1" } } ], "allow_headers": [ - "content-type" + "content-type", + "x-amz-api-version" ], "allow_query": [], "response": { - "status": 400, + "status": 202, "headers": { - "content-type": "application/xml", "date": { "from": "now" } }, "body": { - "encoding": "utf8", - "data": "\nInvalidArgumentFixture error" - }, - "framing": "chunked" + "encoding": "empty" + } } }, { @@ -115959,7 +118451,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "POST" } }, { @@ -115967,52 +118459,128 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { - "at": "/body_base64", + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "1Standard" + } + }, + { + "at": "/query/restore", "optional": false, "rule": { "is": "equal", - "value": "" + "value": "restore" } }, { - "at": "/query/list-type", + "at": "/query/versionId", "optional": false, "rule": { "is": "equal", - "value": "2" + "value": "fixture-version-1" + } + } + ], + "allow_headers": [ + "content-type", + "x-amz-api-version" + ], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "date": { + "from": "now" } }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/state", + "optional": false, + "rule": { + "is": "equal", + "value": "started" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/restore-without-days", + "profile": "s3", + "lane": "core", + "purpose": "Restore a GLACIER object without Days, which only an Intelligent-Tiering archive may leave out", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html" + ], + "call": { + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "standard" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ { - "at": "/query/prefix", + "at": "/method", "optional": false, "rule": { "is": "equal", - "value": "object-tests/board/" + "value": "POST" } }, { - "at": "/query/continuation-token", + "at": "/path", "optional": false, "rule": { "is": "equal", - "value": "fixture-marker+/ce6f21ae951d=" + "value": "/fixture/object-tests/archive/object.txt" } }, { - "at": "/query/encoding-type", + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "Standard" + } + }, + { + "at": "/query/restore", "optional": false, "rule": { "is": "equal", - "value": "url" + "value": "" } } ], "allow_headers": [ - "content-type" + "content-type", + "x-amz-api-version" ], "allow_query": [], "response": { @@ -116025,7 +118593,592 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidArgumentThe continuation token provided is incorrectcontinuation-tokenNQMNJ1VWXJVB4568Xe4ibV4/CeMc0lPl/vnTn1PlV2EEGNHZ+ST6o8IyEOh1TYXGMx01Jf1TkbwfTtRpHhsL/Tjn/tA=" + "data": "\nMalformedXMLFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "MalformedXML" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/restore-not-archived", + "profile": "s3", + "lane": "core", + "purpose": "Restore a STANDARD object, which S3 refuses with 403 InvalidObjectState", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html" + ], + "call": { + "days": 1, + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "standard" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "POST" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/archive/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "1Standard" + } + }, + { + "at": "/query/restore", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type", + "x-amz-api-version" + ], + "allow_query": [], + "response": { + "status": 403, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidObjectStateFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 403 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidObjectState" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/restore-in-progress", + "profile": "s3", + "lane": "core", + "purpose": "Restore an object a second time while the first restore runs, which S3 refuses with 409 RestoreAlreadyInProgress", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html" + ], + "call": { + "days": 1, + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "standard" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "POST" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/archive/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "1Standard" + } + }, + { + "at": "/query/restore", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type", + "x-amz-api-version" + ], + "allow_query": [], + "response": { + "status": 409, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nRestoreAlreadyInProgressFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 409 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "RestoreAlreadyInProgress" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/restore-expedited", + "profile": "s3", + "lane": "core", + "purpose": "Start restoring a GLACIER object at the Expedited tier, which a high priority names", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html" + ], + "call": { + "days": 1, + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "high" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "POST" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/archive/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "1Expedited" + } + }, + { + "at": "/query/restore", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type", + "x-amz-api-version" + ], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/state", + "optional": false, + "rule": { + "is": "equal", + "value": "started" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/restore", + "profile": "s3", + "lane": "core", + "purpose": "Start restoring a GLACIER object for one day at the Standard tier, which S3 accepts with 202", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html" + ], + "call": { + "days": 1, + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "standard" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "POST" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/archive/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "1Standard" + } + }, + { + "at": "/query/restore", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [ + "content-type", + "x-amz-api-version" + ], + "allow_query": [], + "response": { + "status": 202, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/state", + "optional": false, + "rule": { + "is": "equal", + "value": "started" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/list-bad-marker", + "profile": "s3", + "lane": "core", + "purpose": "Report S3's 400 InvalidArgument for a continuation token it did not issue", + "sources": [ + "aws-sdk-cpp/generated/src/aws-cpp-sdk-s3-crt" + ], + "call": { + "continuation_token": "fixture-marker+/ce6f21ae951d=", + "op": "list_page", + "prefix": "object-tests/board/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/list-type", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/board/" + } + }, + { + "at": "/query/continuation-token", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-marker+/ce6f21ae951d=" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidArgumentFixture error" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/list-type", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/board/" + } + }, + { + "at": "/query/continuation-token", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-marker+/ce6f21ae951d=" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidArgumentThe continuation token provided is incorrectcontinuation-tokenNQMNJ1VWXJVB4568Xe4ibV4/CeMc0lPl/vnTn1PlV2EEGNHZ+ST6o8IyEOh1TYXGMx01Jf1TkbwfTtRpHhsL/Tjn/tA=" }, "framing": "chunked" } @@ -121866,6 +125019,2527 @@ ], "refusal": null }, + { + "id": "operations/s3/list-versions-unversioned", + "profile": "s3", + "lane": "core", + "purpose": "List the versions in a bucket that was never versioned, where each key has one version named null", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html" + ], + "call": { + "include": [ + "versions" + ], + "op": "list_page", + "prefix": "object-tests/versions/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtnulltrue2024-01-01T00:00:00.000Z"fixture-a1"2STANDARD" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtnulltrue2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDurl" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "versions" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtnulltrue2024-01-01T00:00:00.000Z"fixture-a1"2STANDARD" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/entries/0/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/entries/0/version", + "optional": false, + "rule": { + "is": "equal", + "value": "null" + } + }, + { + "at": "/value/entries/0/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/0/size", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } + }, + { + "at": "/value/entries/0/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-a1\"" + } + }, + { + "at": "/value/entries/0/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries", + "optional": false, + "rule": { + "is": "array_length", + "value": 1 + } + }, + { + "at": "/value/prefixes", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + }, + { + "at": "/value/continuation_token", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/value/next_version_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/list-versions-encoded-key", + "profile": "s3", + "lane": "core", + "purpose": "List the versions of a key with a space and a non-ASCII letter, which an encoded listing sends encoded", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html" + ], + "call": { + "include": [ + "versions" + ], + "op": "list_page", + "prefix": "object-tests/versions/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a b é.txtfixture-version-1true2024-01-01T00:00:00.000Z"fixture-a1"2STANDARD" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a+b+%C3%A9.txtfixture-version-1true2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDurl" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "versions" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a b é.txtfixture-version-1true2024-01-01T00:00:00.000Z"fixture-a1"2STANDARD" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/entries/0/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a b é.txt" + } + }, + { + "at": "/value/entries/0/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + }, + { + "at": "/value/entries/0/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/0/size", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } + }, + { + "at": "/value/entries/0/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-a1\"" + } + }, + { + "at": "/value/entries/0/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries", + "optional": false, + "rule": { + "is": "array_length", + "value": 1 + } + }, + { + "at": "/value/prefixes", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + }, + { + "at": "/value/continuation_token", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/value/next_version_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/list-versions-next-page", + "profile": "s3", + "lane": "core", + "purpose": "List the next page of versions from a key marker and a version marker", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html" + ], + "call": { + "continuation_token": "object-tests/versions/a.txt", + "include": [ + "versions" + ], + "op": "list_page", + "page_size": 2, + "prefix": "object-tests/versions/", + "version_marker": "fixture-version-1" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/max-keys", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/query/key-marker", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/query/version-id-marker", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/object-tests/versions/a.txtfixture-version-12falseobject-tests/versions/b.txtfixture-version-3true2024-01-01T00:00:00.000Z"fixture-b1"1STANDARD" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/max-keys", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/query/key-marker", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/query/version-id-marker", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/object-tests/versions/a.txtfixture-version-12falseobject-tests/versions/b.txtfixture-version-3true2024-01-01T00:00:00.000Z"fixture-b1"1STANDARDurl" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "versions" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/max-keys", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/query/key-marker", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/query/version-id-marker", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/object-tests/versions/a.txtfixture-version-12falseobject-tests/versions/b.txtfixture-version-3true2024-01-01T00:00:00.000Z"fixture-b1"1STANDARD" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/entries/0/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/b.txt" + } + }, + { + "at": "/value/entries/0/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-3" + } + }, + { + "at": "/value/entries/0/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/0/size", + "optional": false, + "rule": { + "is": "equal", + "value": 1 + } + }, + { + "at": "/value/entries/0/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-b1\"" + } + }, + { + "at": "/value/entries/0/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries", + "optional": false, + "rule": { + "is": "array_length", + "value": 1 + } + }, + { + "at": "/value/prefixes", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + }, + { + "at": "/value/continuation_token", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/value/next_version_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/list-versions-first-page", + "profile": "s3", + "lane": "core", + "purpose": "List the first page of versions, which names the key and version to continue from", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html" + ], + "call": { + "include": [ + "versions" + ], + "op": "list_page", + "page_size": 2, + "prefix": "object-tests/versions/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/max-keys", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/object-tests/versions/a.txtfixture-version-12trueobject-tests/versions/a.txtfixture-version-2true2024-01-01T00:00:00.000Z"fixture-a2"2STANDARDobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARD" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/max-keys", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/object-tests/versions/a.txtfixture-version-12trueobject-tests/versions/a.txtfixture-version-2true2024-01-01T00:00:00.000Z"fixture-a2"2STANDARDobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDurl" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "versions" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/max-keys", + "optional": false, + "rule": { + "is": "equal", + "value": "2" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/object-tests/versions/a.txtfixture-version-12trueobject-tests/versions/a.txtfixture-version-2true2024-01-01T00:00:00.000Z"fixture-a2"2STANDARDobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARD" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/entries/0/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/entries/0/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-2" + } + }, + { + "at": "/value/entries/0/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/0/size", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } + }, + { + "at": "/value/entries/0/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-a2\"" + } + }, + { + "at": "/value/entries/0/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries/1/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/entries/1/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + }, + { + "at": "/value/entries/1/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": false + } + }, + { + "at": "/value/entries/1/size", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } + }, + { + "at": "/value/entries/1/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-a1\"" + } + }, + { + "at": "/value/entries/1/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries", + "optional": false, + "rule": { + "is": "array_length", + "value": 2 + } + }, + { + "at": "/value/prefixes", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + }, + { + "at": "/value/continuation_token", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/next_version_marker", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/list-versions-delimited", + "profile": "s3", + "lane": "core", + "purpose": "List versions with a delimiter, which rolls the versions under a deeper prefix into one common prefix", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html" + ], + "call": { + "delimiter": "/", + "include": [ + "versions" + ], + "op": "list_page", + "prefix": "object-tests/versions/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/delimiter", + "optional": false, + "rule": { + "is": "equal", + "value": "/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000/falseobject-tests/versions/a.txtfixture-version-1true2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDobject-tests/versions/nested/" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/delimiter", + "optional": false, + "rule": { + "is": "equal", + "value": "/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000/falseobject-tests/versions/a.txtfixture-version-1true2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDobject-tests/versions/nested/url" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "versions" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/query/delimiter", + "optional": false, + "rule": { + "is": "equal", + "value": "/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000/falseobject-tests/versions/a.txtfixture-version-1true2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDobject-tests/versions/nested/" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/entries/0/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/entries/0/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + }, + { + "at": "/value/entries/0/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/0/size", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } + }, + { + "at": "/value/entries/0/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-a1\"" + } + }, + { + "at": "/value/entries/0/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries", + "optional": false, + "rule": { + "is": "array_length", + "value": 1 + } + }, + { + "at": "/value/prefixes", + "optional": false, + "rule": { + "is": "equal", + "value": [ + "object-tests/versions/nested/" + ] + } + }, + { + "at": "/value/continuation_token", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/value/next_version_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/list-versions-delete-marker", + "profile": "s3", + "lane": "core", + "purpose": "List a deleted key's delete marker as its current entry, before the version it hides", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html" + ], + "call": { + "include": [ + "versions" + ], + "op": "list_page", + "prefix": "object-tests/versions/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtfixture-marker-1true2024-01-01T00:00:00.000Zobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARD" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtfixture-marker-1true2024-01-01T00:00:00.000Zobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDurl" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "versions" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtfixture-marker-1true2024-01-01T00:00:00.000Zobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARD" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/entries/0/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/entries/0/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-marker-1" + } + }, + { + "at": "/value/entries/0/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/0/delete_marker", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/1/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/entries/1/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + }, + { + "at": "/value/entries/1/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": false + } + }, + { + "at": "/value/entries/1/size", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } + }, + { + "at": "/value/entries/1/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-a1\"" + } + }, + { + "at": "/value/entries/1/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries", + "optional": false, + "rule": { + "is": "array_length", + "value": 2 + } + }, + { + "at": "/value/prefixes", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + }, + { + "at": "/value/continuation_token", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/value/next_version_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/list-versions", + "profile": "s3", + "lane": "core", + "purpose": "List every version of each key, newest first, with the current one marked IsLatest", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html" + ], + "call": { + "include": [ + "versions" + ], + "op": "list_page", + "prefix": "object-tests/versions/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtfixture-version-2true2024-01-01T00:00:00.000Z"fixture-a2"2STANDARDobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDobject-tests/versions/b.txtfixture-version-3true2024-01-01T00:00:00.000Z"fixture-b1"1STANDARD" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtfixture-version-2true2024-01-01T00:00:00.000Z"fixture-a2"2STANDARDobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDobject-tests/versions/b.txtfixture-version-3true2024-01-01T00:00:00.000Z"fixture-b1"1STANDARDurl" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "versions" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + }, + "body": { + "encoding": "utf8", + "data": "\nfixtureobject-tests/versions/1000falseobject-tests/versions/a.txtfixture-version-2true2024-01-01T00:00:00.000Z"fixture-a2"2STANDARDobject-tests/versions/a.txtfixture-version-1false2024-01-01T00:00:00.000Z"fixture-a1"2STANDARDobject-tests/versions/b.txtfixture-version-3true2024-01-01T00:00:00.000Z"fixture-b1"1STANDARD" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/entries/0/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/entries/0/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-2" + } + }, + { + "at": "/value/entries/0/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/0/size", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } + }, + { + "at": "/value/entries/0/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-a2\"" + } + }, + { + "at": "/value/entries/0/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries/1/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/a.txt" + } + }, + { + "at": "/value/entries/1/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + }, + { + "at": "/value/entries/1/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": false + } + }, + { + "at": "/value/entries/1/size", + "optional": false, + "rule": { + "is": "equal", + "value": 2 + } + }, + { + "at": "/value/entries/1/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-a1\"" + } + }, + { + "at": "/value/entries/1/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries/2/key", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/b.txt" + } + }, + { + "at": "/value/entries/2/version", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-3" + } + }, + { + "at": "/value/entries/2/is_current_version", + "optional": false, + "rule": { + "is": "equal", + "value": true + } + }, + { + "at": "/value/entries/2/size", + "optional": false, + "rule": { + "is": "equal", + "value": 1 + } + }, + { + "at": "/value/entries/2/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-b1\"" + } + }, + { + "at": "/value/entries/2/delete_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + false + ] + } + }, + { + "at": "/value/entries", + "optional": false, + "rule": { + "is": "array_length", + "value": 3 + } + }, + { + "at": "/value/prefixes", + "optional": false, + "rule": { + "is": "equal", + "value": [] + } + }, + { + "at": "/value/continuation_token", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/value/next_version_marker", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, { "id": "operations/s3/list-prefix-without-slash", "profile": "s3", @@ -135789,6 +141463,513 @@ ], "refusal": null }, + { + "id": "operations/s3/get-tagging-version", + "profile": "s3", + "lane": "core", + "purpose": "Get the tags of a previous version, named by versionId in the query", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "s3.get_tagging", + "version": "fixture-version-1" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nprojectobject-tests" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "tagging" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nprojectobject-tests" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/tags", + "optional": false, + "rule": { + "is": "equal", + "value": { + "project": "object-tests" + } + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/get-tagging-deleted-version", + "profile": "s3", + "lane": "core", + "purpose": "Send a tag call on a version that was deleted", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "s3.get_tagging", + "version": "fixture-version-1" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 404, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nNoSuchVersionFixture error" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "tagging" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 404, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nNoSuchVersionFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 404 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "NoSuchVersion" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/get-tagging-malformed-version", + "profile": "s3", + "lane": "core", + "purpose": "Send a tag call on a version ID that S3 could never have given, which it answers as an invalid argument", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "s3.get_tagging", + "version": "3sL4kqtJlcpXroDTDmJ.rmSpXd3dIbrHY" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "3sL4kqtJlcpXroDTDmJ.rmSpXd3dIbrHY" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidArgumentFixture error" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "tagging" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "3sL4kqtJlcpXroDTDmJ.rmSpXd3dIbrHY" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidArgumentFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidArgument" + } + } + ], + "refusal": null + }, { "id": "operations/s3/put-tagging", "profile": "s3", @@ -136094,7 +142275,531 @@ }, "body": { "encoding": "utf8", - "data": "\nBadRequestFixture error" + "data": "\nBadRequestFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "BadRequest" + } + } + ], + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "tags" + } + }, + { + "at": "/status", + "optional": true, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "BadRequest" + } + } + ] + }, + { + "id": "operations/s3/put-tagging-key-128", + "profile": "s3", + "lane": "core", + "purpose": "Set a tag whose key has 128 characters, the longest a key may be", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "s3.put_tagging", + "tags": { + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" + } + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-tagging-key-129", + "profile": "s3", + "lane": "core", + "purpose": "Report a tag key of 129 characters, one more than a key may have, as an error. A client may refuse it", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "s3.put_tagging", + "tags": { + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" + } + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidTagFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidTag" + } + } + ], + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "tags" + } + }, + { + "at": "/status", + "optional": true, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "InvalidTag" + } + } + ] + }, + { + "id": "operations/s3/put-tagging-value-256", + "profile": "s3", + "lane": "core", + "purpose": "Set a tag whose value has 256 characters, the longest a value may be", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "s3.put_tagging", + "tags": { + "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + } + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-tagging-value-257", + "profile": "s3", + "lane": "core", + "purpose": "Report a tag value of 257 characters, one more than a value may have, as an error. A client may refuse it", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "s3.put_tagging", + "tags": { + "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + } + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidTagFixture error" }, "framing": "chunked" } @@ -136124,7 +142829,7 @@ "optional": false, "rule": { "is": "equal", - "value": "BadRequest" + "value": "InvalidTag" } } ], @@ -136166,16 +142871,16 @@ "optional": true, "rule": { "is": "equal", - "value": "BadRequest" + "value": "InvalidTag" } } ] }, { - "id": "operations/s3/put-tagging-key-128", + "id": "operations/s3/put-tagging-special-characters", "profile": "s3", "lane": "core", - "purpose": "Set a tag whose key has 128 characters, the longest a key may be", + "purpose": "Set a tag with a space and each of + - = . _ : / @, which S3 allows, escaped as XML text", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], @@ -136183,7 +142888,7 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" + "a b+c-d=e.f_g:h/i@j": "k l+m-n=o.p_q:r/s@t" } }, "exchanges": [ @@ -136212,7 +142917,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + "value": "a b+c-d=e.f_g:h/i@jk l+m-n=o.p_q:r/s@t" } }, { @@ -136273,10 +142978,10 @@ "refusal": null }, { - "id": "operations/s3/put-tagging-key-129", + "id": "operations/s3/put-tagging-invalid-character", "profile": "s3", "lane": "core", - "purpose": "Report a tag key of 129 characters, one more than a key may have, as an error. A client may refuse it", + "purpose": "Report a tag key with !, which S3 does not allow, as an error. A client may refuse it", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], @@ -136284,7 +142989,7 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" + "a!b": "c" } }, "exchanges": [ @@ -136313,7 +143018,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + "value": "a!bc" } }, { @@ -136434,120 +143139,26 @@ ] }, { - "id": "operations/s3/put-tagging-value-256", + "id": "operations/s3/put-tagging-duplicate-key", "profile": "s3", "lane": "core", - "purpose": "Set a tag whose value has 256 characters, the longest a value may be", + "purpose": "Report a tag set that names one key twice as an error. A client may refuse it, or report it unsupported where its API cannot repeat a key", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], "call": { "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", - "tags": { - "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" - } - }, - "exchanges": [ - { - "alternatives": [ - { - "request": [ - { - "at": "/method", - "optional": false, - "rule": { - "is": "equal", - "value": "PUT" - } - }, - { - "at": "/path", - "optional": false, - "rule": { - "is": "equal", - "value": "/fixture/object-tests/tags/object.txt" - } - }, - { - "at": "/body_text", - "optional": false, - "rule": { - "is": "xml", - "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" - } - }, - { - "at": "/query/tagging", - "optional": false, - "rule": { - "is": "equal", - "value": "" - } - }, - { - "at": "/headers/x-amz-checksum-crc64nvme", - "optional": false, - "rule": { - "is": "matches", - "pattern": "[A-Za-z0-9+/]{11}=" - } - }, - { - "at": "", - "optional": false, - "rule": { - "is": "body_checksum", - "header": "x-amz-checksum-crc64nvme", - "algorithm": "crc64nvme" - } - } - ], - "allow_headers": [ - "content-type" - ], - "allow_query": [], - "response": { - "status": 200, - "headers": { - "date": { - "from": "now" - } - }, - "body": { - "encoding": "empty" - } - } - } - ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "ok" + "tags": [ + { + "key": "project", + "value": "a" + }, + { + "key": "project", + "value": "b" } - } - ], - "refusal": null - }, - { - "id": "operations/s3/put-tagging-value-257", - "profile": "s3", - "lane": "core", - "purpose": "Report a tag value of 257 characters, one more than a value may have, as an error. A client may refuse it", - "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" - ], - "call": { - "key": "object-tests/tags/object.txt", - "op": "s3.put_tagging", - "tags": { - "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" - } + ] }, "exchanges": [ { @@ -136575,7 +143186,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "value": "projectaprojectb" } }, { @@ -136693,13 +143304,14 @@ "value": "InvalidTag" } } - ] + ], + "decline_permitted": true }, { - "id": "operations/s3/put-tagging-special-characters", + "id": "operations/s3/put-tagging-version", "profile": "s3", "lane": "core", - "purpose": "Set a tag with a space and each of + - = . _ : / @, which S3 allows, escaped as XML text", + "purpose": "Set the tags of a previous version, named by versionId in the query", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], @@ -136707,8 +143319,9 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "a b+c-d=e.f_g:h/i@j": "k l+m-n=o.p_q:r/s@t" - } + "project": "object-tests" + }, + "version": "fixture-version-1" }, "exchanges": [ { @@ -136736,7 +143349,7 @@ "optional": false, "rule": { "is": "xml", - "value": "a b+c-d=e.f_g:h/i@jk l+m-n=o.p_q:r/s@t" + "value": "projectobject-tests" } }, { @@ -136763,6 +143376,90 @@ "header": "x-amz-checksum-crc64nvme", "algorithm": "crc64nvme" } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + } + }, + "body": { + "encoding": "empty" + } + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "projectobject-tests" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "tagging" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } } ], "allow_headers": [ @@ -136797,10 +143494,10 @@ "refusal": null }, { - "id": "operations/s3/put-tagging-invalid-character", + "id": "operations/s3/put-tagging-deleted-version", "profile": "s3", "lane": "core", - "purpose": "Report a tag key with !, which S3 does not allow, as an error. A client may refuse it", + "purpose": "Send a tag call on a version that was deleted", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], @@ -136808,8 +143505,9 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "a!b": "c" - } + "project": "object-tests" + }, + "version": "fixture-version-1" }, "exchanges": [ { @@ -136837,7 +143535,7 @@ "optional": false, "rule": { "is": "xml", - "value": "a!bc" + "value": "projectobject-tests" } }, { @@ -136864,6 +143562,14 @@ "header": "x-amz-checksum-crc64nvme", "algorithm": "crc64nvme" } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } } ], "allow_headers": [ @@ -136871,7 +143577,7 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 404, "headers": { "content-type": "application/xml", "date": { @@ -136880,7 +143586,86 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidTagFixture error" + "data": "\nNoSuchVersionFixture error" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "projectobject-tests" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "tagging" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 404, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nNoSuchVersionFixture error" }, "framing": "chunked" } @@ -136902,7 +143687,7 @@ "optional": false, "rule": { "is": "equal", - "value": 400 + "value": 404 } }, { @@ -136910,74 +143695,27 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidTag" + "value": "NoSuchVersion" } } ], - "refusal": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "refused" - } - }, - { - "at": "/kind", - "optional": false, - "rule": { - "is": "matches", - "pattern": ".+" - } - }, - { - "at": "/parameter", - "optional": false, - "rule": { - "is": "equal", - "value": "tags" - } - }, - { - "at": "/status", - "optional": true, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": true, - "rule": { - "is": "equal", - "value": "InvalidTag" - } - } - ] + "refusal": null }, { - "id": "operations/s3/put-tagging-duplicate-key", + "id": "operations/s3/put-tagging-malformed-version", "profile": "s3", "lane": "core", - "purpose": "Report a tag set that names one key twice as an error. A client may refuse it, or report it unsupported where its API cannot repeat a key", + "purpose": "Send a tag call on a version ID that S3 could never have given, which it answers as an invalid argument", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], "call": { "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", - "tags": [ - { - "key": "project", - "value": "a" - }, - { - "key": "project", - "value": "b" - } - ] + "tags": { + "project": "object-tests" + }, + "version": "3sL4kqtJlcpXroDTDmJ.rmSpXd3dIbrHY" }, "exchanges": [ { @@ -137005,7 +143743,7 @@ "optional": false, "rule": { "is": "xml", - "value": "projectaprojectb" + "value": "projectobject-tests" } }, { @@ -137032,6 +143770,93 @@ "header": "x-amz-checksum-crc64nvme", "algorithm": "crc64nvme" } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "3sL4kqtJlcpXroDTDmJ.rmSpXd3dIbrHY" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidArgumentFixture error" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/tags/object.txt" + } + }, + { + "at": "/body_text", + "optional": false, + "rule": { + "is": "xml", + "value": "projectobject-tests" + } + }, + { + "at": "/query/tagging", + "optional": false, + "rule": { + "is": "equal", + "value": "tagging" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" + } + }, + { + "at": "", + "optional": false, + "rule": { + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" + } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "3sL4kqtJlcpXroDTDmJ.rmSpXd3dIbrHY" + } } ], "allow_headers": [ @@ -137048,7 +143873,7 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidTagFixture error" + "data": "\nInvalidArgumentFixture error" }, "framing": "chunked" } @@ -137078,53 +143903,11 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidTag" - } - } - ], - "refusal": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "refused" - } - }, - { - "at": "/kind", - "optional": false, - "rule": { - "is": "matches", - "pattern": ".+" - } - }, - { - "at": "/parameter", - "optional": false, - "rule": { - "is": "equal", - "value": "tags" - } - }, - { - "at": "/status", - "optional": true, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": true, - "rule": { - "is": "equal", - "value": "InvalidTag" + "value": "InvalidArgument" } } ], - "decline_permitted": true + "refusal": null }, { "id": "operations/s3/put-internal-error", @@ -186271,6 +193054,435 @@ ], "refusal": null }, + { + "id": "operations/s3-express/list-versions", + "profile": "s3-express", + "lane": "core", + "purpose": "Send ListObjectVersions to a directory bucket, which keeps no versions", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html" + ], + "call": { + "include": [ + "versions" + ], + "op": "list_page", + "prefix": "object-tests/versions/" + }, + "exchanges": [ + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/" + } + }, + { + "at": "/query/session", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=offline/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "absent" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "content-type": "application/xml" + }, + "body": { + "encoding": "utf8", + "data": "\nfixture-session-tokenfixture-secret-keyfixture-access-keySESSION_EXPIRATION" + }, + "body_time": { + "text": "SESSION_EXPIRATION", + "offset_seconds": 300 + } + } + } + ] + }, + { + "alternatives": [ + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-session-token" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=fixture-access-key/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 501, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nNotImplementedFixture error" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-session-token" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=fixture-access-key/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + }, + { + "at": "/query/encoding-type", + "optional": false, + "rule": { + "is": "equal", + "value": "url" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 501, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nNotImplementedFixture error" + }, + "framing": "chunked" + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "GET" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "" + } + }, + { + "at": "/query/versions", + "optional": false, + "rule": { + "is": "equal", + "value": "versions" + } + }, + { + "at": "/query/prefix", + "optional": false, + "rule": { + "is": "equal", + "value": "object-tests/versions/" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/" + } + }, + { + "at": "/headers/host", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture--euc1-az1--x-s3.s3express-euc1-az1.fixture.invalid" + } + }, + { + "at": "/headers/x-amz-s3session-token", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-session-token" + } + }, + { + "at": "/headers/authorization", + "optional": false, + "rule": { + "is": "matches", + "pattern": "AWS4-HMAC-SHA256 Credential=fixture-access-key/[0-9]{8}/eu-central-1/s3express/aws4_request, SignedHeaders=.+, Signature=[a-f0-9]{64}" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 501, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nNotImplementedFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/status", + "optional": false, + "rule": { + "is": "equal", + "value": 501 + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "NotImplemented" + } + } + ], + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", + "optional": false, + "rule": { + "is": "equal", + "value": "include" + } + }, + { + "at": "/status", + "optional": true, + "rule": { + "is": "equal", + "value": 501 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "NotImplemented" + } + } + ] + }, { "id": "operations/s3-express/list-prefix-without-slash", "profile": "s3-express", diff --git a/src/model.rs b/src/model.rs index 5694e9f..7981d52 100644 --- a/src/model.rs +++ b/src/model.rs @@ -272,12 +272,14 @@ pub enum Rule { }, } -/// A subrequest of an Azure Blob Batch, with its path decoded. +/// A subrequest of an Azure Blob Batch, with its path and query decoded. No query means none. #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[serde(deny_unknown_fields)] pub struct BatchSubrequest { pub method: String, pub path: String, + #[serde(default, skip_serializing_if = "BTreeMap::is_empty")] + pub query: BTreeMap, } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/src/request_rules.rs b/src/request_rules.rs index 0ce1329..1e7b6a8 100644 --- a/src/request_rules.rs +++ b/src/request_rules.rs @@ -5,7 +5,7 @@ use crate::model::{BatchSubrequest, ChecksumAlgorithm}; use base64::{Engine, engine::general_purpose::STANDARD}; use serde_json::Value; -use std::collections::BTreeSet; +use std::collections::{BTreeMap, BTreeSet}; fn request_header<'a>(request: &'a Value, name: &str) -> Option<&'a str> { request["headers"][name].as_str() @@ -142,18 +142,35 @@ pub(crate) fn check_blob_batch( .or_else(|| target.strip_prefix("http://")) .map(|rest| rest.find('/').map_or("/", |start| &rest[start..])) .unwrap_or(target); - let path = path.split('?').next().unwrap_or(path); - let decoded = percent_encoding::percent_decode_str(path) - .decode_utf8() - .map_err(|_| format!("the path of part {index} does not decode to UTF-8"))?; - sent.push((method.to_owned(), decoded.into_owned())); + let (path, query) = path.split_once('?').unwrap_or((path, "")); + let decode = |text: &str| { + percent_encoding::percent_decode_str(text) + .decode_utf8() + .map(|decoded| decoded.into_owned()) + .map_err(|_| format!("part {index} does not decode to UTF-8")) + }; + let mut parameters = BTreeMap::new(); + for pair in query.split('&').filter(|pair| !pair.is_empty()) { + let (name, value) = pair.split_once('=').unwrap_or((pair, "")); + parameters.insert(decode(name)?, decode(value)?); + } + sent.push((method.to_owned(), decode(path)?, parameters)); } for subrequest in expected { let position = sent .iter() - .position(|(method, path)| *method == subrequest.method && *path == subrequest.path) - .ok_or_else(|| format!("no subrequest {} {}", subrequest.method, subrequest.path))?; + .position(|(method, path, query)| { + *method == subrequest.method + && *path == subrequest.path + && *query == subrequest.query + }) + .ok_or_else(|| { + format!( + "no subrequest {} {} with the query {:?}", + subrequest.method, subrequest.path, subrequest.query + ) + })?; sent.remove(position); } Ok(()) @@ -239,16 +256,44 @@ mod tests { ) } + #[test] + fn a_blob_batch_subrequest_matches_its_decoded_query() { + let expected = [BatchSubrequest { + method: "DELETE".into(), + path: "/c/b".into(), + query: BTreeMap::from([("versionid".into(), "2024-01-01T00:00:00.0000000Z".into())]), + }]; + let versioned = format!( + "{}--batch_x--", + deletion(0, "/c/b?versionid=2024-01-01T00%3A00%3A00.0000000Z") + ); + assert_eq!( + check_blob_batch(&batch_request(&versioned), &expected), + Ok(()) + ); + + // Without the version the current blob would go, and with a snapshot another one. + for wrong in ["/c/b", "/c/b?snapshot=2024-01-01T00:00:00.0000000Z"] { + let body = format!("{}--batch_x--", deletion(0, wrong)); + assert!( + check_blob_batch(&batch_request(&body), &expected).is_err(), + "{wrong}" + ); + } + } + #[test] fn a_blob_batch_needs_every_subrequest_in_a_well_formed_part() { let expected = [ BatchSubrequest { method: "DELETE".into(), path: "/c/a b".into(), + query: BTreeMap::new(), }, BatchSubrequest { method: "DELETE".into(), path: "/c/b".into(), + query: BTreeMap::new(), }, ]; let body = format!( From d54d6112dc8a6f2cf42308895f592fb60b11a507 Mon Sep 17 00:00:00 2001 From: Tip ten Brink <75669206+tiptenbrink@users.noreply.github.com> Date: Sat, 3 Oct 2026 13:36:46 +0200 Subject: [PATCH 3/3] Pin the borink adapter at object-storage a231d3b. Co-Authored-By: Claude Opus 5.5 (1M context) --- adapters/borink/Cargo.lock | 6 +++--- adapters/borink/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/adapters/borink/Cargo.lock b/adapters/borink/Cargo.lock index d502883..2b90395 100644 --- a/adapters/borink/Cargo.lock +++ b/adapters/borink/Cargo.lock @@ -33,7 +33,7 @@ dependencies = [ [[package]] name = "borink-object-storage-crypto" version = "0.0.3" -source = "git+https://github.com/borink-org/object-storage.git?rev=deb671c5bd30939bef1bb1144f36c3a43e66d9d0#deb671c5bd30939bef1bb1144f36c3a43e66d9d0" +source = "git+https://github.com/borink-org/object-storage.git?rev=a231d3b10ac7ac983813efc052a1ac60a966a1b3#a231d3b10ac7ac983813efc052a1ac60a966a1b3" dependencies = [ "borink-object-storage-proto", "hmac", @@ -45,12 +45,12 @@ dependencies = [ [[package]] name = "borink-object-storage-proto" version = "0.0.3" -source = "git+https://github.com/borink-org/object-storage.git?rev=deb671c5bd30939bef1bb1144f36c3a43e66d9d0#deb671c5bd30939bef1bb1144f36c3a43e66d9d0" +source = "git+https://github.com/borink-org/object-storage.git?rev=a231d3b10ac7ac983813efc052a1ac60a966a1b3#a231d3b10ac7ac983813efc052a1ac60a966a1b3" [[package]] name = "borink-object-tests-adapter" version = "0.0.0" -source = "git+https://github.com/borink-org/object-storage.git?rev=deb671c5bd30939bef1bb1144f36c3a43e66d9d0#deb671c5bd30939bef1bb1144f36c3a43e66d9d0" +source = "git+https://github.com/borink-org/object-storage.git?rev=a231d3b10ac7ac983813efc052a1ac60a966a1b3#a231d3b10ac7ac983813efc052a1ac60a966a1b3" dependencies = [ "base64 0.22.1", "borink-object-storage-crypto", diff --git a/adapters/borink/Cargo.toml b/adapters/borink/Cargo.toml index 707eee7..fd02335 100644 --- a/adapters/borink/Cargo.toml +++ b/adapters/borink/Cargo.toml @@ -11,7 +11,7 @@ publish = false [dependencies] # The adapter itself lives in borink-org/object-storage, beside the crates whose # API it calls. This is the commit whose adapter speaks this revision's protocol. -borink-object-tests-adapter = { git = "https://github.com/borink-org/object-storage.git", rev = "deb671c5bd30939bef1bb1144f36c3a43e66d9d0" } +borink-object-tests-adapter = { git = "https://github.com/borink-org/object-storage.git", rev = "a231d3b10ac7ac983813efc052a1ac60a966a1b3" } [features] # HTTPS, which only the live probes need. Offline grading uses plain HTTP on loopback.