aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firestore/core/test
diff options
context:
space:
mode:
Diffstat (limited to 'Firestore/core/test')
-rw-r--r--Firestore/core/test/firebase/firestore/auth/CMakeLists.txt34
-rw-r--r--Firestore/core/test/firebase/firestore/auth/credentials_provider_test.cc53
-rw-r--r--Firestore/core/test/firebase/firestore/auth/empty_credentials_provider_test.cc50
-rw-r--r--Firestore/core/test/firebase/firestore/auth/firebase_credentials_provider_test.mm98
-rw-r--r--Firestore/core/test/firebase/firestore/auth/token_test.cc33
-rw-r--r--Firestore/core/test/firebase/firestore/auth/user_test.cc54
-rw-r--r--Firestore/core/test/firebase/firestore/model/CMakeLists.txt7
-rw-r--r--Firestore/core/test/firebase/firestore/model/document_key_test.cc153
-rw-r--r--Firestore/core/test/firebase/firestore/model/document_test.cc76
-rw-r--r--Firestore/core/test/firebase/firestore/model/field_path_test.cc46
-rw-r--r--Firestore/core/test/firebase/firestore/model/field_value_test.cc53
-rw-r--r--Firestore/core/test/firebase/firestore/model/maybe_document_test.cc66
-rw-r--r--Firestore/core/test/firebase/firestore/model/no_document_test.cc51
-rw-r--r--Firestore/core/test/firebase/firestore/model/resource_path_test.cc14
-rw-r--r--Firestore/core/test/firebase/firestore/model/snapshot_version_test.cc56
-rw-r--r--Firestore/core/test/firebase/firestore/remote/serializer_test.cc71
16 files changed, 879 insertions, 36 deletions
diff --git a/Firestore/core/test/firebase/firestore/auth/CMakeLists.txt b/Firestore/core/test/firebase/firestore/auth/CMakeLists.txt
new file mode 100644
index 0000000..f470bd7
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/auth/CMakeLists.txt
@@ -0,0 +1,34 @@
+# Copyright 2018 Google
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cc_test(
+ firebase_firestore_auth_test
+ SOURCES
+ credentials_provider_test.cc
+ empty_credentials_provider_test.cc
+ token_test.cc
+ user_test.cc
+ DEPENDS
+ firebase_firestore_auth
+)
+
+if(APPLE)
+ cc_test(
+ firebase_firestore_auth_apple_test
+ SOURCES
+ firebase_credentials_provider_test.mm
+ DEPENDS
+ firebase_firestore_auth_apple
+ )
+endif(APPLE)
diff --git a/Firestore/core/test/firebase/firestore/auth/credentials_provider_test.cc b/Firestore/core/test/firebase/firestore/auth/credentials_provider_test.cc
new file mode 100644
index 0000000..1748422
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/auth/credentials_provider_test.cc
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/auth/credentials_provider.h"
+
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace auth {
+
+#define UNUSED(x) (void)(x)
+
+TEST(CredentialsProvider, Typedef) {
+ TokenListener token_listener = [](const Token& token,
+ const absl::string_view error) {
+ UNUSED(token);
+ UNUSED(error);
+ };
+ EXPECT_NE(nullptr, token_listener);
+ EXPECT_TRUE(token_listener);
+
+ token_listener = nullptr;
+ EXPECT_EQ(nullptr, token_listener);
+ EXPECT_FALSE(token_listener);
+
+ UserChangeListener user_change_listener = [](const User& user) {
+ UNUSED(user);
+ };
+ EXPECT_NE(nullptr, user_change_listener);
+ EXPECT_TRUE(user_change_listener);
+
+ user_change_listener = nullptr;
+ EXPECT_EQ(nullptr, user_change_listener);
+ EXPECT_FALSE(user_change_listener);
+}
+
+} // namespace auth
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/auth/empty_credentials_provider_test.cc b/Firestore/core/test/firebase/firestore/auth/empty_credentials_provider_test.cc
new file mode 100644
index 0000000..123f952
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/auth/empty_credentials_provider_test.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/auth/empty_credentials_provider.h"
+
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace auth {
+
+TEST(EmptyCredentialsProvider, GetToken) {
+ EmptyCredentialsProvider credentials_provider;
+ credentials_provider.GetToken(
+ /*force_refresh=*/true,
+ [](const Token& token, const absl::string_view error) {
+ EXPECT_EQ("", token.token());
+ const User& user = token.user();
+ EXPECT_EQ("", user.uid());
+ EXPECT_FALSE(user.is_authenticated());
+ EXPECT_EQ("", error);
+ });
+}
+
+TEST(EmptyCredentialsProvider, SetListener) {
+ EmptyCredentialsProvider credentials_provider;
+ credentials_provider.SetUserChangeListener([](const User& user) {
+ EXPECT_EQ("", user.uid());
+ EXPECT_FALSE(user.is_authenticated());
+ });
+
+ credentials_provider.SetUserChangeListener(nullptr);
+}
+
+} // namespace auth
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/auth/firebase_credentials_provider_test.mm b/Firestore/core/test/firebase/firestore/auth/firebase_credentials_provider_test.mm
new file mode 100644
index 0000000..8d2b361
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/auth/firebase_credentials_provider_test.mm
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/auth/firebase_credentials_provider_apple.h"
+
+#import <FirebaseCore/FIRApp.h>
+#import <FirebaseCore/FIRAppInternal.h>
+#import <FirebaseCore/FIROptionsInternal.h>
+
+#include "Firestore/core/src/firebase/firestore/util/string_apple.h"
+
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace auth {
+
+// TODO(zxu123): Make this an integration test and get infos from environment.
+// Set a .plist file here to enable the test-case.
+static NSString* const kPlist = @"";
+
+class FirebaseCredentialsProviderTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ app_ready_ = false;
+ if (![kPlist hasSuffix:@".plist"]) {
+ return;
+ }
+
+ static dispatch_once_t once_token;
+ dispatch_once(&once_token, ^{
+ FIROptions* options = [[FIROptions alloc] initWithContentsOfFile:kPlist];
+ [FIRApp configureWithOptions:options];
+ });
+
+ // Set getUID implementation.
+ FIRApp* default_app = [FIRApp defaultApp];
+ default_app.getUIDImplementation = ^NSString* {
+ return @"I'm a fake uid.";
+ };
+ app_ready_ = true;
+ }
+
+ bool app_ready_;
+};
+
+// Set kPlist above before enable.
+TEST_F(FirebaseCredentialsProviderTest, GetToken) {
+ if (!app_ready_) {
+ return;
+ }
+
+ FirebaseCredentialsProvider credentials_provider([FIRApp defaultApp]);
+ credentials_provider.GetToken(
+ /*force_refresh=*/true,
+ [](const Token& token, const absl::string_view error) {
+ EXPECT_EQ("", token.token());
+ const User& user = token.user();
+ EXPECT_EQ("I'm a fake uid.", user.uid());
+ EXPECT_TRUE(user.is_authenticated());
+ EXPECT_EQ("", error) << error;
+ });
+}
+
+// Set kPlist above before enable.
+TEST_F(FirebaseCredentialsProviderTest, SetListener) {
+ if (!app_ready_) {
+ return;
+ }
+
+ FirebaseCredentialsProvider credentials_provider([FIRApp defaultApp]);
+ credentials_provider.SetUserChangeListener([](const User& user) {
+ EXPECT_EQ("I'm a fake uid.", user.uid());
+ EXPECT_TRUE(user.is_authenticated());
+ });
+
+ // TODO(wilhuff): We should wait for the above expectations to actually happen
+ // before continuing.
+
+ credentials_provider.SetUserChangeListener(nullptr);
+}
+
+} // namespace auth
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/auth/token_test.cc b/Firestore/core/test/firebase/firestore/auth/token_test.cc
new file mode 100644
index 0000000..a0f2c48
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/auth/token_test.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/auth/token.h"
+
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace auth {
+
+TEST(Token, Getter) {
+ Token token("token", User("abc"));
+ EXPECT_EQ("token", token.token());
+ EXPECT_EQ(User("abc"), token.user());
+}
+
+} // namespace auth
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/auth/user_test.cc b/Firestore/core/test/firebase/firestore/auth/user_test.cc
new file mode 100644
index 0000000..a9f764d
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/auth/user_test.cc
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/auth/user.h"
+
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace auth {
+
+TEST(User, Getter) {
+ User anonymous;
+ EXPECT_EQ("", anonymous.uid());
+ EXPECT_FALSE(anonymous.is_authenticated());
+
+ User signin("abc");
+ EXPECT_EQ("abc", signin.uid());
+ EXPECT_TRUE(signin.is_authenticated());
+
+ User copy;
+ copy = signin;
+ EXPECT_EQ(signin, copy);
+}
+
+TEST(User, Unauthenticated) {
+ User unauthenticated = User::Unauthenticated();
+ EXPECT_EQ("", unauthenticated.uid());
+ EXPECT_FALSE(unauthenticated.is_authenticated());
+}
+
+TEST(User, Comparison) {
+ EXPECT_EQ(User(), User());
+ EXPECT_EQ(User("abc"), User("abc"));
+ EXPECT_NE(User(), User("abc"));
+ EXPECT_NE(User("abc"), User("xyz"));
+}
+
+} // namespace auth
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/model/CMakeLists.txt b/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
index 63ed813..0d581bc 100644
--- a/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
+++ b/Firestore/core/test/firebase/firestore/model/CMakeLists.txt
@@ -16,10 +16,15 @@ cc_test(
firebase_firestore_model_test
SOURCES
database_id_test.cc
+ document_key_test.cc
+ document_test.cc
field_path_test.cc
field_value_test.cc
- timestamp_test.cc
+ maybe_document_test.cc
+ no_document_test.cc
resource_path_test.cc
+ snapshot_version_test.cc
+ timestamp_test.cc
DEPENDS
firebase_firestore_model
)
diff --git a/Firestore/core/test/firebase/firestore/model/document_key_test.cc b/Firestore/core/test/firebase/firestore/model/document_key_test.cc
new file mode 100644
index 0000000..0e0df2d
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/document_key_test.cc
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <initializer_list>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "Firestore/core/src/firebase/firestore/model/document_key.h"
+#include "Firestore/core/src/firebase/firestore/model/resource_path.h"
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+TEST(DocumentKey, Constructor_Empty) {
+ const DocumentKey default_key;
+ EXPECT_TRUE(default_key.path().empty());
+
+ const auto& empty_key = DocumentKey::Empty();
+ const auto& another_empty_key = DocumentKey::Empty();
+ EXPECT_EQ(default_key, empty_key);
+ EXPECT_EQ(empty_key, another_empty_key);
+ EXPECT_EQ(&empty_key, &another_empty_key);
+}
+
+TEST(DocumentKey, Constructor_FromPath) {
+ ResourcePath path{"rooms", "firestore", "messages", "1"};
+ const DocumentKey key_from_path_copy{path};
+ // path shouldn't have been moved from.
+ EXPECT_FALSE(path.empty());
+ EXPECT_EQ(key_from_path_copy.path(), path);
+
+ const DocumentKey key_from_moved_path{std::move(path)};
+ EXPECT_TRUE(path.empty());
+ EXPECT_FALSE(key_from_moved_path.path().empty());
+ EXPECT_EQ(key_from_path_copy.path(), key_from_moved_path.path());
+}
+
+TEST(DocumentKey, CopyAndMove) {
+ DocumentKey key({"rooms", "firestore", "messages", "1"});
+ const std::string path_string = "rooms/firestore/messages/1";
+ EXPECT_EQ(path_string, key.path().CanonicalString());
+
+ DocumentKey copied = key;
+ EXPECT_EQ(path_string, copied.path().CanonicalString());
+ EXPECT_EQ(key, copied);
+
+ const DocumentKey moved = std::move(key);
+ EXPECT_EQ(path_string, moved.path().CanonicalString());
+ EXPECT_NE(key, moved);
+ EXPECT_TRUE(key.path().empty());
+
+ // Reassignment.
+
+ key = copied;
+ EXPECT_EQ(copied, key);
+ EXPECT_EQ(path_string, key.path().CanonicalString());
+
+ key = {};
+ EXPECT_TRUE(key.path().empty());
+ key = std::move(copied);
+ EXPECT_NE(copied, key);
+ EXPECT_TRUE(copied.path().empty());
+ EXPECT_EQ(path_string, key.path().CanonicalString());
+}
+
+TEST(DocumentKey, Constructor_StaticFactory) {
+ const auto key_from_segments =
+ DocumentKey::FromSegments({"rooms", "firestore", "messages", "1"});
+ const std::string path_string = "rooms/firestore/messages/1";
+ const auto key_from_string = DocumentKey::FromPathString(path_string);
+ EXPECT_EQ(path_string, key_from_string.path().CanonicalString());
+ EXPECT_EQ(path_string, key_from_segments.path().CanonicalString());
+ EXPECT_EQ(key_from_segments, key_from_string);
+
+ const auto from_empty_path = DocumentKey::FromPathString("");
+ EXPECT_EQ(from_empty_path, DocumentKey{});
+}
+
+TEST(DocumentKey, Constructor_BadArguments) {
+ ASSERT_ANY_THROW(DocumentKey(ResourcePath{"foo"}));
+ ASSERT_ANY_THROW(DocumentKey(ResourcePath{"foo", "bar", "baz"}));
+
+ ASSERT_ANY_THROW(DocumentKey::FromSegments({"foo"}));
+ ASSERT_ANY_THROW(DocumentKey::FromSegments({"foo", "bar", "baz"}));
+
+ ASSERT_ANY_THROW(DocumentKey::FromPathString("invalid"));
+ ASSERT_ANY_THROW(DocumentKey::FromPathString("invalid//string"));
+ ASSERT_ANY_THROW(DocumentKey::FromPathString("invalid/key/path"));
+}
+
+TEST(DocumentKey, IsDocumentKey) {
+ EXPECT_TRUE(DocumentKey::IsDocumentKey({}));
+ EXPECT_FALSE(DocumentKey::IsDocumentKey({"foo"}));
+ EXPECT_TRUE(DocumentKey::IsDocumentKey({"foo", "bar"}));
+ EXPECT_FALSE(DocumentKey::IsDocumentKey({"foo", "bar", "baz"}));
+}
+
+TEST(DocumentKey, Comparison) {
+ const DocumentKey abcd({"a", "b", "c", "d"});
+ const DocumentKey abcd_too({"a", "b", "c", "d"});
+ const DocumentKey xyzw({"x", "y", "z", "w"});
+ EXPECT_EQ(abcd, abcd_too);
+ EXPECT_NE(abcd, xyzw);
+
+ const DocumentKey empty;
+ const DocumentKey a({"a", "a"});
+ const DocumentKey b({"b", "b"});
+ const DocumentKey ab({"a", "a", "b", "b"});
+
+ EXPECT_FALSE(empty < empty);
+ EXPECT_TRUE(empty <= empty);
+ EXPECT_TRUE(empty < a);
+ EXPECT_TRUE(empty <= a);
+ EXPECT_TRUE(a > empty);
+ EXPECT_TRUE(a >= empty);
+
+ EXPECT_FALSE(a < a);
+ EXPECT_TRUE(a <= a);
+ EXPECT_FALSE(a > a);
+ EXPECT_TRUE(a >= a);
+ EXPECT_TRUE(a == a);
+ EXPECT_FALSE(a != a);
+
+ EXPECT_TRUE(a < b);
+ EXPECT_TRUE(a <= b);
+ EXPECT_TRUE(b > a);
+ EXPECT_TRUE(b >= a);
+
+ EXPECT_TRUE(a < ab);
+ EXPECT_TRUE(a <= ab);
+ EXPECT_TRUE(ab > a);
+ EXPECT_TRUE(ab >= a);
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/model/document_test.cc b/Firestore/core/test/firebase/firestore/model/document_test.cc
new file mode 100644
index 0000000..6b72360
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/document_test.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/document.h"
+
+#include "absl/strings/string_view.h"
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+namespace {
+
+inline Document MakeDocument(const absl::string_view data,
+ const absl::string_view path,
+ const Timestamp& timestamp,
+ bool has_local_mutations) {
+ return Document(FieldValue::ObjectValue(
+ {{"field", FieldValue::StringValue(data.data())}}),
+ DocumentKey::FromPathString(path.data()),
+ SnapshotVersion(timestamp), has_local_mutations);
+}
+
+} // anonymous namespace
+
+TEST(Document, Getter) {
+ const Document& doc =
+ MakeDocument("foo", "i/am/a/path", Timestamp(123, 456), true);
+ EXPECT_EQ(MaybeDocument::Type::Document, doc.type());
+ EXPECT_EQ(
+ FieldValue::ObjectValue({{"field", FieldValue::StringValue("foo")}}),
+ doc.data());
+ EXPECT_EQ(DocumentKey::FromPathString("i/am/a/path"), doc.key());
+ EXPECT_EQ(SnapshotVersion(Timestamp(123, 456)), doc.version());
+ EXPECT_TRUE(doc.has_local_mutations());
+}
+
+TEST(Document, Comparison) {
+ EXPECT_EQ(MakeDocument("foo", "i/am/a/path", Timestamp(123, 456), true),
+ MakeDocument("foo", "i/am/a/path", Timestamp(123, 456), true));
+ EXPECT_NE(MakeDocument("foo", "i/am/a/path", Timestamp(123, 456), true),
+ MakeDocument("bar", "i/am/a/path", Timestamp(123, 456), true));
+ EXPECT_NE(
+ MakeDocument("foo", "i/am/a/path", Timestamp(123, 456), true),
+ MakeDocument("foo", "i/am/another/path", Timestamp(123, 456), true));
+ EXPECT_NE(MakeDocument("foo", "i/am/a/path", Timestamp(123, 456), true),
+ MakeDocument("foo", "i/am/a/path", Timestamp(456, 123), true));
+ EXPECT_NE(MakeDocument("foo", "i/am/a/path", Timestamp(123, 456), true),
+ MakeDocument("foo", "i/am/a/path", Timestamp(123, 456), false));
+
+ // Document and MaybeDocument will not equal. In particular, Document and
+ // NoDocument will not equal, which I won't test here.
+ EXPECT_NE(Document(FieldValue::ObjectValue({}),
+ DocumentKey::FromPathString("same/path"),
+ SnapshotVersion(Timestamp()), false),
+ MaybeDocument(DocumentKey::FromPathString("same/path"),
+ SnapshotVersion(Timestamp())));
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/model/field_path_test.cc b/Firestore/core/test/firebase/firestore/model/field_path_test.cc
index 7c7e0a3..a5ae3b2 100644
--- a/Firestore/core/test/firebase/firestore/model/field_path_test.cc
+++ b/Firestore/core/test/firebase/firestore/model/field_path_test.cc
@@ -29,18 +29,18 @@ namespace model {
TEST(FieldPath, Constructors) {
const FieldPath empty_path;
EXPECT_TRUE(empty_path.empty());
- EXPECT_EQ(0, empty_path.size());
+ EXPECT_EQ(0u, empty_path.size());
EXPECT_TRUE(empty_path.begin() == empty_path.end());
const FieldPath path_from_list = {"rooms", "Eros", "messages"};
EXPECT_FALSE(path_from_list.empty());
- EXPECT_EQ(3, path_from_list.size());
+ EXPECT_EQ(3u, path_from_list.size());
EXPECT_TRUE(path_from_list.begin() + 3 == path_from_list.end());
std::vector<std::string> segments{"rooms", "Eros", "messages"};
const FieldPath path_from_segments{segments.begin(), segments.end()};
EXPECT_FALSE(path_from_segments.empty());
- EXPECT_EQ(3, path_from_segments.size());
+ EXPECT_EQ(3u, path_from_segments.size());
EXPECT_TRUE(path_from_segments.begin() + 3 == path_from_segments.end());
FieldPath copied = path_from_list;
@@ -168,13 +168,13 @@ TEST(FieldPath, IsPrefixOf) {
TEST(FieldPath, AccessFailures) {
const FieldPath path;
- ASSERT_DEATH_IF_SUPPORTED(path.first_segment(), "");
- ASSERT_DEATH_IF_SUPPORTED(path.last_segment(), "");
- ASSERT_DEATH_IF_SUPPORTED(path[0], "");
- ASSERT_DEATH_IF_SUPPORTED(path[1], "");
- ASSERT_DEATH_IF_SUPPORTED(path.PopFirst(), "");
- ASSERT_DEATH_IF_SUPPORTED(path.PopFirst(2), "");
- ASSERT_DEATH_IF_SUPPORTED(path.PopLast(), "");
+ ASSERT_ANY_THROW(path.first_segment());
+ ASSERT_ANY_THROW(path.last_segment());
+ ASSERT_ANY_THROW(path[0]);
+ ASSERT_ANY_THROW(path[1]);
+ ASSERT_ANY_THROW(path.PopFirst());
+ ASSERT_ANY_THROW(path.PopFirst(2));
+ ASSERT_ANY_THROW(path.PopLast());
}
TEST(FieldPath, Parsing) {
@@ -201,7 +201,7 @@ TEST(FieldPath, Parsing) {
const auto path_with_dot = FieldPath::FromServerFormat(R"(foo\.bar)");
EXPECT_EQ(path_with_dot.CanonicalString(), "`foo.bar`");
- EXPECT_EQ(path_with_dot.size(), 1);
+ EXPECT_EQ(path_with_dot.size(), 1u);
}
// This is a special case in C++: std::string may contain embedded nulls. To
@@ -213,22 +213,22 @@ TEST(FieldPath, ParseEmbeddedNull) {
str += ".bar";
const auto path = FieldPath::FromServerFormat(str);
- EXPECT_EQ(path.size(), 1);
+ EXPECT_EQ(path.size(), 1u);
EXPECT_EQ(path.CanonicalString(), "foo");
}
TEST(FieldPath, ParseFailures) {
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat(""), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat("."), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat(".."), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat("foo."), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat(".bar"), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat("foo..bar"), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat(R"(foo\)"), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat(R"(foo.\)"), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat("foo`"), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat("foo```"), "");
- ASSERT_DEATH_IF_SUPPORTED(FieldPath::FromServerFormat("`foo"), "");
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat(""));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat("."));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat(".."));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat("foo."));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat(".bar"));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat("foo..bar"));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat(R"(foo\)"));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat(R"(foo.\)"));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat("foo`"));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat("foo```"));
+ ASSERT_ANY_THROW(FieldPath::FromServerFormat("`foo"));
}
TEST(FieldPath, CanonicalStringOfSubstring) {
diff --git a/Firestore/core/test/firebase/firestore/model/field_value_test.cc b/Firestore/core/test/firebase/firestore/model/field_value_test.cc
index 702c0f6..86eb804 100644
--- a/Firestore/core/test/firebase/firestore/model/field_value_test.cc
+++ b/Firestore/core/test/firebase/firestore/model/field_value_test.cc
@@ -144,6 +144,20 @@ TEST(FieldValue, BlobType) {
EXPECT_FALSE(a < a);
}
+TEST(FieldValue, ReferenceType) {
+ const DatabaseId id("project", "database");
+ const FieldValue a =
+ FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"), &id);
+ DocumentKey key = DocumentKey::FromPathString("root/def");
+ const FieldValue b = FieldValue::ReferenceValue(key, &id);
+ const FieldValue c = FieldValue::ReferenceValue(std::move(key), &id);
+ EXPECT_EQ(Type::Reference, a.type());
+ EXPECT_EQ(Type::Reference, b.type());
+ EXPECT_EQ(Type::Reference, c.type());
+ EXPECT_TRUE(a < b);
+ EXPECT_FALSE(a < a);
+}
+
TEST(FieldValue, GeoPointType) {
const FieldValue a = FieldValue::GeoPointValue({1, 2});
const FieldValue b = FieldValue::GeoPointValue({3, 4});
@@ -280,6 +294,23 @@ TEST(FieldValue, Copy) {
clone = null_value;
EXPECT_EQ(FieldValue::NullValue(), clone);
+ const DatabaseId database_id("project", "database");
+ const FieldValue reference_value = FieldValue::ReferenceValue(
+ DocumentKey::FromPathString("root/abc"), &database_id);
+ clone = reference_value;
+ EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
+ &database_id),
+ clone);
+ EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
+ &database_id),
+ reference_value);
+ clone = clone;
+ EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
+ &database_id),
+ clone);
+ clone = null_value;
+ EXPECT_EQ(FieldValue::NullValue(), clone);
+
const FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
clone = geo_point_value;
EXPECT_EQ(FieldValue::GeoPointValue({1, 2}), clone);
@@ -361,7 +392,7 @@ TEST(FieldValue, Move) {
clone = FieldValue::NullValue();
EXPECT_EQ(FieldValue::NullValue(), clone);
- const FieldValue timestamp_value = FieldValue::TimestampValue({100, 200});
+ FieldValue timestamp_value = FieldValue::TimestampValue({100, 200});
clone = std::move(timestamp_value);
EXPECT_EQ(FieldValue::TimestampValue({100, 200}), clone);
clone = FieldValue::NullValue();
@@ -373,13 +404,23 @@ TEST(FieldValue, Move) {
clone = FieldValue::NullValue();
EXPECT_EQ(FieldValue::NullValue(), clone);
- const FieldValue blob_value = FieldValue::BlobValue(Bytes("abc"), 4);
+ FieldValue blob_value = FieldValue::BlobValue(Bytes("abc"), 4);
clone = std::move(blob_value);
EXPECT_EQ(FieldValue::BlobValue(Bytes("abc"), 4), clone);
clone = FieldValue::NullValue();
EXPECT_EQ(FieldValue::NullValue(), clone);
- const FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
+ const DatabaseId database_id("project", "database");
+ FieldValue reference_value = FieldValue::ReferenceValue(
+ DocumentKey::FromPathString("root/abc"), &database_id);
+ clone = std::move(reference_value);
+ EXPECT_EQ(FieldValue::ReferenceValue(DocumentKey::FromPathString("root/abc"),
+ &database_id),
+ clone);
+ clone = null_value;
+ EXPECT_EQ(FieldValue::NullValue(), clone);
+
+ FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
clone = std::move(geo_point_value);
EXPECT_EQ(FieldValue::GeoPointValue({1, 2}), clone);
clone = null_value;
@@ -415,6 +456,9 @@ TEST(FieldValue, CompareMixedType) {
const FieldValue timestamp_value = FieldValue::TimestampValue({100, 200});
const FieldValue string_value = FieldValue::StringValue("abc");
const FieldValue blob_value = FieldValue::BlobValue(Bytes("abc"), 4);
+ const DatabaseId database_id("project", "database");
+ const FieldValue reference_value = FieldValue::ReferenceValue(
+ DocumentKey::FromPathString("root/abc"), &database_id);
const FieldValue geo_point_value = FieldValue::GeoPointValue({1, 2});
const FieldValue array_value =
FieldValue::ArrayValue(std::vector<FieldValue>());
@@ -425,7 +469,8 @@ TEST(FieldValue, CompareMixedType) {
EXPECT_TRUE(number_value < timestamp_value);
EXPECT_TRUE(timestamp_value < string_value);
EXPECT_TRUE(string_value < blob_value);
- EXPECT_TRUE(blob_value < geo_point_value);
+ EXPECT_TRUE(blob_value < reference_value);
+ EXPECT_TRUE(reference_value < geo_point_value);
EXPECT_TRUE(geo_point_value < array_value);
EXPECT_TRUE(array_value < object_value);
}
diff --git a/Firestore/core/test/firebase/firestore/model/maybe_document_test.cc b/Firestore/core/test/firebase/firestore/model/maybe_document_test.cc
new file mode 100644
index 0000000..005798a
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/maybe_document_test.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/maybe_document.h"
+
+#include "absl/strings/string_view.h"
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+namespace {
+
+inline MaybeDocument MakeMaybeDocument(const absl::string_view path,
+ const Timestamp& timestamp) {
+ return MaybeDocument(DocumentKey::FromPathString(path.data()),
+ SnapshotVersion(timestamp));
+}
+
+inline bool operator<(const MaybeDocument& lhs, const MaybeDocument& rhs) {
+ static const DocumentKeyComparator less;
+ return less(lhs, rhs);
+}
+
+} // anonymous namespace
+
+TEST(MaybeDocument, Getter) {
+ const MaybeDocument& doc =
+ MakeMaybeDocument("i/am/a/path", Timestamp(123, 456));
+ EXPECT_EQ(MaybeDocument::Type::Unknown, doc.type());
+ EXPECT_EQ(DocumentKey::FromPathString("i/am/a/path"), doc.key());
+ EXPECT_EQ(SnapshotVersion(Timestamp(123, 456)), doc.version());
+}
+
+TEST(MaybeDocument, Comparison) {
+ EXPECT_TRUE(MakeMaybeDocument("root/123", Timestamp(456, 123)) <
+ MakeMaybeDocument("root/456", Timestamp(123, 456)));
+ // MaybeDocument comparision is purely key-based.
+ EXPECT_FALSE(MakeMaybeDocument("root/123", Timestamp(111, 111)) <
+ MakeMaybeDocument("root/123", Timestamp(222, 222)));
+
+ EXPECT_EQ(MakeMaybeDocument("root/123", Timestamp(456, 123)),
+ MakeMaybeDocument("root/123", Timestamp(456, 123)));
+ EXPECT_NE(MakeMaybeDocument("root/123", Timestamp(456, 123)),
+ MakeMaybeDocument("root/456", Timestamp(456, 123)));
+ EXPECT_NE(MakeMaybeDocument("root/123", Timestamp(456, 123)),
+ MakeMaybeDocument("root/123", Timestamp(123, 456)));
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/model/no_document_test.cc b/Firestore/core/test/firebase/firestore/model/no_document_test.cc
new file mode 100644
index 0000000..825820f
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/no_document_test.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/no_document.h"
+
+#include "absl/strings/string_view.h"
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+namespace {
+
+inline NoDocument MakeNoDocument(const absl::string_view path,
+ const Timestamp& timestamp) {
+ return NoDocument(DocumentKey::FromPathString(path.data()),
+ SnapshotVersion(timestamp));
+}
+
+} // anonymous namespace
+
+TEST(NoDocument, Getter) {
+ const NoDocument& doc = MakeNoDocument("i/am/a/path", Timestamp(123, 456));
+ EXPECT_EQ(MaybeDocument::Type::NoDocument, doc.type());
+ EXPECT_EQ(DocumentKey::FromPathString("i/am/a/path"), doc.key());
+ EXPECT_EQ(SnapshotVersion(Timestamp(123, 456)), doc.version());
+
+ // NoDocument and MaybeDocument will not equal.
+ EXPECT_NE(NoDocument(DocumentKey::FromPathString("same/path"),
+ SnapshotVersion(Timestamp())),
+ MaybeDocument(DocumentKey::FromPathString("same/path"),
+ SnapshotVersion(Timestamp())));
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/model/resource_path_test.cc b/Firestore/core/test/firebase/firestore/model/resource_path_test.cc
index 317a1db..637e78e 100644
--- a/Firestore/core/test/firebase/firestore/model/resource_path_test.cc
+++ b/Firestore/core/test/firebase/firestore/model/resource_path_test.cc
@@ -29,18 +29,18 @@ namespace model {
TEST(ResourcePath, Constructor) {
const ResourcePath empty_path;
EXPECT_TRUE(empty_path.empty());
- EXPECT_EQ(0, empty_path.size());
+ EXPECT_EQ(0u, empty_path.size());
EXPECT_TRUE(empty_path.begin() == empty_path.end());
const ResourcePath path_from_list{{"rooms", "Eros", "messages"}};
EXPECT_FALSE(path_from_list.empty());
- EXPECT_EQ(3, path_from_list.size());
+ EXPECT_EQ(3u, path_from_list.size());
EXPECT_TRUE(path_from_list.begin() + 3 == path_from_list.end());
std::vector<std::string> segments{"rooms", "Eros", "messages"};
const ResourcePath path_from_segments{segments.begin(), segments.end()};
EXPECT_FALSE(path_from_segments.empty());
- EXPECT_EQ(3, path_from_segments.size());
+ EXPECT_EQ(3u, path_from_segments.size());
EXPECT_TRUE(path_from_segments.begin() + 3 == path_from_segments.end());
ResourcePath copied = path_from_list;
@@ -74,7 +74,7 @@ TEST(ResourcePath, Comparison) {
TEST(ResourcePath, Parsing) {
const auto parse = [](const std::pair<std::string, size_t> expected) {
- const auto path = ResourcePath::Parse(expected.first);
+ const auto path = ResourcePath::FromString(expected.first);
return std::make_pair(path.CanonicalString(), path.size());
};
const auto make_expected = [](const std::string& str, const size_t size) {
@@ -92,12 +92,12 @@ TEST(ResourcePath, Parsing) {
expected = make_expected(R"(foo/__!?#@..`..\`/baz)", 3);
EXPECT_EQ(expected, parse(expected));
- EXPECT_EQ(ResourcePath::Parse("/foo/").CanonicalString(), "foo");
+ EXPECT_EQ(ResourcePath::FromString("/foo/").CanonicalString(), "foo");
}
TEST(ResourcePath, ParseFailures) {
- ASSERT_DEATH_IF_SUPPORTED(ResourcePath::Parse("//"), "");
- ASSERT_DEATH_IF_SUPPORTED(ResourcePath::Parse("foo//bar"), "");
+ ASSERT_ANY_THROW(ResourcePath::FromString("//"));
+ ASSERT_ANY_THROW(ResourcePath::FromString("foo//bar"));
}
} // namespace model
diff --git a/Firestore/core/test/firebase/firestore/model/snapshot_version_test.cc b/Firestore/core/test/firebase/firestore/model/snapshot_version_test.cc
new file mode 100644
index 0000000..e359f84
--- /dev/null
+++ b/Firestore/core/test/firebase/firestore/model/snapshot_version_test.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/core/src/firebase/firestore/model/snapshot_version.h"
+
+#include "gtest/gtest.h"
+
+namespace firebase {
+namespace firestore {
+namespace model {
+
+TEST(SnapshotVersion, Getter) {
+ SnapshotVersion version(Timestamp(123, 456));
+ EXPECT_EQ(Timestamp(123, 456), version.timestamp());
+
+ const SnapshotVersion& no_version = SnapshotVersion::None();
+ EXPECT_EQ(Timestamp(), no_version.timestamp());
+}
+
+TEST(SnapshotVersion, Comparison) {
+ EXPECT_LT(SnapshotVersion::None(), SnapshotVersion(Timestamp(123, 456)));
+
+ EXPECT_LT(SnapshotVersion(Timestamp(123, 456)),
+ SnapshotVersion(Timestamp(456, 123)));
+ EXPECT_GT(SnapshotVersion(Timestamp(456, 123)),
+ SnapshotVersion(Timestamp(123, 456)));
+ EXPECT_LE(SnapshotVersion(Timestamp(123, 456)),
+ SnapshotVersion(Timestamp(456, 123)));
+ EXPECT_LE(SnapshotVersion(Timestamp(123, 456)),
+ SnapshotVersion(Timestamp(123, 456)));
+ EXPECT_GE(SnapshotVersion(Timestamp(456, 123)),
+ SnapshotVersion(Timestamp(123, 456)));
+ EXPECT_GE(SnapshotVersion(Timestamp(123, 456)),
+ SnapshotVersion(Timestamp(123, 456)));
+ EXPECT_EQ(SnapshotVersion(Timestamp(123, 456)),
+ SnapshotVersion(Timestamp(123, 456)));
+ EXPECT_NE(SnapshotVersion(Timestamp(123, 456)),
+ SnapshotVersion(Timestamp(456, 123)));
+}
+
+} // namespace model
+} // namespace firestore
+} // namespace firebase
diff --git a/Firestore/core/test/firebase/firestore/remote/serializer_test.cc b/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
index 1be5a87..35f417e 100644
--- a/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
+++ b/Firestore/core/test/firebase/firestore/remote/serializer_test.cc
@@ -16,8 +16,15 @@
#include "Firestore/core/src/firebase/firestore/remote/serializer.h"
-#include <gtest/gtest.h>
+#include <pb.h>
#include <pb_encode.h>
+#include <vector>
+
+#include "Firestore/core/src/firebase/firestore/model/field_value.h"
+#include "gtest/gtest.h"
+
+using firebase::firestore::model::FieldValue;
+using firebase::firestore::remote::Serializer;
TEST(Serializer, CanLinkToNanopb) {
// This test doesn't actually do anything interesting as far as actually using
@@ -26,3 +33,65 @@ TEST(Serializer, CanLinkToNanopb) {
// the test.
pb_ostream_from_buffer(NULL, 0);
}
+
+// Fixture for running serializer tests.
+class SerializerTest : public ::testing::Test {
+ public:
+ SerializerTest() : serializer(/*DatabaseId("p", "d")*/) {
+ }
+ Serializer serializer;
+
+ void ExpectRoundTrip(const FieldValue& model,
+ const Serializer::TypedValue& proto,
+ FieldValue::Type type) {
+ EXPECT_EQ(type, model.type());
+ EXPECT_EQ(type, proto.type);
+ Serializer::TypedValue actual_proto = serializer.EncodeFieldValue(model);
+ EXPECT_EQ(type, actual_proto.type);
+ EXPECT_EQ(proto, actual_proto);
+ EXPECT_EQ(model, serializer.DecodeFieldValue(proto));
+ }
+
+ void ExpectRoundTrip(const Serializer::TypedValue& proto,
+ std::vector<uint8_t> bytes,
+ FieldValue::Type type) {
+ EXPECT_EQ(type, proto.type);
+ std::vector<uint8_t> actual_bytes;
+ Serializer::EncodeTypedValue(proto, &actual_bytes);
+ EXPECT_EQ(bytes, actual_bytes);
+ Serializer::TypedValue actual_proto = Serializer::DecodeTypedValue(bytes);
+ EXPECT_EQ(type, actual_proto.type);
+ EXPECT_EQ(proto, actual_proto);
+ }
+};
+
+TEST_F(SerializerTest, EncodesNullModelToProto) {
+ FieldValue model = FieldValue::NullValue();
+ Serializer::TypedValue proto{FieldValue::Type::Null,
+ google_firestore_v1beta1_Value_init_default};
+ // sanity check (the _init_default above should set this to _NULL_VALUE)
+ EXPECT_EQ(google_protobuf_NullValue_NULL_VALUE, proto.value.null_value);
+ ExpectRoundTrip(model, proto, FieldValue::Type::Null);
+}
+
+TEST_F(SerializerTest, EncodesNullProtoToBytes) {
+ Serializer::TypedValue proto{FieldValue::Type::Null,
+ google_firestore_v1beta1_Value_init_default};
+ // sanity check (the _init_default above should set this to _NULL_VALUE)
+ EXPECT_EQ(google_protobuf_NullValue_NULL_VALUE, proto.value.null_value);
+
+ /* NB: proto bytes were created via:
+ echo 'null_value: NULL_VALUE' \
+ | ./build/external/protobuf/src/protobuf-build/src/protoc \
+ -I./Firestore/Protos/protos \
+ -I./build/external/protobuf/src/protobuf/src/ \
+ --encode=google.firestore.v1beta1.Value \
+ google/firestore/v1beta1/document.proto \
+ > output.bin
+ */
+ std::vector<uint8_t> bytes{0x58, 0x00};
+ ExpectRoundTrip(proto, bytes, FieldValue::Type::Null);
+}
+
+// TODO(rsgowman): Test [en|de]coding multiple protos into the same output
+// vector.