blob: 7426894ce0ff23d24d27f0a9e519acd8fb0f8209 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "peridot/bin/cloud_provider_firestore/firestore/encoding.h"
#include <string>
#include <google/protobuf/util/time_util.h>
#include <gtest/gtest.h>
#include "peridot/bin/cloud_provider_firestore/firestore/testing/encoding.h"
#include "peridot/lib/convert/convert.h"
namespace cloud_provider_firestore {
namespace {
// Creates correct std::strings with \0 bytes inside from C-style string
// constants.
std::string operator"" _s(const char* str, size_t size) {
return std::string(str, size);
}
using StringEncodingTest = ::testing::TestWithParam<std::string>;
TEST_P(StringEncodingTest, BackAndForth) {
std::string data = GetParam();
std::string encoded;
std::string decoded;
encoded = EncodeKey(data);
EXPECT_EQ('+', encoded.back());
EXPECT_TRUE(DecodeKey(encoded, &decoded));
EXPECT_EQ(data, decoded);
}
INSTANTIATE_TEST_CASE_P(ExampleData, StringEncodingTest,
::testing::Values(""_s, "abcdef"_s, "\x02\x7F"_s,
"~!@#$%^&*()_+-="_s, "\0"_s,
"bazinga\0\0\0"_s));
TEST(BatchEncodingTest, Empty) {
cloud_provider::CommitPack commits;
ASSERT_TRUE(cloud_provider::EncodeCommitPack({}, &commits));
google::firestore::v1beta1::Document document;
ASSERT_TRUE(EncodeCommitBatch(commits, &document));
std::vector<cloud_provider::CommitPackEntry> entries;
std::string timestamp;
ASSERT_TRUE(DecodeCommitBatch(document, &entries, &timestamp));
EXPECT_EQ(0u, entries.size());
}
TEST(BatchEncodingTest, TwoCommits) {
cloud_provider::CommitPack commits;
ASSERT_TRUE(cloud_provider::EncodeCommitPack(
{{"id0", "data0"}, {"id1", "data1"}}, &commits));
google::firestore::v1beta1::Document document;
ASSERT_TRUE(EncodeCommitBatch(commits, &document));
std::vector<cloud_provider::CommitPackEntry> entries;
std::string timestamp;
ASSERT_TRUE(DecodeCommitBatch(document, &entries, &timestamp));
EXPECT_EQ(2u, entries.size());
EXPECT_EQ("id0", entries[0].id);
EXPECT_EQ("data0", entries[0].data);
EXPECT_EQ("id1", entries[1].id);
EXPECT_EQ("data1", entries[1].data);
}
TEST(BatchEncodingTest, Timestamp) {
cloud_provider::CommitPack commits;
ASSERT_TRUE(cloud_provider::EncodeCommitPack({{"id0", "data0"}}, &commits));
google::firestore::v1beta1::Document document;
google::protobuf::Timestamp protobuf_timestamp;
ASSERT_TRUE(google::protobuf::util::TimeUtil::FromString(
"2018-06-26T14:39:22+00:00", &protobuf_timestamp));
std::string original_timestamp;
ASSERT_TRUE(protobuf_timestamp.SerializeToString(&original_timestamp));
EncodeCommitBatchWithTimestamp(commits, original_timestamp, &document);
std::vector<cloud_provider::CommitPackEntry> entries;
std::string decoded_timestamp;
EXPECT_TRUE(DecodeCommitBatch(document, &entries, &decoded_timestamp));
EXPECT_EQ(original_timestamp, decoded_timestamp);
}
TEST(BatchEncodingTest, DecodingErrors) {
std::vector<cloud_provider::CommitPackEntry> entries;
std::string timestamp;
{
// Empty document.
google::firestore::v1beta1::Document document;
EXPECT_FALSE(DecodeCommitBatch(document, &entries, &timestamp));
}
{
// Non-empty but the commit key is missing.
google::firestore::v1beta1::Document document;
(*document.mutable_fields())["some_field"].set_integer_value(3);
EXPECT_FALSE(DecodeCommitBatch(document, &entries, &timestamp));
}
{
// Commits field is not an array.
google::firestore::v1beta1::Document document;
(*document.mutable_fields())["commits"].set_integer_value(3);
EXPECT_FALSE(DecodeCommitBatch(document, &entries, &timestamp));
}
{
// Commits contains a commit that is not a map.
google::firestore::v1beta1::Document document;
google::firestore::v1beta1::ArrayValue* commit_array =
(*document.mutable_fields())["commits"].mutable_array_value();
commit_array->add_values()->set_integer_value(3);
EXPECT_FALSE(DecodeCommitBatch(document, &entries, &timestamp));
}
{
// Commits contains a commit that misses the "data" field.
google::firestore::v1beta1::Document document;
google::firestore::v1beta1::ArrayValue* commit_array =
(*document.mutable_fields())["commits"].mutable_array_value();
google::firestore::v1beta1::MapValue* commit_value =
commit_array->add_values()->mutable_map_value();
*((*commit_value->mutable_fields())["id"].mutable_bytes_value()) =
"some_id";
EXPECT_FALSE(DecodeCommitBatch(document, &entries, &timestamp));
}
{
// Commits contains a commit that misses the "id" field.
google::firestore::v1beta1::Document document;
google::firestore::v1beta1::ArrayValue* commit_array =
(*document.mutable_fields())["commits"].mutable_array_value();
google::firestore::v1beta1::MapValue* commit_value =
commit_array->add_values()->mutable_map_value();
*((*commit_value->mutable_fields())["data"].mutable_bytes_value()) =
"some_data";
EXPECT_FALSE(DecodeCommitBatch(document, &entries, &timestamp));
}
{
// Correct batch (sanity check).
google::firestore::v1beta1::Document document;
google::firestore::v1beta1::ArrayValue* commit_array =
(*document.mutable_fields())["commits"].mutable_array_value();
google::firestore::v1beta1::MapValue* commit_value =
commit_array->add_values()->mutable_map_value();
*((*commit_value->mutable_fields())["id"].mutable_bytes_value()) =
"some_id";
*((*commit_value->mutable_fields())["data"].mutable_bytes_value()) =
"some_data";
EXPECT_TRUE(DecodeCommitBatch(document, &entries, &timestamp));
}
}
} // namespace
} // namespace cloud_provider_firestore