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

any-test.c++ (15827B)


      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 "any.h"
     23 #include "message.h"
     24 #include <kj/compat/gtest.h>
     25 #include "test-util.h"
     26 
     27 namespace capnp {
     28 namespace _ {  // private
     29 namespace {
     30 
     31 TEST(Any, AnyPointer) {
     32   MallocMessageBuilder builder;
     33   auto root = builder.getRoot<test::TestAnyPointer>();
     34 
     35   initTestMessage(root.getAnyPointerField().initAs<TestAllTypes>());
     36   checkTestMessage(root.getAnyPointerField().getAs<TestAllTypes>());
     37   checkTestMessage(root.asReader().getAnyPointerField().getAs<TestAllTypes>());
     38 
     39   root.getAnyPointerField().setAs<Text>("foo");
     40   EXPECT_EQ("foo", root.getAnyPointerField().getAs<Text>());
     41   EXPECT_EQ("foo", root.asReader().getAnyPointerField().getAs<Text>());
     42 
     43   root.getAnyPointerField().setAs<Data>(data("foo"));
     44   EXPECT_EQ(data("foo"), root.getAnyPointerField().getAs<Data>());
     45   EXPECT_EQ(data("foo"), root.asReader().getAnyPointerField().getAs<Data>());
     46 
     47   {
     48     root.getAnyPointerField().setAs<List<uint32_t>>({123, 456, 789});
     49 
     50     {
     51       List<uint32_t>::Builder list = root.getAnyPointerField().getAs<List<uint32_t>>();
     52       ASSERT_EQ(3u, list.size());
     53       EXPECT_EQ(123u, list[0]);
     54       EXPECT_EQ(456u, list[1]);
     55       EXPECT_EQ(789u, list[2]);
     56     }
     57 
     58     {
     59       List<uint32_t>::Reader list = root.asReader().getAnyPointerField().getAs<List<uint32_t>>();
     60       ASSERT_EQ(3u, list.size());
     61       EXPECT_EQ(123u, list[0]);
     62       EXPECT_EQ(456u, list[1]);
     63       EXPECT_EQ(789u, list[2]);
     64     }
     65   }
     66 
     67   {
     68     root.getAnyPointerField().setAs<List<Text>>({"foo", "bar"});
     69 
     70     {
     71       List<Text>::Builder list = root.getAnyPointerField().getAs<List<Text>>();
     72       ASSERT_EQ(2u, list.size());
     73       EXPECT_EQ("foo", list[0]);
     74       EXPECT_EQ("bar", list[1]);
     75     }
     76 
     77     {
     78       List<Text>::Reader list = root.asReader().getAnyPointerField().getAs<List<Text>>();
     79       ASSERT_EQ(2u, list.size());
     80       EXPECT_EQ("foo", list[0]);
     81       EXPECT_EQ("bar", list[1]);
     82     }
     83   }
     84 
     85   {
     86     {
     87       List<TestAllTypes>::Builder list = root.getAnyPointerField().initAs<List<TestAllTypes>>(2);
     88       ASSERT_EQ(2u, list.size());
     89       initTestMessage(list[0]);
     90     }
     91 
     92     {
     93       List<TestAllTypes>::Builder list = root.getAnyPointerField().getAs<List<TestAllTypes>>();
     94       ASSERT_EQ(2u, list.size());
     95       checkTestMessage(list[0]);
     96       checkTestMessageAllZero(list[1]);
     97     }
     98 
     99     {
    100       List<TestAllTypes>::Reader list =
    101           root.asReader().getAnyPointerField().getAs<List<TestAllTypes>>();
    102       ASSERT_EQ(2u, list.size());
    103       checkTestMessage(list[0]);
    104       checkTestMessageAllZero(list[1]);
    105     }
    106   }
    107 }
    108 
    109 TEST(Any, AnyStruct) {
    110   MallocMessageBuilder builder;
    111   auto root = builder.getRoot<test::TestAnyPointer>();
    112 
    113   initTestMessage(root.getAnyPointerField().initAs<TestAllTypes>());
    114   checkTestMessage(root.getAnyPointerField().getAs<TestAllTypes>());
    115   checkTestMessage(root.asReader().getAnyPointerField().getAs<TestAllTypes>());
    116 
    117   auto allTypes = root.getAnyPointerField().getAs<AnyStruct>().as<TestAllTypes>();
    118   auto allTypesReader = root.getAnyPointerField().getAs<AnyStruct>().asReader().as<TestAllTypes>();
    119   allTypes.setInt32Field(100);
    120   EXPECT_EQ(100, allTypes.getInt32Field());
    121   EXPECT_EQ(100, allTypesReader.getInt32Field());
    122 
    123   EXPECT_EQ(48, root.getAnyPointerField().getAs<AnyStruct>().getDataSection().size());
    124   EXPECT_EQ(20, root.getAnyPointerField().getAs<AnyStruct>().getPointerSection().size());
    125 
    126   EXPECT_EQ(48, root.getAnyPointerField().asReader().getAs<AnyStruct>().getDataSection().size());
    127   EXPECT_EQ(20, root.getAnyPointerField().asReader().getAs<AnyStruct>().getPointerSection().size());
    128 
    129   auto b = toAny(root.getAnyPointerField().getAs<TestAllTypes>());
    130   EXPECT_EQ(48, b.getDataSection().size());
    131   EXPECT_EQ(20, b.getPointerSection().size());
    132 
    133 #if !_MSC_VER || defined(__clang__) // TODO(msvc): ICE on the necessary constructor; see any.h.
    134   b = root.getAnyPointerField().getAs<TestAllTypes>();
    135   EXPECT_EQ(48, b.getDataSection().size());
    136   EXPECT_EQ(20, b.getPointerSection().size());
    137 #endif
    138 
    139   auto r = toAny(root.getAnyPointerField().getAs<TestAllTypes>().asReader());
    140   EXPECT_EQ(48, r.getDataSection().size());
    141   EXPECT_EQ(20, r.getPointerSection().size());
    142 
    143   r = toAny(root.getAnyPointerField().getAs<TestAllTypes>()).asReader();
    144   EXPECT_EQ(48, r.getDataSection().size());
    145   EXPECT_EQ(20, r.getPointerSection().size());
    146 
    147 #if !_MSC_VER || defined(__clang__)  // TODO(msvc): ICE on the necessary constructor; see any.h.
    148   r = root.getAnyPointerField().getAs<TestAllTypes>().asReader();
    149   EXPECT_EQ(48, r.getDataSection().size());
    150   EXPECT_EQ(20, r.getPointerSection().size());
    151 #endif
    152 
    153   {
    154     MallocMessageBuilder b2;
    155     auto root2 = b2.getRoot<test::TestAnyPointer>();
    156     auto sb = root2.getAnyPointerField().initAsAnyStruct(
    157         r.getDataSection().size() / 8, r.getPointerSection().size());
    158 
    159     EXPECT_EQ(48, sb.getDataSection().size());
    160     EXPECT_EQ(20, sb.getPointerSection().size());
    161 
    162     // TODO: is there a higher-level API for this?
    163     memcpy(sb.getDataSection().begin(), r.getDataSection().begin(), r.getDataSection().size());
    164   }
    165 
    166   {
    167     auto ptrs = r.getPointerSection();
    168     EXPECT_EQ("foo", ptrs[0].getAs<Text>());
    169     EXPECT_EQ("bar", kj::heapString(ptrs[1].getAs<Data>().asChars()));
    170     EXPECT_EQ("xyzzy", ptrs[15].getAs<List<Text>>()[1]);
    171   }
    172 
    173   {
    174     auto ptrs = b.getPointerSection();
    175     EXPECT_EQ("foo", ptrs[0].getAs<Text>());
    176     EXPECT_EQ("bar", kj::heapString(ptrs[1].getAs<Data>().asChars()));
    177     EXPECT_EQ("xyzzy", ptrs[15].getAs<List<Text>>()[1]);
    178   }
    179 }
    180 
    181 TEST(Any, AnyList) {
    182   MallocMessageBuilder builder;
    183   auto root = builder.getRoot<test::TestAnyPointer>();
    184   List<TestAllTypes>::Builder b = root.getAnyPointerField().initAs<List<TestAllTypes>>(2);
    185   initTestMessage(b[0]);
    186 
    187   auto ptr = root.getAnyPointerField().getAs<AnyList>();
    188 
    189   EXPECT_EQ(2, ptr.size());
    190   EXPECT_EQ(48, ptr.as<List<AnyStruct>>()[0].getDataSection().size());
    191   EXPECT_EQ(20, ptr.as<List<AnyStruct>>()[0].getPointerSection().size());
    192 
    193   auto readPtr = root.getAnyPointerField().asReader().getAs<AnyList>();
    194 
    195   EXPECT_EQ(2, readPtr.size());
    196   EXPECT_EQ(48, readPtr.as<List<AnyStruct>>()[0].getDataSection().size());
    197   EXPECT_EQ(20, readPtr.as<List<AnyStruct>>()[0].getPointerSection().size());
    198 
    199   auto alb = toAny(root.getAnyPointerField().getAs<List<TestAllTypes>>());
    200   EXPECT_EQ(2, alb.size());
    201   EXPECT_EQ(48, alb.as<List<AnyStruct>>()[0].getDataSection().size());
    202   EXPECT_EQ(20, alb.as<List<AnyStruct>>()[0].getPointerSection().size());
    203 
    204 #if !_MSC_VER || defined(__clang__) // TODO(msvc): ICE on the necessary constructor; see any.h.
    205   alb = root.getAnyPointerField().getAs<List<TestAllTypes>>();
    206   EXPECT_EQ(2, alb.size());
    207   EXPECT_EQ(48, alb.as<List<AnyStruct>>()[0].getDataSection().size());
    208   EXPECT_EQ(20, alb.as<List<AnyStruct>>()[0].getPointerSection().size());
    209 #endif
    210 
    211   auto alr = toAny(root.getAnyPointerField().getAs<List<TestAllTypes>>().asReader());
    212   EXPECT_EQ(2, alr.size());
    213   EXPECT_EQ(48, alr.as<List<AnyStruct>>()[0].getDataSection().size());
    214   EXPECT_EQ(20, alr.as<List<AnyStruct>>()[0].getPointerSection().size());
    215 
    216   alr = toAny(root.getAnyPointerField().getAs<List<TestAllTypes>>()).asReader();
    217   EXPECT_EQ(2, alr.size());
    218   EXPECT_EQ(48, alr.as<List<AnyStruct>>()[0].getDataSection().size());
    219   EXPECT_EQ(20, alr.as<List<AnyStruct>>()[0].getPointerSection().size());
    220 
    221 #if !_MSC_VER || defined(__clang__) // TODO(msvc): ICE on the necessary constructor; see any.h.
    222   alr = root.getAnyPointerField().getAs<List<TestAllTypes>>().asReader();
    223   EXPECT_EQ(2, alr.size());
    224   EXPECT_EQ(48, alr.as<List<AnyStruct>>()[0].getDataSection().size());
    225   EXPECT_EQ(20, alr.as<List<AnyStruct>>()[0].getPointerSection().size());
    226 #endif
    227 }
    228 
    229 TEST(Any, AnyStructListCapInSchema) {
    230   MallocMessageBuilder builder;
    231   auto root = builder.getRoot<test::TestAnyOthers>();
    232 
    233   {
    234     initTestMessage(root.initAnyStructFieldAs<TestAllTypes>());
    235     AnyStruct::Builder anyStruct = root.getAnyStructField();
    236     checkTestMessage(anyStruct.as<TestAllTypes>());
    237     checkTestMessage(anyStruct.asReader().as<TestAllTypes>());
    238 
    239     EXPECT_TRUE(root.hasAnyStructField());
    240     auto orphan = root.disownAnyStructField();
    241     checkTestMessage(orphan.getReader().as<TestAllTypes>());
    242     EXPECT_FALSE(root.hasAnyStructField());
    243 
    244     root.adoptAnyStructField(kj::mv(orphan));
    245     EXPECT_TRUE(root.hasAnyStructField());
    246     checkTestMessage(root.getAnyStructField().as<TestAllTypes>());
    247   }
    248 
    249   {
    250     List<int>::Builder list = root.initAnyListFieldAs<List<int>>(3);
    251     list.set(0, 123);
    252     list.set(1, 456);
    253     list.set(2, 789);
    254 
    255     AnyList::Builder anyList = root.getAnyListField();
    256     checkList(anyList.as<List<int>>(), {123, 456, 789});
    257 
    258     EXPECT_TRUE(root.hasAnyListField());
    259     auto orphan = root.disownAnyListField();
    260     checkList(orphan.getReader().as<List<int>>(), {123, 456, 789});
    261     EXPECT_FALSE(root.hasAnyListField());
    262 
    263     root.adoptAnyListField(kj::mv(orphan));
    264     EXPECT_TRUE(root.hasAnyListField());
    265     checkList(root.getAnyListField().as<List<int>>(), {123, 456, 789});
    266   }
    267 
    268 #if !CAPNP_LITE
    269   // This portion of the test relies on a Client, not present in lite-mode.
    270   {
    271     kj::EventLoop loop;
    272     kj::WaitScope waitScope(loop);
    273     int callCount = 0;
    274     root.setCapabilityField(kj::heap<TestInterfaceImpl>(callCount));
    275     Capability::Client client = root.getCapabilityField();
    276     auto req = client.castAs<test::TestInterface>().fooRequest();
    277     req.setI(123);
    278     req.setJ(true);
    279     req.send().wait(waitScope);
    280     EXPECT_EQ(1, callCount);
    281   }
    282 #endif
    283 }
    284 
    285 KJ_TEST("Builder::isStruct() does not corrupt segment pointer") {
    286   MallocMessageBuilder builder(1); // small first segment
    287   auto root = builder.getRoot<AnyPointer>();
    288 
    289   // Do a lot of allocations so that there is likely a segment with a decent
    290   // amount of free space.
    291   initTestMessage(root.initAs<test::TestAllTypes>());
    292 
    293   // This will probably get allocated in a segment that still has room for the
    294   // Data allocation below.
    295   root.initAs<test::TestAllTypes>();
    296 
    297   // At one point, this caused root.builder.segment to point to the segment
    298   // where the struct is allocated, rather than segment where the root pointer
    299   // lives, i.e. segment zero.
    300   EXPECT_TRUE(root.isStruct());
    301 
    302   // If root.builder.segment points to the wrong segment and that segment has free
    303   // space, then this triggers a DREQUIRE failure in WirePointer::setKindAndTarget().
    304   root.initAs<Data>(1);
    305 }
    306 
    307 TEST(Any, Equals) {
    308   MallocMessageBuilder builderA;
    309   auto rootA = builderA.getRoot<test::TestAllTypes>();
    310   auto anyA = builderA.getRoot<AnyPointer>();
    311   initTestMessage(rootA);
    312 
    313   MallocMessageBuilder builderB;
    314   auto rootB = builderB.getRoot<test::TestAllTypes>();
    315   auto anyB = builderB.getRoot<AnyPointer>();
    316   initTestMessage(rootB);
    317 
    318   EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB));
    319 
    320   rootA.setBoolField(false);
    321   EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB));
    322 
    323   rootB.setBoolField(false);
    324   EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB));
    325 
    326   rootB.setEnumField(test::TestEnum::GARPLY);
    327   EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB));
    328 
    329   rootA.setEnumField(test::TestEnum::GARPLY);
    330   EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB));
    331 
    332   rootA.getStructField().setTextField("buzz");
    333   EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB));
    334 
    335   rootB.getStructField().setTextField("buzz");
    336   EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB));
    337 
    338   rootA.initVoidList(3);
    339   EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB));
    340 
    341   rootB.initVoidList(3);
    342   EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB));
    343 
    344   rootA.getBoolList().set(2, true);
    345   EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB));
    346 
    347   rootB.getBoolList().set(2, true);
    348   EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB));
    349 
    350   rootB.getStructList()[1].setTextField("my NEW structlist 2");
    351   EXPECT_EQ(Equality::NOT_EQUAL, anyA.equals(anyB));
    352 
    353   rootA.getStructList()[1].setTextField("my NEW structlist 2");
    354   EXPECT_EQ(Equality::EQUAL, anyA.equals(anyB));
    355 }
    356 
    357 KJ_TEST("Bit list with nonzero pad bits") {
    358   AlignedData<2> segment1 = {{
    359       0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, // eleven bit-sized elements
    360       0xee, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // twelfth bit is set!
    361   }};
    362   kj::ArrayPtr<const word> segments1[1] = {
    363     kj::arrayPtr(segment1.words, 2)
    364   };
    365   SegmentArrayMessageReader message1(kj::arrayPtr(segments1, 1));
    366 
    367   AlignedData<2> segment2 = {{
    368       0x01, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, // eleven bit-sized elements
    369       0xee, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // twelfth bit is not set
    370   }};
    371   kj::ArrayPtr<const word> segments2[1] = {
    372     kj::arrayPtr(segment2.words, 2)
    373   };
    374   SegmentArrayMessageReader message2(kj::arrayPtr(segments2, 1));
    375 
    376   // Should be equal, despite nonzero padding.
    377   KJ_ASSERT(message1.getRoot<AnyList>() == message2.getRoot<AnyList>());
    378 }
    379 
    380 KJ_TEST("Pointer list unequal to struct list") {
    381   AlignedData<1> segment1 = {{
    382       // list with zero pointer-sized elements
    383       0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
    384   }};
    385   kj::ArrayPtr<const word> segments1[1] = {
    386     kj::arrayPtr(segment1.words, 1)
    387   };
    388   SegmentArrayMessageReader message1(kj::arrayPtr(segments1, 1));
    389 
    390   AlignedData<2> segment2 = {{
    391       // struct list of length zero
    392       0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
    393 
    394       // struct list tag, zero elements
    395       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    396   }};
    397   kj::ArrayPtr<const word> segments2[1] = {
    398     kj::arrayPtr(segment2.words, 2)
    399   };
    400   SegmentArrayMessageReader message2(kj::arrayPtr(segments2, 1));
    401 
    402   EXPECT_EQ(Equality::NOT_EQUAL, message1.getRoot<AnyList>().equals(message2.getRoot<AnyList>()));
    403 }
    404 
    405 KJ_TEST("Truncating non-null pointer fields does not preserve equality") {
    406   AlignedData<3> segment1 = {{
    407       // list with one data word and one pointer field
    408       0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
    409 
    410       // data word
    411       0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
    412 
    413       // non-null pointer to zero-sized struct
    414       0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
    415   }};
    416   kj::ArrayPtr<const word> segments1[1] = {
    417     kj::arrayPtr(segment1.words, 3)
    418   };
    419   SegmentArrayMessageReader message1(kj::arrayPtr(segments1, 1));
    420 
    421   AlignedData<2> segment2 = {{
    422       // list with one data word and zero pointers
    423       0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
    424 
    425       // data word
    426       0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
    427   }};
    428   kj::ArrayPtr<const word> segments2[1] = {
    429     kj::arrayPtr(segment2.words, 2)
    430   };
    431   SegmentArrayMessageReader message2(kj::arrayPtr(segments2, 1));
    432 
    433   EXPECT_EQ(Equality::NOT_EQUAL,
    434             message1.getRoot<AnyPointer>().equals(message2.getRoot<AnyPointer>()));
    435 }
    436 
    437 }  // namespace
    438 }  // namespace _ (private)
    439 }  // namespace capnp