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