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

Commit 29f6760

Browse files
committed
added tests
1 parent 409ffd2 commit 29f6760

4 files changed

Lines changed: 176 additions & 8 deletions

File tree

tests/system/test_system.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
TEST_DATABASES,
4747
TEST_DATABASES_W_ENTERPRISE,
4848
IS_KOKORO_TEST,
49+
FIRESTORE_ENTERPRISE_DB,
4950
)
5051

5152

@@ -1688,6 +1689,54 @@ def test_query_stream_w_read_time(query_docs, cleanup, database):
16881689
assert new_values[new_ref.id] == new_data
16891690

16901691

1692+
@pytest.mark.parametrize("database", [FIRESTORE_ENTERPRISE_DB], indirect=True)
1693+
def test_pipeline_w_read_time(query_docs, cleanup, database):
1694+
# return early on kokoro. Test project doesn't currently support pipelines
1695+
# TODO: enable pipeline verification when kokoro test project is whitelisted
1696+
if IS_KOKORO_TEST:
1697+
pytest.skip("skipping pipeline verification on kokoro")
1698+
1699+
collection, stored, allowed_vals = query_docs
1700+
num_vals = len(allowed_vals)
1701+
1702+
1703+
# Find a read_time before adding the new document.
1704+
snapshots = collection.get()
1705+
read_time = snapshots[0].read_time
1706+
1707+
new_data = {
1708+
"a": 9000,
1709+
"b": 1,
1710+
"c": [10000, 1000],
1711+
"stats": {"sum": 9001, "product": 9000},
1712+
}
1713+
_, new_ref = collection.add(new_data)
1714+
# Add to clean-up.
1715+
cleanup(new_ref.delete)
1716+
stored[new_ref.id] = new_data
1717+
1718+
pipeline = collection.where(filter=FieldFilter("b", "==", 1)).pipeline()
1719+
# new query should have new_data
1720+
new_results = list(pipeline.stream())
1721+
new_values = {result.ref.id: result.data() for result in new_results}
1722+
assert len(new_values) == num_vals + 1
1723+
assert new_ref.id in new_values
1724+
assert new_values[new_ref.id] == new_data
1725+
1726+
# query with read_time should not have new)data
1727+
results = list(pipeline.stream(read_time=read_time))
1728+
1729+
values = {result.ref.id: result.data() for result in results}
1730+
1731+
assert len(values) == num_vals
1732+
assert new_ref.id not in values
1733+
for key, value in values.items():
1734+
assert stored[key] == value
1735+
assert value["b"] == 1
1736+
assert value["a"] != 9000
1737+
assert key != new_ref.id
1738+
1739+
16911740
@pytest.mark.parametrize("database", TEST_DATABASES, indirect=True)
16921741
def test_query_with_order_dot_key(client, cleanup, database):
16931742
db = client

tests/system/test_system_async.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
TEST_DATABASES,
5858
TEST_DATABASES_W_ENTERPRISE,
5959
IS_KOKORO_TEST,
60+
FIRESTORE_ENTERPRISE_DB,
6061
)
6162

