Beispiel #1
0
def test_get_testprotos(test_proto):
    testcase = test_proto.get
    firestore_api = mock.Mock(spec=["batch_get_documents", "_client"])
    response = firestore.BatchGetDocumentsResponse()
    response.read_time = Timestamp(seconds=0, nanos=0)
    response.found = document.Document()
    response.found.fields = {}
    response.found.create_time = Timestamp(seconds=0, nanos=0)
    response.found.update_time = Timestamp(seconds=0, nanos=0)
    firestore_api.batch_get_documents.return_value = iter([response])
    firestore_api._client._database_string = "projects/projectID/databases/(default)"
    client, doc = _make_client_document(firestore_api, testcase)
    response.found.name = doc._document_path

    doc.get()  # No '.textprotos' for errors, field_paths.

    expected_request = {
        "database": firestore_api._client._database_string,
        "documents": [doc._document_path],
        "mask": None,
        "transaction": None,
    }

    firestore_api.batch_get_documents.assert_called_once_with(
        request=expected_request,
        metadata=client._rpc_metadata,
    )
Beispiel #2
0
def test_client_recursive_delete():
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.types import firestore

    client = _make_default_client()
    client._firestore_api_internal = mock.Mock(spec=["run_query"])
    collection_ref = client.collection("my_collection")

    results = []
    for index in range(10):
        results.append(
            firestore.RunQueryResponse(
                document=document.Document(name=f"{collection_ref.id}/{index}")
            )
        )

    chunks = [
        results[:3],
        results[3:6],
        results[6:9],
        results[9:],
    ]

    def _get_chunk(*args, **kwargs):
        return iter(chunks.pop(0))

    client._firestore_api_internal.run_query.side_effect = _get_chunk

    bulk_writer = mock.MagicMock()
    bulk_writer.mock_add_spec(spec=["delete", "close"])

    num_deleted = client.recursive_delete(
        collection_ref, bulk_writer=bulk_writer, chunk_size=3
    )
    assert num_deleted == len(results)
def test_basewritebatch_update():
    from google.cloud.firestore_v1.types import common
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.types import write

    client = _make_client()
    batch = _make_derived_write_batch(client)
    assert batch._write_pbs == []

    reference = client.document("cats", "cradle")
    field_path = "head.foot"
    value = u"knees toes shoulders"
    field_updates = {field_path: value}

    ret_val = batch.update(reference, field_updates)
    assert ret_val is None

    map_pb = document.MapValue(fields={"foot": _value_pb(string_value=value)})
    new_write_pb = write.Write(
        update=document.Document(
            name=reference._document_path, fields={"head": _value_pb(map_value=map_pb)},
        ),
        update_mask=common.DocumentMask(field_paths=[field_path]),
        current_document=common.Precondition(exists=True),
    )
    assert batch._write_pbs == [new_write_pb]
Beispiel #4
0
    def test_found(self):
        from google.cloud.firestore_v1.types import document
        from google.cloud._helpers import _datetime_to_pb_timestamp
        from google.cloud.firestore_v1.document import DocumentSnapshot

        now = datetime.datetime.utcnow()
        read_time = _datetime_to_pb_timestamp(now)
        delta = datetime.timedelta(seconds=100)
        update_time = _datetime_to_pb_timestamp(now - delta)
        create_time = _datetime_to_pb_timestamp(now - 2 * delta)

        ref_string = self._dummy_ref_string()
        document_pb = document.Document(
            name=ref_string,
            fields={
                "foo": document.Value(double_value=1.5),
                "bar": document.Value(string_value=u"skillz"),
            },
            create_time=create_time,
            update_time=update_time,
        )
        response_pb = _make_batch_response(found=document_pb, read_time=read_time)

        reference_map = {ref_string: mock.sentinel.reference}
        snapshot = self._call_fut(response_pb, reference_map)
        self.assertIsInstance(snapshot, DocumentSnapshot)
        self.assertIs(snapshot._reference, mock.sentinel.reference)
        self.assertEqual(snapshot._data, {"foo": 1.5, "bar": u"skillz"})
        self.assertTrue(snapshot._exists)
        self.assertEqual(snapshot.read_time.timestamp_pb(), read_time)
        self.assertEqual(snapshot.create_time.timestamp_pb(), create_time)
        self.assertEqual(snapshot.update_time.timestamp_pb(), update_time)
