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

layout-test.c++ (17923B)


      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 #define CAPNP_PRIVATE
     23 #include "layout.h"
     24 #include "message.h"
     25 #include "arena.h"
     26 #include <kj/compat/gtest.h>
     27 
     28 #if CAPNP_DEBUG_TYPES
     29 namespace kj {
     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   // Hack: Allow direct comparisons and multiplications so that we don't have to rewrite the code
     36   //   below.
     37   template <uint64_t maxN, typename T>
     38   inline constexpr Bounded<65535, T> operator*(uint a, Bounded<maxN, T> b) {
     39     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);
     44   }
     45 }
     46 #endif
     47 
     48 namespace capnp {
     49 namespace _ {  // private
     50 namespace {
     51 
     52 TEST(WireFormat, SimpleRawDataStruct) {
     53   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.
     57     0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
     58   }};
     59 
     60   StructReader reader = PointerReader::getRootUnchecked(data.words).getStruct(nullptr);
     61 
     62   EXPECT_EQ(0xefcdab8967452301ull, reader.getDataField<uint64_t>(0 * ELEMENTS));
     63   EXPECT_EQ(0u, reader.getDataField<uint64_t>(1 * ELEMENTS));
     64   EXPECT_EQ(0x67452301u, reader.getDataField<uint32_t>(0 * ELEMENTS));
     65   EXPECT_EQ(0xefcdab89u, reader.getDataField<uint32_t>(1 * ELEMENTS));
     66   EXPECT_EQ(0u, reader.getDataField<uint32_t>(2 * ELEMENTS));
     67   EXPECT_EQ(0x2301u, reader.getDataField<uint16_t>(0 * ELEMENTS));
     68   EXPECT_EQ(0x6745u, reader.getDataField<uint16_t>(1 * ELEMENTS));
     69   EXPECT_EQ(0xab89u, reader.getDataField<uint16_t>(2 * ELEMENTS));
     70   EXPECT_EQ(0xefcdu, reader.getDataField<uint16_t>(3 * ELEMENTS));
     71   EXPECT_EQ(0u, reader.getDataField<uint16_t>(4 * ELEMENTS));
     72 
     73   EXPECT_EQ(321u ^ 0xefcdab8967452301ull, reader.getDataField<uint64_t>(0 * ELEMENTS, 321u));
     74   EXPECT_EQ(321u ^ 0x67452301u, reader.getDataField<uint32_t>(0 * ELEMENTS, 321u));
     75   EXPECT_EQ(321u ^ 0x2301u, reader.getDataField<uint16_t>(0 * ELEMENTS, 321u));
     76   EXPECT_EQ(321u, reader.getDataField<uint64_t>(1 * ELEMENTS, 321u));
     77   EXPECT_EQ(321u, reader.getDataField<uint32_t>(2 * ELEMENTS, 321u));
     78   EXPECT_EQ(321u, reader.getDataField<uint16_t>(4 * ELEMENTS, 321u));
     79 
     80   // Bits
     81   EXPECT_TRUE (reader.getDataField<bool>(0 * ELEMENTS));
     82   EXPECT_FALSE(reader.getDataField<bool>(1 * ELEMENTS));
     83   EXPECT_FALSE(reader.getDataField<bool>(2 * ELEMENTS));
     84   EXPECT_FALSE(reader.getDataField<bool>(3 * ELEMENTS));
     85   EXPECT_FALSE(reader.getDataField<bool>(4 * ELEMENTS));
     86   EXPECT_FALSE(reader.getDataField<bool>(5 * ELEMENTS));
     87   EXPECT_FALSE(reader.getDataField<bool>(6 * ELEMENTS));
     88   EXPECT_FALSE(reader.getDataField<bool>(7 * ELEMENTS));
     89 
     90   EXPECT_TRUE (reader.getDataField<bool>( 8 * ELEMENTS));
     91   EXPECT_TRUE (reader.getDataField<bool>( 9 * ELEMENTS));
     92   EXPECT_FALSE(reader.getDataField<bool>(10 * ELEMENTS));
     93   EXPECT_FALSE(reader.getDataField<bool>(11 * ELEMENTS));
     94   EXPECT_FALSE(reader.getDataField<bool>(12 * ELEMENTS));
     95   EXPECT_TRUE (reader.getDataField<bool>(13 * ELEMENTS));
     96   EXPECT_FALSE(reader.getDataField<bool>(14 * ELEMENTS));
     97   EXPECT_FALSE(reader.getDataField<bool>(15 * ELEMENTS));
     98 
     99   EXPECT_TRUE (reader.getDataField<bool>(63 * ELEMENTS));
    100   EXPECT_FALSE(reader.getDataField<bool>(64 * ELEMENTS));
    101 
    102   EXPECT_TRUE (reader.getDataField<bool>(0 * ELEMENTS, false));
    103   EXPECT_FALSE(reader.getDataField<bool>(1 * ELEMENTS, false));
    104   EXPECT_TRUE (reader.getDataField<bool>(63 * ELEMENTS, false));
    105   EXPECT_FALSE(reader.getDataField<bool>(64 * ELEMENTS, false));
    106   EXPECT_FALSE(reader.getDataField<bool>(0 * ELEMENTS, true));
    107   EXPECT_TRUE (reader.getDataField<bool>(1 * ELEMENTS, true));
    108   EXPECT_FALSE(reader.getDataField<bool>(63 * ELEMENTS, true));
    109   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 
    118 static void setupStruct(StructBuilder builder) {
    119   builder.setDataField<uint64_t>(0 * ELEMENTS, 0x1011121314151617ull);
    120   builder.setDataField<uint32_t>(2 * ELEMENTS, 0x20212223u);
    121   builder.setDataField<uint16_t>(6 * ELEMENTS, 0x3031u);
    122   builder.setDataField<uint8_t>(14 * ELEMENTS, 0x40u);
    123   builder.setDataField<bool>(120 * ELEMENTS, false);
    124   builder.setDataField<bool>(121 * ELEMENTS, false);
    125   builder.setDataField<bool>(122 * ELEMENTS, true);
    126   builder.setDataField<bool>(123 * ELEMENTS, false);
    127   builder.setDataField<bool>(124 * ELEMENTS, true);
    128   builder.setDataField<bool>(125 * ELEMENTS, true);
    129   builder.setDataField<bool>(126 * ELEMENTS, true);
    130   builder.setDataField<bool>(127 * ELEMENTS, false);
    131 
    132   {
    133     StructBuilder subStruct = builder.getPointerField(0 * POINTERS).initStruct(
    134         StructSize(1 * WORDS, 0 * POINTERS));
    135     subStruct.setDataField<uint32_t>(0 * ELEMENTS, 123);
    136   }
    137 
    138   {
    139     ListBuilder list = builder.getPointerField(1 * POINTERS)
    140         .initList(ElementSize::FOUR_BYTES, 3 * ELEMENTS);
    141     EXPECT_EQ(3 * ELEMENTS, list.size());
    142     list.setDataElement<int32_t>(0 * ELEMENTS, 200);
    143     list.setDataElement<int32_t>(1 * ELEMENTS, 201);
    144     list.setDataElement<int32_t>(2 * ELEMENTS, 202);
    145   }
    146 
    147   {
    148     ListBuilder list = builder.getPointerField(2 * POINTERS).initStructList(
    149         4 * ELEMENTS, STRUCTLIST_ELEMENT_SIZE);
    150     EXPECT_EQ(4 * ELEMENTS, list.size());
    151     for (int i = 0; i < 4; i++) {
    152       StructBuilder element = list.getStructElement(i * ELEMENTS);
    153       element.setDataField<int32_t>(0 * ELEMENTS, 300 + i);
    154       element.getPointerField(0 * POINTERS)
    155              .initStruct(StructSize(1 * WORDS, 0 * POINTERS))
    156              .setDataField<int32_t>(0 * ELEMENTS, 400 + i);
    157     }
    158   }
    159 
    160   {
    161     ListBuilder list = builder.getPointerField(3 * POINTERS)
    162                               .initList(ElementSize::POINTER, 5 * ELEMENTS);
    163     EXPECT_EQ(5 * ELEMENTS, list.size());
    164     for (uint i = 0; i < 5; i++) {
    165       ListBuilder element = list.getPointerElement(i * ELEMENTS)
    166                                 .initList(ElementSize::TWO_BYTES, (i + 1) * ELEMENTS);
    167       EXPECT_EQ((i + 1) * ELEMENTS, element.size());
    168       for (uint j = 0; j <= i; j++) {
    169         element.setDataElement<uint16_t>(j * ELEMENTS, 500 + j);
    170       }
    171     }
    172   }
    173 }
    174 
    175 static void checkStruct(StructBuilder builder) {
    176   EXPECT_EQ(0x1011121314151617ull, builder.getDataField<uint64_t>(0 * ELEMENTS));
    177   EXPECT_EQ(0x20212223u, builder.getDataField<uint32_t>(2 * ELEMENTS));
    178   EXPECT_EQ(0x3031u, builder.getDataField<uint16_t>(6 * ELEMENTS));
    179   EXPECT_EQ(0x40u, builder.getDataField<uint8_t>(14 * ELEMENTS));
    180   EXPECT_FALSE(builder.getDataField<bool>(120 * ELEMENTS));
    181   EXPECT_FALSE(builder.getDataField<bool>(121 * ELEMENTS));
    182   EXPECT_TRUE (builder.getDataField<bool>(122 * ELEMENTS));
    183   EXPECT_FALSE(builder.getDataField<bool>(123 * ELEMENTS));
    184   EXPECT_TRUE (builder.getDataField<bool>(124 * ELEMENTS));
    185   EXPECT_TRUE (builder.getDataField<bool>(125 * ELEMENTS));
    186   EXPECT_TRUE (builder.getDataField<bool>(126 * ELEMENTS));
    187   EXPECT_FALSE(builder.getDataField<bool>(127 * ELEMENTS));
    188 
    189   {
    190     StructBuilder subStruct = builder.getPointerField(0 * POINTERS).getStruct(
    191         StructSize(1 * WORDS, 0 * POINTERS), SUBSTRUCT_DEFAULT.words);
    192     EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS));
    193   }
    194 
    195   {
    196     ListBuilder list = builder.getPointerField(1 * POINTERS)
    197                               .getList(ElementSize::FOUR_BYTES, nullptr);
    198     ASSERT_EQ(3 * ELEMENTS, list.size());
    199     EXPECT_EQ(200, list.getDataElement<int32_t>(0 * ELEMENTS));
    200     EXPECT_EQ(201, list.getDataElement<int32_t>(1 * ELEMENTS));
    201     EXPECT_EQ(202, list.getDataElement<int32_t>(2 * ELEMENTS));
    202   }
    203 
    204   {
    205     ListBuilder list = builder.getPointerField(2 * POINTERS)
    206                               .getStructList(STRUCTLIST_ELEMENT_SIZE, nullptr);
    207     ASSERT_EQ(4 * ELEMENTS, list.size());
    208     for (int i = 0; i < 4; i++) {
    209       StructBuilder element = list.getStructElement(i * ELEMENTS);
    210       EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS));
    211       EXPECT_EQ(400 + i,
    212           element.getPointerField(0 * POINTERS)
    213                  .getStruct(StructSize(1 * WORDS, 0 * POINTERS),
    214                             STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
    215                  .getDataField<int32_t>(0 * ELEMENTS));
    216     }
    217   }
    218 
    219   {
    220     ListBuilder list = builder.getPointerField(3 * POINTERS).getList(ElementSize::POINTER, nullptr);
    221     ASSERT_EQ(5 * ELEMENTS, list.size());
    222     for (uint i = 0; i < 5; i++) {
    223       ListBuilder element = list.getPointerElement(i * ELEMENTS)
    224                                 .getList(ElementSize::TWO_BYTES, nullptr);
    225       ASSERT_EQ((i + 1) * ELEMENTS, element.size());
    226       for (uint j = 0; j <= i; j++) {
    227         EXPECT_EQ(500u + j, element.getDataElement<uint16_t>(j * ELEMENTS));
    228       }
    229     }
    230   }
    231 }
    232 
    233 static void checkStruct(StructReader reader) {
    234   EXPECT_EQ(0x1011121314151617ull, reader.getDataField<uint64_t>(0 * ELEMENTS));
    235   EXPECT_EQ(0x20212223u, reader.getDataField<uint32_t>(2 * ELEMENTS));
    236   EXPECT_EQ(0x3031u, reader.getDataField<uint16_t>(6 * ELEMENTS));
    237   EXPECT_EQ(0x40u, reader.getDataField<uint8_t>(14 * ELEMENTS));
    238   EXPECT_FALSE(reader.getDataField<bool>(120 * ELEMENTS));
    239   EXPECT_FALSE(reader.getDataField<bool>(121 * ELEMENTS));
    240   EXPECT_TRUE (reader.getDataField<bool>(122 * ELEMENTS));
    241   EXPECT_FALSE(reader.getDataField<bool>(123 * ELEMENTS));
    242   EXPECT_TRUE (reader.getDataField<bool>(124 * ELEMENTS));
    243   EXPECT_TRUE (reader.getDataField<bool>(125 * ELEMENTS));
    244   EXPECT_TRUE (reader.getDataField<bool>(126 * ELEMENTS));
    245   EXPECT_FALSE(reader.getDataField<bool>(127 * ELEMENTS));
    246 
    247   {
    248     StructReader subStruct = reader.getPointerField(0 * POINTERS)
    249                                    .getStruct(SUBSTRUCT_DEFAULT.words);
    250     EXPECT_EQ(123u, subStruct.getDataField<uint32_t>(0 * ELEMENTS));
    251   }
    252 
    253   {
    254     ListReader list = reader.getPointerField(1 * POINTERS).getList(ElementSize::FOUR_BYTES, nullptr);
    255     ASSERT_EQ(3 * ELEMENTS, list.size());
    256     EXPECT_EQ(200, list.getDataElement<int32_t>(0 * ELEMENTS));
    257     EXPECT_EQ(201, list.getDataElement<int32_t>(1 * ELEMENTS));
    258     EXPECT_EQ(202, list.getDataElement<int32_t>(2 * ELEMENTS));
    259   }
    260 
    261   {
    262     ListReader list = reader.getPointerField(2 * POINTERS)
    263                             .getList(ElementSize::INLINE_COMPOSITE, nullptr);
    264     ASSERT_EQ(4 * ELEMENTS, list.size());
    265     for (int i = 0; i < 4; i++) {
    266       StructReader element = list.getStructElement(i * ELEMENTS);
    267       EXPECT_EQ(300 + i, element.getDataField<int32_t>(0 * ELEMENTS));
    268       EXPECT_EQ(400 + i,
    269           element.getPointerField(0 * POINTERS)
    270                  .getStruct(STRUCTLIST_ELEMENT_SUBSTRUCT_DEFAULT.words)
    271                  .getDataField<int32_t>(0 * ELEMENTS));
    272     }
    273   }
    274 
    275   {
    276     ListReader list = reader.getPointerField(3 * POINTERS).getList(ElementSize::POINTER, nullptr);
    277     ASSERT_EQ(5 * ELEMENTS, list.size());
    278     for (uint i = 0; i < 5; i++) {
    279       ListReader element = list.getPointerElement(i * ELEMENTS)
    280                                .getList(ElementSize::TWO_BYTES, nullptr);
    281       ASSERT_EQ((i + 1) * ELEMENTS, element.size());
    282       for (uint j = 0; j <= i; j++) {
    283         EXPECT_EQ(500u + j, element.getDataElement<uint16_t>(j * ELEMENTS));
    284       }
    285     }
    286   }
    287 }
    288 
    289 TEST(WireFormat, StructRoundTrip_OneSegment) {
    290   MallocMessageBuilder message;
    291   BuilderArena arena(&message);
    292   auto allocation = arena.allocate(1 * WORDS);
    293   SegmentBuilder* segment = allocation.segment;
    294   word* rootLocation = allocation.words;
    295 
    296   StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation)
    297       .initStruct(StructSize(2 * WORDS, 4 * POINTERS));
    298   setupStruct(builder);
    299 
    300   // word count:
    301   //    1  root pointer
    302   //    6  root struct
    303   //    1  sub message
    304   //    2  3-element int32 list
    305   //   13  struct list
    306   //         1 tag
    307   //        12 4x struct
    308   //           1 data section
    309   //           1 pointer section
    310   //           1 sub-struct
    311   //   11  list list
    312   //         5 pointers to sub-lists
    313   //         6 sub-lists (4x 1 word, 1x 2 words)
    314   // -----
    315   //   34
    316   kj::ArrayPtr<const kj::ArrayPtr<const word>> segments = arena.getSegmentsForOutput();
    317   ASSERT_EQ(1u, segments.size());
    318   EXPECT_EQ(34u, segments[0].size());
    319 
    320   checkStruct(builder);
    321   checkStruct(builder.asReader());
    322   checkStruct(PointerReader::getRootUnchecked(segment->getStartPtr()).getStruct(nullptr));
    323   checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4)
    324       .getStruct(nullptr));
    325 }
    326 
    327 TEST(WireFormat, StructRoundTrip_OneSegmentPerAllocation) {
    328   MallocMessageBuilder message(0, AllocationStrategy::FIXED_SIZE);
    329   BuilderArena arena(&message);
    330   auto allocation = arena.allocate(1 * WORDS);
    331   SegmentBuilder* segment = allocation.segment;
    332   word* rootLocation = allocation.words;
    333 
    334   StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation)
    335       .initStruct(StructSize(2 * WORDS, 4 * POINTERS));
    336   setupStruct(builder);
    337 
    338   // Verify that we made 15 segments.
    339   kj::ArrayPtr<const kj::ArrayPtr<const word>> segments = arena.getSegmentsForOutput();
    340   ASSERT_EQ(15u, segments.size());
    341 
    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   EXPECT_EQ( 1u, segments[ 0].size());  // root ref
    345   EXPECT_EQ( 7u, segments[ 1].size());  // root struct
    346   EXPECT_EQ( 2u, segments[ 2].size());  // sub-struct
    347   EXPECT_EQ( 3u, segments[ 3].size());  // 3-element int32 list
    348   EXPECT_EQ(10u, segments[ 4].size());  // struct list
    349   EXPECT_EQ( 2u, segments[ 5].size());  // struct list substruct 1
    350   EXPECT_EQ( 2u, segments[ 6].size());  // struct list substruct 2
    351   EXPECT_EQ( 2u, segments[ 7].size());  // struct list substruct 3
    352   EXPECT_EQ( 2u, segments[ 8].size());  // struct list substruct 4
    353   EXPECT_EQ( 6u, segments[ 9].size());  // list list
    354   EXPECT_EQ( 2u, segments[10].size());  // list list sublist 1
    355   EXPECT_EQ( 2u, segments[11].size());  // list list sublist 2
    356   EXPECT_EQ( 2u, segments[12].size());  // list list sublist 3
    357   EXPECT_EQ( 2u, segments[13].size());  // list list sublist 4
    358   EXPECT_EQ( 3u, segments[14].size());  // list list sublist 5
    359 
    360   checkStruct(builder);
    361   checkStruct(builder.asReader());
    362   checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4)
    363       .getStruct(nullptr));
    364 }
    365 
    366 TEST(WireFormat, StructRoundTrip_MultipleSegmentsWithMultipleAllocations) {
    367   MallocMessageBuilder message(8, AllocationStrategy::FIXED_SIZE);
    368   BuilderArena arena(&message);
    369   auto allocation = arena.allocate(1 * WORDS);
    370   SegmentBuilder* segment = allocation.segment;
    371   word* rootLocation = allocation.words;
    372 
    373   StructBuilder builder = PointerBuilder::getRoot(segment, nullptr, rootLocation)
    374       .initStruct(StructSize(2 * WORDS, 4 * POINTERS));
    375   setupStruct(builder);
    376 
    377   // 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   // Check that each segment has the expected size.  Recall that each object will be prefixed by an
    382   // extra word if its parent is in a different segment.
    383   EXPECT_EQ( 8u, segments[0].size());  // root ref + struct + sub
    384   EXPECT_EQ( 3u, segments[1].size());  // 3-element int32 list
    385   EXPECT_EQ(10u, segments[2].size());  // struct list
    386   EXPECT_EQ( 8u, segments[3].size());  // struct list substructs
    387   EXPECT_EQ( 8u, segments[4].size());  // list list + sublist 1,2
    388   EXPECT_EQ( 7u, segments[5].size());  // list list sublist 3,4,5
    389 
    390   checkStruct(builder);
    391   checkStruct(builder.asReader());
    392   checkStruct(PointerReader::getRoot(segment, nullptr, segment->getStartPtr(), 4)
    393       .getStruct(nullptr));
    394 }
    395 
    396 inline bool isNan(float f) { return f != f; }
    397 inline bool isNan(double f) { return f != f; }
    398 
    399 TEST(WireFormat, NanPatching) {
    400   EXPECT_EQ(0x7fc00000u, mask(kj::nan(), 0));
    401   EXPECT_TRUE(isNan(unmask<float>(0x7fc00000u, 0)));
    402   EXPECT_TRUE(isNan(unmask<float>(0x7fc00001u, 0)));
    403   EXPECT_TRUE(isNan(unmask<float>(0x7fc00005u, 0)));
    404   EXPECT_EQ(0x7fc00000u, mask(unmask<float>(0x7fc00000u, 0), 0));
    405   EXPECT_EQ(0x7ff8000000000000ull, mask((double)kj::nan(), 0));
    406   EXPECT_TRUE(isNan(unmask<double>(0x7ff8000000000000ull, 0)));
    407   EXPECT_TRUE(isNan(unmask<double>(0x7ff8000000000001ull, 0)));
    408   EXPECT_TRUE(isNan(unmask<double>(0x7ff8000000000005ull, 0)));
    409   EXPECT_EQ(0x7ff8000000000000ull, mask(unmask<double>(0x7ff8000000000000ull, 0), 0));
    410 }
    411 
    412 }  // namespace
    413 }  // namespace _ (private)
    414 }  // namespace capnp