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

Commit 0a9af2d

Browse files
committed
added read_rows tests
1 parent 3935744 commit 0a9af2d

1 file changed

Lines changed: 184 additions & 9 deletions

File tree

tests/system/data/test_metrics_async.py

Lines changed: 184 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from google.cloud.bigtable_v2.types import ResponseParams
2626
from google.cloud.bigtable.data._metrics.handlers._base import MetricsHandler
2727
from google.cloud.bigtable.data._metrics.data_model import CompletedOperationMetric, CompletedAttemptMetric, ActiveOperationMetric, OperationState
28+
from google.cloud.bigtable.data.read_rows_query import ReadRowsQuery
2829

2930
from google.cloud.bigtable.data._cross_sync import CrossSync
3031

@@ -193,7 +194,7 @@ async def test_read_rows(self, table, temp_rows, handler, cluster_config):
193194
await temp_rows.add_row(b"row_key_1")
194195
await temp_rows.add_row(b"row_key_2")
195196
handler.clear()
196-
row_list = await table.read_rows({})
197+
row_list = await table.read_rows(ReadRowsQuery())
197198
assert len(row_list) == 2
198199
# validate counts
199200
assert len(handler.completed_operations) == 1
@@ -231,7 +232,38 @@ async def test_read_rows_failure_grpc(
231232
232233
No headers expected
233234
"""
234-
pass
235+
await temp_rows.add_row(b"row_key_1")
236+
handler.clear()
237+
exc = Aborted("injected")
238+
num_retryable = 2
239+
for i in range(num_retryable):
240+
error_injector.push(exc)
241+
error_injector.push(PermissionDenied("terminal"))
242+
with pytest.raises(PermissionDenied):
243+
await table.read_rows(ReadRowsQuery(), retryable_errors=[Aborted])
244+
# validate counts
245+
assert len(handler.completed_operations) == 1
246+
assert len(handler.completed_attempts) == num_retryable + 1
247+
assert len(handler.cancelled_operations) == 0
248+
# validate operation
249+
operation = handler.completed_operations[0]
250+
assert isinstance(operation, CompletedOperationMetric)
251+
assert operation.final_status.name == "PERMISSION_DENIED"
252+
assert operation.op_type.value == "ReadRows"
253+
assert operation.is_streaming is True
254+
assert len(operation.completed_attempts) == num_retryable + 1
255+
assert operation.cluster_id == "unspecified"
256+
assert operation.zone == "global"
257+
# validate attempts
258+
for i in range(num_retryable):
259+
attempt = handler.completed_attempts[i]
260+
assert isinstance(attempt, CompletedAttemptMetric)
261+
assert attempt.end_status.name == "ABORTED"
262+
assert attempt.gfe_latency_ns is None
263+
final_attempt = handler.completed_attempts[num_retryable]
264+
assert isinstance(final_attempt, CompletedAttemptMetric)
265+
assert final_attempt.end_status.name == "PERMISSION_DENIED"
266+
assert final_attempt.gfe_latency_ns is None
235267

236268
@CrossSync.pytest
237269
async def test_read_rows_failure_timeout(self, table, temp_rows, handler):
@@ -240,7 +272,28 @@ async def test_read_rows_failure_timeout(self, table, temp_rows, handler):
240272
241273
No grpc headers expected
242274
"""
243-
pass
275+
await temp_rows.add_row(b"row_key_1")
276+
handler.clear()
277+
with pytest.raises(GoogleAPICallError):
278+
await table.read_rows(ReadRowsQuery(), operation_timeout=0.001)
279+
# validate counts
280+
assert len(handler.completed_operations) == 1
281+
assert len(handler.completed_attempts) == 1
282+
assert len(handler.cancelled_operations) == 0
283+
# validate operation
284+
operation = handler.completed_operations[0]
285+
assert isinstance(operation, CompletedOperationMetric)
286+
assert operation.final_status.name == "DEADLINE_EXCEEDED"
287+
assert operation.op_type.value == "ReadRows"
288+
assert operation.is_streaming is True
289+
assert len(operation.completed_attempts) == 1
290+
assert operation.cluster_id == "unspecified"
291+
assert operation.zone == "global"
292+
# validate attempt
293+
attempt = handler.completed_attempts[0]
294+
assert isinstance(attempt, CompletedAttemptMetric)
295+
assert attempt.end_status.name == "DEADLINE_EXCEEDED"
296+
assert attempt.gfe_latency_ns is None
244297

245298
@CrossSync.pytest
246299
async def test_read_rows_failure_unauthorized(
@@ -249,15 +302,37 @@ async def test_read_rows_failure_unauthorized(
249302
"""
250303
Test failure in backend by accessing an unauthorized family
251304
"""
252-
pass
305+
from google.cloud.bigtable.data.row_filters import FamilyNameRegexFilter
306+
307+
with pytest.raises(GoogleAPICallError) as e:
308+
await authorized_view.read_rows(ReadRowsQuery(row_filter=FamilyNameRegexFilter("unauthorized")))
309+
assert e.value.grpc_status_code.name == "PERMISSION_DENIED"
310+
# validate counts
311+
assert len(handler.completed_operations) == 1
312+
assert len(handler.completed_attempts) == 1
313+
assert len(handler.cancelled_operations) == 0
314+
# validate operation
315+
operation = handler.completed_operations[0]
316+
assert isinstance(operation, CompletedOperationMetric)
317+
assert operation.final_status.name == "PERMISSION_DENIED"
318+
assert operation.op_type.value == "ReadRows"
319+
assert operation.is_streaming is True
320+
assert len(operation.completed_attempts) == 1
321+
assert operation.cluster_id == next(iter(cluster_config.keys()))
322+
assert operation.zone == cluster_config[operation.cluster_id].location.split("/")[-1]
323+
# validate attempt
324+
attempt = handler.completed_attempts[0]
325+
assert isinstance(attempt, CompletedAttemptMetric)
326+
assert attempt.end_status.name == "PERMISSION_DENIED"
327+
assert attempt.gfe_latency_ns >= 0 and attempt.gfe_latency_ns < operation.duration_ns
253328

254329
@CrossSync.pytest
255330
async def test_read_rows_stream(self, table, temp_rows, handler, cluster_config):
256331
await temp_rows.add_row(b"row_key_1")
257332
await temp_rows.add_row(b"row_key_2")
258333
handler.clear()
259334
# full table scan
260-
generator = await table.read_rows_stream({})
335+
generator = await table.read_rows_stream(ReadRowsQuery())
261336
row_list = [r async for r in generator]
262337
assert len(row_list) == 2
263338
# validate counts
@@ -296,7 +371,39 @@ async def test_read_rows_stream_failure_grpc(
296371
297372
No headers expected
298373
"""
299-
pass
374+
await temp_rows.add_row(b"row_key_1")
375+
handler.clear()
376+
exc = Aborted("injected")
377+
num_retryable = 2
378+
for i in range(num_retryable):
379+
error_injector.push(exc)
380+
error_injector.push(PermissionDenied("terminal"))
381+
generator = await table.read_rows_stream(ReadRowsQuery(), retryable_errors=[Aborted])
382+
with pytest.raises(PermissionDenied):
383+
[_ async for _ in generator]
384+
# validate counts
385+
assert len(handler.completed_operations) == 1
386+
assert len(handler.completed_attempts) == num_retryable + 1
387+
assert len(handler.cancelled_operations) == 0
388+
# validate operation
389+
operation = handler.completed_operations[0]
390+
assert isinstance(operation, CompletedOperationMetric)
391+
assert operation.final_status.name == "PERMISSION_DENIED"
392+
assert operation.op_type.value == "ReadRows"
393+
assert operation.is_streaming is True
394+
assert len(operation.completed_attempts) == num_retryable + 1
395+
assert operation.cluster_id == "unspecified"
396+
assert operation.zone == "global"
397+
# validate attempts
398+
for i in range(num_retryable):
399+
attempt = handler.completed_attempts[i]
400+
assert isinstance(attempt, CompletedAttemptMetric)
401+
assert attempt.end_status.name == "ABORTED"
402+
assert attempt.gfe_latency_ns is None
403+
final_attempt = handler.completed_attempts[num_retryable]
404+
assert isinstance(final_attempt, CompletedAttemptMetric)
405+
assert final_attempt.end_status.name == "PERMISSION_DENIED"
406+
assert final_attempt.gfe_latency_ns is None
300407

301408
@CrossSync.pytest
302409
async def test_read_rows_stream_failure_timeout(
@@ -307,7 +414,29 @@ async def test_read_rows_stream_failure_timeout(
307414
308415
No grpc headers expected
309416
"""
310-
pass
417+
await temp_rows.add_row(b"row_key_1")
418+
handler.clear()
419+
generator = await table.read_rows_stream(ReadRowsQuery(), operation_timeout=0.001)
420+
with pytest.raises(GoogleAPICallError):
421+
[_ async for _ in generator]
422+
# validate counts
423+
assert len(handler.completed_operations) == 1
424+
assert len(handler.completed_attempts) == 1
425+
assert len(handler.cancelled_operations) == 0
426+
# validate operation
427+
operation = handler.completed_operations[0]
428+
assert isinstance(operation, CompletedOperationMetric)
429+
assert operation.final_status.name == "DEADLINE_EXCEEDED"
430+
assert operation.op_type.value == "ReadRows"
431+
assert operation.is_streaming is True
432+
assert len(operation.completed_attempts) == 1
433+
assert operation.cluster_id == "unspecified"
434+
assert operation.zone == "global"
435+
# validate attempt
436+
attempt = handler.completed_attempts[0]
437+
assert isinstance(attempt, CompletedAttemptMetric)
438+
assert attempt.end_status.name == "DEADLINE_EXCEEDED"
439+
assert attempt.gfe_latency_ns is None
311440

312441
@CrossSync.pytest
313442
async def test_read_rows_stream_failure_unauthorized(
@@ -316,7 +445,30 @@ async def test_read_rows_stream_failure_unauthorized(
316445
"""
317446
Test failure in backend by accessing an unauthorized family
318447
"""
319-
pass
448+
from google.cloud.bigtable.data.row_filters import FamilyNameRegexFilter
449+
450+
with pytest.raises(GoogleAPICallError) as e:
451+
generator = await authorized_view.read_rows_stream(ReadRowsQuery(row_filter=FamilyNameRegexFilter("unauthorized")))
452+
[_ async for _ in generator]
453+
assert e.value.grpc_status_code.name == "PERMISSION_DENIED"
454+
# validate counts
455+
assert len(handler.completed_operations) == 1
456+
assert len(handler.completed_attempts) == 1
457+
assert len(handler.cancelled_operations) == 0
458+
# validate operation
459+
operation = handler.completed_operations[0]
460+
assert isinstance(operation, CompletedOperationMetric)
461+
assert operation.final_status.name == "PERMISSION_DENIED"
462+
assert operation.op_type.value == "ReadRows"
463+
assert operation.is_streaming is True
464+
assert len(operation.completed_attempts) == 1
465+
assert operation.cluster_id == next(iter(cluster_config.keys()))
466+
assert operation.zone == cluster_config[operation.cluster_id].location.split("/")[-1]
467+
# validate attempt
468+
attempt = handler.completed_attempts[0]
469+
assert isinstance(attempt, CompletedAttemptMetric)
470+
assert attempt.end_status.name == "PERMISSION_DENIED"
471+
assert attempt.gfe_latency_ns >= 0 and attempt.gfe_latency_ns < operation.duration_ns
320472

321473
@CrossSync.pytest
322474
async def test_read_rows_stream_failure_mid_stream(
@@ -325,7 +477,30 @@ async def test_read_rows_stream_failure_mid_stream(
325477
"""
326478
Test failure in grpc stream
327479
"""
328-
pass
480+
await temp_rows.add_row(b"row_key_1")
481+
handler.clear()
482+
error_injector.fail_mid_stream = True
483+
error_injector.push(Aborted("retryable"))
484+
error_injector.push(PermissionDenied("terminal"))
485+
generator = await table.read_rows_stream(ReadRowsQuery(), retryable_errors=[Aborted])
486+
with pytest.raises(PermissionDenied):
487+
[_ async for _ in generator]
488+
# validate counts
489+
assert len(handler.completed_operations) == 1
490+
assert len(handler.completed_attempts) == 2
491+
assert len(handler.cancelled_operations) == 0
492+
# validate operation
493+
operation = handler.completed_operations[0]
494+
assert operation.final_status.name == "PERMISSION_DENIED"
495+
assert operation.op_type.value == "ReadRows"
496+
assert operation.is_streaming is True
497+
assert len(operation.completed_attempts) == 2
498+
# validate retried attempt
499+
attempt = handler.completed_attempts[0]
500+
assert attempt.end_status.name == "ABORTED"
501+
# validate final attempt
502+
final_attempt = handler.completed_attempts[-1]
503+
assert final_attempt.end_status.name == "PERMISSION_DENIED"
329504

330505
@CrossSync.pytest
331506
async def test_read_row(self, table, temp_rows, handler, cluster_config):

0 commit comments

Comments
 (0)