Beispiel #5
0
def test__parse_batch_get_found():
    from google.cloud.firestore_v1.types import document
    from google.cloud._helpers import _datetime_to_pb_timestamp
    from google.cloud.firestore_v1.document import DocumentSnapshot
    from google.cloud.firestore_v1.base_client import _parse_batch_get

    now = datetime.datetime.utcnow()
    read_time = _datetime_to_pb_timestamp(now)
    delta = datetime.timedelta(seconds=100)
    update_time = _datetime_to_pb_timestamp(now - delta)
    create_time = _datetime_to_pb_timestamp(now - 2 * delta)

    ref_string = _dummy_ref_string()
    document_pb = document.Document(
        name=ref_string,
        fields={
            "foo": document.Value(double_value=1.5),
            "bar": document.Value(string_value=u"skillz"),
        },
        create_time=create_time,
        update_time=update_time,
    )
    response_pb = _make_batch_response(found=document_pb, read_time=read_time)

    reference_map = {ref_string: mock.sentinel.reference}
    snapshot = _parse_batch_get(response_pb, reference_map,
                                mock.sentinel.client)
    assert isinstance(snapshot, DocumentSnapshot)
    assert snapshot._reference is mock.sentinel.reference
    assert snapshot._data == {"foo": 1.5, "bar": u"skillz"}
    assert snapshot._exists
    assert snapshot.read_time.timestamp_pb() == read_time
    assert snapshot.create_time.timestamp_pb() == create_time
    assert snapshot.update_time.timestamp_pb() == update_time
def test_add_auto_assigned():
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.document import DocumentReference
    from google.cloud.firestore_v1 import SERVER_TIMESTAMP
    from google.cloud.firestore_v1._helpers import pbs_for_create
    from tests.unit.v1 import _test_helpers

    # Create a minimal fake GAPIC add attach it to a real client.
    firestore_api = mock.Mock(spec=["create_document", "commit"])
    write_result = mock.Mock(
        update_time=mock.sentinel.update_time, spec=["update_time"]
    )

    commit_response = mock.Mock(
        write_results=[write_result],
        spec=["write_results", "commit_time"],
        commit_time=mock.sentinel.commit_time,
    )

    firestore_api.commit.return_value = commit_response
    create_doc_response = document.Document()
    firestore_api.create_document.return_value = create_doc_response
    client = _test_helpers.make_client()
    client._firestore_api_internal = firestore_api

    # Actually make a collection.
    collection = _make_collection_reference(
        "grand-parent", "parent", "child", client=client
    )

    # Actually call add() on our collection; include a transform to make
    # sure transforms during adds work.
    document_data = {"been": "here", "now": SERVER_TIMESTAMP}

    patch = mock.patch("google.cloud.firestore_v1.base_collection._auto_id")
    random_doc_id = "DEADBEEF"
    with patch as patched:
        patched.return_value = random_doc_id
        update_time, document_ref = collection.add(document_data)

    # Verify the response and the mocks.
    assert update_time is mock.sentinel.update_time
    assert isinstance(document_ref, DocumentReference)
    assert document_ref._client is client
    expected_path = collection._path + (random_doc_id,)
    assert document_ref._path == expected_path

    write_pbs = pbs_for_create(document_ref._document_path, document_data)
    firestore_api.commit.assert_called_once_with(
        request={
            "database": client._database_string,
            "writes": write_pbs,
            "transaction": None,
        },
        metadata=client._rpc_metadata,
    )
    # Since we generate the ID locally, we don't call 'create_document'.
    firestore_api.create_document.assert_not_called()
def _write_pb_for_create(document_path, document_data):
    from google.cloud.firestore_v1.types import common
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.types import write
    from google.cloud.firestore_v1 import _helpers

    return write.Write(
        update=document.Document(name=document_path,
                                 fields=_helpers.encode_dict(document_data)),
        current_document=common.Precondition(exists=False),
    )
def _write_pb_for_update(document_path, update_values, field_paths):
    from google.cloud.firestore_v1.types import common
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.types import write
    from google.cloud.firestore_v1 import _helpers

    return write.Write(
        update=document.Document(name=document_path,
                                 fields=_helpers.encode_dict(update_values)),
        update_mask=common.DocumentMask(field_paths=field_paths),
        current_document=common.Precondition(exists=True),
    )
