1 // 2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 8 // Test that header file is self-contained. 9 #include <boost/beast/core/detail/variant.hpp> 10 11 #include <boost/beast/_experimental/unit_test/suite.hpp> 12 #include <exception> 13 #include <string> 14 15 namespace boost { 16 namespace beast { 17 namespace detail { 18 19 class variant_test : public beast::unit_test::suite 20 { 21 public: 22 template<unsigned char I> 23 struct Q 24 { 25 static 26 unsigned char& countboost::beast::detail::variant_test::Q27 count() 28 { 29 static unsigned char n = 0; 30 return n; 31 } 32 33 int value = 0; 34 bool move = false; 35 bool copy = false; 36 37 Q& operator=(Q&& q) = delete; 38 Q& operator=(Q const& q) = delete; 39 ~Qboost::beast::detail::variant_test::Q40 ~Q() 41 { 42 --count(); 43 } 44 Qboost::beast::detail::variant_test::Q45 Q() 46 { 47 ++count(); 48 } 49 Qboost::beast::detail::variant_test::Q50 Q(Q&& q) 51 { 52 if(q.value < 0) 53 throw std::exception{}; 54 ++count(); 55 move = true; 56 } 57 Qboost::beast::detail::variant_test::Q58 Q(Q const& q) 59 { 60 if(q.value < 0) 61 throw std::exception{}; 62 ++count(); 63 copy = true; 64 } 65 Qboost::beast::detail::variant_test::Q66 explicit Q(int value_) 67 : value(value_) 68 { 69 ++count(); 70 } 71 }; 72 73 void testVariant()74 testVariant() 75 { 76 // Default Constructor 77 // Destructor 78 { 79 variant<int> v; 80 BEAST_EXPECT(v.index() == 0); 81 } 82 // emplace 83 { 84 variant<int> v; 85 BEAST_EXPECT(v.index() == 0); 86 v.emplace<1>(10); 87 BEAST_EXPECT(v.index() == 1); 88 BEAST_EXPECT(v.get<1>() == 10); 89 v.emplace<1>(20); 90 BEAST_EXPECT(v.index() == 1); 91 BEAST_EXPECT(v.get<1>() == 20); 92 } 93 { 94 variant<std::string> v; 95 v.emplace<1>("Hello, world!"); 96 BEAST_EXPECT(v.index() == 1); 97 BEAST_EXPECT(v.get<1>() == "Hello, world!"); 98 } 99 { 100 variant<Q<1>> v; 101 BEAST_EXPECT(Q<1>::count() == 0); 102 v.emplace<1>(); 103 BEAST_EXPECT(Q<1>::count() == 1); 104 BEAST_EXPECT(v.get<1>().value == 0); 105 v.emplace<1>(42); 106 BEAST_EXPECT(Q<1>::count() == 1); 107 BEAST_EXPECT(v.get<1>().value == 42); 108 v.reset(); 109 BEAST_EXPECT(Q<1>::count() == 0); 110 } 111 BEAST_EXPECT(Q<1>::count() == 0); 112 { 113 variant<Q<1>, Q<2>, Q<3>> v; 114 BEAST_EXPECT(Q<1>::count() == 0); 115 BEAST_EXPECT(Q<2>::count() == 0); 116 BEAST_EXPECT(Q<3>::count() == 0); 117 v.emplace<1>(); 118 BEAST_EXPECT(Q<1>::count() == 1); 119 BEAST_EXPECT(Q<2>::count() == 0); 120 BEAST_EXPECT(Q<3>::count() == 0); 121 v.emplace<2>(); 122 BEAST_EXPECT(Q<1>::count() == 0); 123 BEAST_EXPECT(Q<2>::count() == 1); 124 BEAST_EXPECT(Q<3>::count() == 0); 125 v.emplace<3>(); 126 BEAST_EXPECT(Q<1>::count() == 0); 127 BEAST_EXPECT(Q<2>::count() == 0); 128 BEAST_EXPECT(Q<3>::count() == 1); 129 v.reset(); 130 BEAST_EXPECT(Q<1>::count() == 0); 131 BEAST_EXPECT(Q<2>::count() == 0); 132 BEAST_EXPECT(Q<3>::count() == 0); 133 } 134 BEAST_EXPECT(Q<1>::count() == 0); 135 BEAST_EXPECT(Q<2>::count() == 0); 136 BEAST_EXPECT(Q<3>::count() == 0); 137 // move 138 { 139 variant<std::string> v1; 140 BEAST_EXPECT(v1.index() == 0); 141 variant<std::string> v2{std::move(v1)}; 142 BEAST_EXPECT(v1.index() == 0); 143 BEAST_EXPECT(v2.index() == 0); 144 v2.emplace<1>("Hello"); 145 BEAST_EXPECT(v2.get<1>() == "Hello"); 146 variant<std::string> v3{std::move(v2)}; 147 BEAST_EXPECT(v2.index() == 0); 148 BEAST_EXPECT(v3.get<1>() == "Hello"); 149 } 150 { 151 variant<Q<1>> v1; 152 BEAST_EXPECT(Q<1>::count() == 0); 153 v1.emplace<1>(); 154 BEAST_EXPECT(Q<1>::count() == 1); 155 BEAST_EXPECT(! v1.get<1>().move); 156 variant<Q<1>> v2{std::move(v1)}; 157 BEAST_EXPECT(v1.index() == 0); 158 BEAST_EXPECT(Q<1>::count() == 1); 159 BEAST_EXPECT(v2.get<1>().move); 160 } 161 BEAST_EXPECT(Q<1>::count() == 0); 162 { 163 variant<Q<1>, Q<2>, Q<3>> v1; 164 BEAST_EXPECT(Q<1>::count() == 0); 165 BEAST_EXPECT(Q<2>::count() == 0); 166 BEAST_EXPECT(Q<3>::count() == 0); 167 v1.emplace<2>(); 168 BEAST_EXPECT(Q<1>::count() == 0); 169 BEAST_EXPECT(Q<2>::count() == 1); 170 BEAST_EXPECT(Q<3>::count() == 0); 171 variant<Q<1>, Q<2>, Q<3>> v2{std::move(v1)}; 172 BEAST_EXPECT(Q<1>::count() == 0); 173 BEAST_EXPECT(Q<2>::count() == 1); 174 BEAST_EXPECT(Q<3>::count() == 0); 175 BEAST_EXPECT(v2.get<2>().move); 176 } 177 BEAST_EXPECT(Q<1>::count() == 0); 178 BEAST_EXPECT(Q<2>::count() == 0); 179 BEAST_EXPECT(Q<3>::count() == 0); 180 // copy 181 { 182 variant<std::string> v1; 183 BEAST_EXPECT(v1.index() == 0); 184 variant<std::string> v2{v1}; 185 BEAST_EXPECT(v1.index() == 0); 186 BEAST_EXPECT(v2.index() == 0); 187 v2.emplace<1>("Hello"); 188 BEAST_EXPECT(v2.get<1>() == "Hello"); 189 variant<std::string> v3{v2}; 190 BEAST_EXPECT(v2.get<1>() == "Hello"); 191 BEAST_EXPECT(v3.get<1>() == "Hello"); 192 } 193 { 194 variant<Q<1>> v1; 195 BEAST_EXPECT(Q<1>::count() == 0); 196 v1.emplace<1>(); 197 BEAST_EXPECT(Q<1>::count() == 1); 198 BEAST_EXPECT(! v1.get<1>().copy); 199 variant<Q<1>> v2{v1}; 200 BEAST_EXPECT(v1.index() == 1); 201 BEAST_EXPECT(Q<1>::count() == 2); 202 BEAST_EXPECT(v2.get<1>().copy); 203 } 204 BEAST_EXPECT(Q<1>::count() == 0); 205 { 206 variant<Q<1>, Q<2>, Q<3>> v1; 207 BEAST_EXPECT(Q<1>::count() == 0); 208 BEAST_EXPECT(Q<2>::count() == 0); 209 BEAST_EXPECT(Q<3>::count() == 0); 210 v1.emplace<2>(); 211 BEAST_EXPECT(Q<1>::count() == 0); 212 BEAST_EXPECT(Q<2>::count() == 1); 213 BEAST_EXPECT(Q<3>::count() == 0); 214 variant<Q<1>, Q<2>, Q<3>> v2{v1}; 215 BEAST_EXPECT(Q<1>::count() == 0); 216 BEAST_EXPECT(Q<2>::count() == 2); 217 BEAST_EXPECT(Q<3>::count() == 0); 218 BEAST_EXPECT(v2.get<2>().copy); 219 } 220 BEAST_EXPECT(Q<1>::count() == 0); 221 BEAST_EXPECT(Q<2>::count() == 0); 222 BEAST_EXPECT(Q<3>::count() == 0); 223 // move assign 224 { 225 variant<std::string> v1; 226 BEAST_EXPECT(v1.index() == 0); 227 variant<std::string> v2; 228 v2 = std::move(v1); 229 BEAST_EXPECT(v1.index() == 0); 230 BEAST_EXPECT(v2.index() == 0); 231 v2.emplace<1>("Hello"); 232 BEAST_EXPECT(v2.get<1>() == "Hello"); 233 variant<std::string> v3; 234 v3 = std::move(v2); 235 BEAST_EXPECT(v2.index() == 0); 236 BEAST_EXPECT(v3.get<1>() == "Hello"); 237 } 238 { 239 variant<Q<1>, Q<2>> v1; 240 variant<Q<1>, Q<2>> v2; 241 v1.emplace<1>(); 242 BEAST_EXPECT(v1.index() == 1); 243 BEAST_EXPECT(Q<1>::count() == 1); 244 v2.emplace<2>(); 245 BEAST_EXPECT(v2.index() == 2); 246 BEAST_EXPECT(Q<2>::count() == 1); 247 v2 = std::move(v1); 248 BEAST_EXPECT(v1.index() == 0); 249 BEAST_EXPECT(v2.index() == 1); 250 BEAST_EXPECT(Q<1>::count() == 1); 251 BEAST_EXPECT(Q<2>::count() == 0); 252 } 253 BEAST_EXPECT(Q<1>::count() == 0); 254 BEAST_EXPECT(Q<2>::count() == 0); 255 { 256 variant<Q<1>> v1; 257 v1.emplace<1>(); 258 BEAST_EXPECT(Q<1>::count() == 1); 259 variant<Q<1>> v2; 260 v2.emplace<1>(); 261 BEAST_EXPECT(Q<1>::count() == 2); 262 v2 = std::move(v1); 263 BEAST_EXPECT(v1.index() == 0); 264 BEAST_EXPECT(v2.index() == 1); 265 BEAST_EXPECT(v2.get<1>().move); 266 BEAST_EXPECT(Q<1>::count() == 1); 267 } 268 BEAST_EXPECT(Q<1>::count() == 0); 269 { 270 variant<Q<1>, Q<2>, Q<3>> v1; 271 v1.emplace<2>(); 272 BEAST_EXPECT(Q<1>::count() == 0); 273 BEAST_EXPECT(Q<2>::count() == 1); 274 BEAST_EXPECT(Q<3>::count() == 0); 275 variant<Q<1>, Q<2>, Q<3>> v2; 276 v2.emplace<2>(); 277 BEAST_EXPECT(Q<1>::count() == 0); 278 BEAST_EXPECT(Q<2>::count() == 2); 279 BEAST_EXPECT(Q<3>::count() == 0); 280 v2 = std::move(v1); 281 BEAST_EXPECT(v1.index() == 0); 282 BEAST_EXPECT(v2.index() == 2); 283 BEAST_EXPECT(v2.get<2>().move); 284 BEAST_EXPECT(Q<1>::count() == 0); 285 BEAST_EXPECT(Q<2>::count() == 1); 286 BEAST_EXPECT(Q<3>::count() == 0); 287 } 288 BEAST_EXPECT(Q<1>::count() == 0); 289 BEAST_EXPECT(Q<2>::count() == 0); 290 BEAST_EXPECT(Q<3>::count() == 0); 291 // copy assign 292 { 293 variant<std::string> v1; 294 BEAST_EXPECT(v1.index() == 0); 295 variant<std::string> v2; 296 v2 = v1; 297 BEAST_EXPECT(v1.index() == 0); 298 BEAST_EXPECT(v2.index() == 0); 299 v2.emplace<1>("Hello"); 300 BEAST_EXPECT(v2.get<1>() == "Hello"); 301 variant<std::string> v3; 302 v3 = v2; 303 BEAST_EXPECT(v2.get<1>() == "Hello"); 304 BEAST_EXPECT(v3.get<1>() == "Hello"); 305 } 306 { 307 variant<Q<1>, Q<2>> v1; 308 variant<Q<1>, Q<2>> v2; 309 v1.emplace<1>(); 310 BEAST_EXPECT(v1.index() == 1); 311 BEAST_EXPECT(Q<1>::count() == 1); 312 v2.emplace<2>(); 313 BEAST_EXPECT(v2.index() == 2); 314 BEAST_EXPECT(Q<2>::count() == 1); 315 v2 = v1; 316 BEAST_EXPECT(v1.index() == 1); 317 BEAST_EXPECT(v2.index() == 1); 318 BEAST_EXPECT(Q<1>::count() == 2); 319 BEAST_EXPECT(Q<2>::count() == 0); 320 } 321 { 322 variant<Q<1>> v1; 323 v1.emplace<1>(); 324 BEAST_EXPECT(Q<1>::count() == 1); 325 variant<Q<1>> v2; 326 v2.emplace<1>(); 327 BEAST_EXPECT(Q<1>::count() == 2); 328 v2 = v1; 329 BEAST_EXPECT(v1.index() == 1); 330 BEAST_EXPECT(v2.index() == 1); 331 BEAST_EXPECT(v2.get<1>().copy); 332 BEAST_EXPECT(Q<1>::count() == 2); 333 } 334 BEAST_EXPECT(Q<1>::count() == 0); 335 { 336 variant<Q<1>, Q<2>, Q<3>> v1; 337 v1.emplace<2>(); 338 BEAST_EXPECT(Q<1>::count() == 0); 339 BEAST_EXPECT(Q<2>::count() == 1); 340 BEAST_EXPECT(Q<3>::count() == 0); 341 variant<Q<1>, Q<2>, Q<3>> v2; 342 v2.emplace<2>(); 343 BEAST_EXPECT(Q<1>::count() == 0); 344 BEAST_EXPECT(Q<2>::count() == 2); 345 BEAST_EXPECT(Q<3>::count() == 0); 346 v2 = v1; 347 BEAST_EXPECT(v1.index() == 2); 348 BEAST_EXPECT(v2.index() == 2); 349 BEAST_EXPECT(v2.get<2>().copy); 350 BEAST_EXPECT(Q<1>::count() == 0); 351 BEAST_EXPECT(Q<2>::count() == 2); 352 BEAST_EXPECT(Q<3>::count() == 0); 353 } 354 BEAST_EXPECT(Q<1>::count() == 0); 355 BEAST_EXPECT(Q<2>::count() == 0); 356 BEAST_EXPECT(Q<3>::count() == 0); 357 // get 358 { 359 variant<std::string> v; 360 v.emplace<1>("Hello"); 361 v.get<1>() = "World!"; 362 BEAST_EXPECT(v.get<1>() == "World!"); 363 } 364 // reset 365 { 366 variant<std::string> v; 367 v.emplace<1>("Hello"); 368 v.reset(); 369 BEAST_EXPECT(v.index() == 0); 370 } 371 { 372 variant<Q<1>> v; 373 BEAST_EXPECT(Q<1>::count() == 0); 374 v.emplace<1>(); 375 BEAST_EXPECT(Q<1>::count() == 1); 376 v.reset(); 377 BEAST_EXPECT(Q<1>::count() == 0); 378 BEAST_EXPECT(v.index() == 0); 379 } 380 { 381 variant<Q<1>, Q<2>, Q<3>> v; 382 BEAST_EXPECT(Q<1>::count() == 0); 383 BEAST_EXPECT(Q<2>::count() == 0); 384 BEAST_EXPECT(Q<3>::count() == 0); 385 v.emplace<2>(); 386 BEAST_EXPECT(Q<1>::count() == 0); 387 BEAST_EXPECT(Q<2>::count() == 1); 388 BEAST_EXPECT(Q<3>::count() == 0); 389 v.reset(); 390 BEAST_EXPECT(Q<1>::count() == 0); 391 BEAST_EXPECT(Q<2>::count() == 0); 392 BEAST_EXPECT(Q<3>::count() == 0); 393 BEAST_EXPECT(v.index() == 0); 394 } 395 BEAST_EXPECT(Q<1>::count() == 0); 396 BEAST_EXPECT(Q<2>::count() == 0); 397 BEAST_EXPECT(Q<3>::count() == 0); 398 399 // basic guarantee 400 { 401 // move 402 variant<Q<1>> v1; 403 v1.emplace<1>(); 404 BEAST_EXPECT(Q<1>::count() == 1); 405 variant<Q<1>> v2; 406 v2.emplace<1>(-1); 407 BEAST_EXPECT(Q<1>::count() == 2); 408 try 409 { 410 v1 = std::move(v2); 411 fail(); 412 } 413 catch(std::exception const&) 414 { 415 BEAST_EXPECT(v1.index() == 0); 416 BEAST_EXPECT(Q<1>::count() == 1); 417 } 418 } 419 BEAST_EXPECT(Q<1>::count() == 0); 420 { 421 // copy 422 variant<Q<1>> v1; 423 v1.emplace<1>(); 424 BEAST_EXPECT(Q<1>::count() == 1); 425 variant<Q<1>> v2; 426 v2.emplace<1>(-1); 427 BEAST_EXPECT(Q<1>::count() == 2); 428 try 429 { 430 v1 = v2; 431 fail(); 432 } 433 catch(std::exception const&) 434 { 435 BEAST_EXPECT(v1.index() == 0); 436 BEAST_EXPECT(Q<1>::count() == 1); 437 } 438 } 439 BEAST_EXPECT(Q<1>::count() == 0); 440 } 441 442 void run()443 run() 444 { 445 testVariant(); 446 } 447 }; 448 449 BEAST_DEFINE_TESTSUITE(beast,core,variant); 450 451 } // detail 452 } // beast 453 } // boost 454