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

Commit 6798ea2

Browse files
committed
fixed more tests
1 parent 0340fce commit 6798ea2

7 files changed

Lines changed: 150 additions & 59 deletions

File tree

tests/unit/data/_async/test__mutate_rows.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from google.cloud.bigtable_v2.types import MutateRowsResponse
1818
from google.cloud.bigtable.data.mutations import RowMutationEntry
1919
from google.cloud.bigtable.data.mutations import DeleteAllFromRow
20+
from google.cloud.bigtable.data._metrics import ActiveOperationMetric
2021
from google.rpc import status_pb2
2122
from google.api_core.exceptions import DeadlineExceeded
2223
from google.api_core.exceptions import Forbidden
@@ -48,6 +49,7 @@ def _make_one(self, *args, **kwargs):
4849
kwargs["attempt_timeout"] = kwargs.pop("attempt_timeout", 0.1)
4950
kwargs["retryable_exceptions"] = kwargs.pop("retryable_exceptions", ())
5051
kwargs["mutation_entries"] = kwargs.pop("mutation_entries", [])
52+
kwargs["metric"] = kwargs.pop("metric", ActiveOperationMetric("MUTATE_ROWS"))
5153
return self._target_class()(*args, **kwargs)
5254

5355
def _make_mutation(self, count=1, size=1):
@@ -90,13 +92,15 @@ def test_ctor(self):
9092
entries = [self._make_mutation(), self._make_mutation()]
9193
operation_timeout = 0.05
9294
attempt_timeout = 0.01
95+
metric = mock.Mock()
9396
retryable_exceptions = ()
9497
instance = self._make_one(
9598
client,
9699
table,
97100
entries,
98101
operation_timeout,
99102
attempt_timeout,
103+
metric,
100104
retryable_exceptions,
101105
)
102106
# running gapic_fn should trigger a client call with baked-in args
@@ -116,6 +120,7 @@ def test_ctor(self):
116120
assert instance.is_retryable(RuntimeError("")) is False
117121
assert instance.remaining_indices == list(range(len(entries)))
118122
assert instance.errors == {}
123+
assert instance._operation_metric == metric
119124

120125
def test_ctor_too_many_entries(self):
121126
"""
@@ -139,6 +144,7 @@ def test_ctor_too_many_entries(self):
139144
entries,
140145
operation_timeout,
141146
attempt_timeout,
147+
mock.Mock(),
142148
)
143149
assert "mutate_rows requests can contain at most 100000 mutations" in str(
144150
e.value
@@ -152,14 +158,15 @@ async def test_mutate_rows_operation(self):
152158
"""
153159
client = mock.Mock()
154160
table = mock.Mock()
161+
metric = ActiveOperationMetric("MUTATE_ROWS")
155162
entries = [self._make_mutation(), self._make_mutation()]
156163
operation_timeout = 0.05
157164
cls = self._target_class()
158165
with mock.patch(
159166
f"{cls.__module__}.{cls.__name__}._run_attempt", CrossSync.Mock()
160167
) as attempt_mock:
161168
instance = self._make_one(
162-
client, table, entries, operation_timeout, operation_timeout
169+
client, table, entries, operation_timeout, operation_timeout, metric
163170
)
164171
await instance.start()
165172
assert attempt_mock.call_count == 1
@@ -173,6 +180,7 @@ async def test_mutate_rows_attempt_exception(self, exc_type):
173180
client = CrossSync.Mock()
174181
table = mock.Mock()
175182
table._request_path = {"table_name": "table"}
183+
metric = ActiveOperationMetric("MUTATE_ROWS")
176184
table.app_profile_id = None
177185
entries = [self._make_mutation(), self._make_mutation()]
178186
operation_timeout = 0.05
@@ -181,7 +189,7 @@ async def test_mutate_rows_attempt_exception(self, exc_type):
181189
found_exc = None
182190
try:
183191
instance = self._make_one(
184-
client, table, entries, operation_timeout, operation_timeout
192+
client, table, entries, operation_timeout, operation_timeout, metric
185193
)
186194
await instance._run_attempt()
187195
except Exception as e:
@@ -203,6 +211,7 @@ async def test_mutate_rows_exception(self, exc_type):
203211

