layout-test.c++ 17.5 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

Kenton Varda's avatar
Kenton Varda committed
22
#define CAPNP_PRIVATE
23
#include "layout.h"
Kenton Varda's avatar
Kenton Varda committed
24
#include "message.h"
25
#include "arena.h"
26
#include <kj/compat/gtest.h>
27

28 29
#if CAPNP_DEBUG_TYPES
namespace kj {
Kenton Varda's avatar
Kenton Varda committed
30
  template <typename T, typename U>
31
  String KJ_STRINGIFY(kj::Quantity<T, U> value) {
32
    return kj::str(unboundAs<uint64_t>(value / kj::unit<kj::Quantity<T, U>>()));
33 34 35 36 37
  }

  // Hack: Allow direct comparisons and multiplications so that we don't have to rewrite the code
  //   below.
  template <uint64_t maxN, typename T>
38 39
  inline constexpr Bounded<65535, T> operator*(uint a, Bounded<maxN, T> b) {
    return assumeBits<16>(a * unbound(b));
40 41
  }
  template <uint b>
42
  inline constexpr Bounded<65535, uint> operator*(uint a, BoundedConst<b>) {
43
    return assumeBits<16>(a * b);
Kenton Varda's avatar
Kenton Varda committed
44 45
  }
}
46
#endif
Kenton Varda's avatar
Kenton Varda committed
47

