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

Commit ee72ae9

Browse files
committed
fixed tests
2 parents 0340fce + 61f8b85 commit ee72ae9

11 files changed

Lines changed: 218 additions & 131 deletions

tests/unit/data/_async/test__mutate_rows.py

Lines changed: 18 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,9 @@ 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(
53+
"metric", ActiveOperationMetric("MUTATE_ROWS")
54+
)
5155
return self._target_class()(*args, **kwargs)
5256

5357
def _make_mutation(self, count=1, size=1):
@@ -90,13 +94,15 @@ def test_ctor(self):
9094
entries = [self._make_mutation(), self._make_mutation()]
9195
operation_timeout = 0.05
9296
attempt_timeout = 0.01
97+
metric = mock.Mock()
9398
retryable_exceptions = ()
9499
instance = self._make_one(
95100
client,
96101
table,
97102
entries,
98103
operation_timeout,
99104
attempt_timeout,
105+
metric,
100106
retryable_exceptions,
101107
)
102108
# running gapic_fn should trigger a client call with baked-in args
@@ -116,6 +122,7 @@ def test_ctor(self):
116122
assert instance.is_retryable(RuntimeError("")) is False
117123
assert instance.remaining_indices == list(range(len(entries)))
118124
assert instance.errors == {}
125+
assert instance._operation_metric == metric
119126

120127
def test_ctor_too_many_entries(self):
121128
"""
@@ -139,6 +146,7 @@ def test_ctor_too_many_entries(self):
139146
entries,
140147
operation_timeout,
141148
attempt_timeout,
149+
mock.Mock(),
142150
)
143151
assert "mutate_rows requests can contain at most 100000 mutations" in str(
144152
e.value
@@ -152,14 +160,15 @@ async def test_mutate_rows_operation(self):
152160
"""
153161
client = mock.Mock()
154162
table = mock.Mock()
163+
metric = ActiveOperationMetric("MUTATE_ROWS")
155164
entries = [self._make_mutation(), self._make_mutation()]
156165
operation_timeout = 0.05
157166
cls = self._target_class()
158167
with mock.patch(
159168
f"{cls.__module__}.{cls.__name__}._run_attempt", CrossSync.Mock()
160169
) as attempt_mock:
161170
instance = self._make_one(
162-
client, table, entries, operation_timeout, operation_timeout
171+
client, table, entries, operation_timeout, operation_timeout, metric
163172
)
164173
await instance.start()
165174
assert attempt_mock.call_count == 1
@@ -173,6 +182,7 @@ async def test_mutate_rows_attempt_exception(self, exc_type):
173182
client = CrossSync.Mock()
174183
table = mock.Mock()
175184
table._request_path = {"table_name": "table"}
185+
metric = ActiveOperationMetric("MUTATE_ROWS")
176186
table.app_profile_id = None
177187
entries = [self._make_mutation(), self._make_mutation()]
178188
operation_timeout = 0.05
@@ -181,7 +191,7 @@ async def test_mutate_rows_attempt_exception(self, exc_type):
181191
found_exc = None
182192
try:
183193
instance = self._make_one(
184-
client, table, entries, operation_timeout, operation_timeout
194+
client, table, entries, operation_timeout, operation_timeout, metric
185195
)
186196
await instance._run_attempt()
187197
except Exception as e:
@@ -203,6 +213,7 @@ async def test_mutate_rows_exception(self, exc_type):
203213

204214
client = mock.Mock()
205215
table = mock.Mock()
216+
metric = ActiveOperationMetric("MUTATE_ROWS")
206217
entries = [self._make_mutation(), self._make_mutation()]
207218
operation_timeout = 0.05
208219
expected_cause = exc_type("abort")
@@ -215,7 +226,7 @@ async def test_mutate_rows_exception(self, exc_type):
215226
found_exc = None
216227
try:
217228
instance = self._make_one(
218-
client, table, entries, operation_timeout, operation_timeout
229+
client, table, entries, operation_timeout, operation_timeout, metric
219230
)
220231
await instance.start()
221232
except MutationsExceptionGroup as e:
@@ -239,6 +250,7 @@ async def test_mutate_rows_exception_retryable_eventually_pass(self, exc_type):
239250

240251
client = mock.Mock()
241252
table = mock.Mock()
253+
metric = ActiveOperationMetric("MUTATE_ROWS")
242254
entries = [self._make_mutation()]
243255
operation_timeout = 1
244256
expected_cause = exc_type("retry")
@@ -255,6 +267,7 @@ async def test_mutate_rows_exception_retryable_eventually_pass(self, exc_type):
255267
entries,
256268
operation_timeout,
257269
operation_timeout,
270+
metric,
258271
retryable_exceptions=(exc_type,),
259272
)
260273
await instance.start()
@@ -271,6 +284,7 @@ async def test_mutate_rows_incomplete_ignored(self):
271284

