diff src/capnproto-0.6.0/c++/src/capnp/dynamic-test.c++ @ 147:45360b968bf4

Cap'n Proto v0.6 + build for OSX
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 22 May 2017 10:01:37 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/capnproto-0.6.0/c++/src/capnp/dynamic-test.c++	Mon May 22 10:01:37 2017 +0100
@@ -0,0 +1,487 @@
+// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
+// Licensed under the MIT License:
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include "dynamic.h"
+#include "message.h"
+#include <kj/debug.h>
+#include <kj/compat/gtest.h>
+#include "test-util.h"
+
+namespace capnp {
+namespace _ {  // private
+namespace {
+
+template <typename Element, typename T>
+void checkList(T reader, std::initializer_list<ReaderFor<Element>> expected) {
+  auto list = reader.template as<DynamicList>();
+  ASSERT_EQ(expected.size(), list.size());
+  for (uint i = 0; i < expected.size(); i++) {
+    EXPECT_EQ(expected.begin()[i], list[i].template as<Element>());
+  }
+
+  auto typed = reader.template as<List<Element>>();
+  ASSERT_EQ(expected.size(), typed.size());
+  for (uint i = 0; i < expected.size(); i++) {
+    EXPECT_EQ(expected.begin()[i], typed[i]);
+  }
+}
+
+TEST(DynamicApi, Build) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());
+
+  initDynamicTestMessage(root);
+  checkTestMessage(root.asReader().as<TestAllTypes>());
+
+  checkDynamicTestMessage(root.asReader());
+  checkDynamicTestMessage(root);
+}
+
+TEST(DynamicApi, Read) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<TestAllTypes>();
+
+  initTestMessage(root);
+
+  checkDynamicTestMessage(toDynamic(root.asReader()));
+  checkDynamicTestMessage(toDynamic(root).asReader());
+  checkDynamicTestMessage(toDynamic(root));
+}
+
+TEST(DynamicApi, Defaults) {
+  AlignedData<1> nullRoot = {{0, 0, 0, 0, 0, 0, 0, 0}};
+  kj::ArrayPtr<const word> segments[1] = {kj::arrayPtr(nullRoot.words, 1)};
+  SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1));
+  auto root = reader.getRoot<DynamicStruct>(Schema::from<TestDefaults>());
+  checkDynamicTestMessage(root);
+}
+
+TEST(DynamicApi, DefaultsBuilder) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestDefaults>());
+
+  checkTestMessage(root.asReader().as<TestDefaults>());
+  checkDynamicTestMessage(root.asReader());
+
+  // This will initialize the whole message, replacing null pointers with copies of defaults.
+  checkDynamicTestMessage(root);
+
+  // Check again now that the message is initialized.
+  checkTestMessage(root.asReader().as<TestDefaults>());
+  checkDynamicTestMessage(root.asReader());
+  checkDynamicTestMessage(root);
+}
+
+TEST(DynamicApi, Zero) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());
+
+  checkDynamicTestMessageAllZero(root.asReader());
+  checkTestMessageAllZero(root.asReader().as<TestAllTypes>());
+  checkDynamicTestMessageAllZero(root);
+  checkTestMessageAllZero(root.asReader().as<TestAllTypes>());
+}
+
+TEST(DynamicApi, ListListsBuild) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestListDefaults>());
+
+  initDynamicTestLists(root);
+  checkTestMessage(root.asReader().as<TestListDefaults>());
+
+  checkDynamicTestLists(root.asReader());
+  checkDynamicTestLists(root);
+}
+
+TEST(DynamicApi, ListListsRead) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<TestListDefaults>();
+
+  initTestMessage(root);
+
+  checkDynamicTestLists(toDynamic(root.asReader()));
+  checkDynamicTestLists(toDynamic(root).asReader());
+  checkDynamicTestLists(toDynamic(root));
+}
+
+TEST(DynamicApi, AnyPointers) {
+  MallocMessageBuilder builder;
+  auto root = builder.getRoot<test::TestAnyPointer>();
+
+  initDynamicTestMessage(
+      root.getAnyPointerField().initAs<DynamicStruct>(Schema::from<TestAllTypes>()));
+  checkTestMessage(root.asReader().getAnyPointerField().getAs<TestAllTypes>());
+
+  checkDynamicTestMessage(
+      root.asReader().getAnyPointerField().getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
+  checkDynamicTestMessage(
+      root.getAnyPointerField().getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
+
+  {
+    {
+      auto list = root.getAnyPointerField().initAs<DynamicList>(Schema::from<List<uint32_t>>(), 4);
+      list.set(0, 123);
+      list.set(1, 456);
+      list.set(2, 789);
+      list.set(3, 123456789);
+    }
+
+    {
+      auto list = root.asReader().getAnyPointerField().getAs<List<uint32_t>>();
+      ASSERT_EQ(4u, list.size());
+      EXPECT_EQ(123u, list[0]);
+      EXPECT_EQ(456u, list[1]);
+      EXPECT_EQ(789u, list[2]);
+      EXPECT_EQ(123456789u, list[3]);
+    }
+
+    checkList<uint32_t>(root.asReader().getAnyPointerField().getAs<DynamicList>(
+        Schema::from<List<uint32_t>>()), {123u, 456u, 789u, 123456789u});
+    checkList<uint32_t>(root.getAnyPointerField().getAs<DynamicList>(
+        Schema::from<List<uint32_t>>()), {123u, 456u, 789u, 123456789u});
+  }
+
+  // Setting an AnyPointer to various types should work.
+  toDynamic(root).set("anyPointerField", capnp::Text::Reader("foo"));
+  EXPECT_EQ("foo", root.getAnyPointerField().getAs<Text>());
+
+  {
+    auto orphan = builder.getOrphanage().newOrphan<TestAllTypes>();
+    initTestMessage(orphan.get());
+    toDynamic(root).set("anyPointerField", orphan.getReader());
+    checkTestMessage(root.getAnyPointerField().getAs<TestAllTypes>());
+
+    toDynamic(root).adopt("anyPointerField", kj::mv(orphan));
+    checkTestMessage(root.getAnyPointerField().getAs<TestAllTypes>());
+  }
+
+  {
+    auto lorphan = builder.getOrphanage().newOrphan<List<uint32_t>>(3);
+    lorphan.get().set(0, 12);
+    lorphan.get().set(1, 34);
+    lorphan.get().set(2, 56);
+    toDynamic(root).set("anyPointerField", lorphan.getReader());
+    auto l = root.getAnyPointerField().getAs<List<uint32_t>>();
+    ASSERT_EQ(3, l.size());
+    EXPECT_EQ(12, l[0]);
+    EXPECT_EQ(34, l[1]);
+    EXPECT_EQ(56, l[2]);
+  }
+
+  // Just compile this one.
+  toDynamic(root).set("anyPointerField", Capability::Client(nullptr));
+  root.getAnyPointerField().getAs<Capability>();
+}
+
+TEST(DynamicApi, DynamicAnyPointers) {
+  MallocMessageBuilder builder;
+  auto root = builder.getRoot<DynamicStruct>(Schema::from<test::TestAnyPointer>());
+
+  initDynamicTestMessage(
+      root.get("anyPointerField").as<AnyPointer>()
+          .initAs<DynamicStruct>(Schema::from<TestAllTypes>()));
+  checkTestMessage(
+      root.asReader().as<test::TestAnyPointer>().getAnyPointerField().getAs<TestAllTypes>());
+
+  checkDynamicTestMessage(
+      root.asReader().get("anyPointerField").as<AnyPointer>()
+          .getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
+  checkDynamicTestMessage(
+      root.asReader().get("anyPointerField").as<AnyPointer>()
+          .getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
+  checkDynamicTestMessage(
+      root.get("anyPointerField").as<AnyPointer>().asReader()
+          .getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
+  checkDynamicTestMessage(
+      root.get("anyPointerField").as<AnyPointer>()
+          .getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
+
+  {
+    {
+      auto list = root.init("anyPointerField").as<AnyPointer>()
+                      .initAs<DynamicList>(Schema::from<List<uint32_t>>(), 4);
+      list.set(0, 123);
+      list.set(1, 456);
+      list.set(2, 789);
+      list.set(3, 123456789);
+    }
+
+    {
+      auto list = root.asReader().as<test::TestAnyPointer>()
+          .getAnyPointerField().getAs<List<uint32_t>>();
+      ASSERT_EQ(4u, list.size());
+      EXPECT_EQ(123u, list[0]);
+      EXPECT_EQ(456u, list[1]);
+      EXPECT_EQ(789u, list[2]);
+      EXPECT_EQ(123456789u, list[3]);
+    }
+
+    checkList<uint32_t>(
+        root.asReader().get("anyPointerField").as<AnyPointer>()
+            .getAs<DynamicList>(Schema::from<List<uint32_t>>()),
+        {123u, 456u, 789u, 123456789u});
+    checkList<uint32_t>(
+        root.asReader().get("anyPointerField").as<AnyPointer>()
+            .getAs<DynamicList>(Schema::from<List<uint32_t>>()),
+        {123u, 456u, 789u, 123456789u});
+    checkList<uint32_t>(
+        root.get("anyPointerField").as<AnyPointer>().asReader()
+            .getAs<DynamicList>(Schema::from<List<uint32_t>>()),
+        {123u, 456u, 789u, 123456789u});
+    checkList<uint32_t>(
+        root.get("anyPointerField").as<AnyPointer>()
+            .getAs<DynamicList>(Schema::from<List<uint32_t>>()),
+        {123u, 456u, 789u, 123456789u});
+  }
+}
+
+TEST(DynamicApi, DynamicAnyStructs) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());
+
+  root.as<AnyStruct>().as<TestAllTypes>().setInt8Field(123);
+  EXPECT_EQ(root.get("int8Field").as<int8_t>(), 123);
+  EXPECT_EQ(root.asReader().as<AnyStruct>().as<TestAllTypes>().getInt8Field(), 123);
+}
+
+#define EXPECT_MAYBE_EQ(name, exp, expected, actual) \
+  KJ_IF_MAYBE(name, exp) { \
+    EXPECT_EQ(expected, actual); \
+  } else { \
+    KJ_FAIL_EXPECT("Maybe was empty."); \
+  }
+
+TEST(DynamicApi, UnionsRead) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<TestUnion>();
+
+  root.getUnion0().setU0f1s32(1234567);
+  root.getUnion1().setU1f1sp("foo");
+  root.getUnion2().setU2f0s1(true);
+  root.getUnion3().setU3f0s64(1234567890123456789ll);
+
+  {
+    auto dynamic = toDynamic(root.asReader());
+    {
+      auto u = dynamic.get("union0").as<DynamicStruct>();
+      EXPECT_MAYBE_EQ(w, u.which(), "u0f1s32", w->getProto().getName());
+      EXPECT_EQ(1234567, u.get("u0f1s32").as<int32_t>());
+    }
+    {
+      auto u = dynamic.get("union1").as<DynamicStruct>();
+      EXPECT_MAYBE_EQ(w, u.which(), "u1f1sp", w->getProto().getName());
+      EXPECT_EQ("foo", u.get("u1f1sp").as<Text>());
+    }
+    {
+      auto u = dynamic.get("union2").as<DynamicStruct>();
+      EXPECT_MAYBE_EQ(w, u.which(), "u2f0s1", w->getProto().getName());
+      EXPECT_TRUE(u.get("u2f0s1").as<bool>());
+    }
+    {
+      auto u = dynamic.get("union3").as<DynamicStruct>();
+      EXPECT_MAYBE_EQ(w, u.which(), "u3f0s64", w->getProto().getName());
+      EXPECT_EQ(1234567890123456789ll, u.get("u3f0s64").as<int64_t>());
+    }
+  }
+
+  {
+    // Again as a builder.
+    auto dynamic = toDynamic(root);
+    {
+      auto u = dynamic.get("union0").as<DynamicStruct>();
+      EXPECT_MAYBE_EQ(w, u.which(), "u0f1s32", w->getProto().getName());
+      EXPECT_EQ(1234567, u.get("u0f1s32").as<int32_t>());
+    }
+    {
+      auto u = dynamic.get("union1").as<DynamicStruct>();
+      EXPECT_MAYBE_EQ(w, u.which(), "u1f1sp", w->getProto().getName());
+      EXPECT_EQ("foo", u.get("u1f1sp").as<Text>());
+    }
+    {
+      auto u = dynamic.get("union2").as<DynamicStruct>();
+      EXPECT_MAYBE_EQ(w, u.which(), "u2f0s1", w->getProto().getName());
+      EXPECT_TRUE(u.get("u2f0s1").as<bool>());
+    }
+    {
+      auto u = dynamic.get("union3").as<DynamicStruct>();
+      EXPECT_MAYBE_EQ(w, u.which(), "u3f0s64", w->getProto().getName());
+      EXPECT_EQ(1234567890123456789ll, u.get("u3f0s64").as<int64_t>());
+    }
+  }
+}
+
+TEST(DynamicApi, UnionsWrite) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestUnion>());
+
+  root.get("union0").as<DynamicStruct>().set("u0f1s32", 1234567);
+  root.get("union1").as<DynamicStruct>().set("u1f1sp", "foo");
+  root.get("union2").as<DynamicStruct>().set("u2f0s1", true);
+  root.get("union3").as<DynamicStruct>().set("u3f0s64", 1234567890123456789ll);
+
+  auto reader = root.asReader().as<TestUnion>();
+  ASSERT_EQ(TestUnion::Union0::U0F1S32, reader.getUnion0().which());
+  EXPECT_EQ(1234567, reader.getUnion0().getU0f1s32());
+
+  ASSERT_EQ(TestUnion::Union1::U1F1SP, reader.getUnion1().which());
+  EXPECT_EQ("foo", reader.getUnion1().getU1f1sp());
+
+  ASSERT_EQ(TestUnion::Union2::U2F0S1, reader.getUnion2().which());
+  EXPECT_TRUE(reader.getUnion2().getU2f0s1());
+
+  ASSERT_EQ(TestUnion::Union3::U3F0S64, reader.getUnion3().which());
+  EXPECT_EQ(1234567890123456789ll, reader.getUnion3().getU3f0s64());
+
+  // Can't access union members by name from the root.
+  EXPECT_ANY_THROW(root.get("u0f1s32"));
+  EXPECT_ANY_THROW(root.set("u0f1s32", 1234567));
+}
+
+TEST(DynamicApi, UnnamedUnion) {
+  MallocMessageBuilder builder;
+  StructSchema schema = Schema::from<test::TestUnnamedUnion>();
+  auto root = builder.initRoot<DynamicStruct>(schema);
+
+  EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
+
+  root.set("bar", 321);
+  EXPECT_EQ(schema.getFieldByName("bar"), KJ_ASSERT_NONNULL(root.which()));
+  EXPECT_EQ(321u, root.get("bar").as<uint>());
+  EXPECT_EQ(321u, root.asReader().get("bar").as<uint>());
+  EXPECT_ANY_THROW(root.get("foo"));
+  EXPECT_ANY_THROW(root.asReader().get("foo"));
+
+  root.set("foo", 123);
+  EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
+  EXPECT_EQ(123u, root.get("foo").as<uint>());
+  EXPECT_EQ(123u, root.asReader().get("foo").as<uint>());
+  EXPECT_ANY_THROW(root.get("bar"));
+  EXPECT_ANY_THROW(root.asReader().get("bar"));
+
+  root.set("bar", 321);
+  EXPECT_EQ(schema.getFieldByName("bar"), KJ_ASSERT_NONNULL(root.which()));
+  EXPECT_EQ(321u, root.get("bar").as<uint>());
+  EXPECT_EQ(321u, root.asReader().get("bar").as<uint>());
+  EXPECT_ANY_THROW(root.get("foo"));
+  EXPECT_ANY_THROW(root.asReader().get("foo"));
+
+  root.set("foo", 123);
+  EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
+  EXPECT_EQ(123u, root.get("foo").as<uint>());
+  EXPECT_EQ(123u, root.asReader().get("foo").as<uint>());
+  EXPECT_ANY_THROW(root.get("bar"));
+  EXPECT_ANY_THROW(root.asReader().get("bar"));
+}
+
+TEST(DynamicApi, ConversionFailures) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());
+
+  root.set("int8Field", 123);
+  EXPECT_NONFATAL_FAILURE(root.set("int8Field", 1234));
+
+  root.set("uInt32Field", 1);
+  EXPECT_NONFATAL_FAILURE(root.set("uInt32Field", -1));
+
+  root.set("int16Field", 5);
+  EXPECT_NONFATAL_FAILURE(root.set("int16Field", 0.5));
+
+  root.set("boolField", true);
+  EXPECT_NONFATAL_FAILURE(root.set("boolField", 1));
+}
+
+TEST(DynamicApi, LateUnion) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<test::TestLateUnion>());
+
+  root.get("theUnion").as<DynamicStruct>().set("qux", "hello");
+  EXPECT_EQ("hello", root.as<test::TestLateUnion>().getTheUnion().getQux());
+}
+
+TEST(DynamicApi, Has) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestDefaults>());
+
+  // Primitive fields are always present even if set to default.
+  EXPECT_TRUE(root.has("int32Field"));
+  root.set("int32Field", 123);
+  EXPECT_TRUE(root.has("int32Field"));
+  root.set("int32Field", -12345678);
+  EXPECT_TRUE(root.has("int32Field"));
+
+  // Pointers are absent until initialized.
+  EXPECT_FALSE(root.has("structField"));
+  root.init("structField");
+  EXPECT_TRUE(root.has("structField"));
+}
+
+TEST(DynamicApi, HasWhenEmpty) {
+  AlignedData<1> nullRoot = {{0, 0, 0, 0, 0, 0, 0, 0}};
+  kj::ArrayPtr<const word> segments[1] = {kj::arrayPtr(nullRoot.words, 1)};
+  SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1));
+  auto root = reader.getRoot<DynamicStruct>(Schema::from<TestDefaults>());
+
+  EXPECT_TRUE(root.has("voidField"));
+  EXPECT_TRUE(root.has("int32Field"));
+  EXPECT_FALSE(root.has("structField"));
+  EXPECT_FALSE(root.has("int32List"));
+}
+
+TEST(DynamicApi, SetEnumFromNative) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());
+
+  root.set("enumField", TestEnum::BAZ);
+  root.set("enumList", {TestEnum::BAR, TestEnum::FOO});
+  EXPECT_EQ(TestEnum::BAZ, root.get("enumField").as<TestEnum>());
+  checkList<TestEnum>(root.get("enumList"), {TestEnum::BAR, TestEnum::FOO});
+}
+
+TEST(DynamicApi, SetDataFromText) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());
+
+  root.set("dataField", "foo");
+  EXPECT_EQ(data("foo"), root.get("dataField").as<Data>());
+}
+
+TEST(DynamicApi, BuilderAssign) {
+  MallocMessageBuilder builder;
+  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());
+
+  // Declare upfront, assign later.
+  // Note that the Python implementation requires defaulted constructors.  Do not delete them!
+  DynamicValue::Builder value;
+  DynamicStruct::Builder structValue;
+  DynamicList::Builder listValue;
+
+  value = root.get("structField");
+  structValue = value.as<DynamicStruct>();
+  structValue.set("int32Field", 123);
+
+  value = root.init("int32List", 1);
+  listValue = value.as<DynamicList>();
+  listValue.set(0, 123);
+}
+
+}  // namespace
+}  // namespace _ (private)
+}  // namespace capnp