|
| 1 | +import pytest |
1 | 2 | from botocore.stub import Stubber |
2 | 3 |
|
3 | 4 | from sentry_sdk.consts import OP, SPANDATA |
4 | | -from tests.integrations.boto3.helpers import capture_spans_by_op |
| 5 | +from tests.integrations.boto3.helpers import ( |
| 6 | + capture_spans_by_op, |
| 7 | + require_botocore_model_fields, |
| 8 | +) |
5 | 9 | from tests.integrations.boto3.helpers import client_factory as client_factory |
6 | 10 |
|
| 11 | +STREAM_ARN = "arn:aws:kinesis:eu-north-1:123456789012:stream/orders" |
| 12 | +CONSUMER_ARN = STREAM_ARN + "/consumer/billing:1760000000" |
7 | 13 |
|
8 | | -def test_request_attributes(client_factory, capture_items): |
9 | | - client = client_factory("kinesis") |
10 | | - stream_arn = "arn:aws:kinesis:eu-north-1:123456789012:stream/orders" |
11 | 14 |
|
| 15 | +def _stubbed_span(client_factory, capture_items, method, params, response): |
| 16 | + client = client_factory("kinesis") |
| 17 | + require_botocore_model_fields( |
| 18 | + client, method, input_fields=tuple(params), output_fields=tuple(response) |
| 19 | + ) |
12 | 20 | with Stubber(client) as stubber: |
13 | | - stubber.add_response( |
14 | | - "list_stream_consumers", {"Consumers": []}, {"StreamARN": stream_arn} |
15 | | - ) |
| 21 | + stubber.add_response(method, response, params) |
16 | 22 | spans = capture_spans_by_op( |
17 | | - lambda: client.list_stream_consumers(**{"StreamARN": stream_arn}), |
18 | | - capture_items, |
| 23 | + lambda: getattr(client, method)(**params), capture_items |
19 | 24 | ) |
20 | | - |
21 | 25 | (span,) = spans[OP.RPC] |
22 | | - attributes = span["attributes"] |
23 | | - assert attributes[SPANDATA.CLOUD_ACCOUNT_ID] == "123456789012" |
24 | | - assert attributes[SPANDATA.CLOUD_RESOURCE_ID] == stream_arn |
| 26 | + return span |
| 27 | + |
| 28 | + |
| 29 | +@pytest.mark.parametrize( |
| 30 | + "method,params,response,expected", |
| 31 | + [ |
| 32 | + pytest.param( |
| 33 | + "put_record", |
| 34 | + {"StreamName": "orders", "Data": b"{}", "PartitionKey": "customer-1"}, |
| 35 | + {"ShardId": "shardId-000000000000", "SequenceNumber": "1"}, |
| 36 | + {SPANDATA.AWS_KINESIS_STREAM_NAME: "orders"}, |
| 37 | + id="stream-name", |
| 38 | + ), |
| 39 | + pytest.param( |
| 40 | + "list_stream_consumers", |
| 41 | + {"StreamARN": STREAM_ARN}, |
| 42 | + {"Consumers": []}, |
| 43 | + { |
| 44 | + SPANDATA.AWS_KINESIS_STREAM_NAME: "orders", |
| 45 | + SPANDATA.CLOUD_RESOURCE_ID: STREAM_ARN, |
| 46 | + }, |
| 47 | + id="stream-arn", |
| 48 | + ), |
| 49 | + pytest.param( |
| 50 | + "deregister_stream_consumer", |
| 51 | + {"ConsumerARN": CONSUMER_ARN}, |
| 52 | + {}, |
| 53 | + { |
| 54 | + SPANDATA.AWS_KINESIS_STREAM_NAME: "orders", |
| 55 | + SPANDATA.CLOUD_RESOURCE_ID: CONSUMER_ARN, |
| 56 | + }, |
| 57 | + id="consumer-arn", |
| 58 | + ), |
| 59 | + pytest.param( |
| 60 | + "list_tags_for_resource", |
| 61 | + {"ResourceARN": CONSUMER_ARN}, |
| 62 | + {"Tags": []}, |
| 63 | + { |
| 64 | + SPANDATA.AWS_KINESIS_STREAM_NAME: "orders", |
| 65 | + SPANDATA.CLOUD_RESOURCE_ID: CONSUMER_ARN, |
| 66 | + }, |
| 67 | + id="resource-arn", |
| 68 | + ), |
| 69 | + ], |
| 70 | +) |
| 71 | +def test_stream_attributes( |
| 72 | + client_factory, capture_items, method, params, response, expected |
| 73 | +): |
| 74 | + span = _stubbed_span(client_factory, capture_items, method, params, response) |
| 75 | + |
| 76 | + assert { |
| 77 | + key: value |
| 78 | + for key, value in span["attributes"].items() |
| 79 | + if key in (SPANDATA.AWS_KINESIS_STREAM_NAME, SPANDATA.CLOUD_RESOURCE_ID) |
| 80 | + } == expected |
| 81 | + |
| 82 | + |
| 83 | +@pytest.mark.parametrize( |
| 84 | + "error_codes,expected_error_type", |
| 85 | + [ |
| 86 | + pytest.param((), None, id="ok"), |
| 87 | + pytest.param( |
| 88 | + ("ProvisionedThroughputExceededException",) * 2, |
| 89 | + "ProvisionedThroughputExceededException", |
| 90 | + id="one-code", |
| 91 | + ), |
| 92 | + pytest.param( |
| 93 | + ("ProvisionedThroughputExceededException", "InternalFailure"), |
| 94 | + "aws_batch_partial_failure", |
| 95 | + id="different-codes", |
| 96 | + ), |
| 97 | + ], |
| 98 | +) |
| 99 | +def test_put_records_outcome( |
| 100 | + client_factory, capture_items, error_codes, expected_error_type |
| 101 | +): |
| 102 | + params = { |
| 103 | + "StreamName": "orders", |
| 104 | + "Records": [ |
| 105 | + {"Data": b"card 4242", "PartitionKey": "customer-1"}, |
| 106 | + {"Data": b"card 4242", "PartitionKey": "customer-2"}, |
| 107 | + {"Data": b"card 4242", "PartitionKey": "customer-3"}, |
| 108 | + ], |
| 109 | + } |
| 110 | + response = { |
| 111 | + "Records": [{"ShardId": "shardId-000000000000", "SequenceNumber": "1"}] |
| 112 | + + [{"ErrorCode": code, "ErrorMessage": "failed"} for code in error_codes], |
| 113 | + } |
| 114 | + # the model's minimum is 1, so the stubber only accepts it for failed records. |
| 115 | + if error_codes: |
| 116 | + response["FailedRecordCount"] = len(error_codes) # type: ignore |
| 117 | + span = _stubbed_span(client_factory, capture_items, "put_records", params, response) |
| 118 | + |
| 119 | + assert span["status"] == ("ok" if expected_error_type is None else "error") |
| 120 | + assert span["attributes"].get(SPANDATA.ERROR_TYPE) == expected_error_type |
0 commit comments