Skip to content

Commit 2bb47d6

Browse files
test(table): billing faults before definition faults; wait for the index
CreateTable with PAY_PER_REQUEST and throughput beside a duplicated name, a missing key, or fewer definitions than keys answers the billing sentence (measured 2026-10-26 at 02:27 and 02:34 UTC). The redefinition test waits for its new index to be active before the table is deleted, since the service refuses DeleteTable while an index is being created, and writes an item with the stored key type. The measurement times in the docstring are corrected to 01:27 and 01:29 UTC, plus the two later runs.
1 parent a430c57 commit 2bb47d6

1 file changed

Lines changed: 38 additions & 5 deletions

File tree

‎tests/test_key_schema_definitions.py‎

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33

44
"""Key schemas whose attributes are missing from AttributeDefinitions.
55
6-
Amazon DynamoDB, measured on 2026-10-25 and 2026-10-26 at 01:30 UTC
7-
(us-east-1), each request twice, on CreateTable and on an UpdateTable GSI
8-
Create:
6+
Amazon DynamoDB, measured on 2026-10-25 and 2026-10-26 at 01:27, 01:29,
7+
02:27 and 02:34 UTC (us-east-1), each request twice, on CreateTable and on
8+
an UpdateTable GSI Create:
99
10+
- A table billing fault is reported first.
1011
- A name defined twice answers ``Attribute Name is duplicated: <name>``,
11-
naming the first name whose second definition comes first, before every
12-
key check.
12+
naming the first name whose second definition comes first, before a
13+
missing key.
1314
- The table's key schema is checked first, then each LSI's, then each GSI's.
1415
A schema with more keys than there are definitions answers ``Invalid
1516
KeySchema: Some index key attribute have no definition``. Otherwise a key
@@ -31,6 +32,7 @@
3132
from __future__ import annotations
3233

3334
import re
35+
import time
3436

3537
import pytest
3638
from botocore.exceptions import ClientError
@@ -170,6 +172,23 @@ def test_create_table_checks_each_key_schema_in_turn(dynamodb_client, case, spec
170172
assert _listed(message) == (keys, names)
171173

172174

175+
BILLING = ("One or more parameter values were invalid: Neither ReadCapacityUnits nor WriteCapacityUnits "
176+
"can be specified when BillingMode is PAY_PER_REQUEST")
177+
178+
179+
@pytest.mark.parametrize(("spec", "table_keys"), [
180+
("pk:S pk:S", ks("pk")),
181+
("pk:S x:S", ks("pk", "sk")),
182+
("pk:S", ks("pk", "sk")),
183+
], ids=["duplicate", "missing_key", "fewer_definitions"])
184+
def test_create_table_reports_a_billing_fault_first(dynamodb_client, spec, table_keys):
185+
def call():
186+
dynamodb_client.create_table(
187+
TableName="never-created-key-definitions", AttributeDefinitions=defs(spec), KeySchema=table_keys,
188+
BillingMode="PAY_PER_REQUEST", ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1})
189+
assert _message(call) == BILLING
190+
191+
173192
@pytest.mark.parametrize(("spec", "table_keys", "gsis", "name"), [
174193
("pk:S pk:S", ks("pk"), [], "pk"),
175194
("pk:S pk:N", ks("pk"), [], "pk"),
@@ -182,6 +201,17 @@ def test_create_table_refuses_a_name_defined_twice(dynamodb_client, spec, table_
182201
assert message == f"Attribute Name is duplicated: {name}"
183202

184203

204+
def _wait_for_index(client, table, index, timeout=120.0):
205+
deadline = time.monotonic() + timeout
206+
while time.monotonic() < deadline:
207+
desc = client.describe_table(TableName=table)["Table"]
208+
status = {i["IndexName"]: i["IndexStatus"] for i in desc.get("GlobalSecondaryIndexes", [])}
209+
if desc["TableStatus"] == "ACTIVE" and status.get(index) == "ACTIVE":
210+
return
211+
time.sleep(0.5)
212+
raise TimeoutError(f"{index} on {table} not ACTIVE after {timeout} s")
213+
214+
185215
def test_update_table_keeps_the_type_of_a_redefined_table_key(dynamodb_client):
186216
with scoped_table(dynamodb_client) as name:
187217
dynamodb_client.update_table(
@@ -196,3 +226,6 @@ def test_update_table_keeps_the_type_of_a_redefined_table_key(dynamodb_client):
196226
desc = dynamodb_client.describe_table(TableName=name)["Table"]
197227
stored = {d["AttributeName"]: d["AttributeType"] for d in desc["AttributeDefinitions"]}
198228
assert stored == {"pk": "S", "g": "S"}
229+
# The table cannot be deleted while the index is being created.
230+
_wait_for_index(dynamodb_client, name, "by-g")
231+
dynamodb_client.put_item(TableName=name, Item={"pk": {"S": "a"}, "g": {"S": "b"}})

0 commit comments

Comments
 (0)