/////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2015 Microsoft Corporation. All rights reserved. // // This code is licensed under the MIT License (MIT). // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include using namespace Guide; struct MyBase { bool foo() { return true; } }; struct MyDerived : public MyBase {}; struct Unrelated {}; SUITE(MaybeNullTests) { TEST(TestMaybeNull1) { #ifdef CONFIRM_COMPILATION_ERRORS // Forbid non-nullptr assignable types maybe_null_ret> f_ret(std::vector{1}); maybe_null_ret> f_ret(std::vector{1}); maybe_null_ret z_ret(10); maybe_null_dbg> y_dbg({1,2}); maybe_null_dbg z_dbg(10); maybe_null_dbg> y_dbg({1,2}); #endif int n = 5; maybe_null_dbg opt_n(&n); int result = 0; bool threw = false; CHECK_THROW(result = *opt_n, fail_fast); maybe_null_ret> x_ret(std::make_shared(10)); // shared_ptr is nullptr assignable maybe_null_dbg> x_dbg(std::make_shared(10)); // shared_ptr is nullptr assignable } TEST(TestMaybeNull2) { int n = 5; maybe_null opt_n(&n); int result = 0; if (opt_n.present()) result = *opt_n; } TEST(TestMaybeNull3) { int n = 5; maybe_null opt_n(&n); int result = 0; if (opt_n != nullptr) result = *opt_n; } int test4_helper(maybe_null p) { if (p != nullptr) return *p; return -1; } TEST(TestMaybeNull4) { int n = 5; int result = 0; result = test4_helper(&n); } int test5_helper(maybe_null_dbg p) { return *p; } TEST(TestMaybeNull5) { int n = 5; int result = 0; bool threw = false; CHECK_THROW(result = test5_helper(&n), fail_fast); } #ifdef CONFIRM_COMPILATION_ERRORS int TestMaybeNull6() { int n; maybe_null o(n); } #endif int g_int; void test7_helper(maybe_null *> outptr) { g_int = 5; if (outptr.present()) *outptr = &g_int; } void test7b_helper(maybe_null_dbg *> outptr) { g_int = 5; if (outptr.present()) *outptr = &g_int; } TEST(TestMaybeNull7a) { maybe_null outval; test7_helper(&outval); CHECK(outval.present() && *outval == 5); } TEST(TestMaybeNull7b) { maybe_null_dbg outval; test7b_helper(&outval); CHECK_THROW((void)*outval, fail_fast); } int test8_helper1(maybe_null_dbg opt) { return *opt; } int test8_helper2a(maybe_null_dbg opt) { if (!opt.present()) return 0; return test8_helper1(opt); } TEST(TestMaybeNull8a) { int n = 5; maybe_null_dbg opt(&n); CHECK_THROW(test8_helper2a(opt), fail_fast); } #ifdef CONVERT_TO_PTR_TO_CONST int test9_helper(maybe_null copt) { if (copt.present()) return *copt; return 0; } void TestMaybeNull9() { int n = 5; maybe_null opt(&n); CHECK_THROW(test9_helper(opt), fail_fast); } #endif TEST(TestMaybeNullCasting) { MyDerived derived; maybe_null p = &derived; CHECK(p.present()); maybe_null q = p; CHECK(q == p); maybe_null_dbg pdbg = &derived; CHECK(pdbg.present()); maybe_null_dbg qdbg = pdbg; CHECK(qdbg == pdbg); #ifdef CONFIRM_COMPILATION_ERRORS maybe_null r = p; maybe_null s = reinterpret_cast(p); #endif maybe_null_dbg t = reinterpret_cast(p.get()); CHECK_THROW((void)(void*)t.get(), fail_fast); maybe_null_dbg u = reinterpret_cast(p.get()); CHECK(u.present()); CHECK((void*)p.get() == (void*)u.get()); } TEST(TestMaybeNullArrow) { MyDerived derived; maybe_null_dbg p = &derived; CHECK_THROW(p->foo(), fail_fast); CHECK(p.present()); CHECK(p->foo()); maybe_null q = p; CHECK(q.present()); CHECK(q->foo()); } TEST(TestMaybeNullCompare) { int i1 = 1; int i2 = 2; maybe_null_dbg p1 = &i1; maybe_null_dbg p1_2 = &i1; maybe_null_dbg p2 = &i2; CHECK_THROW(p1.get(), fail_fast); CHECK_THROW(p1_2.get(), fail_fast); CHECK_THROW(p2.get(), fail_fast); CHECK(p1 != p2); CHECK(!(p1 == p2)); CHECK(p1 == p1); CHECK(p1 == p1_2); // Make sure we no longer throw here CHECK(p1.get() != nullptr); CHECK(p1_2.get() != nullptr); CHECK(p2.get() != nullptr); } TEST(TestMaybeNullCopy) { int i1 = 1; int i2 = 2; maybe_null_dbg p1 = &i1; maybe_null_dbg p1_2 = &i1; maybe_null_dbg p2 = &i2; CHECK(p1 != p2); CHECK(p1 == p1_2); // Make sure we no longer throw here CHECK(p1.get() != nullptr); CHECK(p2.get() != nullptr); p1 = p2; // Make sure we now throw CHECK_THROW(p1.get(), fail_fast); CHECK(p1 == p2); CHECK(p1 != p1_2); // Make sure we no longer throw here CHECK(p1.get() != nullptr); } TEST(TestMaybeNullAssignmentOps) { MyBase base; MyDerived derived; Unrelated unrelated; not_null nnBase(&base); not_null nnDerived(&derived); not_null nnUnrelated(&unrelated); maybe_null_ret mnBase_ret1(&base), mnBase_ret2; mnBase_ret2 = mnBase_ret1; // maybe_null_ret = maybe_null_ret mnBase_ret2 = nnBase; // maybe_null_ret = not_null maybe_null_ret mnDerived_ret(&derived); mnBase_ret2 = mnDerived_ret; // maybe_null_ret = maybe_null_ret mnBase_ret1 = &derived; // maybe_null_ret = U; mnBase_ret1 = nnDerived; // maybe_null_ret = not_null maybe_null_ret mnUnrelated_ret; mnUnrelated_ret = &unrelated; // maybe_null_ret = T maybe_null_dbg mnBase_dbg1(&base), mnBase_dbg2; mnBase_dbg2 = mnBase_dbg1; // maybe_null_dbg = maybe_null_dbg mnBase_dbg2 = nnBase; // maybe_null_dbg = not_null maybe_null_dbg mnDerived_dbg(&derived); mnBase_dbg2 = mnDerived_dbg; // maybe_null_dbg = maybe_null_dbg mnBase_dbg1 = &derived; // maybe_null_dbg = U; mnBase_dbg1 = nnDerived; // maybe_null_dbg = not_null maybe_null_dbg mnUnrelated_dbg; mnUnrelated_dbg = &unrelated; // maybe_null_dbg = T } } int main(int, const char *[]) { return UnitTest::RunAllTests(); }