dynamic-test.c++ 16.9 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// 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:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// 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.
21 22 23

#include "dynamic.h"
#include "message.h"
Kenton Varda's avatar
Kenton Varda committed
24
#include <kj/debug.h>
25
#include <kj/compat/gtest.h>
26 27
#include "test-util.h"

28
namespace capnp {
29
namespace _ {  // private
30 31
namespace {

Kenton Varda's avatar
Kenton Varda committed
32 33
template <typename Element, typename T>
void checkList(T reader, std::initializer_list<ReaderFor<Element>> expected) {
34
  auto list = reader.template as<DynamicList>();
Kenton Varda's avatar
Kenton Varda committed
35 36
  ASSERT_EQ(expected.size(), list.size());
  for (uint i = 0; i < expected.size(); i++) {
37
    EXPECT_EQ(expected.begin()[i], list[i].template as<Element>());
Kenton Varda's avatar
Kenton Varda committed
38 39
  }

40
  auto typed = reader.template as<List<Element>>();
Kenton Varda's avatar
Kenton Varda committed
41 42
  ASSERT_EQ(expected.size(), typed.size());
  for (uint i = 0; i < expected.size(); i++) {
43
    EXPECT_EQ(expected.begin()[i], typed[i]);
Kenton Varda's avatar
Kenton Varda committed
44 45 46 47 48 49 50
  }
}

TEST(DynamicApi, Build) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());

51
  initDynamicTestMessage(root);
Kenton Varda's avatar
Kenton Varda committed
52 53
  checkTestMessage(root.asReader().as<TestAllTypes>());

54 55
  checkDynamicTestMessage(root.asReader());
  checkDynamicTestMessage(root);
Kenton Varda's avatar
Kenton Varda committed
56 57 58
}

TEST(DynamicApi, Read) {
59 60 61
  MallocMessageBuilder builder;
  auto root = builder.initRoot<TestAllTypes>();

Kenton Varda's avatar
Kenton Varda committed
62 63
  initTestMessage(root);

64 65 66
  checkDynamicTestMessage(toDynamic(root.asReader()));
  checkDynamicTestMessage(toDynamic(root).asReader());
  checkDynamicTestMessage(toDynamic(root));
Kenton Varda's avatar
Kenton Varda committed
67 68 69 70
}

TEST(DynamicApi, Defaults) {
  AlignedData<1> nullRoot = {{0, 0, 0, 0, 0, 0, 0, 0}};
71 72
  kj::ArrayPtr<const word> segments[1] = {kj::arrayPtr(nullRoot.words, 1)};
  SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1));
Kenton Varda's avatar
Kenton Varda committed
73
  auto root = reader.getRoot<DynamicStruct>(Schema::from<TestDefaults>());
74
  checkDynamicTestMessage(root);
Kenton Varda's avatar
Kenton Varda committed
75 76 77 78 79 80 81
}

TEST(DynamicApi, DefaultsBuilder) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestDefaults>());

  checkTestMessage(root.asReader().as<TestDefaults>());
82
  checkDynamicTestMessage(root.asReader());
Kenton Varda's avatar
Kenton Varda committed
83 84

  // This will initialize the whole message, replacing null pointers with copies of defaults.
85
  checkDynamicTestMessage(root);
Kenton Varda's avatar
Kenton Varda committed
86 87 88

  // Check again now that the message is initialized.
  checkTestMessage(root.asReader().as<TestDefaults>());
89 90
  checkDynamicTestMessage(root.asReader());
  checkDynamicTestMessage(root);
Kenton Varda's avatar
Kenton Varda committed
91 92 93 94 95 96
}

TEST(DynamicApi, Zero) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());

97
  checkDynamicTestMessageAllZero(root.asReader());
Kenton Varda's avatar
Kenton Varda committed
98
  checkTestMessageAllZero(root.asReader().as<TestAllTypes>());
99
  checkDynamicTestMessageAllZero(root);
Kenton Varda's avatar
Kenton Varda committed
100 101 102 103 104 105 106
  checkTestMessageAllZero(root.asReader().as<TestAllTypes>());
}

TEST(DynamicApi, ListListsBuild) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestListDefaults>());

107
  initDynamicTestLists(root);
Kenton Varda's avatar
Kenton Varda committed
108 109
  checkTestMessage(root.asReader().as<TestListDefaults>());

110 111
  checkDynamicTestLists(root.asReader());
  checkDynamicTestLists(root);
Kenton Varda's avatar
Kenton Varda committed
112 113 114 115 116 117 118 119
}

