File: test_conditional_writes.py

package info (click to toggle)
swift 2.36.0-7
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 23,672 kB
  • sloc: python: 286,220; javascript: 1,059; sh: 619; pascal: 295; makefile: 81; xml: 32
file content (142 lines) | stat: -rw-r--r-- 5,495 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Copyright (c) 2025 Nvidia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from test.s3api import BaseS3TestCaseWithBucket, status_from_error, \
    code_from_error
from botocore.exceptions import ClientError


class TestConditionalWrites(BaseS3TestCaseWithBucket):
    def test_if_none_match_star_simple_put(self):
        client = self.get_s3_client(1)
        key_name = self.create_name('if-none-match-simple')
        # Can create new object fine
        resp = client.put_object(
            Bucket=self.bucket_name,
            Key=key_name,
            IfNoneMatch='*',
            Body=b'',
        )
        self.assertEqual(200, resp['ResponseMetadata']['HTTPStatusCode'])
        # But overwrite is blocked
        with self.assertRaises(ClientError) as caught:
            client.put_object(
                Bucket=self.bucket_name,
                Key=key_name,
                IfNoneMatch='*',
                Body=b'',
            )
        self.assertEqual(412, status_from_error(caught.exception))
        self.assertEqual('PreconditionFailed',
                         code_from_error(caught.exception))

    def test_if_none_match_star_mpu(self):
        client = self.get_s3_client(1)
        key_name = self.create_name('if-none-match-mpu')

        create_mpu_resp = client.create_multipart_upload(
            Bucket=self.bucket_name, Key=key_name)
        self.assertEqual(200, create_mpu_resp[
            'ResponseMetadata']['HTTPStatusCode'])
        upload_id = create_mpu_resp['UploadId']
        parts = []
        for part_num in range(1, 4):
            part_resp = client.upload_part(
                Body=b'x' * 5 * 1024 * 1024,
                Bucket=self.bucket_name, Key=key_name,
                PartNumber=part_num, UploadId=upload_id)
            self.assertEqual(200, part_resp[
                'ResponseMetadata']['HTTPStatusCode'])
            parts.append({
                'ETag': part_resp['ETag'],
                'PartNumber': part_num,
            })

        # Nothing there, so complete succeeds
        complete_mpu_resp = client.complete_multipart_upload(
            Bucket=self.bucket_name,
            Key=key_name,
            MultipartUpload={'Parts': parts[:2]},
            UploadId=upload_id,
            IfNoneMatch='*',
        )
        self.assertEqual(200, complete_mpu_resp[
            'ResponseMetadata']['HTTPStatusCode'])

        # Retrying with more parts fails
        with self.assertRaises(ClientError) as caught:
            client.complete_multipart_upload(
                Bucket=self.bucket_name,
                Key=key_name,
                MultipartUpload={'Parts': parts},
                UploadId=upload_id,
                IfNoneMatch='*',
            )
        self.assertEqual(404, status_from_error(caught.exception))
        self.assertEqual('NoSuchUpload',
                         code_from_error(caught.exception))

        # Ditto fewer
        with self.assertRaises(ClientError) as caught:
            client.complete_multipart_upload(
                Bucket=self.bucket_name,
                Key=key_name,
                MultipartUpload={'Parts': parts[:1]},
                UploadId=upload_id,
                IfNoneMatch='*',
            )
        self.assertEqual(404, status_from_error(caught.exception))
        self.assertEqual('NoSuchUpload',
                         code_from_error(caught.exception))

        # Can retry with all the same parts and 200 though
        complete_mpu_resp = client.complete_multipart_upload(
            Bucket=self.bucket_name,
            Key=key_name,
            MultipartUpload={'Parts': parts[:2]},
            UploadId=upload_id,
            IfNoneMatch='*',
        )
        self.assertEqual(200, complete_mpu_resp[
            'ResponseMetadata']['HTTPStatusCode'])

        # Can still start a new upload
        create_mpu_resp = client.create_multipart_upload(
            Bucket=self.bucket_name, Key=key_name)
        self.assertEqual(200, create_mpu_resp[
            'ResponseMetadata']['HTTPStatusCode'])
        upload_id = create_mpu_resp['UploadId']
        # And upload parts
        part_resp = client.upload_part(
            Body=b'', Bucket=self.bucket_name, Key=key_name,
            PartNumber=1, UploadId=upload_id)
        self.assertEqual(200, part_resp[
            'ResponseMetadata']['HTTPStatusCode'])
        parts = [{
            'ETag': part_resp['ETag'],
            'PartNumber': 1,
        }]
        # But completion will be blocked
        with self.assertRaises(ClientError) as caught:
            client.complete_multipart_upload(
                Bucket=self.bucket_name,
                Key=key_name,
                MultipartUpload={'Parts': parts},
                UploadId=upload_id,
                IfNoneMatch='*',
            )
        self.assertEqual(412, status_from_error(caught.exception))
        self.assertEqual('PreconditionFailed',
                         code_from_error(caught.exception))