Beispiel #9
0
def test_get_testprotos(test_proto):
    testcase = test_proto.get
    firestore_api = mock.Mock(spec=["get_document"])
    response = document.Document()
    firestore_api.get_document.return_value = response
    client, doc = _make_client_document(firestore_api, testcase)

    doc.get()  # No '.textprotos' for errors, field_paths.

    firestore_api.get_document.assert_called_once_with(
        doc._document_path,
        mask=None,
        transaction=None,
        metadata=client._rpc_metadata,
    )
Beispiel #10
0
    def get_update_pb(
        self, document_path, exists=None, allow_empty_mask=False
    ) -> types.write.Write:

        if exists is not None:
            current_document = common.Precondition(exists=exists)
        else:
            current_document = None

        update_pb = write.Write(
            update=document.Document(
                name=document_path, fields=encode_dict(self.set_fields)
            ),
            update_mask=self._get_update_mask(allow_empty_mask),
            current_document=current_document,
        )

        return update_pb
Beispiel #11
0
def test_get_testprotos(test_proto):
    testcase = test_proto.get
    firestore_api = mock.Mock(spec=["get_document"])
    response = document.Document()
    firestore_api.get_document.return_value = response
    client, doc = _make_client_document(firestore_api, testcase)

    doc.get()  # No '.textprotos' for errors, field_paths.

    expected_request = {
        "name": doc._document_path,
        "mask": None,
        "transaction": None,
    }

    firestore_api.get_document.assert_called_once_with(
        request=expected_request,
        metadata=client._rpc_metadata,
    )
Beispiel #12
0
    def test_set(self):
        from google.cloud.firestore_v1.types import document
        from google.cloud.firestore_v1.types import write

        client = _make_client()
        batch = self._make_one(client)
        self.assertEqual(batch._write_pbs, [])

        reference = client.document("another", "one")
        field = "zapzap"
        value = u"meadows and flowers"
        document_data = {field: value}
        ret_val = batch.set(reference, document_data)
        self.assertIsNone(ret_val)
        new_write_pb = write.Write(update=document.Document(
            name=reference._document_path,
            fields={field: _value_pb(string_value=value)},
        ))
        self.assertEqual(batch._write_pbs, [new_write_pb])
Beispiel #13
0
    def _write_pb_for_set(document_path, document_data, merge):
        from google.cloud.firestore_v1.types import common
        from google.cloud.firestore_v1.types import document
        from google.cloud.firestore_v1.types import write
        from google.cloud.firestore_v1 import _helpers

        write_pbs = write.Write(update=document.Document(
            name=document_path, fields=_helpers.encode_dict(document_data)))
        if merge:
            field_paths = [
                field_path for field_path, value in _helpers.extract_fields(
                    document_data, _helpers.FieldPath())
            ]
            field_paths = [
                field_path.to_api_repr() for field_path in sorted(field_paths)
            ]
            mask = common.DocumentMask(field_paths=sorted(field_paths))
            write_pbs._pb.update_mask.CopyFrom(mask._pb)
        return write_pbs
def _doc_get_info(ref_string, values):
    from google.cloud.firestore_v1.types import document
    from google.cloud._helpers import _datetime_to_pb_timestamp
    from google.cloud.firestore_v1 import _helpers

    now = datetime.datetime.utcnow()
    read_time = _datetime_to_pb_timestamp(now)
    delta = datetime.timedelta(seconds=100)
    update_time = _datetime_to_pb_timestamp(now - delta)
    create_time = _datetime_to_pb_timestamp(now - 2 * delta)

    document_pb = document.Document(
        name=ref_string,
        fields=_helpers.encode_dict(values),
        create_time=create_time,
        update_time=update_time,
    )

    return document_pb, read_time
def test_basewritebatch_set():
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.types import write

    client = _make_client()
    batch = _make_derived_write_batch(client)
    assert batch._write_pbs == []

    reference = client.document("another", "one")
    field = "zapzap"
    value = u"meadows and flowers"
    document_data = {field: value}
    ret_val = batch.set(reference, document_data)
    assert ret_val is None
    new_write_pb = write.Write(
        update=document.Document(
            name=reference._document_path,
            fields={field: _value_pb(string_value=value)},
        )
    )
    assert batch._write_pbs == [new_write_pb]