TEST(DynamicApi, ListListsRead) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<TestListDefaults>();

  initTestMessage(root);

120 121 122
  checkDynamicTestLists(toDynamic(root.asReader()));
  checkDynamicTestLists(toDynamic(root).asReader());
  checkDynamicTestLists(toDynamic(root));
Kenton Varda's avatar
Kenton Varda committed
123 124
}

125
TEST(DynamicApi, AnyPointers) {
Kenton Varda's avatar
Kenton Varda committed
126
  MallocMessageBuilder builder;
127
  auto root = builder.getRoot<test::TestAnyPointer>();
Kenton Varda's avatar
Kenton Varda committed
128

129 130 131
  initDynamicTestMessage(
      root.getAnyPointerField().initAs<DynamicStruct>(Schema::from<TestAllTypes>()));
  checkTestMessage(root.asReader().getAnyPointerField().getAs<TestAllTypes>());
Kenton Varda's avatar
Kenton Varda committed
132

133
  checkDynamicTestMessage(
134 135 136
      root.asReader().getAnyPointerField().getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
  checkDynamicTestMessage(
      root.getAnyPointerField().getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
Kenton Varda's avatar
Kenton Varda committed
137 138 139

  {
    {
140
      auto list = root.getAnyPointerField().initAs<DynamicList>(Schema::from<List<uint32_t>>(), 4);
Kenton Varda's avatar
Kenton Varda committed
141 142 143 144 145 146 147
      list.set(0, 123);
      list.set(1, 456);
      list.set(2, 789);
      list.set(3, 123456789);
    }

    {
148
      auto list = root.asReader().getAnyPointerField().getAs<List<uint32_t>>();
Kenton Varda's avatar
Kenton Varda committed
149 150 151 152 153 154 155
      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]);
    }

156
    checkList<uint32_t>(root.asReader().getAnyPointerField().getAs<DynamicList>(
157
        Schema::from<List<uint32_t>>()), {123u, 456u, 789u, 123456789u});
158
    checkList<uint32_t>(root.getAnyPointerField().getAs<DynamicList>(
159
        Schema::from<List<uint32_t>>()), {123u, 456u, 789u, 123456789u});
Kenton Varda's avatar
Kenton Varda committed
160
  }
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

  // 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>();
Kenton Varda's avatar
Kenton Varda committed
192 193
}

