1
1
// ADDITIONAL_COMPILE_FLAGS: -std=c++26 -Xclang -fcontracts -fcontract-evaluation-semantic=enforce
2
+ // -fcontract-group-evaluation-semantic=observe=observe,enforce=enforce
2
3
3
4
#include " nttp_string.h"
4
- #include < map>
5
- #include < string>
6
- #include < cassert>
7
- #include < tuple>
8
- #include < vector>
9
- #include < exception>
10
- #include < format>
11
- #include < functional>
12
- #include < iostream>
13
-
14
- #include " test_macros.h"
15
- #pragma GCC diagnostic ignored "-Wunused-variable"
16
- #pragma GCC diagnostic ignored "-Wunused"
17
- #pragma GCC diagnostic ignored "-Wunused-template"
18
- #pragma GCC diagnostic ignored "-Wunused-parameter"
19
-
20
- #define STR2 (x ) #x
21
- #define STR (x ) STR2(x)
22
- #define CONCAT1 (x, y ) x##y
23
- #define CONCAT (x, y ) CONCAT1(x, y)
24
-
25
- #define REGISTER_TEST (test ) static ::TestRegistrar ANON_VAR (test) = []()
26
-
27
- #define ANON_VAR (id ) CONCAT(anon_var_, CONCAT(id, __LINE__))
28
-
29
- #define COUNTERS_EQ (list, ...) assert(eq(list, {__VA_ARGS__}))
30
-
31
- std::map<std::string, int >& GetCounterStore () {
32
- static std::map<std::string, int > CounterStore;
33
- return CounterStore;
34
- }
35
-
36
- template <TStr Key>
37
- auto & KV = GetCounterStore()[Key.str()];
38
-
39
- inline bool count (bool value) {
40
- KV<" AssertCounter" > += 1 ;
41
- return value;
42
- }
43
-
44
- template <class T , size_t ... N>
45
- auto array_to_tuple_impl (const T* arr, std::index_sequence<N...>) {
46
- return std::tuple{arr[N]...};
47
- }
48
-
49
- template <class T , size_t N>
50
- auto array_to_tuple (T (&arr)[N]) {
51
- return array_to_tuple_impl (arr, std::make_index_sequence<N>{});
52
- }
53
-
54
- template <class T , size_t N>
55
- auto array_to_tuple (const std::array<T, N>& arr) {
56
- return array_to_tuple_impl (arr.data (), std::make_index_sequence<N>{});
57
- }
58
- template <class ... Args>
59
- struct first_type ;
60
-
61
- template <class T , class ... Args>
62
- struct first_type <T, Args...> {
63
- using type = T;
64
- static_assert ((std::is_same_v<T, Args> && ...));
65
- };
66
- template <class T >
67
- struct first_type <T> {
68
- using type = T;
69
- };
70
- template <class ... Args>
71
- using first_type_t = typename first_type<Args...>::type;
72
-
73
- template <class ... Args>
74
- std::vector<first_type_t <Args...>> tuple_to_vector (std::tuple<Args...> const & tuple) {
75
- return std::apply (
76
- [](auto ... values) {
77
- std::vector<first_type_t <Args...>> result;
78
- (result.push_back (values), ...);
79
- return result;
80
- },
81
- tuple);
82
- }
83
-
84
- template <size_t N, class T >
85
- auto initlist_to_tuple (std::initializer_list<T> il) {
86
- assert (il.size () == N);
87
- std::array<T, N> arr = {};
88
- std::copy (il.begin (), il.end (), arr.begin ());
89
- return array_to_tuple (arr);
90
- }
91
-
92
- template <class T >
93
- std::string vector_to_str (std::vector<T> const & V) {
94
- std::string tmp = " [" ;
95
- bool first = true ;
96
- for (auto vv : V) {
97
- if (!first) {
98
- tmp += " , " ;
99
- }
100
- first = false ;
101
- tmp += std::to_string (vv);
102
- }
103
- return tmp + " ]" ;
104
- }
105
-
106
- template <class ... Args>
107
- inline bool eq (std::tuple<Args...>& list, std::initializer_list<int > il) {
108
- auto tup2 = initlist_to_tuple<sizeof ...(Args)>(il);
109
- decltype (tup2) tup3 = list;
110
- bool result = (list == tup2);
111
- if (!result) {
112
- std::string expect_str = vector_to_str (tuple_to_vector (tup2));
113
- std::string actual_str = vector_to_str (tuple_to_vector (tup3));
114
-
115
- std::cout << " Expected: " << expect_str << " \n " ;
116
- std::cout << " Actual: " << actual_str << " \n " ;
117
- std::cout << std::endl;
118
- }
119
- return result;
120
- }
121
-
122
- template <class ... Args>
123
- inline void reset (std::tuple<Args&...> const & list) {
124
- int values[sizeof ...(Args)] = {};
125
- list = array_to_tuple (values);
126
- }
127
-
128
- struct RegisteredTest {
129
- template <class Func >
130
- RegisteredTest (Func xtest) {
131
- Test = xtest;
132
- }
133
-
134
- void operator ()() {
135
- assert (!executed);
136
- Test ();
137
- executed = true ;
138
- }
139
-
140
- RegisteredTest (RegisteredTest const &) = delete ;
141
- RegisteredTest (RegisteredTest&&) = delete ;
142
- ~RegisteredTest () { assert (executed); }
143
-
144
- std::function<void ()> Test;
145
- bool executed = false ;
146
- };
147
-
148
- struct TestRegistrar {
149
- static std::vector<RegisteredTest*>& GetTests () {
150
- static std::vector<RegisteredTest*> TestRegistrars;
151
- return TestRegistrars;
152
- }
153
-
154
- static void RunTests () {
155
- std::cout << " Running " << GetTests ().size () << " tests\n " ;
156
- assert (GetTests ().size () > 0 );
157
- for (auto * Reg : GetTests ()) {
158
- (*Reg)();
159
- }
160
- }
161
-
162
- template <class Func >
163
- TestRegistrar (Func&& f) {
164
- test = new RegisteredTest (std::forward<Func>(f));
165
- GetTests ().push_back (test);
166
- }
167
-
168
- TestRegistrar (TestRegistrar const &) = delete ;
169
-
170
- ~TestRegistrar () { assert (test->executed ); }
171
-
172
- RegisteredTest* test = nullptr ;
173
- };
174
-
175
- struct CounterStoreT {
176
- decltype (auto ) get() { return GetCounterStore (); }
177
-
178
- decltype (auto ) operator [](std::string_view key) { return get ()[std::string (key)]; }
179
-
180
- decltype (auto ) at(std::string_view key) { return get ().at (std::string (key)); }
181
-
182
- std::map<std::string, int >* operator ->() { return &get (); }
183
- };
184
- constinit CounterStoreT CounterStore;
185
-
186
- template <auto , class T >
187
- using AsType = T;
188
-
189
- template <TStr Key>
190
- auto Counter = std::ref(CounterStore[Key.str()]);
191
-
192
- template <TStr... Key>
193
- auto CounterGroup = std::tuple<AsType<Key, int &>...>{GetCounterStore ()[Key.str ()]...};
194
-
195
- struct AliveCounter {
196
- explicit AliveCounter (const char * key) : Counter(&CounterStore[key]) {
197
- assert (Counter && *Counter >= 0 );
198
- *Counter += 1 ;
199
- }
200
-
201
- AliveCounter (nullptr_t ) = delete ;
202
- AliveCounter (void *) = delete ;
203
-
204
- constexpr AliveCounter (int * dest) : Counter(dest) {
205
- assert (Counter && *Counter >= 0 );
206
- *Counter += 1 ;
207
- }
208
-
209
- constexpr AliveCounter (AliveCounter const & RHS) : Counter(RHS.Counter) {
210
- assert (Counter && *Counter >= 0 );
211
- *Counter += 1 ;
212
- }
213
-
214
- ~AliveCounter () {
215
- assert (*Counter >= 1 );
216
- *Counter -= 1 ;
217
- }
218
-
219
- int * Counter;
220
- };
221
-
222
- template <TStr Key>
223
- struct CAliveCounter : private AliveCounter {
224
- CAliveCounter () : AliveCounter(&KV<Key>) {}
225
- CAliveCounter (CAliveCounter const & RHS) : AliveCounter(RHS) {}
226
-
227
- ~CAliveCounter () = default ;
228
- };
5
+ #include " contracts_test.h"
229
6
230
7
namespace fn_template_test {
231
8
template <class T >
@@ -421,6 +198,21 @@ REGISTER_TEST(order_test) {
421
198
422
199
} // namespace order_test
423
200
201
+ namespace exception_handling {
202
+
203
+ void foo (int x) {
204
+ try {
205
+ contract_assert [[clang::contract_group (" observe" )]] ((true ) ? throw 42 : true );
206
+
207
+ } catch (...) {
208
+ assert (false );
209
+ }
210
+ }
211
+
212
+ REGISTER_TEST (test_ex_handling) { foo (0 ); };
213
+
214
+ } // namespace exception_handling
215
+
424
216
#define ASSERT_CEQ (key, value ) assert(GetCounterStore().at(STR(KEY)) == value)
425
217
#define massert (...) assert((__VA_ARGS__))
426
218
int main () { TestRegistrar::RunTests (); }
0 commit comments