capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

serialize-packed-test.c++ (18666B)


      1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #include "serialize-packed.h"
     23 #include <kj/debug.h>
     24 #include <kj/compat/gtest.h>
     25 #include <string>
     26 #include <stdlib.h>
     27 #include "test-util.h"
     28 
     29 namespace capnp {
     30 namespace _ {  // private
     31 namespace {
     32 
     33 class TestPipe: public kj::BufferedInputStream, public kj::OutputStream {
     34 public:
     35   TestPipe()
     36       : preferredReadSize(kj::maxValue), readPos(0) {}
     37   explicit TestPipe(size_t preferredReadSize)
     38       : preferredReadSize(preferredReadSize), readPos(0) {}
     39   ~TestPipe() {}
     40 
     41   const std::string& getData() { return data; }
     42 
     43   kj::ArrayPtr<const byte> getArray() {
     44     return kj::arrayPtr(reinterpret_cast<const byte*>(data.data()), data.size());
     45   }
     46 
     47   void resetRead(size_t preferredReadSize = kj::maxValue) {
     48     readPos = 0;
     49     this->preferredReadSize = preferredReadSize;
     50   }
     51 
     52   bool allRead() {
     53     return readPos == data.size();
     54   }
     55 
     56   void clear(size_t preferredReadSize = kj::maxValue) {
     57     resetRead(preferredReadSize);
     58     data.clear();
     59   }
     60 
     61   void write(const void* buffer, size_t size) override {
     62     data.append(reinterpret_cast<const char*>(buffer), size);
     63   }
     64 
     65   size_t tryRead(void* buffer, size_t minBytes, size_t maxBytes) override {
     66     KJ_ASSERT(maxBytes <= data.size() - readPos, "Overran end of stream.");
     67     size_t amount = kj::min(maxBytes, kj::max(minBytes, preferredReadSize));
     68     memcpy(buffer, data.data() + readPos, amount);
     69     readPos += amount;
     70     return amount;
     71   }
     72 
     73   void skip(size_t bytes) override {
     74     KJ_ASSERT(bytes <= data.size() - readPos, "Overran end of stream.");
     75     readPos += bytes;
     76   }
     77 
     78   kj::ArrayPtr<const byte> tryGetReadBuffer() override {
     79     size_t amount = kj::min(data.size() - readPos, preferredReadSize);
     80     return kj::arrayPtr(reinterpret_cast<const byte*>(data.data() + readPos), amount);
     81   }
     82 
     83 private:
     84   size_t preferredReadSize;
     85   std::string data;
     86   std::string::size_type readPos;
     87 };
     88 
     89 void expectPacksTo(kj::ArrayPtr<const byte> unpackedUnaligned, kj::ArrayPtr<const byte> packed) {
     90   TestPipe pipe;
     91 
     92   auto unpackedSizeInWords = computeUnpackedSizeInWords(packed);
     93   EXPECT_EQ(unpackedUnaligned.size(), unpackedSizeInWords * sizeof(word));
     94 
     95   // Make a guaranteed-to-be-aligned copy of the unpacked buffer.
     96   kj::Array<word> unpackedWords = kj::heapArray<word>(unpackedSizeInWords);
     97   if (unpackedUnaligned.size() != 0u) {
     98     memcpy(unpackedWords.begin(), unpackedUnaligned.begin(), unpackedUnaligned.size());
     99   }
    100   kj::ArrayPtr<const byte> unpacked = unpackedWords.asBytes();
    101 
    102   // -----------------------------------------------------------------
    103   // write
    104 
    105   {
    106     kj::BufferedOutputStreamWrapper bufferedOut(pipe);
    107     PackedOutputStream packedOut(bufferedOut);
    108     packedOut.write(unpacked.begin(), unpacked.size());
    109   }
    110 
    111   if (pipe.getData() != std::string(packed.asChars().begin(), packed.asChars().size())) {
    112     KJ_FAIL_ASSERT("Tried to pack `unpacked`, expected `packed`, got `pipe.getData()`",
    113                    unpacked, packed, pipe.getData());
    114     return;
    115   }
    116 
    117   // -----------------------------------------------------------------
    118   // read
    119 
    120   kj::Array<byte> roundTrip = kj::heapArray<byte>(unpacked.size());
    121 
    122   {
    123     PackedInputStream packedIn(pipe);
    124     packedIn.InputStream::read(roundTrip.begin(), roundTrip.size());
    125     EXPECT_TRUE(pipe.allRead());
    126   }
    127 
    128   if (memcmp(roundTrip.begin(), unpacked.begin(), unpacked.size()) != 0) {
    129     KJ_FAIL_ASSERT("Tried to unpack `packed`, expected `unpacked`, got `roundTrip`",
    130                    packed, unpacked, roundTrip);
    131     return;
    132   }
    133 
    134   for (uint blockSize = 1; blockSize < packed.size(); blockSize <<= 1) {
    135     pipe.resetRead(blockSize);
    136 
    137     {
    138       PackedInputStream packedIn(pipe);
    139       packedIn.InputStream::read(roundTrip.begin(), roundTrip.size());
    140       EXPECT_TRUE(pipe.allRead());
    141     }
    142 
    143     if (memcmp(roundTrip.begin(), unpacked.begin(), unpacked.size()) != 0) {
    144       KJ_FAIL_ASSERT("Tried to unpack `packed`, expected `unpacked`, got `roundTrip`",
    145                      packed, blockSize, unpacked, roundTrip);
    146     }
    147   }
    148 
    149   // -----------------------------------------------------------------
    150   // skip
    151 
    152   pipe.resetRead();
    153 
    154   {
    155     PackedInputStream packedIn(pipe);
    156     packedIn.skip(unpacked.size());
    157     EXPECT_TRUE(pipe.allRead());
    158   }
    159 
    160   for (uint blockSize = 1; blockSize < packed.size(); blockSize <<= 1) {
    161     pipe.resetRead(blockSize);
    162 
    163     {
    164       PackedInputStream packedIn(pipe);
    165       packedIn.skip(unpacked.size());
    166       EXPECT_TRUE(pipe.allRead());
    167     }
    168   }
    169 
    170   pipe.clear();
    171 
    172   // -----------------------------------------------------------------
    173   // write / read multiple
    174 
    175   {
    176     kj::BufferedOutputStreamWrapper bufferedOut(pipe);
    177     PackedOutputStream packedOut(bufferedOut);
    178     for (uint i = 0; i < 5; i++) {
    179       packedOut.write(unpacked.begin(), unpacked.size());
    180     }
    181   }
    182 
    183   for (uint i = 0; i < 5; i++) {
    184     PackedInputStream packedIn(pipe);
    185     packedIn.InputStream::read(&*roundTrip.begin(), roundTrip.size());
    186 
    187     if (memcmp(roundTrip.begin(), unpacked.begin(), unpacked.size()) != 0) {
    188       KJ_FAIL_ASSERT("Tried to unpack `packed`, expected `unpacked`, got `roundTrip`",
    189                      packed, i, unpacked, roundTrip);
    190     }
    191   }
    192 
    193   EXPECT_TRUE(pipe.allRead());
    194 }
    195 
    196 #ifdef __CDT_PARSER__
    197 // CDT doesn't seem to understand these initializer lists.
    198 #define expectPacksTo(...)
    199 #endif
    200 
    201 TEST(Packed, SimplePacking) {
    202   expectPacksTo({}, {});
    203   expectPacksTo({0,0,0,0,0,0,0,0}, {0,0});
    204   expectPacksTo({0,0,12,0,0,34,0,0}, {0x24,12,34});
    205   expectPacksTo({1,3,2,4,5,7,6,8}, {0xff,1,3,2,4,5,7,6,8,0});
    206   expectPacksTo({0,0,0,0,0,0,0,0,1,3,2,4,5,7,6,8}, {0,0,0xff,1,3,2,4,5,7,6,8,0});
    207   expectPacksTo({0,0,12,0,0,34,0,0,1,3,2,4,5,7,6,8}, {0x24,12,34,0xff,1,3,2,4,5,7,6,8,0});
    208   expectPacksTo({1,3,2,4,5,7,6,8,8,6,7,4,5,2,3,1}, {0xff,1,3,2,4,5,7,6,8,1,8,6,7,4,5,2,3,1});
    209 
    210   expectPacksTo(
    211       {1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 0,2,4,0,9,0,5,1},
    212       {0xff,1,2,3,4,5,6,7,8, 3, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 0xd6,2,4,9,5,1});
    213   expectPacksTo(
    214       {1,2,3,4,5,6,7,8, 1,2,3,4,5,6,7,8, 6,2,4,3,9,0,5,1, 1,2,3,4,5,6,7,8, 0,2,4,0,9,0,5,1},
    215       {0xff,1,2,3,4,5,6,7,8, 3, 1,2,3,4,5,6,7,8, 6,2,4,3,9,0,5,1, 1,2,3,4,5,6,7,8, 0xd6,2,4,9,5,1});
    216 
    217   expectPacksTo(
    218       {8,0,100,6,0,1,1,2, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,1,0,2,0,3,1},
    219       {0xed,8,100,6,1,1,2, 0,2, 0xd4,1,2,3,1});
    220 }
    221 
    222 // =======================================================================================
    223 
    224 class TestMessageBuilder: public MallocMessageBuilder {
    225   // A MessageBuilder that tries to allocate an exact number of total segments, by allocating
    226   // minimum-size segments until it reaches the number, then allocating one large segment to
    227   // finish.
    228 
    229 public:
    230   explicit TestMessageBuilder(uint desiredSegmentCount)
    231       : MallocMessageBuilder(0, AllocationStrategy::FIXED_SIZE),
    232         desiredSegmentCount(desiredSegmentCount) {}
    233   ~TestMessageBuilder() {
    234     EXPECT_EQ(0u, desiredSegmentCount);
    235   }
    236 
    237   kj::ArrayPtr<word> allocateSegment(uint minimumSize) override {
    238     if (desiredSegmentCount <= 1) {
    239       if (desiredSegmentCount < 1) {
    240         ADD_FAILURE() << "Allocated more segments than desired.";
    241       } else {
    242         --desiredSegmentCount;
    243       }
    244       return MallocMessageBuilder::allocateSegment(SUGGESTED_FIRST_SEGMENT_WORDS);
    245     } else {
    246       --desiredSegmentCount;
    247       return MallocMessageBuilder::allocateSegment(minimumSize);
    248     }
    249   }
    250 
    251 private:
    252   uint desiredSegmentCount;
    253 };
    254 
    255 TEST(Packed, RoundTrip) {
    256   TestMessageBuilder builder(1);
    257   initTestMessage(builder.initRoot<TestAllTypes>());
    258 
    259   TestPipe pipe;
    260   writePackedMessage(pipe, builder);
    261 
    262   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    263 
    264   PackedMessageReader reader(pipe);
    265   checkTestMessage(reader.getRoot<TestAllTypes>());
    266 }
    267 
    268 TEST(Packed, RoundTripScratchSpace) {
    269   TestMessageBuilder builder(1);
    270   initTestMessage(builder.initRoot<TestAllTypes>());
    271 
    272   TestPipe pipe;
    273   writePackedMessage(pipe, builder);
    274 
    275   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    276 
    277   word scratch[1024];
    278   PackedMessageReader reader(pipe, ReaderOptions(), kj::ArrayPtr<word>(scratch, 1024));
    279   checkTestMessage(reader.getRoot<TestAllTypes>());
    280 }
    281 
    282 TEST(Packed, RoundTripLazy) {
    283   TestMessageBuilder builder(1);
    284   initTestMessage(builder.initRoot<TestAllTypes>());
    285 
    286   TestPipe pipe(1);
    287   writePackedMessage(pipe, builder);
    288 
    289   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    290 
    291   PackedMessageReader reader(pipe);
    292   checkTestMessage(reader.getRoot<TestAllTypes>());
    293 }
    294 
    295 TEST(Packed, RoundTripOddSegmentCount) {
    296   TestMessageBuilder builder(7);
    297   initTestMessage(builder.initRoot<TestAllTypes>());
    298 
    299   TestPipe pipe;
    300   writePackedMessage(pipe, builder);
    301 
    302   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    303 
    304   PackedMessageReader reader(pipe);
    305   checkTestMessage(reader.getRoot<TestAllTypes>());
    306 }
    307 
    308 TEST(Packed, RoundTripOddSegmentCountLazy) {
    309   TestMessageBuilder builder(7);
    310   initTestMessage(builder.initRoot<TestAllTypes>());
    311 
    312   TestPipe pipe(1);
    313   writePackedMessage(pipe, builder);
    314 
    315   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    316 
    317   PackedMessageReader reader(pipe);
    318   checkTestMessage(reader.getRoot<TestAllTypes>());
    319 }
    320 
    321 TEST(Packed, RoundTripEvenSegmentCount) {
    322   TestMessageBuilder builder(10);
    323   initTestMessage(builder.initRoot<TestAllTypes>());
    324 
    325   TestPipe pipe;
    326   writePackedMessage(pipe, builder);
    327 
    328   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    329 
    330   PackedMessageReader reader(pipe);
    331   checkTestMessage(reader.getRoot<TestAllTypes>());
    332 }
    333 
    334 TEST(Packed, RoundTripEvenSegmentCountLazy) {
    335   TestMessageBuilder builder(10);
    336   initTestMessage(builder.initRoot<TestAllTypes>());
    337 
    338   TestPipe pipe(1);
    339   writePackedMessage(pipe, builder);
    340 
    341   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    342 
    343   PackedMessageReader reader(pipe);
    344   checkTestMessage(reader.getRoot<TestAllTypes>());
    345 }
    346 
    347 TEST(Packed, RoundTripTwoMessages) {
    348   TestMessageBuilder builder(1);
    349   initTestMessage(builder.initRoot<TestAllTypes>());
    350 
    351   TestMessageBuilder builder2(1);
    352   builder2.initRoot<TestAllTypes>().setTextField("Second message.");
    353 
    354   TestPipe pipe;
    355   writePackedMessage(pipe, builder);
    356   writePackedMessage(pipe, builder2);
    357 
    358   EXPECT_EQ(computeSerializedSizeInWords(builder) + computeSerializedSizeInWords(builder2),
    359             computeUnpackedSizeInWords(pipe.getArray()));
    360 
    361   {
    362     PackedMessageReader reader(pipe);
    363     checkTestMessage(reader.getRoot<TestAllTypes>());
    364   }
    365 
    366   {
    367     PackedMessageReader reader(pipe);
    368     EXPECT_EQ("Second message.", reader.getRoot<TestAllTypes>().getTextField());
    369   }
    370 }
    371 
    372 // =======================================================================================
    373 
    374 TEST(Packed, RoundTripAllZero) {
    375   TestMessageBuilder builder(1);
    376   builder.initRoot<TestAllTypes>();
    377 
    378   TestPipe pipe;
    379   writePackedMessage(pipe, builder);
    380 
    381   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    382 
    383   PackedMessageReader reader(pipe);
    384   checkTestMessageAllZero(reader.getRoot<TestAllTypes>());
    385 
    386   // Segment table packs to 2 bytes.
    387   // Root pointer packs to 3 bytes.
    388   // Content packs to 2 bytes (zero span).
    389   EXPECT_LE(pipe.getData().size(), 7u);
    390 }
    391 
    392 TEST(Packed, RoundTripAllZeroScratchSpace) {
    393   TestMessageBuilder builder(1);
    394   builder.initRoot<TestAllTypes>();
    395 
    396   TestPipe pipe;
    397   writePackedMessage(pipe, builder);
    398 
    399   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    400 
    401   word scratch[1024];
    402   PackedMessageReader reader(pipe, ReaderOptions(), kj::ArrayPtr<word>(scratch, 1024));
    403   checkTestMessageAllZero(reader.getRoot<TestAllTypes>());
    404 }
    405 
    406 TEST(Packed, RoundTripAllZeroLazy) {
    407   TestMessageBuilder builder(1);
    408   builder.initRoot<TestAllTypes>();
    409 
    410   TestPipe pipe(1);
    411   writePackedMessage(pipe, builder);
    412 
    413   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    414 
    415   PackedMessageReader reader(pipe);
    416   checkTestMessageAllZero(reader.getRoot<TestAllTypes>());
    417 }
    418 
    419 TEST(Packed, RoundTripAllZeroOddSegmentCount) {
    420   TestMessageBuilder builder(3);
    421   builder.initRoot<TestAllTypes>().initStructField().initStructField();
    422 
    423   TestPipe pipe;
    424   writePackedMessage(pipe, builder);
    425 
    426   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    427 
    428   PackedMessageReader reader(pipe);
    429   checkTestMessageAllZero(reader.getRoot<TestAllTypes>());
    430 }
    431 
    432 TEST(Packed, RoundTripAllZeroOddSegmentCountLazy) {
    433   TestMessageBuilder builder(3);
    434   builder.initRoot<TestAllTypes>().initStructField().initStructField();
    435 
    436   TestPipe pipe(1);
    437   writePackedMessage(pipe, builder);
    438 
    439   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    440 
    441   PackedMessageReader reader(pipe);
    442   checkTestMessageAllZero(reader.getRoot<TestAllTypes>());
    443 }
    444 
    445 TEST(Packed, RoundTripAllZeroEvenSegmentCount) {
    446   TestMessageBuilder builder(2);
    447   builder.initRoot<TestAllTypes>().initStructField().initStructField();
    448 
    449   TestPipe pipe;
    450   writePackedMessage(pipe, builder);
    451 
    452   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    453 
    454   PackedMessageReader reader(pipe);
    455   checkTestMessageAllZero(reader.getRoot<TestAllTypes>());
    456 }
    457 
    458 TEST(Packed, RoundTripAllZeroEvenSegmentCountLazy) {
    459   TestMessageBuilder builder(2);
    460   builder.initRoot<TestAllTypes>().initStructField().initStructField();
    461 
    462   TestPipe pipe(1);
    463   writePackedMessage(pipe, builder);
    464 
    465   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    466 
    467   PackedMessageReader reader(pipe);
    468   checkTestMessageAllZero(reader.getRoot<TestAllTypes>());
    469 }
    470 
    471 // =======================================================================================
    472 
    473 TEST(Packed, RoundTripHugeString) {
    474   kj::String huge = kj::heapString(5023);
    475   memset(huge.begin(), 'x', 5023);
    476 
    477   TestMessageBuilder builder(1);
    478   builder.initRoot<TestAllTypes>().setTextField(huge);
    479 
    480   TestPipe pipe;
    481   writePackedMessage(pipe, builder);
    482 
    483   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    484 
    485   PackedMessageReader reader(pipe);
    486   EXPECT_TRUE(reader.getRoot<TestAllTypes>().getTextField() == huge);
    487 }
    488 
    489 TEST(Packed, RoundTripHugeStringScratchSpace) {
    490   kj::String huge = kj::heapString(5023);
    491   memset(huge.begin(), 'x', 5023);
    492 
    493   TestMessageBuilder builder(1);
    494   builder.initRoot<TestAllTypes>().setTextField(huge);
    495 
    496   TestPipe pipe;
    497   writePackedMessage(pipe, builder);
    498 
    499   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    500 
    501   word scratch[1024];
    502   PackedMessageReader reader(pipe, ReaderOptions(), kj::ArrayPtr<word>(scratch, 1024));
    503   EXPECT_TRUE(reader.getRoot<TestAllTypes>().getTextField() == huge);
    504 }
    505 
    506 TEST(Packed, RoundTripHugeStringLazy) {
    507   kj::String huge = kj::heapString(5023);
    508   memset(huge.begin(), 'x', 5023);
    509 
    510   TestMessageBuilder builder(1);
    511   builder.initRoot<TestAllTypes>().setTextField(huge);
    512 
    513   TestPipe pipe(1);
    514   writePackedMessage(pipe, builder);
    515 
    516   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    517 
    518   PackedMessageReader reader(pipe);
    519   EXPECT_TRUE(reader.getRoot<TestAllTypes>().getTextField() == huge);
    520 }
    521 
    522 TEST(Packed, RoundTripHugeStringOddSegmentCount) {
    523   kj::String huge = kj::heapString(5023);
    524   memset(huge.begin(), 'x', 5023);
    525 
    526   TestMessageBuilder builder(3);
    527   builder.initRoot<TestAllTypes>().setTextField(huge);
    528 
    529   TestPipe pipe;
    530   writePackedMessage(pipe, builder);
    531 
    532   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    533 
    534   PackedMessageReader reader(pipe);
    535   EXPECT_TRUE(reader.getRoot<TestAllTypes>().getTextField() == huge);
    536 }
    537 
    538 TEST(Packed, RoundTripHugeStringOddSegmentCountLazy) {
    539   kj::String huge = kj::heapString(5023);
    540   memset(huge.begin(), 'x', 5023);
    541 
    542   TestMessageBuilder builder(3);
    543   builder.initRoot<TestAllTypes>().setTextField(huge);
    544 
    545   TestPipe pipe(1);
    546   writePackedMessage(pipe, builder);
    547 
    548   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    549 
    550   PackedMessageReader reader(pipe);
    551   EXPECT_TRUE(reader.getRoot<TestAllTypes>().getTextField() == huge);
    552 }
    553 
    554 TEST(Packed, RoundTripHugeStringEvenSegmentCount) {
    555   kj::String huge = kj::heapString(5023);
    556   memset(huge.begin(), 'x', 5023);
    557 
    558   TestMessageBuilder builder(2);
    559   builder.initRoot<TestAllTypes>().setTextField(huge);
    560 
    561   TestPipe pipe;
    562   writePackedMessage(pipe, builder);
    563 
    564   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    565 
    566   PackedMessageReader reader(pipe);
    567   EXPECT_TRUE(reader.getRoot<TestAllTypes>().getTextField() == huge);
    568 }
    569 
    570 TEST(Packed, RoundTripHugeStringEvenSegmentCountLazy) {
    571   kj::String huge = kj::heapString(5023);
    572   memset(huge.begin(), 'x', 5023);
    573 
    574   TestMessageBuilder builder(2);
    575   builder.initRoot<TestAllTypes>().setTextField(huge);
    576 
    577   TestPipe pipe(1);
    578   writePackedMessage(pipe, builder);
    579 
    580   EXPECT_EQ(computeSerializedSizeInWords(builder), computeUnpackedSizeInWords(pipe.getArray()));
    581 
    582   PackedMessageReader reader(pipe);
    583   EXPECT_TRUE(reader.getRoot<TestAllTypes>().getTextField() == huge);
    584 }
    585 
    586 // TODO(test):  Test error cases.
    587 
    588 }  // namespace
    589 }  // namespace _ (private)
    590 }  // namespace capnp