Skip to content
This repository was archived by the owner on Apr 1, 2026. It is now read-only.

Commit 66d3254

Browse files
committed
added unauthenticated error test
1 parent 3fb4f13 commit 66d3254

2 files changed

Lines changed: 65 additions & 59 deletions

File tree

google/cloud/bigtable/data/_async/metrics_interceptor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ def _end_attempt(operation, exc, metadata):
8989
async def _get_metadata(source):
9090
"""Helper to extract metadata from a call or RpcError"""
9191
try:
92-
return (await source.trailing_metadata() or []) + (
93-
await source.initial_metadata() or []
92+
return (await source.trailing_metadata() or {}) + (
93+
await source.initial_metadata() or {}
9494
)
9595
except Exception:
9696
# ignore errors while fetching metadata

tests/system/data/test_metrics_async.py

Lines changed: 63 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -127,24 +127,31 @@ async def client(self, error_injector):
127127

128128
@CrossSync.convert
129129
@CrossSync.pytest_fixture(scope="function")
130-
async def temp_rows(self, target):
131-
builder = CrossSync.TempRowBuilder(target)
130+
async def temp_rows(self, table):
131+
builder = CrossSync.TempRowBuilder(table)
132132
yield builder
133133
await builder.delete_rows()
134134

135135
@CrossSync.convert
136136
@CrossSync.pytest_fixture(scope="session")
137-
async def target(self, client, table_id, instance_id, handler):
137+
async def table(self, client, table_id, instance_id, handler):
138138
async with client.get_table(instance_id, table_id) as table:
139139
table._metrics.add_handler(handler)
140140
yield table
141141

142+
@CrossSync.convert
143+
@CrossSync.pytest_fixture(scope="session")
144+
async def authorized_view(self, client, table_id, instance_id, authorized_view_id, handler):
145+
async with client.get_authorized_view(instance_id, table_id, authorized_view_id) as table:
146+
table._metrics.add_handler(handler)
147+
yield table
148+
142149
@CrossSync.pytest
143-
async def test_read_rows(self, target, temp_rows, handler, cluster_config):
150+
async def test_read_rows(self, table, temp_rows, handler, cluster_config):
144151
await temp_rows.add_row(b"row_key_1")
145152
await temp_rows.add_row(b"row_key_2")
146153
handler.clear()
147-
row_list = await target.read_rows({})
154+
row_list = await table.read_rows({})
148155
assert len(row_list) == 2
149156
# validate counts
150157
assert len(handler.completed_operations) == 1
@@ -174,12 +181,12 @@ async def test_read_rows(self, target, temp_rows, handler, cluster_config):
174181
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
175182

176183
@CrossSync.pytest
177-
async def test_read_rows_stream(self, target, temp_rows, handler, cluster_config):
184+
async def test_read_rows_stream(self, table, temp_rows, handler, cluster_config):
178185
await temp_rows.add_row(b"row_key_1")
179186
await temp_rows.add_row(b"row_key_2")
180187
handler.clear()
181188
# full table scan
182-
generator = await target.read_rows_stream({})
189+
generator = await table.read_rows_stream({})
183190
row_list = [r async for r in generator]
184191
assert len(row_list) == 2
185192
# validate counts
@@ -210,10 +217,10 @@ async def test_read_rows_stream(self, target, temp_rows, handler, cluster_config
210217
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
211218

212219
@CrossSync.pytest
213-
async def test_read_row(self, target, temp_rows, handler, cluster_config):
220+
async def test_read_row(self, table, temp_rows, handler, cluster_config):
214221
await temp_rows.add_row(b"row_key_1")
215222
handler.clear()
216-
await target.read_row(b"row_key_1")
223+
await table.read_row(b"row_key_1")
217224
# validate counts
218225
assert len(handler.completed_operations) == 1
219226
assert len(handler.completed_attempts) == 1
@@ -242,7 +249,7 @@ async def test_read_row(self, target, temp_rows, handler, cluster_config):
242249
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
243250

244251
@CrossSync.pytest
245-
async def test_read_rows_sharded(self, target, temp_rows, handler, cluster_config):
252+
async def test_read_rows_sharded(self, table, temp_rows, handler, cluster_config):
246253
from google.cloud.bigtable.data.read_rows_query import ReadRowsQuery
247254
await temp_rows.add_row(b"a")
248255
await temp_rows.add_row(b"b")
@@ -251,7 +258,7 @@ async def test_read_rows_sharded(self, target, temp_rows, handler, cluster_confi
251258
query1 = ReadRowsQuery(row_keys=[b"a", b"c"])
252259
query2 = ReadRowsQuery(row_keys=[b"b", b"d"])
253260
handler.clear()
254-
row_list = await target.read_rows_sharded([query1, query2])
261+
row_list = await table.read_rows_sharded([query1, query2])
255262
assert len(row_list) == 4
256263
# validate counts
257264
assert len(handler.completed_operations) == 2
@@ -281,17 +288,17 @@ async def test_read_rows_sharded(self, target, temp_rows, handler, cluster_confi
281288
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
282289

283290
@CrossSync.pytest
284-
async def test_bulk_mutate_rows(self, target, temp_rows, handler, cluster_config):
291+
async def test_bulk_mutate_rows(self, table, temp_rows, handler, cluster_config):
285292
from google.cloud.bigtable.data.mutations import RowMutationEntry
286293

287294
new_value = uuid.uuid4().hex.encode()
288295
row_key, mutation = await temp_rows.create_row_and_mutation(
289-
target, new_value=new_value
296+
table, new_value=new_value
290297
)
291298
bulk_mutation = RowMutationEntry(row_key, [mutation])
292299

293300
handler.clear()
294-
await target.bulk_mutate_rows([bulk_mutation])
301+
await table.bulk_mutate_rows([bulk_mutation])
295302
# validate counts
296303
assert len(handler.completed_operations) == 1
297304
assert len(handler.completed_attempts) == 1
@@ -320,21 +327,21 @@ async def test_bulk_mutate_rows(self, target, temp_rows, handler, cluster_config
320327
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
321328

322329
@CrossSync.pytest
323-
async def test_mutate_rows_batcher(self, target, temp_rows, handler, cluster_config):
330+
async def test_mutate_rows_batcher(self, table, temp_rows, handler, cluster_config):
324331
from google.cloud.bigtable.data.mutations import RowMutationEntry
325332

326333
new_value, new_value2 = [uuid.uuid4().hex.encode() for _ in range(2)]
327334
row_key, mutation = await temp_rows.create_row_and_mutation(
328-
target, new_value=new_value
335+
table, new_value=new_value
329336
)
330337
row_key2, mutation2 = await temp_rows.create_row_and_mutation(
331-
target, new_value=new_value2
338+
table, new_value=new_value2
332339
)
333340
bulk_mutation = RowMutationEntry(row_key, [mutation])
334341
bulk_mutation2 = RowMutationEntry(row_key2, [mutation2])
335342

336343
handler.clear()
337-
async with target.mutations_batcher() as batcher:
344+
async with table.mutations_batcher() as batcher:
338345
await batcher.append(bulk_mutation)
339346
await batcher.append(bulk_mutation2)
340347
# validate counts
@@ -370,14 +377,14 @@ async def test_mutate_rows_batcher(self, target, temp_rows, handler, cluster_con
370377
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
371378

372379
@CrossSync.pytest
373-
async def test_mutate_row(self, target, temp_rows, handler, cluster_config):
380+
async def test_mutate_row(self, table, temp_rows, handler, cluster_config):
374381
row_key = b"bulk_mutate"
375382
new_value = uuid.uuid4().hex.encode()
376383
row_key, mutation = await temp_rows.create_row_and_mutation(
377-
target, new_value=new_value
384+
table, new_value=new_value
378385
)
379386
handler.clear()
380-
await target.mutate_row(row_key, mutation)
387+
await table.mutate_row(row_key, mutation)
381388
# validate counts
382389
assert len(handler.completed_operations) == 1
383390
assert len(handler.completed_attempts) == 1
@@ -406,8 +413,8 @@ async def test_mutate_row(self, target, temp_rows, handler, cluster_config):
406413
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
407414

408415
@CrossSync.pytest
409-
async def test_sample_row_keys(self, target, temp_rows, handler, cluster_config):
410-
await target.sample_row_keys()
416+
async def test_sample_row_keys(self, table, temp_rows, handler, cluster_config):
417+
await table.sample_row_keys()
411418
# validate counts
412419
assert len(handler.completed_operations) == 1
413420
assert len(handler.completed_attempts) == 1
@@ -436,7 +443,7 @@ async def test_sample_row_keys(self, target, temp_rows, handler, cluster_config)
436443
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
437444

438445
@CrossSync.pytest
439-
async def test_read_modify_write(self, target, temp_rows, handler, cluster_config):
446+
async def test_read_modify_write(self, table, temp_rows, handler, cluster_config):
440447
from google.cloud.bigtable.data.read_modify_write_rules import IncrementRule
441448

442449
row_key = b"test-row-key"
@@ -446,7 +453,7 @@ async def test_read_modify_write(self, target, temp_rows, handler, cluster_confi
446453
row_key, value=0, family=family, qualifier=qualifier
447454
)
448455
rule = IncrementRule(family, qualifier, 1)
449-
await target.read_modify_write_row(row_key, rule)
456+
await table.read_modify_write_row(row_key, rule)
450457
# validate counts
451458
assert len(handler.completed_operations) == 1
452459
assert len(handler.completed_attempts) == 1
@@ -475,7 +482,7 @@ async def test_read_modify_write(self, target, temp_rows, handler, cluster_confi
475482
assert attempt.grpc_throttling_time_ns == 0 # TODO: confirm
476483

477484
@CrossSync.pytest
478-
async def test_check_and_mutate_row(self, target, temp_rows, handler, cluster_config):
485+
async def test_check_and_mutate_row(self, table, temp_rows, handler, cluster_config):
479486
from google.cloud.bigtable.data.mutations import SetCell
480487
from google.cloud.bigtable.data.row_filters import ValueRangeFilter
481488

@@ -491,7 +498,7 @@ async def test_check_and_mutate_row(self, target, temp_rows, handler, cluster_co
491498
family=TEST_FAMILY, qualifier=qualifier, new_value=true_mutation_value
492499
)
493500
predicate = ValueRangeFilter(0, 2)
494-
await target.check_and_mutate_row(
501+
await table.check_and_mutate_row(
495502
row_key,
496503
predicate,
497504
true_case_mutations=true_mutation,
@@ -525,7 +532,7 @@ async def test_check_and_mutate_row(self, target, temp_rows, handler, cluster_co
525532

526533
@CrossSync.pytest
527534
async def test_check_and_mutate_row_failure_grpc(
528-
self, target, temp_rows, handler, error_injector
535+
self, table, temp_rows, handler, error_injector
529536
):
530537
"""
531538
Test failure in grpc layer by injecting an error into an interceptor
@@ -544,7 +551,7 @@ async def test_check_and_mutate_row_failure_grpc(
544551
exc = RuntimeError("injected")
545552
error_injector.push(exc)
546553
with pytest.raises(RuntimeError):
547-
await target.check_and_mutate_row(
554+
await table.check_and_mutate_row(
548555
row_key,
549556
predicate=ValueRangeFilter(0,2),
550557
)
@@ -579,13 +586,13 @@ async def test_check_and_mutate_row_failure_grpc(
579586

580587

581588
@CrossSync.pytest
582-
async def test_check_and_mutate_row_failure_invalid_argument(
583-
self, target, temp_rows, handler
589+
async def test_check_and_mutate_row_failure_timeout(
590+
self, table, temp_rows, handler
584591
):
585592
"""
586-
Test failure on backend by passing invalid argument
593+
Test failure in gapic layer by passing very low timeout
587594
588-
We expect a server-timing header, but no cluster/zone info
595+
No grpc headers expected
589596
"""
590597
from google.cloud.bigtable.data.mutations import SetCell
591598
from google.cloud.bigtable.data.row_filters import ValueRangeFilter
@@ -595,11 +602,16 @@ async def test_check_and_mutate_row_failure_invalid_argument(
595602
qualifier = b"test-qualifier"
596603
await temp_rows.add_row(row_key, value=1, family=family, qualifier=qualifier)
597604

598-
predicate = ValueRangeFilter(-1, -1)
605+
true_mutation_value = b"true-mutation-value"
606+
true_mutation = SetCell(
607+
family=TEST_FAMILY, qualifier=qualifier, new_value=true_mutation_value
608+
)
599609
with pytest.raises(GoogleAPICallError):
600-
await target.check_and_mutate_row(
610+
await table.check_and_mutate_row(
601611
row_key,
602-
predicate,
612+
predicate=ValueRangeFilter(0, 2),
613+
true_case_mutations=true_mutation,
614+
operation_timeout=0.001
603615
)
604616
# validate counts
605617
assert len(handler.completed_operations) == 1
@@ -608,41 +620,35 @@ async def test_check_and_mutate_row_failure_invalid_argument(
608620
# validate operation
609621
operation = handler.completed_operations[0]
610622
assert isinstance(operation, CompletedOperationMetric)
611-
assert operation.final_status.name == "INVALID_ARGUMENT"
623+
assert operation.final_status.name == "DEADLINE_EXCEEDED"
612624
assert operation.cluster_id == "unspecified"
613625
assert operation.zone == "global"
614626
# validate attempt
615627
attempt = handler.completed_attempts[0]
616-
assert attempt.gfe_latency_ns >= 0 and attempt.gfe_latency_ns < operation.duration_ns
617-
628+
assert attempt.gfe_latency_ns is None
618629

619630
@CrossSync.pytest
620-
async def test_check_and_mutate_row_failure_timeout(
621-
self, target, temp_rows, handler, error_injector
631+
async def test_check_and_mutate_row_failure_unauthorized(
632+
self, handler, authorized_view, cluster_config
622633
):
623634
"""
624-
Test failure in gapic layer by passing very low timeout
625-
626-
No grpc headers expected
635+
Test failure in backend by accessing an unauthorized family
627636
"""
628637
from google.cloud.bigtable.data.mutations import SetCell
629638
from google.cloud.bigtable.data.row_filters import ValueRangeFilter
630639

631640
row_key = b"test-row-key"
632-
family = TEST_FAMILY
633641
qualifier = b"test-qualifier"
634-
await temp_rows.add_row(row_key, value=1, family=family, qualifier=qualifier)
635-
636-
true_mutation_value = b"true-mutation-value"
637-
true_mutation = SetCell(
638-
family=TEST_FAMILY, qualifier=qualifier, new_value=true_mutation_value
642+
mutation_value = b"true-mutation-value"
643+
mutation = SetCell(
644+
family="unauthorized", qualifier=qualifier, new_value=mutation_value
639645
)
640646
with pytest.raises(GoogleAPICallError):
641-
await target.check_and_mutate_row(
647+
await authorized_view.check_and_mutate_row(
642648
row_key,
643649
predicate=ValueRangeFilter(0, 2),
644-
true_case_mutations=true_mutation,
645-
operation_timeout=0.001
650+
true_case_mutations=mutation,
651+
false_case_mutations=mutation,
646652
)
647653
# validate counts
648654
assert len(handler.completed_operations) == 1
@@ -651,9 +657,9 @@ async def test_check_and_mutate_row_failure_timeout(
651657
# validate operation
652658
operation = handler.completed_operations[0]
653659
assert isinstance(operation, CompletedOperationMetric)
654-
assert operation.final_status.name == "DEADLINE_EXCEEDED"
655-
assert operation.cluster_id == "unspecified"
656-
assert operation.zone == "global"
660+
assert operation.final_status.name == "PERMISSION_DENIED"
661+
assert operation.cluster_id == next(iter(cluster_config.keys()))
662+
assert operation.zone == cluster_config[operation.cluster_id].location.split("/")[-1]
657663
# validate attempt
658664
attempt = handler.completed_attempts[0]
659-
assert attempt.gfe_latency_ns is None
665+
assert attempt.gfe_latency_ns >= 0 and attempt.gfe_latency_ns < operation.duration_ns

0 commit comments

Comments
 (0)