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

schema-test.c++ (16833B)


      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_TESTING_CAPNP 1
     23 
     24 #include "schema.h"
     25 #include <kj/compat/gtest.h>
     26 #include "test-util.h"
     27 
     28 // TODO(cleanup): Auto-generate stringification functions for union discriminants.
     29 namespace capnp {
     30 namespace schema {
     31 inline kj::String KJ_STRINGIFY(Type::Which which) {
     32   return kj::str(static_cast<uint16_t>(which));
     33 }
     34 }  // namespace schema
     35 }  // namespace capnp
     36 
     37 namespace capnp {
     38 namespace _ {  // private
     39 namespace {
     40 
     41 TEST(Schema, Structs) {
     42   StructSchema schema = Schema::from<TestAllTypes>();
     43 
     44   EXPECT_EQ(typeId<TestAllTypes>(), schema.getProto().getId());
     45 
     46   EXPECT_TRUE(schema.getDependency(typeId<TestEnum>()) == Schema::from<TestEnum>());
     47   EXPECT_TRUE(schema.getDependency(typeId<TestEnum>()) != schema);
     48   EXPECT_TRUE(schema.getDependency(typeId<TestAllTypes>()) == Schema::from<TestAllTypes>());
     49   EXPECT_TRUE(schema.getDependency(typeId<TestAllTypes>()) == schema);
     50   EXPECT_NONFATAL_FAILURE(schema.getDependency(typeId<TestDefaults>()));
     51 
     52   EXPECT_TRUE(schema.asStruct() == schema);
     53   EXPECT_NONFATAL_FAILURE(schema.asEnum());
     54   EXPECT_NONFATAL_FAILURE(schema.asInterface());
     55   ASSERT_EQ("TestAllTypes", schema.getUnqualifiedName());
     56 
     57   ASSERT_EQ(schema.getFields().size(), schema.getProto().getStruct().getFields().size());
     58   StructSchema::Field field = schema.getFields()[0];
     59   EXPECT_EQ("voidField", field.getProto().getName());
     60   EXPECT_TRUE(field.getContainingStruct() == schema);
     61 
     62   StructSchema::Field lookup = schema.getFieldByName("voidField");
     63   EXPECT_TRUE(lookup == field);
     64   EXPECT_TRUE(lookup != schema.getFields()[1]);
     65   EXPECT_FALSE(lookup.getProto().getSlot().getHadExplicitDefault());
     66 
     67   EXPECT_FALSE(schema.getFieldByName("int32Field").getProto().getSlot().getHadExplicitDefault());
     68 
     69   EXPECT_TRUE(Schema::from<TestDefaults>().getFieldByName("int32Field")
     70       .getProto().getSlot().getHadExplicitDefault());
     71 
     72   EXPECT_TRUE(schema.findFieldByName("noSuchField") == nullptr);
     73 
     74   EXPECT_TRUE(schema.findFieldByName("int32Field") != nullptr);
     75   EXPECT_TRUE(schema.findFieldByName("float32List") != nullptr);
     76   EXPECT_TRUE(schema.findFieldByName("dataList") != nullptr);
     77   EXPECT_TRUE(schema.findFieldByName("textField") != nullptr);
     78   EXPECT_TRUE(schema.findFieldByName("structField") != nullptr);
     79 }
     80 
     81 TEST(Schema, FieldLookupOutOfOrder) {
     82   // Tests that name lookup works correctly when the fields are defined out-of-order in the schema
     83   // file.
     84   auto schema = Schema::from<test::TestOutOfOrder>().asStruct();
     85 
     86   EXPECT_EQ("qux", schema.getFields()[0].getProto().getName());
     87   EXPECT_EQ("grault", schema.getFields()[1].getProto().getName());
     88   EXPECT_EQ("bar", schema.getFields()[2].getProto().getName());
     89   EXPECT_EQ("foo", schema.getFields()[3].getProto().getName());
     90   EXPECT_EQ("corge", schema.getFields()[4].getProto().getName());
     91   EXPECT_EQ("waldo", schema.getFields()[5].getProto().getName());
     92   EXPECT_EQ("quux", schema.getFields()[6].getProto().getName());
     93   EXPECT_EQ("garply", schema.getFields()[7].getProto().getName());
     94   EXPECT_EQ("baz", schema.getFields()[8].getProto().getName());
     95 
     96   EXPECT_EQ(3, schema.getFieldByName("foo").getProto().getOrdinal().getExplicit());
     97   EXPECT_EQ(2, schema.getFieldByName("bar").getProto().getOrdinal().getExplicit());
     98   EXPECT_EQ(8, schema.getFieldByName("baz").getProto().getOrdinal().getExplicit());
     99   EXPECT_EQ(0, schema.getFieldByName("qux").getProto().getOrdinal().getExplicit());
    100   EXPECT_EQ(6, schema.getFieldByName("quux").getProto().getOrdinal().getExplicit());
    101   EXPECT_EQ(4, schema.getFieldByName("corge").getProto().getOrdinal().getExplicit());
    102   EXPECT_EQ(1, schema.getFieldByName("grault").getProto().getOrdinal().getExplicit());
    103   EXPECT_EQ(7, schema.getFieldByName("garply").getProto().getOrdinal().getExplicit());
    104   EXPECT_EQ(5, schema.getFieldByName("waldo").getProto().getOrdinal().getExplicit());
    105 }
    106 
    107 TEST(Schema, Unions) {
    108   auto schema = Schema::from<TestUnion>().asStruct();
    109 
    110   EXPECT_TRUE(schema.findFieldByName("bit0") != nullptr);
    111   EXPECT_TRUE(schema.findFieldByName("u1f0s8") == nullptr);
    112 
    113   auto union1 = schema.getFieldByName("union1");
    114   auto union1g = schema.getDependency(union1.getProto().getGroup().getTypeId()).asStruct();
    115   EXPECT_EQ(schema, union1g.getDependency(union1g.getProto().getScopeId()));
    116   EXPECT_TRUE(union1g.findFieldByName("bin0") == nullptr);
    117 
    118   auto u1f0s8 = union1g.getFieldByName("u1f0s8");
    119   EXPECT_EQ("u1f0s8", u1f0s8.getProto().getName());
    120   EXPECT_TRUE(u1f0s8.getContainingStruct() == union1g);
    121 
    122   EXPECT_TRUE(union1g.findFieldByName("u1f1s8") != nullptr);
    123   EXPECT_TRUE(union1g.findFieldByName("u1f0s32") != nullptr);
    124   EXPECT_TRUE(union1g.findFieldByName("u1f0sp") != nullptr);
    125   EXPECT_TRUE(union1g.findFieldByName("u1f1s1") != nullptr);
    126 
    127   EXPECT_TRUE(union1g.findFieldByName("u0f0s1") == nullptr);
    128   EXPECT_TRUE(union1g.findFieldByName("u2f0s8") == nullptr);
    129   EXPECT_TRUE(union1g.findFieldByName("noSuchField") == nullptr);
    130 }
    131 
    132 TEST(Schema, Enums) {
    133   EnumSchema schema = Schema::from<TestEnum>();
    134 
    135   EXPECT_EQ(typeId<TestEnum>(), schema.getProto().getId());
    136 
    137   EXPECT_NONFATAL_FAILURE(schema.getDependency(typeId<TestAllTypes>()));
    138   EXPECT_NONFATAL_FAILURE(schema.getDependency(typeId<TestEnum>()));
    139 
    140   EXPECT_NONFATAL_FAILURE(schema.asStruct());
    141   EXPECT_NONFATAL_FAILURE(schema.asInterface());
    142   EXPECT_TRUE(schema.asEnum() == schema);
    143 
    144   ASSERT_EQ(schema.getEnumerants().size(),
    145             schema.getProto().getEnum().getEnumerants().size());
    146   EnumSchema::Enumerant enumerant = schema.getEnumerants()[0];
    147   EXPECT_EQ("foo", enumerant.getProto().getName());
    148   EXPECT_TRUE(enumerant.getContainingEnum() == schema);
    149 
    150   EnumSchema::Enumerant lookup = schema.getEnumerantByName("foo");
    151   EXPECT_TRUE(lookup == enumerant);
    152   EXPECT_TRUE(lookup != schema.getEnumerants()[1]);
    153 
    154   EXPECT_TRUE(schema.findEnumerantByName("noSuchEnumerant") == nullptr);
    155 
    156   EXPECT_TRUE(schema.findEnumerantByName("bar") != nullptr);
    157   EXPECT_TRUE(schema.findEnumerantByName("qux") != nullptr);
    158   EXPECT_TRUE(schema.findEnumerantByName("corge") != nullptr);
    159   EXPECT_TRUE(schema.findEnumerantByName("grault") != nullptr);
    160 }
    161 
    162 // TODO(someday):  Test interface schemas when interfaces are implemented.
    163 
    164 TEST(Schema, Lists) {
    165   EXPECT_EQ(schema::Type::VOID, Schema::from<List<Void>>().whichElementType());
    166   EXPECT_EQ(schema::Type::BOOL, Schema::from<List<bool>>().whichElementType());
    167   EXPECT_EQ(schema::Type::INT8, Schema::from<List<int8_t>>().whichElementType());
    168   EXPECT_EQ(schema::Type::INT16, Schema::from<List<int16_t>>().whichElementType());
    169   EXPECT_EQ(schema::Type::INT32, Schema::from<List<int32_t>>().whichElementType());
    170   EXPECT_EQ(schema::Type::INT64, Schema::from<List<int64_t>>().whichElementType());
    171   EXPECT_EQ(schema::Type::UINT8, Schema::from<List<uint8_t>>().whichElementType());
    172   EXPECT_EQ(schema::Type::UINT16, Schema::from<List<uint16_t>>().whichElementType());
    173   EXPECT_EQ(schema::Type::UINT32, Schema::from<List<uint32_t>>().whichElementType());
    174   EXPECT_EQ(schema::Type::UINT64, Schema::from<List<uint64_t>>().whichElementType());
    175   EXPECT_EQ(schema::Type::FLOAT32, Schema::from<List<float>>().whichElementType());
    176   EXPECT_EQ(schema::Type::FLOAT64, Schema::from<List<double>>().whichElementType());
    177   EXPECT_EQ(schema::Type::TEXT, Schema::from<List<Text>>().whichElementType());
    178   EXPECT_EQ(schema::Type::DATA, Schema::from<List<Data>>().whichElementType());
    179 
    180   EXPECT_NONFATAL_FAILURE(Schema::from<List<uint16_t>>().getStructElementType());
    181   EXPECT_NONFATAL_FAILURE(Schema::from<List<uint16_t>>().getEnumElementType());
    182   EXPECT_NONFATAL_FAILURE(Schema::from<List<uint16_t>>().getInterfaceElementType());
    183   EXPECT_NONFATAL_FAILURE(Schema::from<List<uint16_t>>().getListElementType());
    184 
    185   {
    186     ListSchema schema = Schema::from<List<TestAllTypes>>();
    187     EXPECT_EQ(schema::Type::STRUCT, schema.whichElementType());
    188     EXPECT_TRUE(schema.getStructElementType() == Schema::from<TestAllTypes>());
    189     EXPECT_NONFATAL_FAILURE(schema.getEnumElementType());
    190     EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType());
    191     EXPECT_NONFATAL_FAILURE(schema.getListElementType());
    192   }
    193 
    194   {
    195     ListSchema schema = Schema::from<List<TestEnum>>();
    196     EXPECT_EQ(schema::Type::ENUM, schema.whichElementType());
    197     EXPECT_TRUE(schema.getEnumElementType() == Schema::from<TestEnum>());
    198     EXPECT_NONFATAL_FAILURE(schema.getStructElementType());
    199     EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType());
    200     EXPECT_NONFATAL_FAILURE(schema.getListElementType());
    201   }
    202 
    203   // TODO(someday):  Test interfaces.
    204 
    205   {
    206     ListSchema schema = Schema::from<List<List<int32_t>>>();
    207     EXPECT_EQ(schema::Type::LIST, schema.whichElementType());
    208     EXPECT_NONFATAL_FAILURE(schema.getStructElementType());
    209     EXPECT_NONFATAL_FAILURE(schema.getEnumElementType());
    210     EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType());
    211 
    212     ListSchema inner = schema.getListElementType();
    213     EXPECT_EQ(schema::Type::INT32, inner.whichElementType());
    214   }
    215 
    216   {
    217     ListSchema schema = Schema::from<List<List<TestAllTypes>>>();
    218     EXPECT_EQ(schema::Type::LIST, schema.whichElementType());
    219     EXPECT_NONFATAL_FAILURE(schema.getStructElementType());
    220     EXPECT_NONFATAL_FAILURE(schema.getEnumElementType());
    221     EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType());
    222 
    223     ListSchema inner = schema.getListElementType();
    224     EXPECT_EQ(schema::Type::STRUCT, inner.whichElementType());
    225     EXPECT_TRUE(inner.getStructElementType() == Schema::from<TestAllTypes>());
    226   }
    227 
    228   {
    229     ListSchema schema = Schema::from<List<List<TestEnum>>>();
    230     EXPECT_EQ(schema::Type::LIST, schema.whichElementType());
    231     EXPECT_NONFATAL_FAILURE(schema.getStructElementType());
    232     EXPECT_NONFATAL_FAILURE(schema.getEnumElementType());
    233     EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType());
    234 
    235     ListSchema inner = schema.getListElementType();
    236     EXPECT_EQ(schema::Type::ENUM, inner.whichElementType());
    237     EXPECT_TRUE(inner.getEnumElementType() == Schema::from<TestEnum>());
    238   }
    239 
    240   {
    241     auto context = Schema::from<TestAllTypes>();
    242     auto type = context.getFieldByName("enumList").getProto().getSlot().getType();
    243 
    244     ListSchema schema = ListSchema::of(type.getList().getElementType(), context);
    245     EXPECT_EQ(schema::Type::ENUM, schema.whichElementType());
    246     EXPECT_TRUE(schema.getEnumElementType() == Schema::from<TestEnum>());
    247     EXPECT_NONFATAL_FAILURE(schema.getStructElementType());
    248     EXPECT_NONFATAL_FAILURE(schema.getInterfaceElementType());
    249     EXPECT_NONFATAL_FAILURE(schema.getListElementType());
    250   }
    251 }
    252 
    253 TEST(Schema, UnnamedUnion) {
    254   StructSchema schema = Schema::from<test::TestUnnamedUnion>();
    255 
    256   EXPECT_TRUE(schema.findFieldByName("") == nullptr);
    257 
    258   EXPECT_TRUE(schema.findFieldByName("foo") != nullptr);
    259   EXPECT_TRUE(schema.findFieldByName("bar") != nullptr);
    260   EXPECT_TRUE(schema.findFieldByName("before") != nullptr);
    261   EXPECT_TRUE(schema.findFieldByName("after") != nullptr);
    262 }
    263 
    264 TEST(Schema, NullSchemas) {
    265   EXPECT_EQ(0xff, (uint)Schema().getProto().which());
    266   EXPECT_TRUE(StructSchema().getProto().isStruct());
    267   EXPECT_TRUE(EnumSchema().getProto().isEnum());
    268   EXPECT_TRUE(InterfaceSchema().getProto().isInterface());
    269   EXPECT_TRUE(ConstSchema().getProto().isConst());
    270 
    271   EXPECT_EQ("(null schema)", Schema().getProto().getDisplayName());
    272   EXPECT_EQ("(null struct schema)", StructSchema().getProto().getDisplayName());
    273   EXPECT_EQ("(null enum schema)", EnumSchema().getProto().getDisplayName());
    274   EXPECT_EQ("(null interface schema)", InterfaceSchema().getProto().getDisplayName());
    275   EXPECT_EQ("(null const schema)", ConstSchema().getProto().getDisplayName());
    276 
    277   EXPECT_TRUE(Schema::from<Capability>() == InterfaceSchema());
    278   EXPECT_EQ(InterfaceSchema().getProto().getId(), typeId<Capability>());
    279 }
    280 
    281 TEST(Schema, Interfaces) {
    282   InterfaceSchema schema = Schema::from<test::TestMoreStuff>();
    283 
    284   EXPECT_EQ(typeId<test::TestMoreStuff>(), schema.getProto().getId());
    285 
    286   EXPECT_TRUE(schema.getDependency(typeId<test::TestCallOrder>()) ==
    287               Schema::from<test::TestCallOrder>());
    288   EXPECT_TRUE(schema.getDependency(typeId<test::TestCallOrder>()) != schema);
    289   EXPECT_NONFATAL_FAILURE(schema.getDependency(typeId<TestDefaults>()));
    290 
    291   EXPECT_TRUE(schema.asInterface() == schema);
    292   EXPECT_NONFATAL_FAILURE(schema.asStruct());
    293   EXPECT_NONFATAL_FAILURE(schema.asEnum());
    294 
    295   ASSERT_EQ(schema.getMethods().size(), schema.getProto().getInterface().getMethods().size());
    296   InterfaceSchema::Method method = schema.getMethods()[0];
    297   EXPECT_EQ("callFoo", method.getProto().getName());
    298   EXPECT_TRUE(method.getContainingInterface() == schema);
    299 
    300   InterfaceSchema::Method lookup = schema.getMethodByName("callFoo");
    301   EXPECT_TRUE(lookup == method);
    302   EXPECT_TRUE(lookup != schema.getMethods()[1]);
    303 
    304   EXPECT_TRUE(Schema::from<TestDefaults>().getFieldByName("int32Field")
    305       .getProto().getSlot().getHadExplicitDefault());
    306 
    307   EXPECT_TRUE(schema.findMethodByName("noSuchMethod") == nullptr);
    308 
    309   EXPECT_TRUE(schema.findMethodByName("callFooWhenResolved") != nullptr);
    310   EXPECT_TRUE(schema.findMethodByName("neverReturn") != nullptr);
    311   EXPECT_TRUE(schema.findMethodByName("hold") != nullptr);
    312   EXPECT_TRUE(schema.findMethodByName("callHeld") != nullptr);
    313   EXPECT_TRUE(schema.findMethodByName("getHeld") != nullptr);
    314 
    315   auto params = schema.getDependency(schema.getMethodByName("methodWithDefaults")
    316       .getProto().getParamStructType()).asStruct();
    317   EXPECT_FALSE(params.getFieldByName("a").getProto().getSlot().getHadExplicitDefault());
    318   EXPECT_TRUE(params.getFieldByName("b").getProto().getSlot().getHadExplicitDefault());
    319   EXPECT_TRUE(params.getFieldByName("c").getProto().getSlot().getHadExplicitDefault());
    320 }
    321 
    322 TEST(Schema, Generics) {
    323   StructSchema allTypes = Schema::from<TestAllTypes>();
    324   StructSchema tap = Schema::from<test::TestAnyPointer>();
    325   StructSchema schema = Schema::from<test::TestUseGenerics>();
    326 
    327   StructSchema branded;
    328 
    329   {
    330     StructSchema::Field basic = schema.getFieldByName("basic");
    331     branded = basic.getType().asStruct();
    332 
    333     StructSchema::Field foo = branded.getFieldByName("foo");
    334     EXPECT_TRUE(foo.getType().asStruct() == allTypes);
    335     EXPECT_TRUE(foo.getType().asStruct() != tap);
    336 
    337     StructSchema instance2 = branded.getFieldByName("rev").getType().asStruct();
    338     StructSchema::Field foo2 = instance2.getFieldByName("foo");
    339     EXPECT_TRUE(foo2.getType().asStruct() == tap);
    340     EXPECT_TRUE(foo2.getType().asStruct() != allTypes);
    341   }
    342 
    343   {
    344     StructSchema inner2 = schema.getFieldByName("inner2").getType().asStruct();
    345 
    346     StructSchema bound = inner2.getFieldByName("innerBound").getType().asStruct();
    347     Type boundFoo = bound.getFieldByName("foo").getType();
    348     EXPECT_FALSE(boundFoo.isAnyPointer());
    349     EXPECT_TRUE(boundFoo.asStruct() == allTypes);
    350 
    351     StructSchema unbound = inner2.getFieldByName("innerUnbound").getType().asStruct();
    352     Type unboundFoo = unbound.getFieldByName("foo").getType();
    353     EXPECT_TRUE(unboundFoo.isAnyPointer());
    354   }
    355 
    356   {
    357     InterfaceSchema cap = schema.getFieldByName("genericCap").getType().asInterface();
    358     InterfaceSchema::Method method = cap.getMethodByName("call");
    359 
    360     StructSchema inner2 = method.getParamType();
    361     StructSchema bound = inner2.getFieldByName("innerBound").getType().asStruct();
    362     Type boundFoo = bound.getFieldByName("foo").getType();
    363     EXPECT_FALSE(boundFoo.isAnyPointer());
    364     EXPECT_TRUE(boundFoo.asStruct() == allTypes);
    365     EXPECT_TRUE(inner2.getFieldByName("baz").getType().isText());
    366 
    367     StructSchema results = method.getResultType();
    368     EXPECT_TRUE(results.getFieldByName("qux").getType().isData());
    369 
    370     EXPECT_TRUE(results.getFieldByName("gen").getType().asStruct() == branded);
    371   }
    372 }
    373 
    374 }  // namespace
    375 }  // namespace _ (private)
    376 }  // namespace capnp