48
namespace capnp {
49
namespace _ {  // private
50 51
namespace {

Kenton Varda's avatar
Kenton Varda committed
52 53
TEST(WireFormat, SimpleRawDataStruct) {
  AlignedData<2> data = {{
54
    // Struct ref, offset = 1, dataSize = 1, pointerCount = 0
55
    0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
56
    // Content for the data section.
Kenton Varda's avatar
Kenton Varda committed
57 58
    0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
  }};
59

Kenton Varda's avatar
Kenton Varda committed
60
  StructReader reader = PointerReader::getRootUnchecked(data.words).getStruct(nullptr);
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

  EXPECT_EQ(0xefcdab8967452301ull, reader.getDataField<uint64_t>(0 * ELEMENTS));
  EXPECT_EQ(0u, reader.getDataField<uint64_t>(1 * ELEMENTS));
  EXPECT_EQ(0x67452301u, reader.getDataField<uint32_t>(0 * ELEMENTS));
  EXPECT_EQ(0xefcdab89u, reader.getDataField<uint32_t>(1 * ELEMENTS));
  EXPECT_EQ(0u, reader.getDataField<uint32_t>(2 * ELEMENTS));
  EXPECT_EQ(0x2301u, reader.getDataField<uint16_t>(0 * ELEMENTS));
  EXPECT_EQ(0x6745u, reader.getDataField<uint16_t>(1 * ELEMENTS));
  EXPECT_EQ(0xab89u, reader.getDataField<uint16_t>(2 * ELEMENTS));
  EXPECT_EQ(0xefcdu, reader.getDataField<uint16_t>(3 * ELEMENTS));
  EXPECT_EQ(0u, reader.getDataField<uint16_t>(4 * ELEMENTS));

  EXPECT_EQ(321u ^ 0xefcdab8967452301ull, reader.getDataField<uint64_t>(0 * ELEMENTS, 321u));
  EXPECT_EQ(321u ^ 0x67452301u, reader.getDataField<uint32_t>(0 * ELEMENTS, 321u));
  EXPECT_EQ(321u ^ 0x2301u, reader.getDataField<uint16_t>(0 * ELEMENTS, 321u));
76 77 78 79 80
  EXPECT_EQ(321u, reader.getDataField<uint64_t>(1 * ELEMENTS, 321u));
  EXPECT_EQ(321u, reader.getDataField<uint32_t>(2 * ELEMENTS, 321u));
  EXPECT_EQ(321u, reader.getDataField<uint16_t>(4 * ELEMENTS, 321u));

  // Bits
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
  EXPECT_TRUE (reader.getDataField<bool>(0 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(1 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(2 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(3 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(4 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(5 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(6 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(7 * ELEMENTS));

  EXPECT_TRUE (reader.getDataField<bool>( 8 * ELEMENTS));
  EXPECT_TRUE (reader.getDataField<bool>( 9 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(10 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(11 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(12 * ELEMENTS));
  EXPECT_TRUE (reader.getDataField<bool>(13 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(14 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(15 * ELEMENTS));

  EXPECT_TRUE (reader.getDataField<bool>(63 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(64 * ELEMENTS));

102 103
  EXPECT_TRUE (reader.getDataField<bool>(0 * ELEMENTS, false));
  EXPECT_FALSE(reader.getDataField<bool>(1 * ELEMENTS, false));
Kenton Varda's avatar
Kenton Varda committed
104
  EXPECT_TRUE (reader.getDataField<bool>(63 * ELEMENTS, false));
105
  EXPECT_FALSE(reader.getDataField<bool>(64 * ELEMENTS, false));
106 107 108 109
  EXPECT_FALSE(reader.getDataField<bool>(0 * ELEMENTS, true));
  EXPECT_TRUE (reader.getDataField<bool>(1 * ELEMENTS, true));
  EXPECT_FALSE(reader.getDataField<bool>(63 * ELEMENTS, true));
  EXPECT_TRUE (reader.getDataField<bool>(64 * ELEMENTS, true));
110 111
}

112
static const AlignedData<2> SUBSTRUCT_DEFAULT = {{0,0,0,0,1,0,0,0,  0,0,0,0,0,0,0,0}};
113
static const AlignedData<2> STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT =
114
    {{0,0,0,0,1,0,0,0,  0,0,0,0,0,0,0,0}};
115

116
static constexpr StructSize STRUCTLIST_ELEMENT_SIZE(1 * WORDS, 1 * POINTERS);
117

Kenton Varda's avatar
Kenton Varda committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
static void setupStruct(StructBuilder builder) {
  builder.setDataField<uint64_t>(0 * ELEMENTS, 0x1011121314151617ull);
  builder.setDataField<uint32_t>(2 * ELEMENTS, 0x20212223u);
  builder.setDataField<uint16_t>(6 * ELEMENTS, 0x3031u);
  builder.setDataField<uint8_t>(14 * ELEMENTS, 0x40u);
  builder.setDataField<bool>(120 * ELEMENTS, false);
  builder.setDataField<bool>(121 * ELEMENTS, false);
  builder.setDataField<bool>(122 * ELEMENTS, true);
  builder.setDataField<bool>(123 * ELEMENTS, false);
  builder.setDataField<bool>(124 * ELEMENTS, true);
  builder.setDataField<bool>(125 * ELEMENTS, true);
  builder.setDataField<bool>(126 * ELEMENTS, true);
  builder.setDataField<bool>(127 * ELEMENTS, false);

  {
133
    StructBuilder subStruct = builder.getPointerField(0 * POINTERS).initStruct(
134
        StructSize(1 * WORDS, 0 * POINTERS));
Kenton Varda's avatar
Kenton Varda committed
135 136 137 138
    subStruct.setDataField<uint32_t>(0 * ELEMENTS, 123);
  }

  {
139
    ListBuilder list = builder.getPointerField(1 * POINTERS)
140
        .initList(ElementSize::FOUR_BYTES, 3 * ELEMENTS);
Kenton Varda's avatar
Kenton Varda committed
141 142 143 144 145 146 147
    EXPECT_EQ(3 * ELEMENTS, list.size());
    list.setDataElement<int32_t>(0 * ELEMENTS, 200);
    list.setDataElement<int32_t>(1 * ELEMENTS, 201);
    list.setDataElement<int32_t>(2 * ELEMENTS, 202);
  }

  {
148 149
    ListBuilder list = builder.getPointerField(2 * POINTERS).initStructList(
        4 * ELEMENTS, STRUCTLIST_ELEMENT_SIZE);
Kenton Varda's avatar
Kenton Varda committed
150 151
    EXPECT_EQ(4 * ELEMENTS, list.size());
    for (int i = 0; i < 4; i++) {
Kenton Varda's avatar
Kenton Varda committed
152
      StructBuilder element = list.getStructElement(i * ELEMENTS);
Kenton Varda's avatar
Kenton Varda committed
153
      element.setDataField<int32_t>(0 * ELEMENTS, 300 + i);
154
      element.getPointerField(0 * POINTERS)
155
             .initStruct(StructSize(1 * WORDS, 0 * POINTERS))
Kenton Varda's avatar
Kenton Varda committed
156 157 158 159 160
             .setDataField<int32_t>(0 * ELEMENTS, 400 + i);
    }
  }

  {
161
    ListBuilder list = builder.getPointerField(3 * POINTERS)
162
                              .initList(ElementSize::POINTER, 5 * ELEMENTS);
Kenton Varda's avatar
Kenton Varda committed
163 164
    EXPECT_EQ(5 * ELEMENTS, list.size());
    for (uint i = 0; i < 5; i++) {
165
      ListBuilder element = list.getPointerElement(i * ELEMENTS)
166
                                .initList(ElementSize::TWO_BYTES, (i + 1) * ELEMENTS);
Kenton Varda's avatar
Kenton Varda committed
167 168 169 170 171 172 173 174
      EXPECT_EQ((i + 1) * ELEMENTS, element.size());
      for (uint j = 0; j <= i; j++) {
        element.setDataElement<uint16_t>(j * ELEMENTS, 500 + j);
      }
    }
  }
}

175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
static void checkStruct(StructBuilder builder) {
  EXPECT_EQ(0x1011121314151617ull, builder.getDataField<uint64_t>(0 * ELEMENTS));
  EXPECT_EQ(0x20212223u, builder.getDataField<uint32_t>(2 * ELEMENTS));
  EXPECT_EQ(0x3031u, builder.getDataField<uint16_t>(6 * ELEMENTS));
  EXPECT_EQ(0x40u, builder.getDataField<uint8_t>(14 * ELEMENTS));
  EXPECT_FALSE(builder.getDataField<bool>(120 * ELEMENTS));
  EXPECT_FALSE(builder.getDataField<bool>(121 * ELEMENTS));
  EXPECT_TRUE (builder.getDataField<bool>(122 * ELEMENTS));
  EXPECT_FALSE(builder.getDataField<bool>(123 * ELEMENTS));
  EXPECT_TRUE (builder.getDataField<bool>(124 * ELEMENTS));
  EXPECT_TRUE (builder.getDataField<bool>(125 * ELEMENTS));
  EXPECT_TRUE (builder.getDataField<bool>(126 * ELEMENTS));
  EXPECT_FALSE(builder.getDataField<bool>(127 * ELEMENTS));

  {
190
    StructBuilder subStruct = builder.getPointerField(0 * POINTERS).getStruct(
191
        StructSize(1 * WORDS, 0 * POINTERS), SUBSTRUCT_DEFAULT.words);
192 193 194 195
    EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS));
  }

  {
196
    ListBuilder list = builder.getPointerField(1 * POINTERS)
197
                              .getList(ElementSize::FOUR_BYTES, nullptr);
198 199 200 201 202 203 204
    ASSERT_EQ(3 * ELEMENTS, list.size());
    EXPECT_EQ(200, list.getDataElement<int32_t>(0 * ELEMENTS));
    EXPECT_EQ(201, list.getDataElement<int32_t>(1 * ELEMENTS));
    EXPECT_EQ(202, list.getDataElement<int32_t>(2 * ELEMENTS));
  }

  {
205 206
    ListBuilder list = builder.getPointerField(2 * POINTERS)
                              .getStructList(STRUCTLIST_ELEMENT_SIZE, nullptr);
207 208
    ASSERT_EQ(4 * ELEMENTS, list.size());
    for (int i = 0; i < 4; i++) {
Kenton Varda's avatar
Kenton Varda committed
209
      StructBuilder element = list.getStructElement(i * ELEMENTS);
210 211
      EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS));
      EXPECT_EQ(400 + i,
212
          element.getPointerField(0 * POINTERS)
213
                 .getStruct(StructSize(1 * WORDS, 0 * POINTERS),
214 215
                            STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
                 .getDataField<int32_t>(0 * ELEMENTS));
216 217 218 219
    }
  }

  {
220
    ListBuilder list = builder.getPointerField(3 * POINTERS).getList(ElementSize::POINTER, nullptr);
221 222
    ASSERT_EQ(5 * ELEMENTS, list.size());
    for (uint i = 0; i < 5; i++) {
223
      ListBuilder element = list.getPointerElement(i * ELEMENTS)
224
                                .getList(ElementSize::TWO_BYTES, nullptr);
225 226 227 228 229 230 231 232
      ASSERT_EQ((i + 1) * ELEMENTS, element.size());
      for (uint j = 0; j <= i; j++) {
        EXPECT_EQ(500u + j, element.getDataElement<uint16_t>(j * ELEMENTS));
      }
    }
  }
}

Kenton Varda's avatar
Kenton Varda committed
233
static void checkStruct(StructReader reader) {
234 235 236 237 238 239 240 241 242 243 244 245
  EXPECT_EQ(0x1011121314151617ull, reader.getDataField<uint64_t>(0 * ELEMENTS));
  EXPECT_EQ(0x20212223u, reader.getDataField<uint32_t>(2 * ELEMENTS));
  EXPECT_EQ(0x3031u, reader.getDataField<uint16_t>(6 * ELEMENTS));
  EXPECT_EQ(0x40u, reader.getDataField<uint8_t>(14 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(120 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(121 * ELEMENTS));
  EXPECT_TRUE (reader.getDataField<bool>(122 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(123 * ELEMENTS));
  EXPECT_TRUE (reader.getDataField<bool>(124 * ELEMENTS));
  EXPECT_TRUE (reader.getDataField<bool>(125 * ELEMENTS));
  EXPECT_TRUE (reader.getDataField<bool>(126 * ELEMENTS));
  EXPECT_FALSE(reader.getDataField<bool>(127 * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
246 247

  {
248 249
    StructReader subStruct = reader.getPointerField(0 * POINTERS)
                                   .getStruct(SUBSTRUCT_DEFAULT.words);
250
    EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
251 252 253
  }

  {
254
    ListReader list = reader.getPointerField(1 * POINTERS).getList(ElementSize::FOUR_BYTES, nullptr);
Kenton Varda's avatar
Kenton Varda committed
255 256 257 258 259 260 261
    ASSERT_EQ(3 * ELEMENTS, list.size());
    EXPECT_EQ(200, list.getDataElement<int32_t>(0 * ELEMENTS));
    EXPECT_EQ(201, list.getDataElement<int32_t>(1 * ELEMENTS));
    EXPECT_EQ(202, list.getDataElement<int32_t>(2 * ELEMENTS));
  }

  {
262
    ListReader list = reader.getPointerField(2 * POINTERS)
263
                            .getList(ElementSize::INLINE_COMPOSITE, nullptr);
Kenton Varda's avatar
Kenton Varda committed
264 265
    ASSERT_EQ(4 * ELEMENTS, list.size());
    for (int i = 0; i < 4; i++) {
266 267
      StructReader element = list.getStructElement(i * ELEMENTS);
      EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
268
      EXPECT_EQ(400 + i,
269 270 271
          element.getPointerField(0 * POINTERS)
                 .getStruct(STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
                 .getDataField<int32_t>(0 * ELEMENTS));
Kenton Varda's avatar
Kenton Varda committed
272 273 274 275
    }
  }

  {
276
    ListReader list = reader.getPointerField(3 * POINTERS).getList(ElementSize::POINTER, nullptr);
Kenton Varda's avatar
Kenton Varda committed
277 278
    ASSERT_EQ(5 * ELEMENTS, list.size());
    for (uint i = 0; i < 5; i++) {
279
      ListReader element = list.getPointerElement(i * ELEMENTS)
280
                               .getList(ElementSize::TWO_BYTES, nullptr);
Kenton Varda's avatar
Kenton Varda committed
281 282 283 284 285 286 287 288
      ASSERT_EQ((i + 1) * ELEMENTS, element.size());
      for (uint j = 0; j <= i; j++) {
        EXPECT_EQ(500u + j, element.getDataElement<uint16_t>(j * ELEMENTS));
      }
    }
  }
}

289
TEST(WireFormat, StructRoundTrip_OneSegment) {
290
  MallocMessageBuilder message;
291
  BuilderArena arena(&message);
292 293 294
  auto allocation = arena.allocate(1 * WORDS);
  SegmentBuilder* segment = allocation.segment;
  word* rootLocation = allocation.words;
Kenton Varda's avatar
Kenton Varda committed
295

296
  StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation)
297
      .initStruct(StructSize(2 * WORDS, 4 * POINTERS));
Kenton Varda's avatar
Kenton Varda committed
298 299 300
  setupStruct(builder);

  // word count:
301
  //    1  root pointer
Kenton Varda's avatar
Kenton Varda committed
302 303 304 305 306 307
  //    6  root struct
  //    1  sub message
  //    2  3-element int32 list
  //   13  struct list
  //         1 tag
  //        12 4x struct
308 309
  //           1 data section
  //           1 pointer section
Kenton Varda's avatar
Kenton Varda committed
310 311
  //           1 sub-struct
  //   11  list list
312
  //         5 pointers to sub-lists
Kenton Varda's avatar
Kenton Varda committed
313 314 315
  //         6 sub-lists (4x 1 word, 1x 2 words)
  // -----
  //   34
316
  kj::ArrayPtr<const kj::ArrayPtr<const word>> segments = arena.getSegmentsForOutput();
317 318
  ASSERT_EQ(1u, segments.size());
  EXPECT_EQ(34u, segments[0].size());
Kenton Varda's avatar
Kenton Varda committed
319

320
  checkStruct(builder);
Kenton Varda's avatar
Kenton Varda committed
321
  checkStruct(builder.asReader());
Kenton Varda's avatar
Kenton Varda committed
322
  checkStruct(PointerReader::getRootUnchecked(segment->getStartPtr()).getStruct(nullptr));
323 324
  checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4)
      .getStruct(nullptr));
Kenton Varda's avatar
Kenton Varda committed
325 326
}

327
TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) {
328
  MallocMessageBuilder message(0, AllocationStrategy::FIXED_SIZE);
329
  BuilderArena arena(&message);
330 331 332
  auto allocation = arena.allocate(1 * WORDS);
  SegmentBuilder* segment = allocation.segment;
  word* rootLocation = allocation.words;
Kenton Varda's avatar
Kenton Varda committed
333

334
  StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation)
335
      .initStruct(StructSize(2 * WORDS, 4 * POINTERS));
Kenton Varda's avatar
Kenton Varda committed
336 337
  setupStruct(builder);

Kenton Varda's avatar
Kenton Varda committed
338
  // Verify that we made 15 segments.
339
  kj::ArrayPtr<const kj::ArrayPtr<const word>> segments = arena.getSegmentsForOutput();
340
  ASSERT_EQ(15u, segments.size());
Kenton Varda's avatar
Kenton Varda committed
341

Kenton Varda's avatar
Kenton Varda committed
342
  // Check that each segment has the expected size.  Recall that the first word of each segment will
343
  // actually be a pointer to the first thing allocated within that segment.
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
  EXPECT_EQ( 1u, segments[ 0].size());  // root ref
  EXPECT_EQ( 7u, segments[ 1].size());  // root struct
  EXPECT_EQ( 2u, segments[ 2].size());  // sub-struct
  EXPECT_EQ( 3u, segments[ 3].size());  // 3-element int32 list
  EXPECT_EQ(10u, segments[ 4].size());  // struct list
  EXPECT_EQ( 2u, segments[ 5].size());  // struct list substruct 1
  EXPECT_EQ( 2u, segments[ 6].size());  // struct list substruct 2
  EXPECT_EQ( 2u, segments[ 7].size());  // struct list substruct 3
  EXPECT_EQ( 2u, segments[ 8].size());  // struct list substruct 4
  EXPECT_EQ( 6u, segments[ 9].size());  // list list
  EXPECT_EQ( 2u, segments[10].size());  // list list sublist 1
  EXPECT_EQ( 2u, segments[11].size());  // list list sublist 2
  EXPECT_EQ( 2u, segments[12].size());  // list list sublist 3
  EXPECT_EQ( 2u, segments[13].size());  // list list sublist 4
  EXPECT_EQ( 3u, segments[14].size());  // list list sublist 5
Kenton Varda's avatar
Kenton Varda committed
359

360
  checkStruct(builder);
Kenton Varda's avatar
Kenton Varda committed
361
  checkStruct(builder.asReader());
362 363
  checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4)
      .getStruct(nullptr));
364 365 366
}

TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) {
367
  MallocMessageBuilder message(8, AllocationStrategy::FIXED_SIZE);
368
  BuilderArena arena(&message);
369 370 371
  auto allocation = arena.allocate(1 * WORDS);
  SegmentBuilder* segment = allocation.segment;
  word* rootLocation = allocation.words;
372

373
  StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation)
374
      .initStruct(StructSize(2 * WORDS, 4 * POINTERS));
375 376 377
  setupStruct(builder);

  // Verify that we made 6 segments.
378
  kj::ArrayPtr<const kj::ArrayPtr<const word>> segments = arena.getSegmentsForOutput();
379
  ASSERT_EQ(6u, segments.size());
380 381 382

  // Check that each segment has the expected size.  Recall that each object will be prefixed by an
  // extra word if its parent is in a different segment.
383 384 385 386 387 388
  EXPECT_EQ( 8u, segments[0].size());  // root ref + struct + sub
  EXPECT_EQ( 3u, segments[1].size());  // 3-element int32 list
  EXPECT_EQ(10u, segments[2].size());  // struct list
  EXPECT_EQ( 8u, segments[3].size());  // struct list substructs
  EXPECT_EQ( 8u, segments[4].size());  // list list + sublist 1,2
  EXPECT_EQ( 7u, segments[5].size());  // list list sublist 3,4,5
389 390 391

  checkStruct(builder);
  checkStruct(builder.asReader());
392 393
  checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4)
      .getStruct(nullptr));
Kenton Varda's avatar
Kenton Varda committed
394 395
}

396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
inline bool isNan(float f) { return f != f; }
inline bool isNan(double f) { return f != f; }

TEST(WireFormat, NanPatching) {
  EXPECT_EQ(0x7fc00000u, mask(kj::nan(), 0));
  EXPECT_TRUE(isNan(unmask<float>(0x7fc00000u, 0)));
  EXPECT_TRUE(isNan(unmask<float>(0x7fc00001u, 0)));
  EXPECT_TRUE(isNan(unmask<float>(0x7fc00005u, 0)));
  EXPECT_EQ(0x7fc00000u, mask(unmask<float>(0x7fc00000u, 0), 0));
  EXPECT_EQ(0x7ff8000000000000ull, mask((double)kj::nan(), 0));
  EXPECT_TRUE(isNan(unmask<double>(0x7ff8000000000000ull, 0)));
  EXPECT_TRUE(isNan(unmask<double>(0x7ff8000000000001ull, 0)));
  EXPECT_TRUE(isNan(unmask<double>(0x7ff8000000000005ull, 0)));
  EXPECT_EQ(0x7ff8000000000000ull, mask(unmask<double>(0x7ff8000000000000ull, 0), 0));
}

412
}  // namespace
413
}  // namespace _ (private)
414
}  // namespace capnp