File Coverage

t/function.cc
Criterion Covered Total %
statement 255 270 94.4
branch 412 1062 38.7
condition n/a
subroutine n/a
pod n/a
total 667 1332 50.0


line stmt bran cond sub pod time code
1             #include "test.h"
2             #include
3             #include
4             #include
5             #include
6              
7             using panda::function;
8             using panda::make_function;
9             using panda::iptr;
10             using panda::function_details::make_method;
11             using panda::function_details::tmp_abstract_function;
12             using test::Tracer;
13              
14             namespace test {
15              
16              
17 0           void void_func(){}
18 0           void void_func2(){}
19 0           void func_int(int){}
20 0           void func_int16(int16_t){}
21 0           void func_double(int){}
22              
23 2           int foo2() {return 1;}
24 4           int plus_one(int a) { return a + 1;}
25              
26 48 50         class Test : public panda::Refcnt {
27             public:
28             int value = 0;
29              
30 8           Test(int value) : value(value) {}
31 12           Test() : value(0) {}
32              
33 0           void foo(int) {}
34 0           void foo2(int) {}
35 4           int bar() {return value + 40;}
36              
37 0           int operator()(int v) {return v;}
38 6           bool operator == (const Test& oth) const { return value == oth.value;}
39             };
40             }
41              
42             using namespace test;
43              
44 19           TEST_CASE("simplest function", "[function]") {
45 2 50         function f = &void_func;
46 1 50         REQUIRE(true);
    50          
    50          
    50          
    0          
    0          
47 1           }
48              
49 19           TEST_CASE("simplest function call", "[function]") {
50 2 50         function f;
51 1 50         f = &plus_one;
    50          
52 1 50         REQUIRE(f(1) == 2);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
53 1           }
54              
55 19           TEST_CASE("function by reference call", "[function]") {
56 2 50         function f;
57 1 50         f = plus_one;
    50          
58 1 50         REQUIRE(f(1) == 2);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
59 1           }
60              
61 19           TEST_CASE("simplest lambda call", "[function]") {
62 1           int a = 13;
63 4 50         function f = [&](){return a;};
64 1 50         REQUIRE(f() == 13);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
65 1           }
66              
67 19           TEST_CASE("simplest method call", "[function]") {
68 2 50         iptr t = new Test();
    50          
69 1           t->value = 14;
70 2 50         auto m = make_function(&Test::bar, t);
71 1 50         REQUIRE(m() == 54);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
72 1           }
73              
74 19           TEST_CASE("mixedcall", "[function]") {
75 2 50         iptr t = new Test();
    50          
76 1           t->value = 14;
77 2 50         auto f = make_function(&Test::bar, t);
78 1 50         REQUIRE(f() == 54);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
79              
80 1 50         f = &foo2;
    50          
81 1 50         REQUIRE(f() == 1);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
82              
83 1           int a = 13;
84 3 50         f = [&](){return a;};
    50          
85 1 50         REQUIRE(f() == 13);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
86 1           }
87              
88 19           TEST_CASE("function ptr comparations", "[function]") {
89 2 50         function f1_void = &void_func;
90 2 50         function f2_void = &void_func;
91 2 50         function f3_void = &void_func2;
92              
93 1 50         REQUIRE(f1_void == f2_void);
    50          
    50          
    50          
    50          
    0          
    0          
94 1 50         REQUIRE(f1_void != f3_void);
    50          
    50          
    50          
    50          
    0          
    0          
95              
96 1 50         REQUIRE(f1_void == tmp_abstract_function(&void_func));
    50          
    50          
    50          
    50          
    50          
    0          
    0          
97 1 50         REQUIRE(f1_void != tmp_abstract_function(&void_func2));
    50          
    50          
    50          
    50          
    50          
    0          
    0          
98 1           }
99              
100 19           TEST_CASE("function ptr comparations covariant", "[function]") {
101             struct Int {
102 0           void operator()(int) {}
103 1           bool operator==(const Int&) const {
104 1           return true;
105             }
106             };
107              
108 2 50         function f1(&func_int);
109 2 50         function f2(&func_int);
110 2 50         function f3(&func_double);
111 2 50         function f4(&func_int);
112              
113 1 50         CHECK(f1 == f2);
    50          
    50          
    50          
    50          
    0          
    0          
114 1 50         CHECK(f1 != f3);
    50          
    50          
    50          
    50          
    0          
    0          
115 1 50         CHECK(f2 != f3);
    50          
    50          
    50          
    50          
    0          
    0          
116 1 50         CHECK(f2 == f4);
    50          
    50          
    50          
    50          
    0          
    0          
117              
118             Int i;
119 2 50         function ff1(i);
120 2 50         function ff2(i);
121              
122 1 50         CHECK(ff1 == ff2);
    50          
    50          
    50          
    50          
    0          
    0          
123 1           }
124              
125 19           TEST_CASE("function covariant copy comparations", "[function]") {
126 1           bool called = false;
127 0           auto lambda = [&](int a) {
128 0           called = true;
129 0           return a;
130 1           };
131              
132 2 50         function f1 = lambda;
133 2 50         function f2(f1);
134 1 50         CHECK(f1 == f2);
    50          
    50          
    50          
    50          
    0          
    0          
135 1 50         CHECK(f2 == f1);
    50          
    50          
    50          
    50          
    0          
    0          
136 1           }
137              
138 19           TEST_CASE("methods comparations", "[function]") {
139 2 50         iptr t = new Test();
    50          
140 2 50         auto m1 = make_function(&Test::foo, t);
141 2 50         auto m2 = make_method(&Test::foo);
142 1 50         REQUIRE(m1 != *m2);
    50          
    50          
    50          
    50          
    0          
    0          
143              
144 1 50         m2->bind(t);
145 1 50         REQUIRE(m1 == function(m2));
    50          
    50          
    50          
    50          
    50          
    0          
    0          
146              
147 2 50         iptr t2 = new Test();
    50          
148 1 50         m2->bind(t2);
149 1 50         REQUIRE(m1 != *m2);
    50          
    50          
    50          
    50          
    0          
    0          
150              
151 2 50         auto m3 = make_method(&Test::foo2);
152 1 50         REQUIRE(m1 != *m3);
    50          
    50          
    50          
    50          
    0          
    0          
153              
154 1           }
155              
156 19           TEST_CASE("lambdas comparations", "[function]") {
157 1           int a = 10;
158 2 50         function l1 = [&](){return a;};
159 2 50         auto l2 = l1;
160 2 50         function l3 = [&](){return a;};
161              
162 1 50         REQUIRE(l1 == l2);
    50          
    50          
    50          
    50          
    0          
    0          
163 1 50         REQUIRE(l1 != l3);
    50          
    50          
    50          
    50          
    0          
    0          
164 1           }
165              
166 19           TEST_CASE("mixed function comparations", "[function]") {
167 1           int a = 10;
168 2 50         function l = [&](){return a;};
169 2 50         function f = &foo2;
170 2 50         iptr t = new Test();
    50          
171 2 50         auto m = make_function(&Test::bar, t);
172              
173 1 50         REQUIRE(l != f);
    50          
    50          
    50          
    50          
    0          
    0          
174 1 50         REQUIRE(m != l);
    50          
    50          
    50          
    50          
    0          
    0          
175 1 50         REQUIRE(m != f);
    50          
    50          
    50          
    50          
    0          
    0          
176 1           }
177              
178 19           TEST_CASE("null function comparations", "[function]") {
179 1           int a = 10;
180 2 50         function n;
181 2 50         function l = [&](){return a;};
182 2 50         function f = &foo2;
183 2 50         iptr t = new Test();
    50          
184 2 50         auto m = make_function(&Test::bar, t);
185              
186 1 50         REQUIRE_FALSE(l == n);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
187 1 50         REQUIRE_FALSE(f == n);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
188 1 50         REQUIRE_FALSE(m == n);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
189              
190 1 50         REQUIRE_FALSE(n == l);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
191 1 50         REQUIRE_FALSE(n == f);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
192 1 50         REQUIRE_FALSE(n == m);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
193 1           }
194              
195 19           TEST_CASE("functors comparations", "[function]") {
196 2 50         function f1 = Test(1);
    50          
197 2 50         function f2 = Test(2);
    50          
198 2 50         function f11 = Test(1);
    50          
199              
200 1 50         REQUIRE(f1 != f2);
    50          
    50          
    50          
    50          
    0          
    0          
201 1 50         REQUIRE(f1 == f11);
    50          
    50          
    50          
    50          
    0          
    0          
202              
203 2 50         auto tmp1 = tmp_abstract_function(Test(1)); // inited from rvalue
    50          
204 1 50         REQUIRE(f1 == tmp1);
    50          
    50          
    50          
    50          
    0          
    0          
205 1           }
206              
207 19           TEST_CASE("function copy ellision", "[function]") {
208 1           Tracer::refresh();
209             {
210 2 50         function f = Tracer(10);
211 2 50         auto f2 = f;
212 1 50         f(11);
213 1 50         f2(12);
214             }
215 1 50         REQUIRE(Tracer::ctor_calls == 1); // 1 for temporary object Tracer(10);
    50          
    50          
    50          
    50          
    0          
    0          
216 1 50         REQUIRE(Tracer::copy_calls == 0);
    50          
    50          
    50          
    50          
    0          
    0          
217 1 50         REQUIRE(Tracer::move_calls == 1); // 1 construction from tmp object function f = Tracer(10);
    50          
    50          
    50          
    50          
    0          
    0          
218 1 50         REQUIRE(Tracer::dtor_calls == 2);
    50          
    50          
    50          
    50          
    0          
    0          
219 1           }
220              
221 19           TEST_CASE("covariant return type optional" , "[function]") {
222 2           function (int)> cb = [](int a) -> int {
223 1           return a;
224 3 50         };
225 1 50         REQUIRE(cb(3).value_or(42) == 3);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
226 1           }
227              
228 19           TEST_CASE("covariant return type double" , "[function]") {
229 2           function cb = [](int a) -> int {
230 1           return a;
231 3 50         };
232 1 50         REQUIRE(cb(3) == 3.0);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
233 1           }
234              
235 19           TEST_CASE("contravariance of arguments" , "[function]") {
236 2           function cb = [](double) -> int {
237 1           return 10;
238 3 50         };
239 1 50         REQUIRE(cb(3) == 10);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
240 1           }
241             struct Base {
242 0 0         virtual ~Base(){}
243 0 0         virtual panda::string name() { return "base";}
244             };
245 2 50         struct Derrived : Base {
246 2 50         virtual panda::string name() override { return "override";}
247             };
248              
249 19           TEST_CASE("contravariance of arguments classes" , "[function]") {
250             using panda::string;
251 2           function cb = [](Base& b) -> Base& {
252 1           return b;
253 3 50         };
254 1           Derrived b;
255 1 50         REQUIRE(cb(b).name() == b.name());
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
256 1           }
257              
258 1           function lamda() {
259 2           Tracer t(1);
260 7           auto wrapper = [t](int a) -> int {
261 1           Tracer o = t;
262 2           return a + 1;
263 2           };
264 2 50         return wrapper;
265             }
266              
267              
268 19           TEST_CASE("function memory", "[function]") {
269              
270 1           Tracer::refresh();
271             {
272 2 50         auto wrapper = lamda();
273 1 50         REQUIRE(wrapper(10) == 11);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
274             }
275              
276 1 50         REQUIRE(Tracer::ctor_total() == Tracer::dtor_calls);
    50          
    50          
    50          
    50          
    0          
    0          
277 1           }
278              
279              
280 19           TEST_CASE("lambda self reference", "[function]") {
281 1           int a = 1;
282             int b;
283 2 50         function outer;
284             {
285 2           auto inner = [=, &b](panda::Ifunction& self) mutable {
286 2 100         if (a == 1) {
287 1           a++;
288 1           self();;
289             } else {
290 1           b = 43;
291             }
292 3           };
293 1 50         outer = inner;
    50          
294             }
295 1 50         outer();
296 1 50         REQUIRE(b == 43);
    50          
    50          
    50          
    50          
    0          
    0          
297 1           }
298              
299 19           TEST_CASE("no capture self reference", "[function]") {
300             static int a = 0;
301 2 50         function outer;
302             {
303 2           auto inner = [](panda::Ifunction& self, int val) {
304             while(false) {self(a);}
305 1           a = val;
306 1           };
307 1 50         outer = inner;
    50          
308             }
309 1 50         outer(1);
310 1 50         REQUIRE(a == 1);
    50          
    50          
    50          
    50          
    0          
    0          
311 1           }
312              
313 19           TEST_CASE("function from null", "[function]") {
314             void (*fptr)();
315 1           fptr = nullptr;
316 2 50         function f = fptr;
317 1 50         REQUIRE(!f);
    50          
    50          
    50          
    0          
    0          
318 1           }
319              
320 19           TEST_CASE("function from null method", "[function]") {
321 1           auto meth = &Test::bar;
322 1           meth = nullptr;
323 2 50         auto m = make_function(meth);
324 1 50         REQUIRE(!m);
    50          
    50          
    50          
    0          
    0          
325 1           }
326              
327 19           TEST_CASE("function from nullable object", "[function]") {
328             struct S {
329 0           void operator()() const {}
330 2           explicit operator bool() const {
331 2           return val;
332             }
333             bool val;
334             };
335              
336 1           S s{false};
337 2 50         function f = s;
338 1 50         REQUIRE(!f);
    50          
    50          
    50          
    0          
    0          
339 1           s.val = true;
340 1 50         f = s;
    50          
341 1 50         REQUIRE(f);
    50          
    50          
    50          
    0          
    0          
342 1           }
343              
344 19           TEST_CASE("lambda self reference gcc bug", "[function]") {
345             struct SomeStruct {
346 1           void method(int val) {
347 1           function ff = [this](panda::Ifunction&, auto... args) mutable {
348 1           this->bar(args...);
349 2 50         };
350 1 50         ff(val);
351 1           }
352              
353 1           void bar(int val) {
354 1           a = val;
355 1           }
356             int a = 10;
357             };
358 1           SomeStruct s;
359 1 50         s.method(20);
360 1 50         REQUIRE(s.a == 20);
    50          
    50          
    50          
    50          
    0          
    0          
361 1           }
362              
363 19           TEST_CASE("lambda self reference auto...", "[function]") {
364 1           int a = 10;
365 1           function f = [&](auto...args) -> int {
366             static_assert(sizeof...(args) == 1, "auto... resolved as without SELF");
367 1           return (a = 20) + 1;
368 2 50         };
369 1 50         int b = f(42);
370 1 50         REQUIRE(a == 20);
    50          
    50          
    50          
    50          
    0          
    0          
371 1 50         REQUIRE(b == 21);
    50          
    50          
    50          
    50          
    0          
    0          
372              
373 1           function f2 = [&](auto&&...args) -> int {
374             static_assert(sizeof...(args) == 1, "auto... resolved as without SELF");
375 1           return 111;
376 2 50         };
377 1 50         CHECK(f2(123) == 111);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
378              
379 1           function f3 = [&](auto&&...args) {
380 1 50         REQUIRE(sizeof...(args) == 1);
    50          
    50          
    50          
    50          
    0          
    0          
381 1           return 111;
382 2 50         };
383 1 50         CHECK(f3(123) == 111);
    50          
    50          
    50          
    50          
    50          
    0          
    0          
384 73 50         }
    50