204212
client = mock.Mock()
205213
table = mock.Mock()
214+
metric = ActiveOperationMetric("MUTATE_ROWS")
206215
entries = [self._make_mutation(), self._make_mutation()]
207216
operation_timeout = 0.05
208217
expected_cause = exc_type("abort")
@@ -215,7 +224,7 @@ async def test_mutate_rows_exception(self, exc_type):
215224
found_exc = None
216225
try:
217226
instance = self._make_one(
218-
client, table, entries, operation_timeout, operation_timeout
227+
client, table, entries, operation_timeout, operation_timeout, metric
219228
)
220229
await instance.start()
221230
except MutationsExceptionGroup as e:
@@ -239,6 +248,7 @@ async def test_mutate_rows_exception_retryable_eventually_pass(self, exc_type):
239248

240249
client = mock.Mock()
241250
table = mock.Mock()
251+
metric = ActiveOperationMetric("MUTATE_ROWS")
242252
entries = [self._make_mutation()]
243253
operation_timeout = 1
244254
expected_cause = exc_type("retry")
@@ -255,6 +265,7 @@ async def test_mutate_rows_exception_retryable_eventually_pass(self, exc_type):
255265
entries,
256266
operation_timeout,
257267
operation_timeout,
268+
metric,
258269
retryable_exceptions=(exc_type,),
259270
)
260271
await instance.start()
@@ -271,6 +282,7 @@ async def test_mutate_rows_incomplete_ignored(self):
271282

