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

one-of-test.c++ (6023B)


      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 "one-of.h"
     23 #include "string.h"
     24 #include <kj/compat/gtest.h>
     25 
     26 namespace kj {
     27 
     28 TEST(OneOf, Basic) {
     29   OneOf<int, float, String> var;
     30 
     31   EXPECT_FALSE(var.is<int>());
     32   EXPECT_FALSE(var.is<float>());
     33   EXPECT_FALSE(var.is<String>());
     34   EXPECT_TRUE(var.tryGet<int>() == nullptr);
     35   EXPECT_TRUE(var.tryGet<float>() == nullptr);
     36   EXPECT_TRUE(var.tryGet<String>() == nullptr);
     37 
     38   var.init<int>(123);
     39 
     40   EXPECT_TRUE(var.is<int>());
     41   EXPECT_FALSE(var.is<float>());
     42   EXPECT_FALSE(var.is<String>());
     43 
     44   EXPECT_EQ(123, var.get<int>());
     45 #if !KJ_NO_EXCEPTIONS && defined(KJ_DEBUG)
     46   EXPECT_ANY_THROW(var.get<float>());
     47   EXPECT_ANY_THROW(var.get<String>());
     48 #endif
     49 
     50   EXPECT_EQ(123, KJ_ASSERT_NONNULL(var.tryGet<int>()));
     51   EXPECT_TRUE(var.tryGet<float>() == nullptr);
     52   EXPECT_TRUE(var.tryGet<String>() == nullptr);
     53 
     54   var.init<String>(kj::str("foo"));
     55 
     56   EXPECT_FALSE(var.is<int>());
     57   EXPECT_FALSE(var.is<float>());
     58   EXPECT_TRUE(var.is<String>());
     59 
     60   EXPECT_EQ("foo", var.get<String>());
     61 
     62   EXPECT_TRUE(var.tryGet<int>() == nullptr);
     63   EXPECT_TRUE(var.tryGet<float>() == nullptr);
     64   EXPECT_EQ("foo", KJ_ASSERT_NONNULL(var.tryGet<String>()));
     65 
     66   OneOf<int, float, String> var2 = kj::mv(var);
     67   EXPECT_EQ("", var.get<String>());
     68   EXPECT_EQ("foo", var2.get<String>());
     69 
     70   var = kj::mv(var2);
     71   EXPECT_EQ("foo", var.get<String>());
     72   EXPECT_EQ("", var2.get<String>());
     73 
     74   auto canCompile KJ_UNUSED = [&]() {
     75     var.allHandled<3>();
     76     // var.allHandled<2>();  // doesn't compile
     77   };
     78 }
     79 
     80 TEST(OneOf, Copy) {
     81   OneOf<int, float, const char*> var;
     82 
     83   OneOf<int, float, const char*> var2 = var;
     84   EXPECT_FALSE(var2.is<int>());
     85   EXPECT_FALSE(var2.is<float>());
     86   EXPECT_FALSE(var2.is<const char*>());
     87 
     88   var.init<int>(123);
     89 
     90   var2 = var;
     91   EXPECT_TRUE(var2.is<int>());
     92   EXPECT_EQ(123, var2.get<int>());
     93 
     94   var.init<const char*>("foo");
     95 
     96   var2 = var;
     97   EXPECT_TRUE(var2.is<const char*>());
     98   EXPECT_STREQ("foo", var2.get<const char*>());
     99 }
    100 
    101 TEST(OneOf, Switch) {
    102   OneOf<int, float, const char*> var;
    103   var = "foo";
    104   uint count = 0;
    105 
    106   {
    107     KJ_SWITCH_ONEOF(var) {
    108       KJ_CASE_ONEOF(i, int) {
    109         KJ_FAIL_ASSERT("expected char*, got int", i);
    110       }
    111       KJ_CASE_ONEOF(s, const char*) {
    112         KJ_EXPECT(kj::StringPtr(s) == "foo");
    113         ++count;
    114       }
    115       KJ_CASE_ONEOF(n, float) {
    116         KJ_FAIL_ASSERT("expected char*, got float", n);
    117       }
    118     }
    119   }
    120 
    121   KJ_EXPECT(count == 1);
    122 
    123   {
    124     KJ_SWITCH_ONEOF(kj::cp(var)) {
    125       KJ_CASE_ONEOF(i, int) {
    126         KJ_FAIL_ASSERT("expected char*, got int", i);
    127       }
    128       KJ_CASE_ONEOF(s, const char*) {
    129         KJ_EXPECT(kj::StringPtr(s) == "foo");
    130       }
    131       KJ_CASE_ONEOF(n, float) {
    132         KJ_FAIL_ASSERT("expected char*, got float", n);
    133       }
    134     }
    135   }
    136 
    137   {
    138     // At one time this failed to compile.
    139     const auto& constVar = var;
    140     KJ_SWITCH_ONEOF(constVar) {
    141       KJ_CASE_ONEOF(i, int) {
    142         KJ_FAIL_ASSERT("expected char*, got int", i);
    143       }
    144       KJ_CASE_ONEOF(s, const char*) {
    145         KJ_EXPECT(kj::StringPtr(s) == "foo");
    146       }
    147       KJ_CASE_ONEOF(n, float) {
    148         KJ_FAIL_ASSERT("expected char*, got float", n);
    149       }
    150     }
    151   }
    152 }
    153 
    154 TEST(OneOf, Maybe) {
    155   Maybe<OneOf<int, float>> var;
    156   var = OneOf<int, float>(123);
    157 
    158   KJ_IF_MAYBE(v, var) {
    159     // At one time this failed to compile. Note that a Maybe<OneOf<...>> isn't necessarily great
    160     // style -- you might be better off with an explicit OneOf<Empty, ...>. Nevertheless, it should
    161     // compile.
    162     KJ_SWITCH_ONEOF(*v) {
    163       KJ_CASE_ONEOF(i, int) {
    164         KJ_EXPECT(i == 123);
    165       }
    166       KJ_CASE_ONEOF(n, float) {
    167         KJ_FAIL_ASSERT("expected int, got float", n);
    168       }
    169     }
    170   }
    171 }
    172 
    173 KJ_TEST("OneOf copy/move from alternative variants") {
    174   {
    175     // Test const copy.
    176     const OneOf<int, float> src = 23.5f;
    177     OneOf<int, bool, float> dst = src;
    178     KJ_ASSERT(dst.is<float>());
    179     KJ_EXPECT(dst.get<float>() == 23.5);
    180   }
    181 
    182   {
    183     // Test case that requires non-const copy.
    184     int arr[3] = {1, 2, 3};
    185     OneOf<int, ArrayPtr<int>> src = ArrayPtr<int>(arr);
    186     OneOf<int, bool, ArrayPtr<int>> dst = src;
    187     KJ_ASSERT(dst.is<ArrayPtr<int>>());
    188     KJ_EXPECT(dst.get<ArrayPtr<int>>().begin() == arr);
    189     KJ_EXPECT(dst.get<ArrayPtr<int>>().size() == kj::size(arr));
    190   }
    191 
    192   {
    193     // Test move.
    194     OneOf<int, String> src = kj::str("foo");
    195     OneOf<int, bool, String> dst = kj::mv(src);
    196     KJ_ASSERT(dst.is<String>());
    197     KJ_EXPECT(dst.get<String>() == "foo");
    198 
    199     String s = kj::mv(dst).get<String>();
    200     KJ_EXPECT(s == "foo");
    201   }
    202 
    203   {
    204     // We can still have nested OneOfs.
    205     OneOf<int, float> src = 23.5f;
    206     OneOf<bool, OneOf<int, float>> dst = src;
    207     KJ_ASSERT((dst.is<OneOf<int, float>>()));
    208     KJ_ASSERT((dst.get<OneOf<int, float>>().is<float>()));
    209     KJ_EXPECT((dst.get<OneOf<int, float>>().get<float>() == 23.5));
    210   }
    211 }
    212 
    213 }  // namespace kj