#include "Luau/NotNull.h" #include "doctest.h" #include #include #include using Luau::NotNull; namespace { struct Test { int x; float y; static int count; Test() { ++count; } ~Test() { --count; } }; int Test::count = 0; } int foo(NotNull p) { return *p; } void bar(int* q) {} TEST_SUITE_BEGIN("NotNull"); TEST_CASE("basic_stuff") { NotNull a = NotNull{new int(55)}; // Does runtime test NotNull b{new int(55)}; // As above // NotNull c = new int(55); // Nope. Mildly regrettable, but implicit conversion from T* to NotNull in the general case is not good. // a = nullptr; // nope NotNull d = a; // No runtime test. a is known not to be null. int e = *d; *d = 1; CHECK(e == 55); const NotNull f = d; *f = 5; // valid: there is a difference between const NotNull and NotNull // f = a; // nope CHECK_EQ(a, d); CHECK(a != b); NotNull g(a); CHECK(g == a); // *g = 123; // nope (void)f; NotNull t{new Test}; t->x = 5; t->y = 3.14f; const NotNull u = t; // u->x = 44; // nope int v = u->x; CHECK(v == 5); bar(a); // a++; // nope // a[41]; // nope // a + 41; // nope // a - 41; // nope delete a; delete b; delete t; CHECK_EQ(0, Test::count); } TEST_CASE("hashable") { std::unordered_map, const char*> map; NotNull a{new int(8)}; NotNull b{new int(10)}; std::string hello = "hello"; std::string world = "world"; map[a] = hello.c_str(); map[b] = world.c_str(); CHECK_EQ(2, map.size()); CHECK_EQ(hello.c_str(), map[a]); CHECK_EQ(world.c_str(), map[b]); delete a; delete b; } TEST_SUITE_END();