194
TEST(DynamicApi, DynamicAnyPointers) {
Kenton Varda's avatar
Kenton Varda committed
195
  MallocMessageBuilder builder;
196
  auto root = builder.getRoot<DynamicStruct>(Schema::from<test::TestAnyPointer>());
Kenton Varda's avatar
Kenton Varda committed
197

198
  initDynamicTestMessage(
199
      root.get("anyPointerField").as<AnyPointer>()
200
          .initAs<DynamicStruct>(Schema::from<TestAllTypes>()));
201 202
  checkTestMessage(
      root.asReader().as<test::TestAnyPointer>().getAnyPointerField().getAs<TestAllTypes>());
Kenton Varda's avatar
Kenton Varda committed
203

204
  checkDynamicTestMessage(
205
      root.asReader().get("anyPointerField").as<AnyPointer>()
206
          .getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
207
  checkDynamicTestMessage(
208
      root.asReader().get("anyPointerField").as<AnyPointer>()
209
          .getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
210
  checkDynamicTestMessage(
211
      root.get("anyPointerField").as<AnyPointer>().asReader()
212
          .getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
213
  checkDynamicTestMessage(
214
      root.get("anyPointerField").as<AnyPointer>()
215
          .getAs<DynamicStruct>(Schema::from<TestAllTypes>()));
Kenton Varda's avatar
Kenton Varda committed
216 217 218

  {
    {
219
      auto list = root.init("anyPointerField").as<AnyPointer>()
220
                      .initAs<DynamicList>(Schema::from<List<uint32_t>>(), 4);
Kenton Varda's avatar
Kenton Varda committed
221 222 223 224 225 226 227
      list.set(0, 123);
      list.set(1, 456);
      list.set(2, 789);
      list.set(3, 123456789);
    }

    {
228 229
      auto list = root.asReader().as<test::TestAnyPointer>()
          .getAnyPointerField().getAs<List<uint32_t>>();
Kenton Varda's avatar
Kenton Varda committed
230 231 232 233 234 235 236 237
      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>(
238
        root.asReader().get("anyPointerField").as<AnyPointer>()
239
            .getAs<DynamicList>(Schema::from<List<uint32_t>>()),
Kenton Varda's avatar
Kenton Varda committed
240 241
        {123u, 456u, 789u, 123456789u});
    checkList<uint32_t>(
242
        root.asReader().get("anyPointerField").as<AnyPointer>()
243
            .getAs<DynamicList>(Schema::from<List<uint32_t>>()),
244 245
        {123u, 456u, 789u, 123456789u});
    checkList<uint32_t>(
246
        root.get("anyPointerField").as<AnyPointer>().asReader()
247
            .getAs<DynamicList>(Schema::from<List<uint32_t>>()),
Kenton Varda's avatar
Kenton Varda committed
248 249
        {123u, 456u, 789u, 123456789u});
    checkList<uint32_t>(
250
        root.get("anyPointerField").as<AnyPointer>()
251
            .getAs<DynamicList>(Schema::from<List<uint32_t>>()),
Kenton Varda's avatar
Kenton Varda committed
252 253 254 255
        {123u, 456u, 789u, 123456789u});
  }
}

256 257 258 259 260 261 262 263 264
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);
}

265 266 267 268
#define EXPECT_MAYBE_EQ(name, exp, expected, actual) \
  KJ_IF_MAYBE(name, exp) { \
    EXPECT_EQ(expected, actual); \
  } else { \
269
    KJ_FAIL_EXPECT("Maybe was empty."); \
270 271
  }

Kenton Varda's avatar
Kenton Varda committed
272 273 274 275 276 277 278 279 280 281 282 283
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());
    {
284
      auto u = dynamic.get("union0").as<DynamicStruct>();
285
      EXPECT_MAYBE_EQ(w, u.which(), "u0f1s32", w->getProto().getName());
286
      EXPECT_EQ(1234567, u.get("u0f1s32").as<int32_t>());
Kenton Varda's avatar
Kenton Varda committed
287 288
    }
    {
289
      auto u = dynamic.get("union1").as<DynamicStruct>();
290
      EXPECT_MAYBE_EQ(w, u.which(), "u1f1sp", w->getProto().getName());
291
      EXPECT_EQ("foo", u.get("u1f1sp").as<Text>());
Kenton Varda's avatar
Kenton Varda committed
292 293
    }
    {
294
      auto u = dynamic.get("union2").as<DynamicStruct>();
295
      EXPECT_MAYBE_EQ(w, u.which(), "u2f0s1", w->getProto().getName());
296
      EXPECT_TRUE(u.get("u2f0s1").as<bool>());
Kenton Varda's avatar
Kenton Varda committed
297 298
    }
    {
299
      auto u = dynamic.get("union3").as<DynamicStruct>();
300
      EXPECT_MAYBE_EQ(w, u.which(), "u3f0s64", w->getProto().getName());
301
      EXPECT_EQ(1234567890123456789ll, u.get("u3f0s64").as<int64_t>());
Kenton Varda's avatar
Kenton Varda committed
302 303 304 305 306 307 308
    }
  }

  {
    // Again as a builder.
    auto dynamic = toDynamic(root);
    {
309
      auto u = dynamic.get("union0").as<DynamicStruct>();
310
      EXPECT_MAYBE_EQ(w, u.which(), "u0f1s32", w->getProto().getName());
311
      EXPECT_EQ(1234567, u.get("u0f1s32").as<int32_t>());
Kenton Varda's avatar
Kenton Varda committed
312 313
    }
    {
314
      auto u = dynamic.get("union1").as<DynamicStruct>();
315
      EXPECT_MAYBE_EQ(w, u.which(), "u1f1sp", w->getProto().getName());
316
      EXPECT_EQ("foo", u.get("u1f1sp").as<Text>());
Kenton Varda's avatar
Kenton Varda committed
317 318
    }
    {
319
      auto u = dynamic.get("union2").as<DynamicStruct>();
320
      EXPECT_MAYBE_EQ(w, u.which(), "u2f0s1", w->getProto().getName());
321
      EXPECT_TRUE(u.get("u2f0s1").as<bool>());
Kenton Varda's avatar
Kenton Varda committed
322 323
    }
    {
324
      auto u = dynamic.get("union3").as<DynamicStruct>();
325
      EXPECT_MAYBE_EQ(w, u.which(), "u3f0s64", w->getProto().getName());
326
      EXPECT_EQ(1234567890123456789ll, u.get("u3f0s64").as<int64_t>());
Kenton Varda's avatar
Kenton Varda committed
327 328 329 330 331 332 333 334
    }
  }
}

TEST(DynamicApi, UnionsWrite) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestUnion>());

335 336 337 338
  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);