272283
client = mock.Mock()
273284
table = mock.Mock()
285+
metric = ActiveOperationMetric("MUTATE_ROWS")
274286
entries = [self._make_mutation()]
275287
operation_timeout = 0.05
276288
with mock.patch.object(
@@ -282,7 +294,7 @@ async def test_mutate_rows_incomplete_ignored(self):
282294
found_exc = None
283295
try:
284296
instance = self._make_one(
285-
client, table, entries, operation_timeout, operation_timeout
297+
client, table, entries, operation_timeout, operation_timeout, metric
286298
)
287299
await instance.start()
288300
except MutationsExceptionGroup as e:

tests/unit/data/_async/test__read_rows.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import pytest
1616

1717
from google.cloud.bigtable.data._cross_sync import CrossSync
18+
from google.cloud.bigtable.data._metrics import ActiveOperationMetric
1819

1920
# try/except added for compatibility with python < 3.8
2021
try:
@@ -59,6 +60,7 @@ def test_ctor(self):
5960
expected_operation_timeout = 42
6061
expected_request_timeout = 44
6162
time_gen_mock = mock.Mock()
63+
expected_metric = mock.Mock()
6264
subpath = "_async" if CrossSync.is_async else "_sync_autogen"
6365
with mock.patch(
6466
f"google.cloud.bigtable.data.{subpath}._read_rows._attempt_timeout_generator",
@@ -69,6 +71,7 @@ def test_ctor(self):
6971
table,
7072
operation_timeout=expected_operation_timeout,
7173
attempt_timeout=expected_request_timeout,
74+
metric=expected_metric,
7275
)
7376
assert time_gen_mock.call_count == 1
7477
time_gen_mock.assert_called_once_with(
@@ -81,6 +84,7 @@ def test_ctor(self):
8184
assert instance.request.table_name == "test_table"
8285
assert instance.request.app_profile_id == table.app_profile_id
8386
assert instance.request.rows_limit == row_limit
87+
assert instance._operation_metric == expected_metric
8488

8589
@pytest.mark.parametrize(
8690
"in_keys,last_key,expected",
@@ -269,7 +273,7 @@ async def mock_stream():
269273
table = mock.Mock()
270274
table._request_path = {"table_name": "table_name"}
271275
table.app_profile_id = "app_profile_id"
272-
instance = self._make_one(query, table, 10, 10)
276+
instance = self._make_one(query, table, 10, 10, ActiveOperationMetric("READ_ROWS"))
273277
assert instance._remaining_count == start_limit
274278
# read emit_num rows
275279
async for val in instance.chunk_stream(awaitable_stream()):
@@ -308,7 +312,7 @@ async def mock_stream():
308312
table = mock.Mock()
309313
table._request_path = {"table_name": "table_name"}
310314
table.app_profile_id = "app_profile_id"
311-
instance = self._make_one(query, table, 10, 10)
315+
instance = self._make_one(query, table, 10, 10, ActiveOperationMetric("READ_ROWS"))
312316
assert instance._remaining_count == start_limit
313317
with pytest.raises(InvalidChunk) as e:
314318
# read emit_num rows
@@ -334,7 +338,7 @@ async def mock_stream():
334338
with mock.patch.object(
335339
self._get_target_class(), "_read_rows_attempt"
336340
) as mock_attempt:
337-
instance = self._make_one(mock.Mock(), mock.Mock(), 1, 1)
341+
instance = self._make_one(mock.Mock(), mock.Mock(), 1, 1, ActiveOperationMetric("READ_ROWS"))
338342
wrapped_gen = mock_stream()
339343
mock_attempt.return_value = wrapped_gen
340344
gen = instance.start_operation()

tests/unit/data/_async/test_client.py

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,6 @@ async def test_ctor(self):
12051205
assert instance_key in client._active_instances
12061206
assert client._instance_owners[instance_key] == {id(table)}
12071207
assert isinstance(table._metrics, BigtableClientSideMetricsController)
1208-
assert table._metrics.interceptor == client._metrics_interceptor
12091208
assert table.default_operation_timeout == expected_operation_timeout
12101209
assert table.default_attempt_timeout == expected_attempt_timeout
12111210
assert (
@@ -1547,7 +1546,6 @@ async def test_ctor(self):
15471546
assert instance_key in client._active_instances
15481547
assert client._instance_owners[instance_key] == {id(view)}
15491548
assert isinstance(view._metrics, BigtableClientSideMetricsController)
1550-
assert view._metrics.interceptor == client._metrics_interceptor
15511549
assert view.default_operation_timeout == expected_operation_timeout
15521550
assert view.default_attempt_timeout == expected_attempt_timeout
15531551
assert (
@@ -1959,9 +1957,19 @@ async def test_read_row(self):
19591957
async with self._make_client() as client:
19601958
table = client.get_table("instance", "table")
19611959
row_key = b"test_1"
1962-
with mock.patch.object(table, "read_rows") as read_rows:
1960+
with mock.patch.object(CrossSync, "_ReadRowsOperation") as mock_op_constructor:
1961+
mock_op = mock.Mock()
19631962
expected_result = object()
1964-
read_rows.side_effect = lambda *args, **kwargs: [expected_result]
1963+
1964+
if CrossSync.is_async:
1965+
1966+
async def mock_generator():
1967+
yield expected_result
1968+
1969+
mock_op.start_operation.return_value = mock_generator()
1970+
else:
1971+
mock_op.start_operation.return_value = [expected_result]
1972+
mock_op_constructor.return_value = mock_op
19651973
expected_op_timeout = 8
19661974
expected_req_timeout = 4
19671975
row = await table.read_row(
@@ -1970,43 +1978,52 @@ async def test_read_row(self):
19701978
attempt_timeout=expected_req_timeout,
19711979
)
19721980
assert row == expected_result
1973-
assert read_rows.call_count == 1
1974-
args, kwargs = read_rows.call_args_list[0]
1981+
assert mock_op_constructor.call_count == 1
1982+
args, kwargs = mock_op_constructor.call_args_list[0]
19751983
assert kwargs["operation_timeout"] == expected_op_timeout
19761984
assert kwargs["attempt_timeout"] == expected_req_timeout
1977-
assert len(args) == 1
1985+
assert len(args) == 2
19781986
assert isinstance(args[0], ReadRowsQuery)
19791987
query = args[0]
19801988
assert query.row_keys == [row_key]
19811989
assert query.row_ranges == []
19821990
assert query.limit == 1
1991+
assert args[1] is table
19831992

19841993
@CrossSync.pytest
19851994
async def test_read_row_w_filter(self):
19861995
"""Test reading a single row with an added filter"""
19871996
async with self._make_client() as client:
19881997
table = client.get_table("instance", "table")
19891998
row_key = b"test_1"
1990-
with mock.patch.object(table, "read_rows") as read_rows:
1999+
with mock.patch.object(CrossSync, "_ReadRowsOperation") as mock_op_constructor:
2000+
mock_op = mock.Mock()
19912001
expected_result = object()
1992-
read_rows.side_effect = lambda *args, **kwargs: [expected_result]
2002+
2003+
if CrossSync.is_async:
2004+
2005+
async def mock_generator():
2006+
yield expected_result
2007+
2008+
mock_op.start_operation.return_value = mock_generator()
2009+
else:
2010+
mock_op.start_operation.return_value = [expected_result]
2011+
mock_op_constructor.return_value = mock_op
19932012
expected_op_timeout = 8
19942013
expected_req_timeout = 4
1995-
mock_filter = mock.Mock()
1996-
expected_filter = {"filter": "mock filter"}
1997-
mock_filter._to_dict.return_value = expected_filter
2014+
expected_filter = mock.Mock()
19982015
row = await table.read_row(
19992016
row_key,
20002017
operation_timeout=expected_op_timeout,
20012018
attempt_timeout=expected_req_timeout,
20022019
row_filter=expected_filter,
20032020
)
20042021
assert row == expected_result
2005-
assert read_rows.call_count == 1
2006-
args, kwargs = read_rows.call_args_list[0]
2022+
assert mock_op_constructor.call_count == 1
2023+
args, kwargs = mock_op_constructor.call_args_list[0]
20072024
assert kwargs["operation_timeout"] == expected_op_timeout
20082025
assert kwargs["attempt_timeout"] == expected_req_timeout
2009-
assert len(args) == 1
2026+
assert len(args) == 2
20102027
assert isinstance(args[0], ReadRowsQuery)
20112028
query = args[0]
20122029
assert query.row_keys == [row_key]
@@ -2020,9 +2037,19 @@ async def test_read_row_no_response(self):
20202037
async with self._make_client() as client:
20212038
table = client.get_table("instance", "table")
20222039
row_key = b"test_1"
2023-
with mock.patch.object(table, "read_rows") as read_rows:
2024-
# return no rows
2025-
read_rows.side_effect = lambda *args, **kwargs: []
2040+
with mock.patch.object(CrossSync, "_ReadRowsOperation") as mock_op_constructor:
2041+
mock_op = mock.Mock()
2042+
2043+
if CrossSync.is_async:
2044+
2045+
async def mock_generator():
2046+
if False:
2047+
yield
2048+
2049+
mock_op.start_operation.return_value = mock_generator()
2050+
else:
2051+
mock_op.start_operation.return_value = []
2052+
mock_op_constructor.return_value = mock_op
20262053
expected_op_timeout = 8
20272054
expected_req_timeout = 4
20282055
result = await table.read_row(
@@ -2031,8 +2058,8 @@ async def test_read_row_no_response(self):
20312058
attempt_timeout=expected_req_timeout,
20322059
)
20332060
assert result is None
2034-
assert read_rows.call_count == 1
2035-
args, kwargs = read_rows.call_args_list[0]
2061+
assert mock_op_constructor.call_count == 1
2062+
args, kwargs = mock_op_constructor.call_args_list[0]
20362063
assert kwargs["operation_timeout"] == expected_op_timeout
20372064
assert kwargs["attempt_timeout"] == expected_req_timeout
20382065
assert isinstance(args[0], ReadRowsQuery)
@@ -2055,22 +2082,34 @@ async def test_row_exists(self, return_value, expected_result):
20552082
async with self._make_client() as client:
20562083
table = client.get_table("instance", "table")
20572084
row_key = b"test_1"
2058-
with mock.patch.object(table, "read_rows") as read_rows:
2059-
# return no rows
2060-
read_rows.side_effect = lambda *args, **kwargs: return_value
2061-
expected_op_timeout = 1
2062-
expected_req_timeout = 2
2085+
with mock.patch.object(CrossSync, "_ReadRowsOperation") as mock_op_constructor:
2086+
mock_op = mock.Mock()
2087+
if CrossSync.is_async:
2088+
2089+
async def mock_generator():
2090+
for item in return_value:
2091+
yield item
2092+
2093+
mock_op.start_operation.return_value = mock_generator()
2094+
else:
2095+
mock_op.start_operation.return_value = return_value
2096+
mock_op_constructor.return_value = mock_op
2097+
expected_op_timeout = 2
2098+
expected_req_timeout = 1
20632099
result = await table.row_exists(
20642100
row_key,
20652101
operation_timeout=expected_op_timeout,
20662102
attempt_timeout=expected_req_timeout,
20672103
)
20682104
assert expected_result == result
2069-
assert read_rows.call_count == 1
2070-
args, kwargs = read_rows.call_args_list[0]
2105+
assert mock_op_constructor.call_count == 1
2106+
args, kwargs = mock_op_constructor.call_args_list[0]
20712107
assert kwargs["operation_timeout"] == expected_op_timeout
20722108
assert kwargs["attempt_timeout"] == expected_req_timeout
2073-
assert isinstance(args[0], ReadRowsQuery)
2109+
query = args[0]
2110+
assert isinstance(query, ReadRowsQuery)
2111+
assert query.row_keys == [row_key]
2112+
assert query.limit == 1
20742113
expected_filter = {
20752114
"chain": {
20762115
"filters": [
@@ -2079,10 +2118,6 @@ async def test_row_exists(self, return_value, expected_result):
20792118
]
20802119
}
20812120
}
2082-
query = args[0]
2083-
assert query.row_keys == [row_key]
2084-
assert query.row_ranges == []
2085-
assert query.limit == 1
20862121
assert query.filter._to_dict() == expected_filter
20872122

20882123

0 commit comments

Comments
 (0)