-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_ntbs.cpp
195 lines (165 loc) · 5.36 KB
/
test_ntbs.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include "ntbs.hpp"
using namespace ltl;
static_assert( ntbs::cat( ntbs::cat<',',' '>("Hello","world"), '!')
== "Hello, world!" );
// test 'size' and 'data' overloads
static_assert( ntbs::size('c') == 2 );
static_assert( *ntbs::data('c') == 'c' );
constexpr char c = 'c';
static_assert( ntbs::size(c) == 2 );
static_assert( *ntbs::data(c) == 'c' );
static_assert( ntbs::size("c") == 2 );
static_assert( ntbs::array{"c"} == ntbs::data("c") );
constexpr auto& c0 = "c";
static_assert( ntbs::size(c0) == 2 );
static_assert( ntbs::data(c0) == c0 );
constexpr char d0[] = "d";
static_assert( ntbs::size(d0) == 2 );
static_assert( ntbs::data(d0) == d0 );
static_assert( ntbs::size(decltype(d0){}) == 2 );
static_assert( *ntbs::data(decltype(d0){}) == '\0' );
constexpr auto a0 = ntbs::array{"a"};
static_assert( sizeof a0 == 2 );
static_assert( size(a0) == 2 );
static_assert( data(a0) == a0 );
// Note that iteration includes null terminator, just as for char[N]
//
constexpr auto test_range_for_iterate = [](auto const& a)
{
int i = 0;
for (auto&& e : a)
i += (e == "hi"[i]);
return i == sizeof(a) && a[i-1] == 0;
};
static_assert( test_range_for_iterate("hi") );
static_assert( test_range_for_iterate(ntbs::array{"hi"}) );
constexpr auto test_sized_iterate = [](auto const& a)
{
int i = 0;
while ( i != size(a) )
++i;
return i == sizeof(a) && a[i-1] == 0;
};
static_assert( test_sized_iterate(ntbs::array{"ho"}) );
// test cats producing null array
constexpr auto null = ntbs::cat();
static_assert( null == "" );
static_assert( null == ntbs::cat(""));
static_assert( sizeof null == 1 );
static_assert( size(null) == 1 );
static_assert( null[0] == 0 );
// test cats producing single null-terminated char
constexpr auto car = ntbs::cat('c');
constexpr auto cas = ntbs::cat("c");
constexpr auto cac = cat(car); // ADL
static_assert( car == cas );
static_assert( car == cac );
static_assert( sizeof car == 2 );
static_assert( size(car) == 2 );
// test cat multi-char string-literal and returned array type
constexpr auto hello = ntbs::cat("hello");
constexpr auto hollo = cat(hello);
static_assert( hello == "hello" );
static_assert( hollo == "hello" );
static_assert( sizeof hello == 6 );
static_assert( size(hello) == 6 );
// test null cut
constexpr auto cul = ntbs::cut("");
static_assert( cul == ntbs::cut<0>("") );
static_assert( cul == ntbs::cut<-1>("") );
static_assert( cul == ntbs::cut<0,0>("") );
static_assert( cul == ntbs::cut<0,-1>("") );
static_assert( cul == ntbs::cut<-1,0>("") );
static_assert( cul == ntbs::cut<-1,-1>("") );
static_assert( sizeof cul == 1 && cul[0] == 0);
// test cut of single char
constexpr auto cut1 = ntbs::cut("c");
static_assert( cut1 == "c" );
static_assert( cut(cut1) == "c" );
static_assert( ntbs::cut<0>(cut1) == "c" ); // No ADL with explicit Args
static_assert( ntbs::cut<-2>(cut1) == "c" );
static_assert( ntbs::cut<-2,-1>(cut1) == "c" );
static_assert( sizeof cut1 == 2 );
static_assert( size(cut1) == 2 );
// test cut of multi-char string-literal
constexpr auto hullo = ntbs::cut("hello");
constexpr auto hullu = cut(hello);
static_assert( hullo == "hello" );
static_assert( hullu == "hello" );
// test lexicographic cmp
static_assert( ntbs::cmp("","") == 0 );
static_assert( ntbs::cmp("","a") < 0 );
static_assert( ntbs::cmp("a","a") == 0 );
static_assert( ntbs::cmp("a","aa") < 0 );
static_assert( ntbs::cmp("aa","a") > 0 );
static_assert( ntbs::cmp("a\0","a") == 0 ); // Embedded null, cmp equal
static_assert( ntbs::cat("a\0") != "a" ); // Embedded null, != unequal
// Little cats
static_assert( ntbs::cat('a','b') == "ab" );
static_assert( ntbs::cat('a',"b") == "ab" );
static_assert( ntbs::cat("a",'b') == "ab" );
static_assert( ntbs::cat("a","b") == "ab" );
// 'Big Cat' for compile time benchmarking
// (MSVC 19.2 warns that the K64 declaration will use 64K stack
// and the K256 big cat fails)
//
//constexpr ntbs::array<65536> K64{};
//constexpr auto K256 = cat(K64, K64, K64, K64); // 1.1s
//static_assert(size(K256) == 262144 - 3);
/* Runtime tests */
// If ntbs.hpp is compiled with NTBS_NULL_CHECK = 1
// then null checks are enabled (follows NDEBUG by default)
// and these tests with non-null terminated arrays should throw
// yielding a compile error in constexpr evaluation
// or an exception at runtime.
//
auto test_cat_throw = []
{
const char* thrown = nullptr;
using char5 = char[5];
try {
ntbs::cat(char5{'t','h','r','o','w'});
}
catch (const char* str)
{
thrown = str;
}
return thrown;
};
auto test_cut_throw = []
{
const char* thrown = nullptr;
using char5 = char[5];
try {
ntbs::cut(char5{'t','h','r','o','w'});
}
catch (const char* str)
{
thrown = str;
}
return thrown;
};
#include <cassert>
#include <cstdio>
int main()
{
auto cat_threw = test_cat_throw();
auto cut_threw = test_cut_throw();
if (cat_threw) puts(cat_threw);
if (cut_threw) puts(cut_threw);
using ntbs::cat;
using ntbs::array;
// cmp of non-null-terminated array fails in constexpr evaluation
//static_assert( cmp(array<1>{'!'},array<1>{'!'}) == 0 ); // FAIL
auto mut = cat("Hello");
mut[5] = '!'; // write over null terminator
#if NTBS_NULL_CHECK
try { cmp(mut,mut); }
catch (const char* str) { puts(str); }
assert( cat_threw );
assert( cut_threw );
#else
assert( ! cat_threw );
assert( ! cut_threw );
#endif
}