Kenton Varda's avatar
Kenton Varda committed
339 340 341 342 343 344 345 346 347 348 349 350 351

  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());
352 353 354 355

  // Can't access union members by name from the root.
  EXPECT_ANY_THROW(root.get("u0f1s32"));
  EXPECT_ANY_THROW(root.set("u0f1s32", 1234567));
356 357
}

358 359 360 361 362
TEST(DynamicApi, UnnamedUnion) {
  MallocMessageBuilder builder;
  StructSchema schema = Schema::from<test::TestUnnamedUnion>();
  auto root = builder.initRoot<DynamicStruct>(schema);

363
  EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
364 365

  root.set("bar", 321);
366
  EXPECT_EQ(schema.getFieldByName("bar"), KJ_ASSERT_NONNULL(root.which()));
367 368 369 370 371 372
  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);
373
  EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
374 375 376 377 378
  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"));

379 380
  root.set("bar", 321);
  EXPECT_EQ(schema.getFieldByName("bar"), KJ_ASSERT_NONNULL(root.which()));
381 382 383 384 385
  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"));

386 387
  root.set("foo", 123);
  EXPECT_EQ(schema.getFieldByName("foo"), KJ_ASSERT_NONNULL(root.which()));
388 389 390 391 392
  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"));
}
393

Kenton Varda's avatar
Kenton Varda committed
394 395 396 397 398
TEST(DynamicApi, ConversionFailures) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());

  root.set("int8Field", 123);
399
  EXPECT_NONFATAL_FAILURE(root.set("int8Field", 1234));
Kenton Varda's avatar
Kenton Varda committed
400 401

  root.set("uInt32Field", 1);
402
  EXPECT_NONFATAL_FAILURE(root.set("uInt32Field", -1));
Kenton Varda's avatar
Kenton Varda committed
403 404

  root.set("int16Field", 5);
405
  EXPECT_NONFATAL_FAILURE(root.set("int16Field", 0.5));
Kenton Varda's avatar
Kenton Varda committed
406 407

  root.set("boolField", true);
408
  EXPECT_NONFATAL_FAILURE(root.set("boolField", 1));
Kenton Varda's avatar
Kenton Varda committed
409 410
}

411 412 413 414
TEST(DynamicApi, LateUnion) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<DynamicStruct>(Schema::from<test::TestLateUnion>());

415
  root.get("theUnion").as<DynamicStruct>().set("qux", "hello");
416 417 418
  EXPECT_EQ("hello", root.as<test::TestLateUnion>().getTheUnion().getQux());
}

419 420
TEST(DynamicApi, Has) {
  MallocMessageBuilder builder;
421
  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestDefaults>());
422

423 424
  // Primitive fields are always present even if set to default.
  EXPECT_TRUE(root.has("int32Field"));
425 426 427
  root.set("int32Field", 123);
  EXPECT_TRUE(root.has("int32Field"));
  root.set("int32Field", -12345678);
428
  EXPECT_TRUE(root.has("int32Field"));
429

430
  // Pointers are absent until initialized.
431 432 433 434 435
  EXPECT_FALSE(root.has("structField"));
  root.init("structField");
  EXPECT_TRUE(root.has("structField"));
}

436 437
TEST(DynamicApi, HasWhenEmpty) {
  AlignedData<1> nullRoot = {{0, 0, 0, 0, 0, 0, 0, 0}};
438 439
  kj::ArrayPtr<const word> segments[1] = {kj::arrayPtr(nullRoot.words, 1)};
  SegmentArrayMessageReader reader(kj::arrayPtr(segments, 1));
440 441
  auto root = reader.getRoot<DynamicStruct>(Schema::from<TestDefaults>());

442 443
  EXPECT_TRUE(root.has("voidField"));
  EXPECT_TRUE(root.has("int32Field"));
444 445 446 447 448 449 450 451 452 453 454 455 456 457
  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});
}

458 459 460 461 462 463 464 465
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>());
}

466 467 468 469 470
TEST(DynamicApi, BuilderAssign) {
  MallocMessageBuilder builder;
  auto root = builder.initRoot<DynamicStruct>(Schema::from<TestAllTypes>());

  // Declare upfront, assign later.
471
  // Note that the Python implementation requires defaulted constructors.  Do not delete them!
472
  DynamicValue::Builder value;
473 474
  DynamicStruct::Builder structValue;
  DynamicList::Builder listValue;
475 476 477 478 479 480 481 482 483 484

  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);
}

485
}  // namespace
486
}  // namespace _ (private)
487
}  // namespace capnp