aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/core/test
diff options
context:
space:
mode:
authorGravatar rsgowman <rgowman@google.com>2018-05-15 17:02:08 -0400
committerGravatar GitHub <noreply@github.com>2018-05-15 17:02:08 -0400
commit520a0c0a84c34897aae10564ed48ec3efc508fbf (patch)
treeaaab4065909619e87d8f798916fe747c9c022a33 /Firestore/core/test
parentc555778bcfd77a9644f65c00b2b2cf516f4f08d1 (diff)
[De]serialize empty Document instances (#1262)
* [De]serialize empty Document instances Still TODO: - non-empty - NoDocument - ErrorHandling
Diffstat (limited to 'Firestore/core/test')
-rw-r--r--Firestore/core/test/firebase/firestore/remote/serializer_test.cc115
1 files changed, 114 insertions, 1 deletions
diff --git a/Firestore/core/test/firebase/firestore/remote/serializer_test.cc b/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
index 38277e2..a147309 100644
--- a/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
+++ b/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
@@ -33,9 +33,11 @@
#include <vector>
#include "Firestore/Protos/cpp/google/firestore/v1beta1/document.pb.h"
+#include "Firestore/Protos/cpp/google/firestore/v1beta1/firestore.pb.h"
#include "Firestore/core/include/firebase/firestore/firestore_errors.h"
#include "Firestore/core/include/firebase/firestore/timestamp.h"
#include "Firestore/core/src/firebase/firestore/model/field_value.h"
+#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
#include "Firestore/core/src/firebase/firestore/timestamp_internal.h"
#include "Firestore/core/src/firebase/firestore/util/status.h"
#include "Firestore/core/src/firebase/firestore/util/statusor.h"
@@ -48,8 +50,13 @@ using firebase::Timestamp;
using firebase::TimestampInternal;
using firebase::firestore::FirestoreErrorCode;
using firebase::firestore::model::DatabaseId;
+using firebase::firestore::model::Document;
+using firebase::firestore::model::DocumentKey;
using firebase::firestore::model::FieldValue;
+using firebase::firestore::model::MaybeDocument;
+using firebase::firestore::model::NoDocument;
using firebase::firestore::model::ObjectValue;
+using firebase::firestore::model::SnapshotVersion;
using firebase::firestore::remote::Serializer;
using firebase::firestore::testutil::Key;
using firebase::firestore::util::Status;
@@ -73,6 +80,7 @@ TEST(Serializer, CanLinkToNanopb) {
class SerializerTest : public ::testing::Test {
public:
SerializerTest() : serializer(kDatabaseId) {
+ msg_diff.ReportDifferencesToString(&message_differences);
}
const DatabaseId kDatabaseId{"p", "d"};
@@ -92,6 +100,15 @@ class SerializerTest : public ::testing::Test {
ExpectDeserializationRoundTrip(model, proto, type);
}
+ void ExpectRoundTrip(
+ const DocumentKey& key,
+ const FieldValue& value,
+ const SnapshotVersion& update_time,
+ const google::firestore::v1beta1::BatchGetDocumentsResponse& proto) {
+ ExpectSerializationRoundTrip(key, value, update_time, proto);
+ ExpectDeserializationRoundTrip(key, value, update_time, proto);
+ }
+
/**
* Checks the status. Don't use directly; use one of the relevant macros
* instead. eg:
@@ -145,6 +162,16 @@ class SerializerTest : public ::testing::Test {
return bytes;
}
+ std::vector<uint8_t> EncodeDocument(Serializer* serializer,
+ const DocumentKey& key,
+ const FieldValue& value) {
+ std::vector<uint8_t> bytes;
+ Status status =
+ serializer->EncodeDocument(key, value.object_value(), &bytes);
+ EXPECT_OK(status);
+ return bytes;
+ }
+
void Mutate(uint8_t* byte,
uint8_t expected_initial_value,
uint8_t new_value) {
@@ -202,7 +229,7 @@ class SerializerTest : public ::testing::Test {
google::firestore::v1beta1::Value actual_proto;
bool ok = actual_proto.ParseFromArray(bytes.data(), bytes.size());
EXPECT_TRUE(ok);
- EXPECT_TRUE(MessageDifferencer::Equals(proto, actual_proto));
+ EXPECT_TRUE(msg_diff.Compare(proto, actual_proto)) << message_differences;
}
void ExpectDeserializationRoundTrip(
@@ -220,6 +247,65 @@ class SerializerTest : public ::testing::Test {
EXPECT_EQ(type, actual_model.type());
EXPECT_EQ(model, actual_model);
}
+
+ void ExpectSerializationRoundTrip(
+ const DocumentKey& key,
+ const FieldValue& value,
+ const SnapshotVersion& update_time,
+ const google::firestore::v1beta1::BatchGetDocumentsResponse& proto) {
+ std::vector<uint8_t> bytes = EncodeDocument(&serializer, key, value);
+ google::firestore::v1beta1::Document actual_proto;
+ bool ok = actual_proto.ParseFromArray(bytes.data(), bytes.size());
+ EXPECT_TRUE(ok);
+
+ // TODO(rsgowman): Right now, we only support Document (and don't support
+ // NoDocument). That should change in the next PR or so.
+ EXPECT_TRUE(proto.has_found());
+
+ // Slight weirdness: When we *encode* a document for sending it to the
+ // backend, we don't encode the update_time (or create_time). But when we
+ // *decode* a document, we *do* decode the update_time (though we still
+ // ignore the create_time). Therefore, we'll verify the update_time
+ // independently, and then strip it out before comparing the rest.
+ EXPECT_FALSE(actual_proto.has_create_time());
+ EXPECT_EQ(update_time.timestamp().seconds(),
+ proto.found().update_time().seconds());
+ EXPECT_EQ(update_time.timestamp().nanoseconds(),
+ proto.found().update_time().nanos());
+ google::firestore::v1beta1::BatchGetDocumentsResponse proto_copy{proto};
+ proto_copy.mutable_found()->clear_update_time();
+ proto_copy.mutable_found()->clear_create_time();
+
+ EXPECT_TRUE(msg_diff.Compare(proto_copy.found(), actual_proto))
+ << message_differences;
+ }
+
+ void ExpectDeserializationRoundTrip(
+ const DocumentKey& key,
+ const FieldValue& value,
+ const SnapshotVersion& update_time,
+ const google::firestore::v1beta1::BatchGetDocumentsResponse& proto) {
+ size_t size = proto.ByteSizeLong();
+ std::vector<uint8_t> bytes(size);
+ bool status = proto.SerializeToArray(bytes.data(), size);
+ EXPECT_TRUE(status);
+ StatusOr<std::unique_ptr<MaybeDocument>> actual_model_status =
+ serializer.DecodeMaybeDocument(bytes);
+ EXPECT_OK(actual_model_status);
+ std::unique_ptr<MaybeDocument> actual_model =
+ std::move(actual_model_status).ValueOrDie();
+
+ // TODO(rsgowman): Right now, we only support Document (and don't support
+ // NoDocument). That should change in the next PR or so.
+ EXPECT_EQ(MaybeDocument::Type::Document, actual_model->type());
+ Document* actual_doc_model = static_cast<Document*>(actual_model.get());
+ EXPECT_EQ(key, actual_model->key());
+ EXPECT_EQ(value, actual_doc_model->data());
+ EXPECT_EQ(update_time, actual_model->version());
+ }
+
+ std::string message_differences;
+ MessageDifferencer msg_diff;
};
TEST_F(SerializerTest, EncodesNull) {
@@ -517,5 +603,32 @@ TEST_F(SerializerTest, BadKey) {
}
}
+TEST_F(SerializerTest, EncodesEmptyDocument) {
+ DocumentKey key = DocumentKey::FromPathString("path/to/the/doc");
+ FieldValue empty_value = FieldValue::ObjectValueFromMap({});
+ SnapshotVersion update_time = SnapshotVersion{{1234, 5678}};
+
+ google::firestore::v1beta1::BatchGetDocumentsResponse proto;
+ google::firestore::v1beta1::Document* doc_proto = proto.mutable_found();
+ doc_proto->set_name(serializer.EncodeKey(key));
+ doc_proto->mutable_fields();
+
+ google::protobuf::Timestamp* update_time_proto =
+ doc_proto->mutable_update_time();
+ update_time_proto->set_seconds(1234);
+ update_time_proto->set_nanos(5678);
+
+ // Note that we ignore create time in our serializer. We never set it, and
+ // never read it (other than to throw it away). But the server could (and
+ // probably does) set it, so we need to be able to discard it properly. The
+ // ExpectRoundTrip deals with this asymmetry.
+ google::protobuf::Timestamp* create_time_proto =
+ doc_proto->mutable_create_time();
+ create_time_proto->set_seconds(8765);
+ create_time_proto->set_nanos(4321);
+
+ ExpectRoundTrip(key, empty_value, update_time, proto);
+}
+
// TODO(rsgowman): Test [en|de]coding multiple protos into the same output
// vector.