272285
client = mock.Mock()
273286
table = mock.Mock()
287+
metric = ActiveOperationMetric("MUTATE_ROWS")
274288
entries = [self._make_mutation()]
275289
operation_timeout = 0.05
276290
with mock.patch.object(
@@ -282,7 +296,7 @@ async def test_mutate_rows_incomplete_ignored(self):
282296
found_exc = None
283297
try:
284298
instance = self._make_one(
285-
client, table, entries, operation_timeout, operation_timeout
299+
client, table, entries, operation_timeout, operation_timeout, metric
286300
)
287301
await instance.start()
288302
except MutationsExceptionGroup as e:

tests/unit/data/_async/test__read_rows.py

Lines changed: 13 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,9 @@ 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(
277+
query, table, 10, 10, ActiveOperationMetric("READ_ROWS")
278+
)
273279
assert instance._remaining_count == start_limit
274280
# read emit_num rows
275281
async for val in instance.chunk_stream(awaitable_stream()):
@@ -308,7 +314,9 @@ async def mock_stream():
308314
table = mock.Mock()
309315
table._request_path = {"table_name": "table_name"}
310316
table.app_profile_id = "app_profile_id"
311-
instance = self._make_one(query, table, 10, 10)
317+
instance = self._make_one(
318+
query, table, 10, 10, ActiveOperationMetric("READ_ROWS")
319+
)
312320
assert instance._remaining_count == start_limit
313321
with pytest.raises(InvalidChunk) as e:
314322
# read emit_num rows
@@ -334,7 +342,9 @@ async def mock_stream():
334342
with mock.patch.object(
335343
self._get_target_class(), "_read_rows_attempt"
336344
) as mock_attempt:
337-
instance = self._make_one(mock.Mock(), mock.Mock(), 1, 1)
345+
instance = self._make_one(
346+
mock.Mock(), mock.Mock(), 1, 1, ActiveOperationMetric("READ_ROWS")
347+
)
338348
wrapped_gen = mock_stream()
339349
mock_attempt.return_value = wrapped_gen
340350
gen = instance.start_operation()

tests/unit/data/_async/test_client.py

Lines changed: 75 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,21 @@ 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(
1961+
CrossSync, "_ReadRowsOperation"
1962+
) as mock_op_constructor:
1963+
mock_op = mock.Mock()
19631964
expected_result = object()
1964-
read_rows.side_effect = lambda *args, **kwargs: [expected_result]
1965+
1966+
if CrossSync.is_async:
1967+
1968+
async def mock_generator():
1969+
yield expected_result
1970+
1971+
mock_op.start_operation.return_value = mock_generator()
1972+
else:
1973+
mock_op.start_operation.return_value = [expected_result]
1974+
mock_op_constructor.return_value = mock_op
19651975
expected_op_timeout = 8
19661976
expected_req_timeout = 4
19671977
row = await table.read_row(
@@ -1970,43 +1980,54 @@ async def test_read_row(self):
19701980
attempt_timeout=expected_req_timeout,
19711981
)
19721982
assert row == expected_result
1973-
assert read_rows.call_count == 1
1974-
args, kwargs = read_rows.call_args_list[0]
1983+
assert mock_op_constructor.call_count == 1
1984+
args, kwargs = mock_op_constructor.call_args_list[0]
19751985
assert kwargs["operation_timeout"] == expected_op_timeout
19761986
assert kwargs["attempt_timeout"] == expected_req_timeout
1977-
assert len(args) == 1
1987+
assert len(args) == 2
19781988
assert isinstance(args[0], ReadRowsQuery)
19791989
query = args[0]
19801990
assert query.row_keys == [row_key]
19811991
assert query.row_ranges == []
19821992
assert query.limit == 1
1993+
assert args[1] is table
19831994

19841995
@CrossSync.pytest
19851996
async def test_read_row_w_filter(self):
19861997
"""Test reading a single row with an added filter"""
19871998
async with self._make_client() as client:
19881999
table = client.get_table("instance", "table")
19892000
row_key = b"test_1"
1990-
with mock.patch.object(table, "read_rows") as read_rows:
2001+
with mock.patch.object(
2002+
CrossSync, "_ReadRowsOperation"
2003+
) as mock_op_constructor:
2004+
mock_op = mock.Mock()
19912005
expected_result = object()
1992-
read_rows.side_effect = lambda *args, **kwargs: [expected_result]
2006+
2007+
if CrossSync.is_async:
2008+
2009+
async def mock_generator():
2010+
yield expected_result
2011+
2012+
mock_op.start_operation.return_value = mock_generator()
2013+
else:
2014+
mock_op.start_operation.return_value = [expected_result]
2015+
mock_op_constructor.return_value = mock_op
19932016
expected_op_timeout = 8
19942017
expected_req_timeout = 4
1995-
mock_filter = mock.Mock()
1996-
expected_filter = {"filter": "mock filter"}
1997-
mock_filter._to_dict.return_value = expected_filter
2018+
expected_filter = mock.Mock()
19982019
row = await table.read_row(
19992020
row_key,
20002021
operation_timeout=expected_op_timeout,
20012022
attempt_timeout=expected_req_timeout,
20022023
row_filter=expected_filter,
20032024
)
20042025
assert row == expected_result
2005-
assert read_rows.call_count == 1
2006-
args, kwargs = read_rows.call_args_list[0]
2026+
assert mock_op_constructor.call_count == 1
2027+
args, kwargs = mock_op_constructor.call_args_list[0]
20072028
assert kwargs["operation_timeout"] == expected_op_timeout
20082029
assert kwargs["attempt_timeout"] == expected_req_timeout
2009-
assert len(args) == 1
2030+
assert len(args) == 2
20102031
assert isinstance(args[0], ReadRowsQuery)
20112032
query = args[0]
20122033
assert query.row_keys == [row_key]
@@ -2020,9 +2041,21 @@ async def test_read_row_no_response(self):
20202041
async with self._make_client() as client:
20212042
table = client.get_table("instance", "table")
20222043
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: []
2044+
with mock.patch.object(
2045+
CrossSync, "_ReadRowsOperation"
2046+
) as mock_op_constructor:
2047+
mock_op = mock.Mock()
2048+
2049+
if CrossSync.is_async:
2050+
2051+
async def mock_generator():
2052+
if False:
2053+
yield
2054+
2055+
mock_op.start_operation.return_value = mock_generator()
2056+
else:
2057+
mock_op.start_operation.return_value = []
2058+
mock_op_constructor.return_value = mock_op
20262059
expected_op_timeout = 8
20272060
expected_req_timeout = 4
20282061
result = await table.read_row(
@@ -2031,8 +2064,8 @@ async def test_read_row_no_response(self):
20312064
attempt_timeout=expected_req_timeout,
20322065
)
20332066
assert result is None
2034-
assert read_rows.call_count == 1
2035-
args, kwargs = read_rows.call_args_list[0]
2067+
assert mock_op_constructor.call_count == 1
2068+
args, kwargs = mock_op_constructor.call_args_list[0]
20362069
assert kwargs["operation_timeout"] == expected_op_timeout
20372070
assert kwargs["attempt_timeout"] == expected_req_timeout
20382071
assert isinstance(args[0], ReadRowsQuery)
@@ -2055,22 +2088,36 @@ async def test_row_exists(self, return_value, expected_result):
20552088
async with self._make_client() as client:
20562089
table = client.get_table("instance", "table")
20572090
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
2091+
with mock.patch.object(
2092+
CrossSync, "_ReadRowsOperation"
2093+
) as mock_op_constructor:
2094+
mock_op = mock.Mock()
2095+
if CrossSync.is_async:
2096+
2097+
async def mock_generator():
2098+
for item in return_value:
2099+
yield item
2100+
2101+
mock_op.start_operation.return_value = mock_generator()
2102+
else:
2103+
mock_op.start_operation.return_value = return_value
2104+
mock_op_constructor.return_value = mock_op
2105+
expected_op_timeout = 2
2106+
expected_req_timeout = 1
20632107
result = await table.row_exists(
20642108
row_key,
20652109
operation_timeout=expected_op_timeout,
20662110
attempt_timeout=expected_req_timeout,
20672111
)
20682112
assert expected_result == result
2069-
assert read_rows.call_count == 1
2070-
args, kwargs = read_rows.call_args_list[0]
2113+
assert mock_op_constructor.call_count == 1
2114+
args, kwargs = mock_op_constructor.call_args_list[0]
20712115
assert kwargs["operation_timeout"] == expected_op_timeout
20722116
assert kwargs["attempt_timeout"] == expected_req_timeout
2073-
assert isinstance(args[0], ReadRowsQuery)
2117+
query = args[0]
2118+
assert isinstance(query, ReadRowsQuery)
2119+
assert query.row_keys == [row_key]
2120+
assert query.limit == 1
20742121
expected_filter = {
20752122
"chain": {
20762123
"filters": [
@@ -2079,10 +2126,6 @@ async def test_row_exists(self, return_value, expected_result):
20792126
]
20802127
}
20812128
}
2082-
query = args[0]
2083-
assert query.row_keys == [row_key]
2084-
assert query.row_ranges == []
2085-
assert query.limit == 1
20862129
assert query.filter._to_dict() == expected_filter
20872130

20882131

0 commit comments

Comments
 (0)