%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
// Copyright 2019 The Chromium 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 "serializer_traits.h" #include <array> #include "serializable.h" #include "test_platform.h" // The purpose of this test is to ensure that the // {Field}SerializerTraits<X>::Serialize methods invoke the appropriate // functions from cbor.h; so, it's usually sufficient to compare with what // cbor.h function invocations would produce, rather than making assertions on // the specific bytes emitted by the SerializerTraits code. namespace v8_crdtp { namespace { // ============================================================================= // SerializerTraits - Encodes field values of protocol objects in CBOR. // ============================================================================= TEST(SerializerTraits, Bool) { std::vector<uint8_t> out; SerializerTraits<bool>::Serialize(true, &out); SerializerTraits<bool>::Serialize(false, &out); EXPECT_THAT(out, testing::ElementsAre(cbor::EncodeTrue(), cbor::EncodeFalse())); } TEST(SerializerTraits, Double) { std::vector<uint8_t> out; SerializerTraits<double>::Serialize(1.00001, &out); std::vector<uint8_t> expected; cbor::EncodeDouble(1.00001, &expected); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } TEST(SerializerTraits, Int32) { std::vector<uint8_t> out; SerializerTraits<int32_t>::Serialize(42, &out); std::vector<uint8_t> expected; cbor::EncodeInt32(42, &expected); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } TEST(SerializerTraits, VectorOfInt32) { std::vector<int32_t> ints = {1, 2, 3}; std::vector<uint8_t> out; SerializerTraits<std::vector<int32_t>>::Serialize(ints, &out); std::vector<uint8_t> expected; expected.push_back(cbor::EncodeIndefiniteLengthArrayStart()); for (int32_t v : ints) cbor::EncodeInt32(v, &expected); expected.push_back(cbor::EncodeStop()); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } // Foo is an example for a domain specific type. class Foo : public Serializable { public: Foo(int32_t value) : value(value) {} int32_t value; void AppendSerialized(std::vector<uint8_t>* out) const override { // In production, this would be generated code which emits a // CBOR map that has STRING8 keys corresponding to the field names // and field values encoded using SerializerTraits::Serialize. // // For the test we simplify this drastically and just emit the field // value, for conveniently testing std::vector<std::unique_ptr<Foo>>, // as well as the convenience methods for raw pointer and unique_ptr. SerializerTraits<int32_t>::Serialize(value, out); } }; TEST(SerializerTraits, VectorOfDomainSpecificType) { std::vector<std::unique_ptr<Foo>> foos; foos.push_back(std::make_unique<Foo>(1)); foos.push_back(std::make_unique<Foo>(2)); foos.push_back(std::make_unique<Foo>(3)); std::vector<uint8_t> out; SerializerTraits<std::vector<std::unique_ptr<Foo>>>::Serialize(foos, &out); std::vector<uint8_t> expected; expected.push_back(cbor::EncodeIndefiniteLengthArrayStart()); for (int32_t v : {1, 2, 3}) cbor::EncodeInt32(v, &expected); expected.push_back(cbor::EncodeStop()); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } TEST(SerializerTraits, ConstRefAndUniquePtr) { // Shows that SerializerTraits<Foo> allows unique_ptr. Foo foo(42); auto bar = std::make_unique<Foo>(21); std::vector<uint8_t> out; // In this case, |foo| is taken as a const Foo&. SerializerTraits<Foo>::Serialize(foo, &out); // In this case, |bar| is taken as a const std::unique_ptr<Foo>&. SerializerTraits<std::unique_ptr<Foo>>::Serialize(bar, &out); std::vector<uint8_t> expected; cbor::EncodeInt32(42, &expected); cbor::EncodeInt32(21, &expected); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } TEST(SerializerTraits, UTF8String) { std::string msg = "Hello, 🌎."; std::vector<uint8_t> out; SerializerTraits<std::string>::Serialize(msg, &out); std::vector<uint8_t> expected; cbor::EncodeString8(SpanFrom(msg), &expected); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } // A trivial model of Exported. // (see // https://cs.chromium.org/chromium/src/out/Debug/gen/v8/include/inspector/Debugger.h). struct Exported { std::string msg; void AppendSerialized(std::vector<uint8_t>* out) const { cbor::EncodeString8(SpanFrom(msg), out); } }; TEST(SerializerTraits, Exported) { Exported exported; exported.msg = "Hello, world."; std::vector<uint8_t> out; SerializerTraits<Exported>::Serialize(exported, &out); std::vector<uint8_t> expected; cbor::EncodeString8(SpanFrom(exported.msg), &expected); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } // ============================================================================= // FieldSerializerTraits - Encodes fields of protocol objects in CBOR // ============================================================================= TEST(FieldSerializerTraits, RequiredField) { std::string value = "Hello, world."; std::vector<uint8_t> out; SerializeField(SpanFrom("msg"), value, &out); std::vector<uint8_t> expected; cbor::EncodeString8(SpanFrom("msg"), &expected); cbor::EncodeString8(SpanFrom(value), &expected); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } template <typename T> class FieldSerializerTraits_MaybeTest : public ::testing::Test {}; using MaybeTypes = ::testing::Types<detail::ValueMaybe<bool>, detail::ValueMaybe<double>, detail::ValueMaybe<int32_t>, detail::ValueMaybe<std::string>, detail::PtrMaybe<Foo>, detail::PtrMaybe<std::vector<std::unique_ptr<Foo>>>>; TYPED_TEST_SUITE(FieldSerializerTraits_MaybeTest, MaybeTypes); TYPED_TEST(FieldSerializerTraits_MaybeTest, NoOutputForFieldsIfNotJust) { std::vector<uint8_t> out; SerializeField(SpanFrom("maybe"), TypeParam(), &out); EXPECT_THAT(out, testing::ElementsAreArray(std::vector<uint8_t>())); } TEST(FieldSerializerTraits, MaybeBool) { std::vector<uint8_t> out; SerializeField(SpanFrom("true"), detail::ValueMaybe<bool>(true), &out); SerializeField(SpanFrom("false"), detail::ValueMaybe<bool>(false), &out); std::vector<uint8_t> expected; cbor::EncodeString8(SpanFrom("true"), &expected); expected.push_back(cbor::EncodeTrue()); cbor::EncodeString8(SpanFrom("false"), &expected); expected.push_back(cbor::EncodeFalse()); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } TEST(FieldSerializerTraits, MaybeDouble) { std::vector<uint8_t> out; SerializeField(SpanFrom("dbl"), detail::ValueMaybe<double>(3.14), &out); std::vector<uint8_t> expected; cbor::EncodeString8(SpanFrom("dbl"), &expected); cbor::EncodeDouble(3.14, &expected); EXPECT_THAT(out, testing::ElementsAreArray(expected)); } TEST(FieldSerializerTraits, MaybePtrFoo) { std::vector<uint8_t> out; SerializeField(SpanFrom("foo"), detail::PtrMaybe<Foo>(std::make_unique<Foo>(42)), &out); std::vector<uint8_t> expected; cbor::EncodeString8(SpanFrom("foo"), &expected); cbor::EncodeInt32(42, &expected); // Simplified relative to production. EXPECT_THAT(out, testing::ElementsAreArray(expected)); } } // namespace } // namespace v8_crdtp