6263
RETRIES = retries.AsyncRetry(
@@ -1611,6 +1612,54 @@ async def test_query_stream_w_read_time(query_docs, cleanup, database):
16111612
assert new_values[new_ref.id] == new_data
16121613

16131614

1615+
@pytest.mark.parametrize("database", [FIRESTORE_ENTERPRISE_DB], indirect=True)
1616+
async def test_pipeline_w_read_time(query_docs, cleanup, database):
1617+
# return early on kokoro. Test project doesn't currently support pipelines
1618+
# TODO: enable pipeline verification when kokoro test project is whitelisted
1619+
if IS_KOKORO_TEST:
1620+
pytest.skip("skipping pipeline verification on kokoro")
1621+
1622+
collection, stored, allowed_vals = query_docs
1623+
num_vals = len(allowed_vals)
1624+
1625+
# Find a read_time before adding the new document.
1626+
snapshots = await collection.get()
1627+
read_time = snapshots[0].read_time
1628+
1629+
new_data = {
1630+
"a": 9000,
1631+
"b": 1,
1632+
"c": [10000, 1000],
1633+
"stats": {"sum": 9001, "product": 9000},
1634+
}
1635+
_, new_ref = await collection.add(new_data)
1636+
# Add to clean-up.
1637+
cleanup(new_ref.delete)
1638+
stored[new_ref.id] = new_data
1639+
1640+
pipeline = collection.where(filter=FieldFilter("b", "==", 1)).pipeline()
1641+
1642+
# new query should have new_data
1643+
new_results = [result async for result in pipeline.stream()]
1644+
new_values = {result.ref.id: result.data() for result in new_results}
1645+
assert len(new_values) == num_vals + 1
1646+
assert new_ref.id in new_values
1647+
assert new_values[new_ref.id] == new_data
1648+
1649+
# pipeline with read_time should not have new_data
1650+
results = [result async for result in pipeline.stream(read_time=read_time)]
1651+
1652+
values = {result.ref.id: result.data() for result in results}
1653+
1654+
assert len(values) == num_vals
1655+
assert new_ref.id not in values
1656+
for key, value in values.items():
1657+
assert stored[key] == value
1658+
assert value["b"] == 1
1659+
assert value["a"] != 9000
1660+
assert key != new_ref.id
1661+
1662+
16141663
@pytest.mark.parametrize("database", TEST_DATABASES, indirect=True)
16151664
async def test_query_with_order_dot_key(client, cleanup, database):
16161665
db = client

tests/unit/v1/test_async_pipeline.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,36 @@ async def test_async_pipeline_stream_with_transaction():
320320
assert request.transaction == b"123"
321321

322322

323+
@pytest.mark.asyncio
324+
async def test_async_pipeline_stream_with_read_time():
325+
"""
326+
test stream pipeline with read_time
327+
"""
328+
import datetime
329+
330+
from google.cloud.firestore_v1.types import ExecutePipelineResponse
331+
from google.cloud.firestore_v1.types import ExecutePipelineRequest
332+
333+
client = mock.Mock()
334+
client.project = "A"
335+
client._database = "B"
336+
mock_rpc = mock.AsyncMock()
337+
client._firestore_api.execute_pipeline = mock_rpc
338+
339+
read_time = datetime.datetime.now(tz=datetime.timezone.utc)
340+
341+
mock_rpc.return_value = _async_it([ExecutePipelineResponse()])
342+
ppl_1 = _make_async_pipeline(client=client)
343+
344+
[r async for r in ppl_1.stream(read_time=read_time)]
345+
assert mock_rpc.call_count == 1
346+
request = mock_rpc.call_args[0][0]
347+
assert isinstance(request, ExecutePipelineRequest)
348+
assert request.structured_pipeline == ppl_1._to_pb()
349+
assert request.database == "projects/A/databases/B"
350+
assert request.read_time == read_time
351+
352+
323353
@pytest.mark.asyncio
324354
async def test_async_pipeline_stream_stream_equivalence():
325355
"""
@@ -364,16 +394,22 @@ async def test_async_pipeline_stream_stream_equivalence_mocked():
364394
"""
365395
pipeline.stream should call pipeline.stream internally
366396
"""
397+
import datetime
398+
367399
ppl_1 = _make_async_pipeline()
368400
expected_data = [object(), object()]
369-
expected_arg = object()
401+
expected_transaction = object()
402+
expected_read_time = datetime.datetime.now(tz=datetime.timezone.utc)
370403
with mock.patch.object(ppl_1, "stream") as mock_stream:
371404
mock_stream.return_value = _async_it(expected_data)
372-
stream_results = await ppl_1.execute(expected_arg)
405+
stream_results = await ppl_1.execute(
406+
transaction=expected_transaction, read_time=expected_read_time
407+
)
373408
assert mock_stream.call_count == 1
374409
assert mock_stream.call_args[0] == ()
375-
assert len(mock_stream.call_args[1]) == 1
376-
assert mock_stream.call_args[1]["transaction"] == expected_arg
410+
assert len(mock_stream.call_args[1]) == 2
411+
assert mock_stream.call_args[1]["transaction"] == expected_transaction
412+
assert mock_stream.call_args[1]["read_time"] == expected_read_time
377413
assert stream_results == expected_data
378414

379415

tests/unit/v1/test_pipeline.py

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,34 @@ def test_pipeline_stream_with_transaction():
302302
assert request.transaction == b"123"
303303

304304

305+
def test_pipeline_stream_with_read_time():
306+
"""
307+
test stream pipeline with read_time
308+
"""
309+
import datetime
310+
311+
from google.cloud.firestore_v1.types import ExecutePipelineResponse
312+
from google.cloud.firestore_v1.types import ExecutePipelineRequest
313+
314+
client = mock.Mock()
315+
client.project = "A"
316+
client._database = "B"
317+
mock_rpc = client._firestore_api.execute_pipeline
318+
319+
read_time = datetime.datetime.now(tz=datetime.timezone.utc)
320+
321+
mock_rpc.return_value = [ExecutePipelineResponse()]
322+
ppl_1 = _make_pipeline(client=client)
323+
324+
list(ppl_1.stream(read_time=read_time))
325+
assert mock_rpc.call_count == 1
326+
request = mock_rpc.call_args[0][0]
327+
assert isinstance(request, ExecutePipelineRequest)
328+
assert request.structured_pipeline == ppl_1._to_pb()
329+
assert request.database == "projects/A/databases/B"
330+
assert request.read_time == read_time
331+
332+
305333
def test_pipeline_execute_stream_equivalence():
306334
"""
307335
Pipeline.execute should provide same results from pipeline.stream, as a list
@@ -341,16 +369,22 @@ def test_pipeline_execute_stream_equivalence_mocked():
341369
"""
342370
pipeline.execute should call pipeline.stream internally
343371
"""
372+
import datetime
373+
344374
ppl_1 = _make_pipeline()
345375
expected_data = [object(), object()]
346-
expected_arg = object()
376+
expected_transaction = object()
377+
expected_read_time = datetime.datetime.now(tz=datetime.timezone.utc)
347378
with mock.patch.object(ppl_1, "stream") as mock_stream:
348379
mock_stream.return_value = expected_data
349-
stream_results = ppl_1.execute(expected_arg)
380+
stream_results = ppl_1.execute(
381+
transaction=expected_transaction, read_time=expected_read_time
382+
)
350383
assert mock_stream.call_count == 1
351384
assert mock_stream.call_args[0] == ()
352-
assert len(mock_stream.call_args[1]) == 1
353-
assert mock_stream.call_args[1]["transaction"] == expected_arg
385+
assert len(mock_stream.call_args[1]) == 2
386+
assert mock_stream.call_args[1]["transaction"] == expected_transaction
387+
assert mock_stream.call_args[1]["read_time"] == expected_read_time
354388
assert stream_results == expected_data
355389

356390

0 commit comments

Comments
 (0)