Beispiel #16
0
async def test_asynccollectionreference_chunkify():
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.types import firestore

    client = _make_client()
    col = client.collection("my-collection")

    client._firestore_api_internal = mock.Mock(spec=["run_query"])

    results = []
    for index in range(10):
        name = (
            f"projects/project-project/databases/(default)/"
            f"documents/my-collection/{index}"
        )
        results.append(
            firestore.RunQueryResponse(document=document.Document(name=name),),
        )

    chunks = [
        results[:3],
        results[3:6],
        results[6:9],
        results[9:],
    ]

    async def _get_chunk(*args, **kwargs):
        return AsyncIter(chunks.pop(0))

    client._firestore_api_internal.run_query.side_effect = _get_chunk

    counter = 0
    expected_lengths = [3, 3, 3, 1]
    async for chunk in col._chunkify(3):
        msg = f"Expected chunk of length {expected_lengths[counter]} at index {counter}. Saw {len(chunk)}."
        assert len(chunk) == expected_lengths[counter], msg
        counter += 1
def test_basewritebatch_create():
    from google.cloud.firestore_v1.types import common
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.types import write

    client = _make_client()
    batch = _make_derived_write_batch(client)
    assert batch._write_pbs == []

    reference = client.document("this", "one")
    document_data = {"a": 10, "b": 2.5}
    ret_val = batch.create(reference, document_data)
    assert ret_val is None
    new_write_pb = write.Write(
        update=document.Document(
            name=reference._document_path,
            fields={
                "a": _value_pb(integer_value=document_data["a"]),
                "b": _value_pb(double_value=document_data["b"]),
            },
        ),
        current_document=common.Precondition(exists=False),
    )
    assert batch._write_pbs == [new_write_pb]
Beispiel #18
0
    def test_create(self):
        from google.cloud.firestore_v1.types import common
        from google.cloud.firestore_v1.types import document
        from google.cloud.firestore_v1.types import write

        client = _make_client()
        batch = self._make_one(client)
        self.assertEqual(batch._write_pbs, [])

        reference = client.document("this", "one")
        document_data = {"a": 10, "b": 2.5}
        ret_val = batch.create(reference, document_data)
        self.assertIsNone(ret_val)
        new_write_pb = write.Write(
            update=document.Document(
                name=reference._document_path,
                fields={
                    "a": _value_pb(integer_value=document_data["a"]),
                    "b": _value_pb(double_value=document_data["b"]),
                },
            ),
            current_document=common.Precondition(exists=False),
        )
        self.assertEqual(batch._write_pbs, [new_write_pb])
Beispiel #19
0
def test_client_recursive_delete_from_document():
    from google.cloud.firestore_v1.types import document
    from google.cloud.firestore_v1.types import firestore

    client = _make_default_client()
    client._firestore_api_internal = mock.Mock(
        spec=["run_query", "list_collection_ids"]
    )
    collection_ref = client.collection("my_collection")

    collection_1_id: str = "collection_1_id"
    collection_2_id: str = "collection_2_id"

    parent_doc = collection_ref.document("parent")

    collection_1_results = []
    collection_2_results = []

    for index in range(10):
        collection_1_results.append(
            firestore.RunQueryResponse(
                document=document.Document(name=f"{collection_1_id}/{index}"),
            ),
        )

        collection_2_results.append(
            firestore.RunQueryResponse(
                document=document.Document(name=f"{collection_2_id}/{index}"),
            ),
        )

    col_1_chunks = [
        collection_1_results[:3],
        collection_1_results[3:6],
        collection_1_results[6:9],
        collection_1_results[9:],
    ]

    col_2_chunks = [
        collection_2_results[:3],
        collection_2_results[3:6],
        collection_2_results[6:9],
        collection_2_results[9:],
    ]

    def _get_chunk(*args, **kwargs):
        start_at = (
            kwargs["request"]["structured_query"].start_at.values[0].reference_value
        )

        if collection_1_id in start_at:
            return iter(col_1_chunks.pop(0))
        return iter(col_2_chunks.pop(0))

    client._firestore_api_internal.run_query.side_effect = _get_chunk
    client._firestore_api_internal.list_collection_ids.return_value = [
        collection_1_id,
        collection_2_id,
    ]

    bulk_writer = mock.MagicMock()
    bulk_writer.mock_add_spec(spec=["delete", "close"])

    num_deleted = client.recursive_delete(
        parent_doc, bulk_writer=bulk_writer, chunk_size=3
    )

    expected_len = len(collection_1_results) + len(collection_2_results) + 1
    assert num_deleted == expected_len