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/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. diff --git a/cases/operations.json b/cases/operations.json index abb7476..7ddd19c 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", @@ -136,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", @@ -223,6 +226,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", @@ -254,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", @@ -319,6 +325,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 +336,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", @@ -352,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", @@ -370,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", @@ -425,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", @@ -450,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", @@ -512,6 +527,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", @@ -544,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", @@ -551,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", @@ -617,10 +640,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", @@ -733,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", @@ -792,6 +818,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 +870,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", @@ -870,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", @@ -924,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", @@ -946,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", @@ -977,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", @@ -1027,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", @@ -1047,12 +1096,19 @@ "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", "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\"", @@ -10519,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", @@ -15862,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": [ @@ -15892,7 +16354,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/read/object.txt" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -15902,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" } } } @@ -15945,7 +16400,7 @@ "optional": false, "rule": { "is": "equal", - "value": 304 + "value": 409 } }, { @@ -15953,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" }, @@ -16002,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": "" } } } @@ -16044,7 +16498,7 @@ "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 304 } }, { @@ -16059,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": [ { @@ -16089,7 +16543,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/versions-mtydohr2/deleted.txt" + "value": "/fixture/object-tests/read/object.txt" } }, { @@ -16101,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" } } } @@ -16141,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": [ { @@ -16226,7 +16642,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/versions-mtydohr2/object.txt" + "value": "/fixture/object-tests/versions-mtydohr2/deleted.txt" } }, { @@ -16242,7 +16658,7 @@ "optional": false, "rule": { "is": "equal", - "value": "2024-01-01T00:00:00.2318906Z" + "value": "2024-01-01T00:00:00.0160641Z" } } ], @@ -16251,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=" } } } @@ -16286,7 +16702,7 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-5769a0807b46\"" + "value": "\"fixture-3f26f9cf7bbe\"" } }, { @@ -16310,7 +16726,7 @@ "optional": false, "rule": { "is": "equal", - "value": "ZlTHNMyrj0QP8IJetEPcfw==" + "value": "ASCk+RlqX5659SPzH5FNpw==" } }, { @@ -16318,7 +16734,7 @@ "optional": false, "rule": { "is": "equal", - "value": "2024-01-01T00:00:00.2318906Z" + "value": "2024-01-01T00:00:00.0160641Z" } }, { @@ -16326,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": [ { @@ -16366,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" } }, { @@ -16438,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" } } ], @@ -16451,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=" } } } @@ -16488,7 +16839,7 @@ "optional": false, "rule": { "is": "equal", - "value": "\"fixture-16c44f0af72d\"" + "value": "\"fixture-5769a0807b46\"" } }, { @@ -16496,7 +16847,7 @@ "optional": false, "rule": { "is": "equal", - "value": 30 + "value": 2 } }, { @@ -16512,7 +16863,7 @@ "optional": false, "rule": { "is": "equal", - "value": "H1VC0PNTmj+yaCRN4U931g==" + "value": "ZlTHNMyrj0QP8IJetEPcfw==" } }, { @@ -16520,7 +16871,7 @@ "optional": false, "rule": { "is": "equal", - "value": "2024-01-01T00:00:00.7556278Z" + "value": "2024-01-01T00:00:00.2318906Z" } }, { @@ -16528,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" ], @@ -16572,8 +16897,8 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "end": 5, - "start": 5 + "end": 2, + "start": 6 } }, "exchanges": [ @@ -16610,7 +16935,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=5-4" + "value": "bytes=6-1" } } ], @@ -16670,7 +16995,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=5-4" + "value": "bytes=6-1" } } ], @@ -16789,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" ], @@ -16800,7 +17125,8 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "start": 40 + "end": 5, + "start": 5 } }, "exchanges": [ @@ -16837,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" } } }, @@ -16890,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" } } } @@ -16921,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" ], @@ -16955,8 +17353,7 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "end": 64, - "start": 28 + "start": 40 } }, "exchanges": [ @@ -16993,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" } } }, @@ -17053,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" } } } @@ -17091,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" ], @@ -17157,8 +17508,8 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "end": 1, - "start": 0 + "end": 64, + "start": 28 } }, "exchanges": [ @@ -17195,7 +17546,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=0-0" + "value": "bytes=28-63" } } ], @@ -17204,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" @@ -17220,7 +17571,7 @@ }, "body": { "encoding": "base64", - "data": "MA==" + "data": "Y3Q=" } } }, @@ -17255,7 +17606,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=0-0" + "value": "bytes=28-63" } } ], @@ -17264,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" @@ -17280,7 +17631,7 @@ }, "body": { "encoding": "base64", - "data": "MA==" + "data": "Y3Q=" } } } @@ -17309,7 +17660,7 @@ "optional": false, "rule": { "is": "equal", - "value": 1 + "value": 2 } }, { @@ -17333,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" ], @@ -17351,8 +17710,8 @@ "key": "object-tests/read/object.txt", "op": "get", "range": { - "end": 6, - "start": 2 + "end": 1, + "start": 0 } }, "exchanges": [ @@ -17389,7 +17748,7 @@ "optional": false, "rule": { "is": "equal", - "value": "bytes=2-5" + "value": "bytes=0-0" } } ], @@ -17398,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" @@ -17414,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==" } } }, @@ -23131,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": [ { @@ -23152,7 +23705,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "HEAD" } }, { @@ -23160,7 +23713,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -23170,30 +23723,6 @@ "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": [], @@ -23201,18 +23730,27 @@ "response": { "status": 200, "headers": { - "content-type": "application/xml", + "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-creation-time": "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": "utf8", - "data": "object-tests/versions-mtydohr2/deleted.txt" - }, - "framing": "chunked" + "encoding": "base64", + "data": "" + } } } ] @@ -23228,44 +23766,61 @@ } }, { - "at": "/value/entries", + "at": "/value/etag", "optional": false, "rule": { - "is": "array_length", - "value": 0 + "is": "equal", + "value": "\"fixture-16c44f0af72d\"" } }, { - "at": "/value/prefixes", + "at": "/value/size", "optional": false, "rule": { - "is": "array_length", - "value": 0 + "is": "equal", + "value": 30 } }, { - "at": "/value/continuation_token", + "at": "/value/content_type", "optional": false, "rule": { "is": "equal", - "value": "" + "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/list-bad-marker", + "id": "operations/azure/restore-not-archived", "profile": "azure", "lane": "core", - "purpose": "list bad marker", + "purpose": "Restore a blob that is online already, which Azure answers with 200 as a readable blob", "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": "Hot" }, "exchanges": [ { @@ -23277,7 +23832,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -23285,7 +23840,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -23296,53 +23851,42 @@ "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": "Hot" } }, { - "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": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" - }, - "x-ms-error-code": "InvalidQueryParameterValue" + } }, "body": { - "encoding": "utf8", - "data": "InvalidQueryParameterValueFixture error" + "encoding": "empty" } } } @@ -23355,43 +23899,33 @@ "optional": false, "rule": { "is": "equal", - "value": "error" - } - }, - { - "at": "/status", - "optional": false, - "rule": { - "is": "equal", - "value": 400 + "value": "ok" } }, { - "at": "/code", + "at": "/value/state", "optional": false, "rule": { "is": "equal", - "value": "InvalidQueryParameterValue" + "value": "readable" } } ], "refusal": null }, { - "id": "operations/azure/list-bad-marker-code-in-body", + "id": "operations/azure/restore-while-rehydrating", "profile": "azure", "lane": "core", - "purpose": "list bad marker, with the error code only in the XML body", + "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/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": "constructed", "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": [ { @@ -23403,7 +23937,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -23411,7 +23945,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -23422,52 +23956,45 @@ "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": "BlobBeingRehydrated" }, "body": { "encoding": "utf8", - "data": "InvalidQueryParameterValueFixture error" + "data": "BlobBeingRehydratedFixture error" } } } @@ -23488,7 +24015,7 @@ "optional": false, "rule": { "is": "equal", - "value": 400 + "value": 409 } }, { @@ -23496,23 +24023,25 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidQueryParameterValue" + "value": "BlobBeingRehydrated" } } ], "refusal": null }, { - "id": "operations/azure/list-container-missing", + "id": "operations/azure/restore-high-priority", "profile": "azure", "lane": "core", - "purpose": "list container missing. A client reports it as container_not_found: the bucket or container is absent, not the object", + "purpose": "Start rehydrating an archived blob to Cool at High priority", "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": { - "op": "list_page", - "prefix": "" + "key": "object-tests/archive/object.txt", + "op": "restore", + "priority": "high", + "tier": "Cool" }, "exchanges": [ { @@ -23524,7 +24053,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -23532,7 +24061,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -23544,44 +24073,41 @@ } }, { - "at": "/query/restype", + "at": "/query/comp", "optional": false, "rule": { "is": "equal", - "value": "container" + "value": "tier" } }, { - "at": "/query/comp", + "at": "/headers/x-ms-access-tier", "optional": false, "rule": { "is": "equal", - "value": "list" + "value": "Cool" } }, { - "at": "/query/prefix", - "optional": true, + "at": "/headers/x-ms-rehydrate-priority", + "optional": false, "rule": { "is": "equal", - "value": "" + "value": "High" } } ], "allow_headers": [], "allow_query": [], "response": { - "status": 404, + "status": 202, "headers": { - "content-type": "application/xml", "date": { "from": "now" - }, - "x-ms-error-code": "ContainerNotFound" + } }, "body": { - "encoding": "utf8", - "data": "ContainerNotFoundFixture error" + "encoding": "empty" } } } @@ -23594,48 +24120,631 @@ "optional": false, "rule": { "is": "equal", - "value": "error" + "value": "ok" } }, { - "at": "/status", + "at": "/value/state", "optional": false, "rule": { "is": "equal", - "value": 404 + "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": [ { - "at": "/code", + "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": "ContainerNotFound" + "value": "ok" } }, { - "at": "/kind", + "at": "/value/state", "optional": false, "rule": { "is": "equal", - "value": "container_not_found" + "value": "started" } } ], "refusal": null }, { - "id": "operations/azure/list-delimited", + "id": "operations/azure/list-after-delete-with-versions", "profile": "azure", "lane": "core", - "purpose": "list delimited", + "purpose": "list after delete with versions", "sources": [ "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" ], "call": { - "delimiter": "/", "op": "list_page", - "prefix": "object-tests/board/" + "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" + } + } + } + ] + } + ], + "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": "InvalidQueryParameterValue" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/list-bad-marker-code-in-body", + "profile": "azure", + "lane": "core", + "purpose": "list bad marker, with the error code only in the XML body", + "sources": [ + "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp", + "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": "constructed", + "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" + } + }, + "body": { + "encoding": "utf8", + "data": "InvalidQueryParameterValueFixture 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": "InvalidQueryParameterValue" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/list-container-missing", + "profile": "azure", + "lane": "core", + "purpose": "list container missing. A client reports it as container_not_found: the bucket or container is absent, not the object", + "sources": [ + "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" + ], + "call": { + "op": "list_page", + "prefix": "" + }, + "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": true, + "rule": { + "is": "equal", + "value": "" + } + } + ], + "allow_headers": [], + "allow_query": [], + "response": { + "status": 404, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + }, + "x-ms-error-code": "ContainerNotFound" + }, + "body": { + "encoding": "utf8", + "data": "ContainerNotFoundFixture 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": "ContainerNotFound" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "equal", + "value": "container_not_found" + } + } + ], + "refusal": null + }, + { + "id": "operations/azure/list-delimited", + "profile": "azure", + "lane": "core", + "purpose": "list delimited", + "sources": [ + "azure-sdk-for-cpp/sdk/storage/azure-storage-blobs/src/blob_rest_client.cpp" + ], + "call": { + "delimiter": "/", + "op": "list_page", + "prefix": "object-tests/board/" }, "exchanges": [ { @@ -34670,19 +35779,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 +35826,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 +35866,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 +35939,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 +35972,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 +36034,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 +36079,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 +36160,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 +36205,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 +36244,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -35116,7 +36252,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -35128,32 +36264,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 +36329,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 +36370,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -35224,48 +36378,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 +36435,7 @@ "optional": false, "rule": { "is": "equal", - "value": 400 + "value": 404 } }, { @@ -35294,25 +36443,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 +36482,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -35340,7 +36490,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" + "value": "" } }, { @@ -35348,38 +36498,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 +36548,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 +36578,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -35444,36 +36590,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 +36640,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 +36684,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -35523,7 +36692,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -35531,7 +36700,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "" } }, { @@ -35539,25 +36708,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 +36741,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 +36792,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -35631,7 +36800,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" } }, { @@ -35639,32 +36808,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 +36862,7 @@ "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 400 } }, { @@ -35693,24 +36870,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 +36908,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -35738,7 +36916,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" } }, { @@ -35746,7 +36924,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 +36954,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 +36973,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 +37008,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -35846,7 +37024,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 +37069,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 +37099,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -35926,36 +37111,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 +37153,7 @@ "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 409 } }, { @@ -35984,25 +37161,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 +37199,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -36034,36 +37211,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 +37253,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 +37306,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -36125,28 +37318,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 +37354,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 +37406,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -36225,41 +37418,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" @@ -37153,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": [ { @@ -37177,7 +38751,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -37189,11 +38763,11 @@ } }, { - "at": "/body_text", + "at": "/body_base64", "optional": false, "rule": { - "is": "xml", - "value": "projectobject-tests" + "is": "equal", + "value": "" } }, { @@ -37205,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" } } } @@ -37241,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": [ { @@ -37279,7 +38851,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -37291,11 +38863,11 @@ } }, { - "at": "/body_text", + "at": "/body_base64", "optional": false, "rule": { - "is": "xml", - "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9" + "is": "equal", + "value": "" } }, { @@ -37307,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" } } } @@ -37343,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" ], @@ -37359,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": [ @@ -37398,7 +38969,7 @@ "optional": false, "rule": { "is": "xml", - "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9tag10value10" + "value": "projectobject-tests" } }, { @@ -37424,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" } } } @@ -37447,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" ], @@ -37522,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": [ @@ -37551,7 +39071,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9" } }, { @@ -37604,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" ], @@ -37615,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": [ @@ -37644,7 +39174,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9tag10value10" } }, { @@ -37757,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" ], @@ -37768,7 +39298,7 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" } }, "exchanges": [ @@ -37797,7 +39327,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" } }, { @@ -37850,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" ], @@ -37861,7 +39391,7 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" } }, "exchanges": [ @@ -37890,7 +39420,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" } }, { @@ -38003,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" ], @@ -38014,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": [ @@ -38043,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" } }, { @@ -38096,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" ], @@ -38107,7 +39637,7 @@ "key": "object-tests/tags/object.txt", "op": "azure.set_tags", "tags": { - "a@b": "c" + "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, "exchanges": [ @@ -38136,7 +39666,7 @@ "optional": false, "rule": { "is": "xml", - "value": "a@bc" + "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, { @@ -38168,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" } } } @@ -38201,7 +39731,7 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidTag" + "value": "TagsTooLarge" } } ], @@ -38243,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": [ { @@ -38409,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", @@ -82810,6 +84790,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 +85003,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 +85054,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 +85093,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 +85172,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 +85219,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 +85276,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 +85337,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 +85374,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -83257,7 +85382,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -83269,28 +85394,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 +85447,7 @@ "optional": false, "rule": { "is": "equal", - "value": 409 + "value": 404 } }, { @@ -83319,25 +85455,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 +85494,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -83365,7 +85502,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" + "value": "" } }, { @@ -83373,40 +85510,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 +85553,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 +85590,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/pages/object.vhd" + "value": "/fixture/object-tests/copy/target.txt" } }, { @@ -83481,7 +85598,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" + "value": "" } }, { @@ -83489,23 +85606,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 +85635,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 +85668,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 +85696,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -83600,19 +85716,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 +85773,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 +85804,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -83703,7 +85812,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" } }, { @@ -83711,24 +85820,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 +85874,7 @@ "optional": false, "rule": { "is": "equal", - "value": 409 + "value": 400 } }, { @@ -83757,25 +85882,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 +85920,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -83803,7 +85928,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "cHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHA=" } }, { @@ -83811,32 +85936,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 +85990,7 @@ "optional": false, "rule": { "is": "equal", - "value": 412 + "value": 409 } }, { @@ -83865,24 +85998,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 +86035,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/append/object.log" + "value": "/fixture/object-tests/pages/object.vhd" } }, { @@ -83910,34 +86043,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 +86089,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 +86150,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 +86188,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 +86242,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -84098,19 +86254,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 +86279,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 +86312,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 +86349,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -84206,19 +86361,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 +86379,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 +86399,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 +86449,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/leases/object.txt" + "value": "/fixture/object-tests/append/object.log" } }, { @@ -84293,7 +86457,7 @@ "optional": false, "rule": { "is": "equal", - "value": "c2Vjb25k" + "value": "" } }, { @@ -84301,24 +86465,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 +86495,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": [ { @@ -85003,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": [ { @@ -85027,7 +87472,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -85039,11 +87484,11 @@ } }, { - "at": "/body_text", + "at": "/body_base64", "optional": false, "rule": { - "is": "xml", - "value": "projectobject-tests" + "is": "equal", + "value": "" } }, { @@ -85055,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" } } ], @@ -85075,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" } } } @@ -85108,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": [ { @@ -85146,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" } } } @@ -85200,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": [ { @@ -85237,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" } }, { @@ -85253,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" } } ], @@ -85274,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" } } } @@ -85307,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": [ @@ -85352,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" } }, { @@ -85375,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" @@ -85402,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": [ { @@ -85434,7 +87912,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/write/object.txt" + "value": "/fixture/object-tests/tiers/object.txt" } }, { @@ -85442,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": [ { @@ -85492,7 +88019,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/write/object.txt" + "value": "/fixture/object-tests/tiers/object.txt" } }, { @@ -85500,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": [ { @@ -85590,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": [ @@ -102086,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": [ { @@ -102108,7 +104791,7 @@ "optional": false, "rule": { "is": "equal", - "value": "DELETE" + "value": "POST" } }, { @@ -102116,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": [ @@ -102133,7 +104841,7 @@ ], "allow_query": [], "response": { - "status": 503, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -102142,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": [ { @@ -102158,7 +104919,7 @@ "optional": false, "rule": { "is": "equal", - "value": "DELETE" + "value": "POST" } }, { @@ -102166,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": [ @@ -102183,7 +104969,7 @@ ], "allow_query": [], "response": { - "status": 503, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -102192,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": [ { @@ -102209,7 +105047,7 @@ "optional": false, "rule": { "is": "equal", - "value": "DELETE" + "value": "POST" } }, { @@ -102217,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": [ @@ -102234,7 +105097,7 @@ ], "allow_query": [], "response": { - "status": 503, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -102243,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": [ { @@ -102260,7 +105176,7 @@ "optional": false, "rule": { "is": "equal", - "value": "DELETE" + "value": "POST" } }, { @@ -102268,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": [ @@ -102285,7 +105226,7 @@ ], "allow_query": [], "response": { - "status": 503, + "status": 200, "headers": { "content-type": "application/xml", "date": { @@ -102294,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": [ @@ -107571,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": [ @@ -107601,7 +110791,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/read/object.txt" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -107611,14 +110801,6 @@ "is": "equal", "value": "" } - }, - { - "at": "/headers/if-none-match", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-ad03f2ab332a\"" - } } ], "allow_headers": [ @@ -107626,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" } }, { @@ -107654,7 +110837,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/read/object.txt" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -107665,14 +110848,6 @@ "value": "" } }, - { - "at": "/headers/if-none-match", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-ad03f2ab332a\"" - } - }, { "at": "/headers/range", "optional": false, @@ -107687,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" } } ] @@ -107717,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" }, @@ -114918,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": [ { @@ -114940,7 +118276,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "HEAD" } }, { @@ -114948,7 +118284,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture" + "value": "/fixture/object-tests/archive/object.txt" } }, { @@ -114958,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" + } } }, { @@ -115010,7 +118451,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "POST" } }, { @@ -115018,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": { @@ -115076,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" } @@ -120917,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", @@ -128746,64 +135369,691 @@ "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" + } + ], + "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": "/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/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": "/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/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 + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "error" + } + }, + { + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InternalError" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/copy-replace-metadata", + "profile": "s3", + "lane": "core", + "purpose": "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", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html" + ], + "call": { + "content_type": "text/plain", + "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": "/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/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" + } + }, + { + "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"" + } + } + }, + { + "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/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/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"" + } + } + } + ] + } + ], + "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-replace-metadata-only", + "profile": "s3", + "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": "/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/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/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/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/copy-clear-metadata", + "profile": "s3", + "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": "/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/source\\.txt" + } }, - "framing": "chunked" - } - } - ], - "optional": true - }, - { - "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", + "at": "/headers/x-amz-metadata-directive", "optional": false, "rule": { "is": "equal", - "value": "" - } - }, - { - "at": "/headers/x-amz-copy-source", - "optional": false, - "rule": { - "is": "matches", - "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" + "value": "REPLACE" } } ], @@ -128821,16 +136071,10 @@ }, "body": { "encoding": "utf8", - "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" - }, - "framing": "chunked" + "data": "\n2024-01-01T00:00:00.000Z"fixture-etag"" + } } - } - ], - "optional": true - }, - { - "alternatives": [ + }, { "request": [ { @@ -128838,7 +136082,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "HEAD" } }, { @@ -128846,7 +136090,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/copy/target.txt" + "value": "/object-tests/copy/source.txt" } }, { @@ -128856,14 +136100,73 @@ "is": "equal", "value": "" } - }, + } + ], + "then": [ { - "at": "/headers/x-amz-copy-source", - "optional": false, - "rule": { - "is": "matches", - "pattern": "/?fixture[^/]*/object-tests/copy/source\\.txt" - } + "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/source\\.txt" + } + }, + { + "at": "/headers/x-amz-metadata-directive", + "optional": false, + "rule": { + "is": "equal", + "value": "REPLACE" + } + } + ], + "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": [ @@ -128873,20 +136176,19 @@ "response": { "status": 200, "headers": { - "content-type": "application/xml", + "content-length": "5", "date": { "from": "now" - } + }, + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { - "encoding": "utf8", - "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" - }, - "framing": "chunked" + "encoding": "empty" + } } } - ], - "optional": true + ] } ], "expect": [ @@ -128895,36 +136197,53 @@ "optional": false, "rule": { "is": "equal", - "value": "error" + "value": "ok" + } + } + ], + "refusal": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "refused" } }, { - "at": "/code", + "at": "/kind", + "optional": false, + "rule": { + "is": "matches", + "pattern": ".+" + } + }, + { + "at": "/parameter", "optional": false, "rule": { "is": "equal", - "value": "InternalError" + "value": "metadata" } } ], - "refusal": null + "decline_permitted": true }, { - "id": "operations/s3/copy-replace-metadata", + "id": "operations/s3/copy-replace-tags", "profile": "s3", "lane": "core", - "purpose": "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", + "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": { - "content_type": "text/plain", "key": "object-tests/copy/target.txt", - "metadata": { - "colour": "blue" - }, "op": "copy", - "source_key": "object-tests/copy/source.txt" + "source_key": "object-tests/copy/source.txt", + "tags": { + "project": "copied" + } }, "exchanges": [ { @@ -128964,7 +136283,7 @@ } }, { - "at": "/headers/x-amz-metadata-directive", + "at": "/headers/x-amz-tagging-directive", "optional": false, "rule": { "is": "equal", @@ -128972,19 +136291,11 @@ } }, { - "at": "/headers/x-amz-meta-colour", - "optional": false, - "rule": { - "is": "equal", - "value": "blue" - } - }, - { - "at": "/headers/content-type", + "at": "/headers/x-amz-tagging", "optional": false, "rule": { "is": "equal", - "value": "text/plain" + "value": "project=copied" } } ], @@ -129071,7 +136382,7 @@ } }, { - "at": "/headers/x-amz-metadata-directive", + "at": "/headers/x-amz-tagging-directive", "optional": false, "rule": { "is": "equal", @@ -129079,19 +136390,11 @@ } }, { - "at": "/headers/x-amz-meta-colour", - "optional": false, - "rule": { - "is": "equal", - "value": "blue" - } - }, - { - "at": "/headers/content-type", + "at": "/headers/x-amz-tagging", "optional": false, "rule": { "is": "equal", - "value": "text/plain" + "value": "project=copied" } } ], @@ -129151,10 +136454,10 @@ "refusal": null }, { - "id": "operations/s3/copy-replace-tags", + "id": "operations/s3/copy-clear-tags", "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 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" ], @@ -129162,9 +136465,7 @@ "key": "object-tests/copy/target.txt", "op": "copy", "source_key": "object-tests/copy/source.txt", - "tags": { - "project": "copied" - } + "tags": {} }, "exchanges": [ { @@ -129213,10 +136514,10 @@ }, { "at": "/headers/x-amz-tagging", - "optional": false, + "optional": true, "rule": { "is": "equal", - "value": "project=copied" + "value": "" } } ], @@ -129312,10 +136613,10 @@ }, { "at": "/headers/x-amz-tagging", - "optional": false, + "optional": true, "rule": { "is": "equal", - "value": "project=copied" + "value": "" } } ], @@ -129372,7 +136673,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": "tags" + } + } + ], + "decline_permitted": true }, { "id": "operations/s3/copy-storage-class", @@ -131970,19 +139297,979 @@ "refusal": null }, { - "id": "operations/s3/put-computing-sha256", + "id": "operations/s3/put-computing-sha256", + "profile": "s3", + "lane": "core", + "purpose": "Compute the SHA256 checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-sha256 or in a trailer of an aws-chunked body", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Y2hlY2tzdW0K", + "checksum": { + "algorithm": "sha256" + }, + "key": "object-tests/checksums/sha256.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/checksums/sha256.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "Y2hlY2tzdW0K" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "SHA256" + } + }, + { + "at": "/headers/x-amz-checksum-sha256", + "optional": false, + "rule": { + "is": "equal", + "value": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/checksums/sha256.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1zaGEyNTY6WUJXanArcXlWOVBZZENUTGtZSjlXTGV2ZWdpUlI4NmJUNDZqeGZ3ZXU5ST0NCg0K" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "SHA256" + } + }, + { + "at": "/headers/x-amz-content-sha256", + "optional": false, + "rule": { + "is": "equal", + "value": "STREAMING-UNSIGNED-PAYLOAD-TRAILER" + } + }, + { + "at": "/headers/content-encoding", + "optional": false, + "rule": { + "is": "equal", + "value": "aws-chunked" + } + }, + { + "at": "/headers/x-amz-decoded-content-length", + "optional": false, + "rule": { + "is": "equal", + "value": "9" + } + }, + { + "at": "/headers/x-amz-trailer", + "optional": false, + "rule": { + "is": "equal", + "value": "x-amz-checksum-sha256" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-636b73750000\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-with-sha256", + "profile": "s3", + "lane": "core", + "purpose": "Send a SHA256 checksum that the caller gives, in x-amz-checksum-sha256", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Y2hlY2tzdW0K", + "checksum": { + "algorithm": "sha256", + "value_base64": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + }, + "key": "object-tests/checksums/sha256.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/checksums/sha256.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "Y2hlY2tzdW0K" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "SHA256" + } + }, + { + "at": "/headers/x-amz-checksum-sha256", + "optional": false, + "rule": { + "is": "equal", + "value": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-636b73750000\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-computing-sha1", + "profile": "s3", + "lane": "core", + "purpose": "Compute the SHA1 checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-sha1 or in a trailer of an aws-chunked body", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Y2hlY2tzdW0K", + "checksum": { + "algorithm": "sha1" + }, + "key": "object-tests/checksums/sha1.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/checksums/sha1.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "Y2hlY2tzdW0K" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "SHA1" + } + }, + { + "at": "/headers/x-amz-checksum-sha1", + "optional": false, + "rule": { + "is": "equal", + "value": "Ll2vAgHd6waKYtXgjaGGV6ssa+k=" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/checksums/sha1.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1zaGExOkxsMnZBZ0hkNndhS1l0WGdqYUdHVjZzc2Eraz0NCg0K" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "SHA1" + } + }, + { + "at": "/headers/x-amz-content-sha256", + "optional": false, + "rule": { + "is": "equal", + "value": "STREAMING-UNSIGNED-PAYLOAD-TRAILER" + } + }, + { + "at": "/headers/content-encoding", + "optional": false, + "rule": { + "is": "equal", + "value": "aws-chunked" + } + }, + { + "at": "/headers/x-amz-decoded-content-length", + "optional": false, + "rule": { + "is": "equal", + "value": "9" + } + }, + { + "at": "/headers/x-amz-trailer", + "optional": false, + "rule": { + "is": "equal", + "value": "x-amz-checksum-sha1" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-636b73750000\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-with-sha1", + "profile": "s3", + "lane": "core", + "purpose": "Send a SHA1 checksum that the caller gives, in x-amz-checksum-sha1", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Y2hlY2tzdW0K", + "checksum": { + "algorithm": "sha1", + "value_base64": "Ll2vAgHd6waKYtXgjaGGV6ssa+k=" + }, + "key": "object-tests/checksums/sha1.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/checksums/sha1.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "Y2hlY2tzdW0K" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "SHA1" + } + }, + { + "at": "/headers/x-amz-checksum-sha1", + "optional": false, + "rule": { + "is": "equal", + "value": "Ll2vAgHd6waKYtXgjaGGV6ssa+k=" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-636b73750000\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-computing-crc64nvme", + "profile": "s3", + "lane": "core", + "purpose": "Compute the CRC64NVME checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-crc64nvme or in a trailer of an aws-chunked body", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Y2hlY2tzdW0K", + "checksum": { + "algorithm": "crc64nvme" + }, + "key": "object-tests/checksums/crc64nvme.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/checksums/crc64nvme.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "Y2hlY2tzdW0K" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "CRC64NVME" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "equal", + "value": "XGkNQVJiTLw=" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + }, + { + "request": [ + { + "at": "/method", + "optional": false, + "rule": { + "is": "equal", + "value": "PUT" + } + }, + { + "at": "/path", + "optional": false, + "rule": { + "is": "equal", + "value": "/fixture/object-tests/checksums/crc64nvme.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1jcmM2NG52bWU6WEdrTlFWSmlUTHc9DQoNCg==" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "CRC64NVME" + } + }, + { + "at": "/headers/x-amz-content-sha256", + "optional": false, + "rule": { + "is": "equal", + "value": "STREAMING-UNSIGNED-PAYLOAD-TRAILER" + } + }, + { + "at": "/headers/content-encoding", + "optional": false, + "rule": { + "is": "equal", + "value": "aws-chunked" + } + }, + { + "at": "/headers/x-amz-decoded-content-length", + "optional": false, + "rule": { + "is": "equal", + "value": "9" + } + }, + { + "at": "/headers/x-amz-trailer", + "optional": false, + "rule": { + "is": "equal", + "value": "x-amz-checksum-crc64nvme" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-636b73750000\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-with-crc64nvme", + "profile": "s3", + "lane": "core", + "purpose": "Send a CRC64NVME checksum that the caller gives, in x-amz-checksum-crc64nvme", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Y2hlY2tzdW0K", + "checksum": { + "algorithm": "crc64nvme", + "value_base64": "XGkNQVJiTLw=" + }, + "key": "object-tests/checksums/crc64nvme.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/checksums/crc64nvme.txt" + } + }, + { + "at": "/body_base64", + "optional": false, + "rule": { + "is": "equal", + "value": "Y2hlY2tzdW0K" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "equal", + "value": "CRC64NVME" + } + }, + { + "at": "/headers/x-amz-checksum-crc64nvme", + "optional": false, + "rule": { + "is": "equal", + "value": "XGkNQVJiTLw=" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 200, + "headers": { + "date": { + "from": "now" + }, + "etag": "\"fixture-636b73750000\"", + "x-amz-checksum-crc32": "ItMTFg==", + "x-amz-checksum-type": "FULL_OBJECT" + }, + "body": { + "encoding": "base64", + "data": "" + } + } + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + }, + { + "at": "/value/etag", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-636b73750000\"" + } + }, + { + "at": "/value/version", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + null, + "" + ] + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-computing-crc32c", "profile": "s3", "lane": "core", - "purpose": "Compute the SHA256 checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-sha256 or in a trailer of an aws-chunked body", + "purpose": "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", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" ], "call": { "body_base64": "Y2hlY2tzdW0K", "checksum": { - "algorithm": "sha256" + "algorithm": "crc32c" }, - "key": "object-tests/checksums/sha256.txt", + "key": "object-tests/checksums/crc32c.txt", "op": "put" }, "exchanges": [ @@ -132003,7 +140290,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/sha256.txt" + "value": "/fixture/object-tests/checksums/crc32c.txt" } }, { @@ -132019,15 +140306,15 @@ "optional": true, "rule": { "is": "equal", - "value": "SHA256" + "value": "CRC32C" } }, { - "at": "/headers/x-amz-checksum-sha256", + "at": "/headers/x-amz-checksum-crc32c", "optional": false, "rule": { "is": "equal", - "value": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + "value": "6dErUA==" } } ], @@ -132066,7 +140353,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/sha256.txt" + "value": "/fixture/object-tests/checksums/crc32c.txt" } }, { @@ -132074,7 +140361,7 @@ "optional": false, "rule": { "is": "equal", - "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1zaGEyNTY6WUJXanArcXlWOVBZZENUTGtZSjlXTGV2ZWdpUlI4NmJUNDZqeGZ3ZXU5ST0NCg0K" + "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1jcmMzMmM6NmRFclVBPT0NCg0K" } }, { @@ -132082,7 +140369,7 @@ "optional": true, "rule": { "is": "equal", - "value": "SHA256" + "value": "CRC32C" } }, { @@ -132114,7 +140401,7 @@ "optional": false, "rule": { "is": "equal", - "value": "x-amz-checksum-sha256" + "value": "x-amz-checksum-crc32c" } } ], @@ -132173,20 +140460,20 @@ "refusal": null }, { - "id": "operations/s3/put-with-sha256", + "id": "operations/s3/put-with-crc32c", "profile": "s3", "lane": "core", - "purpose": "Send a SHA256 checksum that the caller gives, in x-amz-checksum-sha256", + "purpose": "Send a CRC32C checksum that the caller gives, in x-amz-checksum-crc32c", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" ], "call": { "body_base64": "Y2hlY2tzdW0K", "checksum": { - "algorithm": "sha256", - "value_base64": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + "algorithm": "crc32c", + "value_base64": "6dErUA==" }, - "key": "object-tests/checksums/sha256.txt", + "key": "object-tests/checksums/crc32c.txt", "op": "put" }, "exchanges": [ @@ -132207,7 +140494,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/sha256.txt" + "value": "/fixture/object-tests/checksums/crc32c.txt" } }, { @@ -132223,15 +140510,15 @@ "optional": true, "rule": { "is": "equal", - "value": "SHA256" + "value": "CRC32C" } }, { - "at": "/headers/x-amz-checksum-sha256", + "at": "/headers/x-amz-checksum-crc32c", "optional": false, "rule": { "is": "equal", - "value": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + "value": "6dErUA==" } } ], @@ -132290,19 +140577,19 @@ "refusal": null }, { - "id": "operations/s3/put-computing-sha1", + "id": "operations/s3/put-computing-crc32", "profile": "s3", "lane": "core", - "purpose": "Compute the SHA1 checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-sha1 or in a trailer of an aws-chunked body", + "purpose": "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", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" ], "call": { "body_base64": "Y2hlY2tzdW0K", "checksum": { - "algorithm": "sha1" + "algorithm": "crc32" }, - "key": "object-tests/checksums/sha1.txt", + "key": "object-tests/checksums/crc32.txt", "op": "put" }, "exchanges": [ @@ -132323,7 +140610,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/sha1.txt" + "value": "/fixture/object-tests/checksums/crc32.txt" } }, { @@ -132339,15 +140626,15 @@ "optional": true, "rule": { "is": "equal", - "value": "SHA1" + "value": "CRC32" } }, { - "at": "/headers/x-amz-checksum-sha1", + "at": "/headers/x-amz-checksum-crc32", "optional": false, "rule": { "is": "equal", - "value": "Ll2vAgHd6waKYtXgjaGGV6ssa+k=" + "value": "ItMTFg==" } } ], @@ -132386,7 +140673,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/sha1.txt" + "value": "/fixture/object-tests/checksums/crc32.txt" } }, { @@ -132394,7 +140681,7 @@ "optional": false, "rule": { "is": "equal", - "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1zaGExOkxsMnZBZ0hkNndhS1l0WGdqYUdHVjZzc2Eraz0NCg0K" + "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1jcmMzMjpJdE1URmc9PQ0KDQo=" } }, { @@ -132402,7 +140689,7 @@ "optional": true, "rule": { "is": "equal", - "value": "SHA1" + "value": "CRC32" } }, { @@ -132434,7 +140721,7 @@ "optional": false, "rule": { "is": "equal", - "value": "x-amz-checksum-sha1" + "value": "x-amz-checksum-crc32" } } ], @@ -132493,20 +140780,26 @@ "refusal": null }, { - "id": "operations/s3/put-with-sha1", + "id": "operations/s3/put-two-checksums", "profile": "s3", "lane": "core", - "purpose": "Send a SHA1 checksum that the caller gives, in x-amz-checksum-sha1", + "purpose": "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", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" ], "call": { "body_base64": "Y2hlY2tzdW0K", - "checksum": { - "algorithm": "sha1", - "value_base64": "Ll2vAgHd6waKYtXgjaGGV6ssa+k=" - }, - "key": "object-tests/checksums/sha1.txt", + "checksums": [ + { + "algorithm": "crc32", + "value_base64": "ItMTFg==" + }, + { + "algorithm": "sha256", + "value_base64": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + } + ], + "key": "object-tests/checksums/two.txt", "op": "put" }, "exchanges": [ @@ -132527,7 +140820,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/sha1.txt" + "value": "/fixture/object-tests/checksums/two.txt" } }, { @@ -132539,19 +140832,30 @@ } }, { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, + "at": "/headers/x-amz-checksum-crc32", + "optional": false, "rule": { "is": "equal", - "value": "SHA1" + "value": "ItMTFg==" } }, { - "at": "/headers/x-amz-checksum-sha1", + "at": "/headers/x-amz-checksum-sha256", "optional": false, "rule": { "is": "equal", - "value": "Ll2vAgHd6waKYtXgjaGGV6ssa+k=" + "value": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + } + }, + { + "at": "/headers/x-amz-sdk-checksum-algorithm", + "optional": true, + "rule": { + "is": "one_of", + "values": [ + "CRC32", + "SHA256" + ] } } ], @@ -132560,19 +140864,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 400, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nInvalidRequestExpecting a single x-amz-checksum- header. Multiple checksum Types are not allowed.fixturefixture" + }, + "framing": "chunked" } } ] @@ -132584,46 +140887,84 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/etag", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-636b73750000\"" + "value": 400 } }, { - "at": "/value/version", - "optional": true, + "at": "/code", + "optional": false, "rule": { - "is": "one_of", - "values": [ - null, - "" - ] + "is": "equal", + "value": "InvalidRequest" } } ], - "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": "checksums" + } + }, + { + "at": "/status", + "optional": true, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "InvalidRequest" + } + } + ] }, { - "id": "operations/s3/put-computing-crc64nvme", + "id": "operations/s3/put-with-tags", "profile": "s3", "lane": "core", - "purpose": "Compute the CRC64NVME checksum of the body and send it, base64 of its big-endian bytes, in x-amz-checksum-crc64nvme or in a trailer of an aws-chunked body", + "purpose": "Write an object with tags", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" ], "call": { - "body_base64": "Y2hlY2tzdW0K", - "checksum": { - "algorithm": "crc64nvme" - }, - "key": "object-tests/checksums/crc64nvme.txt", - "op": "put" + "body_base64": "Zmlyc3Q=", + "key": "object-tests/tags/object.txt", + "op": "put", + "tags": { + "project": "object-tests" + } }, "exchanges": [ { @@ -132643,7 +140984,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/crc64nvme.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -132651,23 +140992,15 @@ "optional": false, "rule": { "is": "equal", - "value": "Y2hlY2tzdW0K" - } - }, - { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, - "rule": { - "is": "equal", - "value": "CRC64NVME" + "value": "Zmlyc3Q=" } }, { - "at": "/headers/x-amz-checksum-crc64nvme", + "at": "/headers/x-amz-tagging", "optional": false, "rule": { "is": "equal", - "value": "XGkNQVJiTLw=" + "value": "project=object-tests" } } ], @@ -132681,16 +141014,48 @@ "date": { "from": "now" }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { - "encoding": "base64", - "data": "" + "encoding": "empty" } } - }, + } + ] + } + ], + "expect": [ + { + "at": "/outcome", + "optional": false, + "rule": { + "is": "equal", + "value": "ok" + } + } + ], + "refusal": null + }, + { + "id": "operations/s3/put-with-tags-special-characters", + "profile": "s3", + "lane": "core", + "purpose": "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", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + ], + "call": { + "body_base64": "Zmlyc3Q=", + "key": "object-tests/tags/object.txt", + "op": "put", + "tags": { + "a b+c-d=e.f_g:h/i@j": "k l+m-n=o.p_q:r/s@t" + } + }, + "exchanges": [ + { + "alternatives": [ { "request": [ { @@ -132706,7 +141071,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/crc64nvme.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -132714,47 +141079,15 @@ "optional": false, "rule": { "is": "equal", - "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1jcmM2NG52bWU6WEdrTlFWSmlUTHc9DQoNCg==" - } - }, - { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, - "rule": { - "is": "equal", - "value": "CRC64NVME" - } - }, - { - "at": "/headers/x-amz-content-sha256", - "optional": false, - "rule": { - "is": "equal", - "value": "STREAMING-UNSIGNED-PAYLOAD-TRAILER" - } - }, - { - "at": "/headers/content-encoding", - "optional": false, - "rule": { - "is": "equal", - "value": "aws-chunked" - } - }, - { - "at": "/headers/x-amz-decoded-content-length", - "optional": false, - "rule": { - "is": "equal", - "value": "9" + "value": "Zmlyc3Q=" } }, { - "at": "/headers/x-amz-trailer", + "at": "/headers/x-amz-tagging", "optional": false, "rule": { "is": "equal", - "value": "x-amz-checksum-crc64nvme" + "value": "a%20b%2Bc-d%3De.f_g%3Ah%2Fi%40j=k%20l%2Bm-n%3Do.p_q%3Ar%2Fs%40t" } } ], @@ -132768,13 +141101,11 @@ "date": { "from": "now" }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + "etag": "\"fixture-etag\"", + "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }, "body": { - "encoding": "base64", - "data": "" + "encoding": "empty" } } } @@ -132789,45 +141120,32 @@ "is": "equal", "value": "ok" } - }, - { - "at": "/value/etag", - "optional": false, - "rule": { - "is": "equal", - "value": "\"fixture-636b73750000\"" - } - }, - { - "at": "/value/version", - "optional": true, - "rule": { - "is": "one_of", - "values": [ - null, - "" - ] - } } ], "refusal": null }, { - "id": "operations/s3/put-with-crc64nvme", + "id": "operations/s3/put-with-tags-duplicate-key", "profile": "s3", "lane": "core", - "purpose": "Send a CRC64NVME checksum that the caller gives, in x-amz-checksum-crc64nvme", + "purpose": "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", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" ], "call": { - "body_base64": "Y2hlY2tzdW0K", - "checksum": { - "algorithm": "crc64nvme", - "value_base64": "XGkNQVJiTLw=" - }, - "key": "object-tests/checksums/crc64nvme.txt", - "op": "put" + "body_base64": "Zmlyc3Q=", + "key": "object-tests/tags/object.txt", + "op": "put", + "tags": [ + { + "key": "project", + "value": "a" + }, + { + "key": "project", + "value": "b" + } + ] }, "exchanges": [ { @@ -132847,7 +141165,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/crc64nvme.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -132855,23 +141173,15 @@ "optional": false, "rule": { "is": "equal", - "value": "Y2hlY2tzdW0K" - } - }, - { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, - "rule": { - "is": "equal", - "value": "CRC64NVME" + "value": "Zmlyc3Q=" } }, { - "at": "/headers/x-amz-checksum-crc64nvme", + "at": "/headers/x-amz-tagging", "optional": false, "rule": { "is": "equal", - "value": "XGkNQVJiTLw=" + "value": "project=a&project=b" } } ], @@ -132880,19 +141190,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 400, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nInvalidArgumentFixture error" + }, + "framing": "chunked" } } ] @@ -132904,46 +141213,81 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/etag", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-636b73750000\"" + "value": 400 } }, { - "at": "/value/version", + "at": "/code", + "optional": false, + "rule": { + "is": "equal", + "value": "InvalidArgument" + } + } + ], + "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": "one_of", - "values": [ - null, - "" - ] + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "InvalidArgument" } } ], - "refusal": null + "decline_permitted": true }, { - "id": "operations/s3/put-computing-crc32c", + "id": "operations/s3/get-tagging", "profile": "s3", "lane": "core", - "purpose": "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", + "purpose": "Read the tags of an object", "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" ], "call": { - "body_base64": "Y2hlY2tzdW0K", - "checksum": { - "algorithm": "crc32c" - }, - "key": "object-tests/checksums/crc32c.txt", - "op": "put" + "key": "object-tests/tags/object.txt", + "op": "s3.get_tagging" }, "exchanges": [ { @@ -132955,7 +141299,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -132963,7 +141307,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/crc32c.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -132971,23 +141315,15 @@ "optional": false, "rule": { "is": "equal", - "value": "Y2hlY2tzdW0K" - } - }, - { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, - "rule": { - "is": "equal", - "value": "CRC32C" + "value": "" } }, { - "at": "/headers/x-amz-checksum-crc32c", + "at": "/query/tagging", "optional": false, "rule": { "is": "equal", - "value": "6dErUA==" + "value": "" } } ], @@ -132998,19 +141334,58 @@ "response": { "status": 200, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "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-none", + "profile": "s3", + "lane": "core", + "purpose": "Report no tags for an object without any, which S3 answers with an empty TagSet", + "sources": [ + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" + ], + "call": { + "key": "object-tests/tags/object.txt", + "op": "s3.get_tagging" + }, + "exchanges": [ + { + "alternatives": [ { "request": [ { @@ -133018,7 +141393,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -133026,7 +141401,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/crc32c.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -133034,47 +141409,15 @@ "optional": false, "rule": { "is": "equal", - "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1jcmMzMmM6NmRFclVBPT0NCg0K" - } - }, - { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, - "rule": { - "is": "equal", - "value": "CRC32C" - } - }, - { - "at": "/headers/x-amz-content-sha256", - "optional": false, - "rule": { - "is": "equal", - "value": "STREAMING-UNSIGNED-PAYLOAD-TRAILER" - } - }, - { - "at": "/headers/content-encoding", - "optional": false, - "rule": { - "is": "equal", - "value": "aws-chunked" - } - }, - { - "at": "/headers/x-amz-decoded-content-length", - "optional": false, - "rule": { - "is": "equal", - "value": "9" + "value": "" } }, { - "at": "/headers/x-amz-trailer", + "at": "/query/tagging", "optional": false, "rule": { "is": "equal", - "value": "x-amz-checksum-crc32c" + "value": "" } } ], @@ -133085,17 +141428,16 @@ "response": { "status": 200, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\n" + }, + "framing": "chunked" } } ] @@ -133111,43 +141453,28 @@ } }, { - "at": "/value/etag", + "at": "/value/tags", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-636b73750000\"" - } - }, - { - "at": "/value/version", - "optional": true, - "rule": { - "is": "one_of", - "values": [ - null, - "" - ] + "value": {} } } ], "refusal": null }, { - "id": "operations/s3/put-with-crc32c", + "id": "operations/s3/get-tagging-version", "profile": "s3", "lane": "core", - "purpose": "Send a CRC32C checksum that the caller gives, in x-amz-checksum-crc32c", + "purpose": "Get the tags of a previous version, named by versionId in the query", "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" ], "call": { - "body_base64": "Y2hlY2tzdW0K", - "checksum": { - "algorithm": "crc32c", - "value_base64": "6dErUA==" - }, - "key": "object-tests/checksums/crc32c.txt", - "op": "put" + "key": "object-tests/tags/object.txt", + "op": "s3.get_tagging", + "version": "fixture-version-1" }, "exchanges": [ { @@ -133159,7 +141486,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -133167,7 +141494,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/crc32c.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -133175,23 +141502,23 @@ "optional": false, "rule": { "is": "equal", - "value": "Y2hlY2tzdW0K" + "value": "" } }, { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, + "at": "/query/tagging", + "optional": false, "rule": { "is": "equal", - "value": "CRC32C" + "value": "" } }, { - "at": "/headers/x-amz-checksum-crc32c", + "at": "/query/versionId", "optional": false, "rule": { "is": "equal", - "value": "6dErUA==" + "value": "fixture-version-1" } } ], @@ -133202,17 +141529,78 @@ "response": { "status": 200, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + } }, "body": { - "encoding": "base64", - "data": "" + "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" } } ] @@ -133228,42 +141616,30 @@ } }, { - "at": "/value/etag", + "at": "/value/tags", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-636b73750000\"" - } - }, - { - "at": "/value/version", - "optional": true, - "rule": { - "is": "one_of", - "values": [ - null, - "" - ] + "value": { + "project": "object-tests" + } } } ], "refusal": null }, { - "id": "operations/s3/put-computing-crc32", + "id": "operations/s3/get-tagging-deleted-version", "profile": "s3", "lane": "core", - "purpose": "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", + "purpose": "Send a tag call on a version that was deleted", "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" ], "call": { - "body_base64": "Y2hlY2tzdW0K", - "checksum": { - "algorithm": "crc32" - }, - "key": "object-tests/checksums/crc32.txt", - "op": "put" + "key": "object-tests/tags/object.txt", + "op": "s3.get_tagging", + "version": "fixture-version-1" }, "exchanges": [ { @@ -133275,7 +141651,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -133283,7 +141659,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/crc32.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -133291,23 +141667,23 @@ "optional": false, "rule": { "is": "equal", - "value": "Y2hlY2tzdW0K" + "value": "" } }, { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, + "at": "/query/tagging", + "optional": false, "rule": { "is": "equal", - "value": "CRC32" + "value": "" } }, { - "at": "/headers/x-amz-checksum-crc32", + "at": "/query/versionId", "optional": false, "rule": { "is": "equal", - "value": "ItMTFg==" + "value": "fixture-version-1" } } ], @@ -133316,19 +141692,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 404, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nNoSuchVersionFixture error" + }, + "framing": "chunked" } }, { @@ -133338,7 +141713,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -133346,7 +141721,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/crc32.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -133354,47 +141729,23 @@ "optional": false, "rule": { "is": "equal", - "value": "OQ0KY2hlY2tzdW0KDQowDQp4LWFtei1jaGVja3N1bS1jcmMzMjpJdE1URmc9PQ0KDQo=" - } - }, - { - "at": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, - "rule": { - "is": "equal", - "value": "CRC32" - } - }, - { - "at": "/headers/x-amz-content-sha256", - "optional": false, - "rule": { - "is": "equal", - "value": "STREAMING-UNSIGNED-PAYLOAD-TRAILER" - } - }, - { - "at": "/headers/content-encoding", - "optional": false, - "rule": { - "is": "equal", - "value": "aws-chunked" + "value": "" } }, { - "at": "/headers/x-amz-decoded-content-length", + "at": "/query/tagging", "optional": false, "rule": { "is": "equal", - "value": "9" + "value": "tagging" } }, { - "at": "/headers/x-amz-trailer", + "at": "/query/versionId", "optional": false, "rule": { "is": "equal", - "value": "x-amz-checksum-crc32" + "value": "fixture-version-1" } } ], @@ -133403,19 +141754,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 404, "headers": { + "content-type": "application/xml", "date": { "from": "now" - }, - "etag": "\"fixture-636b73750000\"", - "x-amz-checksum-crc32": "ItMTFg==", - "x-amz-checksum-type": "FULL_OBJECT" + } }, "body": { - "encoding": "base64", - "data": "" - } + "encoding": "utf8", + "data": "\nNoSuchVersionFixture error" + }, + "framing": "chunked" } } ] @@ -133427,53 +141777,40 @@ "optional": false, "rule": { "is": "equal", - "value": "ok" + "value": "error" } }, { - "at": "/value/etag", + "at": "/status", "optional": false, "rule": { "is": "equal", - "value": "\"fixture-636b73750000\"" + "value": 404 } }, { - "at": "/value/version", - "optional": true, + "at": "/code", + "optional": false, "rule": { - "is": "one_of", - "values": [ - null, - "" - ] + "is": "equal", + "value": "NoSuchVersion" } } ], "refusal": null }, { - "id": "operations/s3/put-two-checksums", + "id": "operations/s3/get-tagging-malformed-version", "profile": "s3", "lane": "core", - "purpose": "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", + "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_PutObject.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" ], "call": { - "body_base64": "Y2hlY2tzdW0K", - "checksums": [ - { - "algorithm": "crc32", - "value_base64": "ItMTFg==" - }, - { - "algorithm": "sha256", - "value_base64": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" - } - ], - "key": "object-tests/checksums/two.txt", - "op": "put" + "key": "object-tests/tags/object.txt", + "op": "s3.get_tagging", + "version": "3sL4kqtJlcpXroDTDmJ.rmSpXd3dIbrHY" }, "exchanges": [ { @@ -133485,7 +141822,7 @@ "optional": false, "rule": { "is": "equal", - "value": "PUT" + "value": "GET" } }, { @@ -133493,7 +141830,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/fixture/object-tests/checksums/two.txt" + "value": "/fixture/object-tests/tags/object.txt" } }, { @@ -133501,34 +141838,85 @@ "optional": false, "rule": { "is": "equal", - "value": "Y2hlY2tzdW0K" + "value": "" } }, { - "at": "/headers/x-amz-checksum-crc32", + "at": "/query/tagging", "optional": false, "rule": { "is": "equal", - "value": "ItMTFg==" + "value": "" } }, { - "at": "/headers/x-amz-checksum-sha256", + "at": "/query/versionId", "optional": false, "rule": { "is": "equal", - "value": "YBWjp+qyV9PYdCTLkYJ9WLevegiRR86bT46jxfweu9I=" + "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": "/headers/x-amz-sdk-checksum-algorithm", - "optional": true, + "at": "/method", + "optional": false, "rule": { - "is": "one_of", - "values": [ - "CRC32", - "SHA256" - ] + "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" } } ], @@ -133546,7 +141934,7 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidRequestExpecting a single x-amz-checksum- header. Multiple checksum Types are not allowed.fixturefixture" + "data": "\nInvalidArgumentFixture error" }, "framing": "chunked" } @@ -133576,65 +141964,23 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidRequest" + "value": "InvalidArgument" } } ], - "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": "checksums" - } - }, - { - "at": "/status", - "optional": true, - "rule": { - "is": "equal", - "value": 400 - } - }, - { - "at": "/code", - "optional": true, - "rule": { - "is": "equal", - "value": "InvalidRequest" - } - } - ] + "refusal": null }, { - "id": "operations/s3/put-with-tags", + "id": "operations/s3/put-tagging", "profile": "s3", "lane": "core", - "purpose": "Write an object with tags", + "purpose": "Replace the tags of an object", "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], "call": { - "body_base64": "Zmlyc3Q=", "key": "object-tests/tags/object.txt", - "op": "put", + "op": "s3.put_tagging", "tags": { "project": "object-tests" } @@ -133661,19 +142007,36 @@ } }, { - "at": "/body_base64", + "at": "/body_text", "optional": false, "rule": { - "is": "equal", - "value": "Zmlyc3Q=" + "is": "xml", + "value": "projectobject-tests" } }, { - "at": "/headers/x-amz-tagging", + "at": "/query/tagging", "optional": false, "rule": { "is": "equal", - "value": "project=object-tests" + "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" } } ], @@ -133686,9 +142049,7 @@ "headers": { "date": { "from": "now" - }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + } }, "body": { "encoding": "empty" @@ -133711,19 +142072,27 @@ "refusal": null }, { - "id": "operations/s3/put-with-tags-special-characters", + "id": "operations/s3/put-tagging-10-tags", "profile": "s3", "lane": "core", - "purpose": "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", + "purpose": "Set 10 tags, the most an object takes", "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], "call": { - "body_base64": "Zmlyc3Q=", "key": "object-tests/tags/object.txt", - "op": "put", + "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" + "tag00": "value0", + "tag01": "value1", + "tag02": "value2", + "tag03": "value3", + "tag04": "value4", + "tag05": "value5", + "tag06": "value6", + "tag07": "value7", + "tag08": "value8", + "tag09": "value9" } }, "exchanges": [ @@ -133748,19 +142117,36 @@ } }, { - "at": "/body_base64", + "at": "/body_text", "optional": false, "rule": { - "is": "equal", - "value": "Zmlyc3Q=" + "is": "xml", + "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9" } }, { - "at": "/headers/x-amz-tagging", + "at": "/query/tagging", "optional": false, "rule": { "is": "equal", - "value": "a%20b%2Bc-d%3De.f_g%3Ah%2Fi%40j=k%20l%2Bm-n%3Do.p_q%3Ar%2Fs%40t" + "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" } } ], @@ -133773,9 +142159,7 @@ "headers": { "date": { "from": "now" - }, - "etag": "\"fixture-etag\"", - "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" + } }, "body": { "encoding": "empty" @@ -133798,27 +142182,29 @@ "refusal": null }, { - "id": "operations/s3/put-with-tags-duplicate-key", + "id": "operations/s3/put-tagging-11-tags", "profile": "s3", "lane": "core", - "purpose": "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", + "purpose": "Report 11 tags, one more than an object takes, as an error. A client may refuse them", "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], "call": { - "body_base64": "Zmlyc3Q=", "key": "object-tests/tags/object.txt", - "op": "put", - "tags": [ - { - "key": "project", - "value": "a" - }, - { - "key": "project", - "value": "b" - } - ] + "op": "s3.put_tagging", + "tags": { + "tag00": "value0", + "tag01": "value1", + "tag02": "value2", + "tag03": "value3", + "tag04": "value4", + "tag05": "value5", + "tag06": "value6", + "tag07": "value7", + "tag08": "value8", + "tag09": "value9", + "tag10": "value10" + } }, "exchanges": [ { @@ -133842,19 +142228,36 @@ } }, { - "at": "/body_base64", + "at": "/body_text", "optional": false, "rule": { - "is": "equal", - "value": "Zmlyc3Q=" + "is": "xml", + "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9tag10value10" } }, { - "at": "/headers/x-amz-tagging", + "at": "/query/tagging", "optional": false, "rule": { "is": "equal", - "value": "project=a&project=b" + "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" } } ], @@ -133872,7 +142275,7 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidArgumentFixture error" + "data": "\nBadRequestFixture error" }, "framing": "chunked" } @@ -133902,7 +142305,7 @@ "optional": false, "rule": { "is": "equal", - "value": "InvalidArgument" + "value": "BadRequest" } } ], @@ -133944,23 +142347,25 @@ "optional": true, "rule": { "is": "equal", - "value": "InvalidArgument" + "value": "BadRequest" } } - ], - "decline_permitted": true + ] }, { - "id": "operations/s3/get-tagging", + "id": "operations/s3/put-tagging-key-128", "profile": "s3", "lane": "core", - "purpose": "Read the tags of an object", + "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_GetObjectTagging.html" + "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], "call": { "key": "object-tests/tags/object.txt", - "op": "s3.get_tagging" + "op": "s3.put_tagging", + "tags": { + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" + } }, "exchanges": [ { @@ -133972,7 +142377,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -133984,11 +142389,11 @@ } }, { - "at": "/body_base64", + "at": "/body_text", "optional": false, "rule": { - "is": "equal", - "value": "" + "is": "xml", + "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" } }, { @@ -133998,99 +142403,22 @@ "is": "equal", "value": "" } - } - ], - "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-none", - "profile": "s3", - "lane": "core", - "purpose": "Report no tags for an object without any, which S3 answers with an empty TagSet", - "sources": [ - "https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html" - ], - "call": { - "key": "object-tests/tags/object.txt", - "op": "s3.get_tagging" - }, - "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", + "at": "/headers/x-amz-checksum-crc64nvme", "optional": false, "rule": { - "is": "equal", - "value": "" + "is": "matches", + "pattern": "[A-Za-z0-9+/]{11}=" } }, { - "at": "/query/tagging", + "at": "", "optional": false, "rule": { - "is": "equal", - "value": "" + "is": "body_checksum", + "header": "x-amz-checksum-crc64nvme", + "algorithm": "crc64nvme" } } ], @@ -134101,16 +142429,13 @@ "response": { "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" } }, "body": { - "encoding": "utf8", - "data": "\n" - }, - "framing": "chunked" + "encoding": "empty" + } } } ] @@ -134124,23 +142449,15 @@ "is": "equal", "value": "ok" } - }, - { - "at": "/value/tags", - "optional": false, - "rule": { - "is": "equal", - "value": {} - } } ], "refusal": null }, { - "id": "operations/s3/put-tagging", + "id": "operations/s3/put-tagging-key-129", "profile": "s3", "lane": "core", - "purpose": "Replace the tags of an object", + "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" ], @@ -134148,7 +142465,7 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "project": "object-tests" + "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" } }, "exchanges": [ @@ -134177,7 +142494,7 @@ "optional": false, "rule": { "is": "xml", - "value": "projectobject-tests" + "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" } }, { @@ -134211,15 +142528,18 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 400, "headers": { + "content-type": "application/xml", "date": { "from": "now" } }, "body": { - "encoding": "empty" - } + "encoding": "utf8", + "data": "\nInvalidTagFixture error" + }, + "framing": "chunked" } } ] @@ -134231,17 +142551,74 @@ "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": "InvalidTag" } } ], - "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": "tags" + } + }, + { + "at": "/status", + "optional": true, + "rule": { + "is": "equal", + "value": 400 + } + }, + { + "at": "/code", + "optional": true, + "rule": { + "is": "equal", + "value": "InvalidTag" + } + } + ] }, { - "id": "operations/s3/put-tagging-10-tags", + "id": "operations/s3/put-tagging-value-256", "profile": "s3", "lane": "core", - "purpose": "Set 10 tags, the most an object takes", + "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" ], @@ -134249,16 +142626,7 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "tag00": "value0", - "tag01": "value1", - "tag02": "value2", - "tag03": "value3", - "tag04": "value4", - "tag05": "value5", - "tag06": "value6", - "tag07": "value7", - "tag08": "value8", - "tag09": "value9" + "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, "exchanges": [ @@ -134287,7 +142655,7 @@ "optional": false, "rule": { "is": "xml", - "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9" + "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, { @@ -134348,10 +142716,10 @@ "refusal": null }, { - "id": "operations/s3/put-tagging-11-tags", + "id": "operations/s3/put-tagging-value-257", "profile": "s3", "lane": "core", - "purpose": "Report 11 tags, one more than an object takes, as an error. A client may refuse them", + "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" ], @@ -134359,17 +142727,7 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "tag00": "value0", - "tag01": "value1", - "tag02": "value2", - "tag03": "value3", - "tag04": "value4", - "tag05": "value5", - "tag06": "value6", - "tag07": "value7", - "tag08": "value8", - "tag09": "value9", - "tag10": "value10" + "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, "exchanges": [ @@ -134398,7 +142756,7 @@ "optional": false, "rule": { "is": "xml", - "value": "tag00value0tag01value1tag02value2tag03value3tag04value4tag05value5tag06value6tag07value7tag08value8tag09value9tag10value10" + "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" } }, { @@ -134441,7 +142799,7 @@ }, "body": { "encoding": "utf8", - "data": "\nBadRequestFixture error" + "data": "\nInvalidTagFixture error" }, "framing": "chunked" } @@ -134471,7 +142829,7 @@ "optional": false, "rule": { "is": "equal", - "value": "BadRequest" + "value": "InvalidTag" } } ], @@ -134513,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" ], @@ -134530,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": [ @@ -134559,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" } }, { @@ -134620,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" ], @@ -134631,8 +142989,176 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk": "v" + "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/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-duplicate-key", + "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", + "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" + } + ] }, "exchanges": [ { @@ -134660,7 +143186,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkv" + "value": "projectaprojectb" } }, { @@ -134778,13 +143304,14 @@ "value": "InvalidTag" } } - ] + ], + "decline_permitted": true }, { - "id": "operations/s3/put-tagging-value-256", + "id": "operations/s3/put-tagging-version", "profile": "s3", "lane": "core", - "purpose": "Set a tag whose value has 256 characters, the longest a value may be", + "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" ], @@ -134792,8 +143319,9 @@ "key": "object-tests/tags/object.txt", "op": "s3.put_tagging", "tags": { - "k": "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" - } + "project": "object-tests" + }, + "version": "fixture-version-1" }, "exchanges": [ { @@ -134821,7 +143349,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "value": "projectobject-tests" } }, { @@ -134848,6 +143376,14 @@ "header": "x-amz-checksum-crc64nvme", "algorithm": "crc64nvme" } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } } ], "allow_headers": [ @@ -134865,40 +143401,7 @@ "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": [ { @@ -134922,7 +143425,7 @@ "optional": false, "rule": { "is": "xml", - "value": "kvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" + "value": "projectobject-tests" } }, { @@ -134930,7 +143433,7 @@ "optional": false, "rule": { "is": "equal", - "value": "" + "value": "tagging" } }, { @@ -134949,6 +143452,14 @@ "header": "x-amz-checksum-crc64nvme", "algorithm": "crc64nvme" } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } } ], "allow_headers": [ @@ -134956,18 +143467,15 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 200, "headers": { - "content-type": "application/xml", "date": { "from": "now" } }, "body": { - "encoding": "utf8", - "data": "\nInvalidTagFixture error" - }, - "framing": "chunked" + "encoding": "empty" + } } } ] @@ -134979,74 +143487,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": "InvalidTag" + "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": "InvalidTag" - } - } - ] + "refusal": null }, { - "id": "operations/s3/put-tagging-special-characters", + "id": "operations/s3/put-tagging-deleted-version", "profile": "s3", "lane": "core", - "purpose": "Set a tag with a space and each of + - = . _ : / @, which S3 allows, escaped as XML text", + "purpose": "Send a tag call on a version that was deleted", "sources": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html" ], @@ -135054,8 +143505,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": [ { @@ -135083,7 +143535,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" } }, { @@ -135110,6 +143562,14 @@ "header": "x-amz-checksum-crc64nvme", "algorithm": "crc64nvme" } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } } ], "allow_headers": [ @@ -135117,50 +143577,20 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 404, "headers": { + "content-type": "application/xml", "date": { "from": "now" } }, "body": { - "encoding": "empty" - } + "encoding": "utf8", + "data": "\nNoSuchVersionFixture error" + }, + "framing": "chunked" } - } - ] - } - ], - "expect": [ - { - "at": "/outcome", - "optional": false, - "rule": { - "is": "equal", - "value": "ok" - } - } - ], - "refusal": null - }, - { - "id": "operations/s3/put-tagging-invalid-character", - "profile": "s3", - "lane": "core", - "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" - ], - "call": { - "key": "object-tests/tags/object.txt", - "op": "s3.put_tagging", - "tags": { - "a!b": "c" - } - }, - "exchanges": [ - { - "alternatives": [ + }, { "request": [ { @@ -135184,7 +143614,7 @@ "optional": false, "rule": { "is": "xml", - "value": "a!bc" + "value": "projectobject-tests" } }, { @@ -135192,7 +143622,7 @@ "optional": false, "rule": { "is": "equal", - "value": "" + "value": "tagging" } }, { @@ -135211,6 +143641,14 @@ "header": "x-amz-checksum-crc64nvme", "algorithm": "crc64nvme" } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "fixture-version-1" + } } ], "allow_headers": [ @@ -135218,7 +143656,7 @@ ], "allow_query": [], "response": { - "status": 400, + "status": 404, "headers": { "content-type": "application/xml", "date": { @@ -135227,7 +143665,7 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidTagFixture error" + "data": "\nNoSuchVersionFixture error" }, "framing": "chunked" } @@ -135249,7 +143687,7 @@ "optional": false, "rule": { "is": "equal", - "value": 400 + "value": 404 } }, { @@ -135257,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": [ { @@ -135352,7 +143743,7 @@ "optional": false, "rule": { "is": "xml", - "value": "projectaprojectb" + "value": "projectobject-tests" } }, { @@ -135379,6 +143770,14 @@ "header": "x-amz-checksum-crc64nvme", "algorithm": "crc64nvme" } + }, + { + "at": "/query/versionId", + "optional": false, + "rule": { + "is": "equal", + "value": "3sL4kqtJlcpXroDTDmJ.rmSpXd3dIbrHY" + } } ], "allow_headers": [ @@ -135395,7 +143794,86 @@ }, "body": { "encoding": "utf8", - "data": "\nInvalidTagFixture error" + "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": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 400, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nInvalidArgumentFixture error" }, "framing": "chunked" } @@ -135425,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", @@ -141046,6 +149482,142 @@ ], "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": [ + { + "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", + "optional": false, + "rule": { + "is": "equal", + "value": "1" + } + }, + { + "at": "/query/uploadId", + "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" + } + }, + { + "at": "/headers/x-amz-copy-source-if-match", + "optional": false, + "rule": { + "is": "equal", + "value": "\"fixture-0123456789ab\"" + } + } + ], + "allow_headers": [ + "content-type" + ], + "allow_query": [], + "response": { + "status": 412, + "headers": { + "content-type": "application/xml", + "date": { + "from": "now" + } + }, + "body": { + "encoding": "utf8", + "data": "\nPreconditionFailedFixture error" + }, + "framing": "chunked" + } + } + ] + } + ], + "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": "PreconditionFailed" + } + }, + { + "at": "/kind", + "optional": false, + "rule": { + "is": "equal", + "value": "precondition" + } + } + ], + "refusal": null + }, { "id": "operations/s3/staged-after-abort", "profile": "s3", @@ -184482,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", @@ -194161,22 +203162,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 +203904,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 +203960,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 +217086,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 +217318,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 +217438,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/multipart/object.bin" + "value": "/object-tests/keys/question?mark.txt" } }, { @@ -207734,16 +217534,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 +217639,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/question?mark.txt" + "value": "/object-tests/keys/hash#tag.txt" } }, { @@ -207935,16 +217735,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 +217840,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/hash#tag.txt" + "value": "/object-tests/keys/percent%20.txt" } }, { @@ -208136,16 +217936,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 +218041,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/percent%20.txt" + "value": "/object-tests/keys/plus+plus.txt" } }, { @@ -208337,16 +218137,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 +218242,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/plus+plus.txt" + "value": "/object-tests/keys/space name.txt" } }, { @@ -208538,16 +218338,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 +218443,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/space name.txt" + "value": "/object-tests/keys/café/雪.txt" } }, { @@ -208739,16 +218539,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 +218644,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/café/雪.txt" + "value": "/object-tests/keys/double//slash.txt" } }, { @@ -208940,16 +218740,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 +218845,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/double//slash.txt" + "value": "/object-tests/keys/trailing-slash/" } }, { @@ -209141,16 +218941,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 +219046,7 @@ "optional": false, "rule": { "is": "equal", - "value": "/object-tests/keys/trailing-slash/" + "value": "/object-tests/multipart/object.bin" } }, { @@ -209254,7 +219054,7 @@ "optional": false, "rule": { "is": "equal", - "value": "cGFydA==" + "value": "" } }, { @@ -209342,18 +219142,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 +219166,7 @@ "optional": false, "rule": { "is": "equal", - "value": "GET" + "value": "PUT" } }, { @@ -209374,17 +219174,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 +219209,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 +219225,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 +219240,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 +219351,7 @@ "at": "/headers/x-amz-s3session-token", "optional": false, "rule": { - "is": "equal", - "value": "fixture-session-token" + "is": "absent" } }, { @@ -209495,7 +219359,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 +219386,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 +219415,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 +219434,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 +219515,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 +219568,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 +219660,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 +219676,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 +219757,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 +219773,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 +219876,8 @@ "framing": "chunked" } } - ] + ], + "optional": true }, { "alternatives": [ @@ -210377,7 +220172,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 +220285,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 +220300,7 @@ ], "allow_query": [], "response": { - "status": 200, + "status": 412, "headers": { "content-type": "application/xml", "date": { @@ -210566,13 +220309,12 @@ }, "body": { "encoding": "utf8", - "data": "\nInternalErrorWe encountered an internal error. Please try again.fixturefixture" + "data": "\nPreconditionFailedFixture error" }, "framing": "chunked" } } - ], - "optional": true + ] } ], "expect": [ @@ -210584,12 +220326,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" } } ], 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!(