Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/tests/NotNull.test.cpp
2723 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#include "Luau/NotNull.h"
3
4
#include "doctest.h"
5
6
#include <stdio.h>
7
#include <unordered_map>
8
#include <string>
9
10
using Luau::NotNull;
11
12
static_assert(!std::is_convertible<NotNull<int>, bool>::value, "NotNull<T> ought not to be convertible into bool");
13
14
namespace
15
{
16
17
struct Test
18
{
19
int x;
20
float y;
21
22
static int count;
23
Test()
24
{
25
++count;
26
}
27
28
~Test()
29
{
30
--count;
31
}
32
};
33
34
int Test::count = 0;
35
36
} // namespace
37
38
int foo(NotNull<int> p)
39
{
40
return *p;
41
}
42
43
void bar(int* q) {}
44
45
TEST_SUITE_BEGIN("NotNull");
46
47
TEST_CASE("basic_stuff")
48
{
49
NotNull<int> a = NotNull{new int(55)}; // Does runtime test
50
NotNull<int> b{new int(55)}; // As above
51
// NotNull<int> c = new int(55); // Nope. Mildly regrettable, but implicit conversion from T* to NotNull<T> in the general case is not
52
// good.
53
54
// a = nullptr; // nope
55
56
NotNull<int> d = a; // No runtime test. a is known not to be null.
57
58
int e = *d;
59
*d = 1;
60
CHECK(e == 55);
61
62
const NotNull<int> f = d;
63
*f = 5; // valid: there is a difference between const NotNull<T> and NotNull<const T>
64
// f = a; // nope
65
66
CHECK_EQ(a, d);
67
CHECK(a != b);
68
69
NotNull<const int> g(a);
70
CHECK(g == a);
71
72
// *g = 123; // nope
73
74
(void)f;
75
76
NotNull<Test> t{new Test};
77
t->x = 5;
78
t->y = 3.14f;
79
80
const NotNull<Test> u = t;
81
u->x = 44;
82
int v = u->x;
83
CHECK(v == 44);
84
85
bar(a);
86
87
// a++; // nope
88
// a[41]; // nope
89
// a + 41; // nope
90
// a - 41; // nope
91
92
delete a;
93
delete b;
94
delete t;
95
96
CHECK_EQ(0, Test::count);
97
}
98
99
TEST_CASE("hashable")
100
{
101
std::unordered_map<NotNull<int>, const char*> map;
102
int a_ = 8;
103
int b_ = 10;
104
105
NotNull<int> a{&a_};
106
NotNull<int> b{&b_};
107
108
std::string hello = "hello";
109
std::string world = "world";
110
111
map[a] = hello.c_str();
112
map[b] = world.c_str();
113
114
CHECK_EQ(2, map.size());
115
CHECK_EQ(hello.c_str(), map[a]);
116
CHECK_EQ(world.c_str(), map[b]);
117
}
118
119
TEST_CASE("const")
120
{
121
int p = 0;
122
int q = 0;
123
124
NotNull<int> n{&p};
125
126
*n = 123;
127
128
NotNull<const int> m = n; // Conversion from NotNull<T> to NotNull<const T> is allowed
129
130
CHECK(123 == *m); // readonly access of m is ok
131
132
// *m = 321; // nope. m points at const data.
133
134
// NotNull<int> o = m; // nope. Conversion from NotNull<const T> to NotNull<T> is forbidden
135
136
NotNull<int> n2{&q};
137
m = n2; // ok. m points to const data, but is not itself const
138
139
const NotNull<int> m2 = n;
140
// m2 = n2; // nope. m2 is const.
141
*m2 = 321; // ok. m2 is const, but points to mutable data
142
143
CHECK(321 == *n);
144
}
145
146
TEST_CASE("const_compatibility")
147
{
148
int* raw = new int(8);
149
150
NotNull<int> a(raw);
151
NotNull<const int> b(raw);
152
NotNull<const int> c = a;
153
// NotNull<int> d = c; // nope - no conversion from const to non-const
154
155
CHECK_EQ(*c, 8);
156
157
delete raw;
158
}
159
160
TEST_SUITE_END();
161
162