from uuid import uuid4 import boto3 import pytest from moto import mock_aws @mock_aws class TestS3ObjectAttributes: def setup_method(self, *args) -> None: # pylint: disable=unused-argument self.bucket_name = str(uuid4()) self.s3_resource = boto3.resource("s3", region_name="us-east-1") self.client = boto3.client("s3", region_name="us-east-1") self.bucket = self.s3_resource.Bucket(self.bucket_name) self.bucket.create() self.key = self.bucket.put_object(Key="mykey", Body=b"somedata") def test_get_etag(self): actual_etag = self.key.e_tag[1:-1] # etag comes with quotes originally resp = self.client.get_object_attributes( Bucket=self.bucket_name, Key="mykey", ObjectAttributes=["ETag"] ) headers = set(resp["ResponseMetadata"]["HTTPHeaders"].keys()) assert "x-amz-version-id" not in headers assert "last-modified" in headers resp.pop("ResponseMetadata") assert set(resp.keys()) == {"ETag", "LastModified"} assert resp["ETag"] == actual_etag def test_get_attributes_storageclass(self): resp = self.client.get_object_attributes( Bucket=self.bucket_name, Key="mykey", ObjectAttributes=["StorageClass"] ) resp.pop("ResponseMetadata") assert set(resp.keys()) == {"StorageClass", "LastModified"} assert resp["StorageClass"] == "STANDARD" def test_get_attributes_size(self): resp = self.client.get_object_attributes( Bucket=self.bucket_name, Key="mykey", ObjectAttributes=["ObjectSize"] ) resp.pop("ResponseMetadata") assert set(resp.keys()) == {"ObjectSize", "LastModified"} assert resp["ObjectSize"] == 8 @pytest.mark.parametrize( "algo_val", [ ("CRC32", "6Le+Qw=="), ("SHA1", "hvfkN/qlp/zhXR3cuerq6jd2Z7g="), ("SHA256", "ypeBEsobvcr6wjGzmiPcTaeG7/gUfE5yuYB3ha/uSLs="), ], ) def test_get_attributes_checksum(self, algo_val): algo, value = algo_val self.client.put_object( Bucket=self.bucket_name, Key="cs", Body="a", ChecksumAlgorithm=algo ) resp = self.client.get_object_attributes( Bucket=self.bucket_name, Key="mykey", ObjectAttributes=["Checksum"] ) resp.pop("ResponseMetadata") # Checksum is not returned, because it's not set assert set(resp.keys()) == {"LastModified"} # Retrieve checksum from key that was created with CRC32 resp = self.client.get_object_attributes( Bucket=self.bucket_name, Key="cs", ObjectAttributes=["Checksum"] ) resp.pop("ResponseMetadata") assert set(resp.keys()) == {"Checksum", "LastModified"} assert resp["Checksum"] == {f"Checksum{algo}": value} def test_get_attributes_multiple(self): resp = self.client.get_object_attributes( Bucket=self.bucket_name, Key="mykey", ObjectAttributes=["ObjectSize", "StorageClass"], ) headers = set(resp["ResponseMetadata"]["HTTPHeaders"].keys()) assert "x-amz-version-id" not in headers resp.pop("ResponseMetadata") assert set(resp.keys()) == {"ObjectSize", "LastModified", "StorageClass"} assert resp["ObjectSize"] == 8 assert resp["StorageClass"] == "STANDARD" def test_get_versioned_object(self): self.bucket.Versioning().enable() key2 = self.bucket.put_object(Key="mykey", Body=b"moredata") resp = self.client.get_object_attributes( Bucket=self.bucket_name, Key="mykey", ObjectAttributes=["ETag"] ) headers = resp["ResponseMetadata"]["HTTPHeaders"] header_keys = set(headers.keys()) assert "x-amz-version-id" in header_keys assert headers["x-amz-version-id"] == key2.version_id resp.pop("ResponseMetadata") assert set(resp.keys()) == {"ETag", "LastModified", "VersionId"} assert resp["VersionId"] == key2.version_id