Commit | Line | Data |
---|---|---|
07e253aa PA |
1 | /* Self tests for function_view for GDB, the GNU debugger. |
2 | ||
42a4f53d | 3 | Copyright (C) 2017-2019 Free Software Foundation, Inc. |
07e253aa PA |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "defs.h" | |
268a13a5 TT |
21 | #include "gdbsupport/selftest.h" |
22 | #include "gdbsupport/function-view.h" | |
07e253aa PA |
23 | |
24 | namespace selftests { | |
25 | namespace function_view { | |
26 | ||
27 | static int | |
28 | plus_one_fn_int (int val) | |
29 | { | |
30 | return ++val; | |
31 | } | |
32 | ||
33 | static short | |
34 | plus_one_fn_short (short val) | |
35 | { | |
36 | return ++val; | |
37 | } | |
38 | ||
39 | static int | |
40 | call_callback_int (int val, gdb::function_view <int (int)> callback) | |
41 | { | |
42 | return callback (val); | |
43 | } | |
44 | ||
45 | static void | |
46 | call_callback_void (int val, gdb::function_view <void (int)> callback) | |
47 | { | |
48 | callback (val); | |
49 | } | |
50 | ||
51 | struct plus_one_int_func_obj | |
52 | { | |
53 | int operator () (int val) | |
54 | { | |
55 | ++call_count; | |
56 | return ++val; | |
57 | } | |
58 | ||
59 | /* Number of times called. */ | |
60 | int call_count = 0; | |
61 | }; | |
62 | ||
63 | static void | |
64 | run_tests () | |
65 | { | |
66 | /* A simple lambda. */ | |
67 | auto plus_one_lambda = [] (int val) { return ++val; }; | |
68 | ||
69 | /* A function_view that references the lambda. */ | |
70 | gdb::function_view<int (int)> plus_one_func_view (plus_one_lambda); | |
71 | ||
72 | /* Check calling the lambda directly. */ | |
73 | SELF_CHECK (plus_one_lambda (0) == 1); | |
74 | SELF_CHECK (plus_one_lambda (1) == 2); | |
75 | ||
76 | /* Check calling lambda via the view. */ | |
77 | SELF_CHECK (plus_one_func_view (2) == 3); | |
78 | SELF_CHECK (plus_one_func_view (3) == 4); | |
79 | ||
80 | /* Check calling a function that takes a function_view as argument, | |
81 | by value. Pass a lambda, making sure a function_view is properly | |
82 | constructed implicitly. */ | |
83 | SELF_CHECK (call_callback_int (1, [] (int val) | |
84 | { | |
85 | return val + 2; | |
86 | }) == 3); | |
87 | ||
88 | /* Same, passing a named/lvalue lambda. */ | |
89 | SELF_CHECK (call_callback_int (1, plus_one_lambda) == 2); | |
90 | /* Same, passing a named/lvalue function_view (should copy). */ | |
91 | SELF_CHECK (call_callback_int (1, plus_one_func_view) == 2); | |
92 | ||
93 | /* Check constructing a function view over a function-object | |
94 | callable, and calling it. */ | |
95 | plus_one_int_func_obj func_obj; | |
96 | SELF_CHECK (func_obj (0) == 1); | |
97 | SELF_CHECK (call_callback_int (1, func_obj) == 2); | |
98 | /* Check that the callable was referenced, not copied. */ | |
99 | SELF_CHECK (func_obj.call_count == 2); | |
100 | ||
101 | /* Check constructing a function_view over a free-function callable, | |
102 | and calling it. */ | |
103 | SELF_CHECK (call_callback_int (1, plus_one_fn_int) == 2); | |
104 | ||
105 | /* Check calling a function with a | |
106 | compatible-but-not-exactly-the-same prototype. */ | |
107 | SELF_CHECK (call_callback_int (1, [] (short val) -> short | |
108 | { | |
109 | return val + 2; | |
110 | }) == 3); | |
111 | /* Same, but passing a function pointer. */ | |
112 | SELF_CHECK (call_callback_int (1, plus_one_fn_short) == 2); | |
113 | ||
114 | /* Like std::function, a function_view that expects a void return | |
115 | can reference callables with non-void return type. The result is | |
116 | simply discarded. Check a lambda, function object and a function | |
117 | pointer. */ | |
118 | call_callback_void (1, [] (int val) -> int | |
119 | { | |
120 | return val + 2; | |
121 | }); | |
122 | call_callback_void (1, func_obj); | |
123 | call_callback_void (1, plus_one_fn_int); | |
124 | ||
125 | /* Check that the main ctor doesn't hijack the copy ctor. */ | |
126 | auto plus_one_func_view2 (plus_one_func_view); | |
127 | auto plus_one_func_view3 (plus_one_func_view2); | |
128 | static_assert (std::is_same<decltype (plus_one_func_view), | |
129 | decltype (plus_one_func_view2)>::value, ""); | |
130 | static_assert (std::is_same<decltype (plus_one_func_view), | |
131 | decltype (plus_one_func_view3)>::value, ""); | |
132 | ||
133 | SELF_CHECK (plus_one_func_view3 (1) == 2); | |
134 | ||
135 | /* Likewise, but propagate a NULL callable. If this calls the main | |
136 | function_view ctor instead of the copy ctor by mistake, then | |
137 | null_func_2 ends up non-NULL (because it'd instead reference | |
138 | null_func_1 as just another callable). */ | |
139 | constexpr gdb::function_view<int (int)> null_func_view_1 = nullptr; | |
140 | constexpr auto null_func_view_2 (null_func_view_1); | |
141 | ||
142 | /* While at it, check whether the function_view is bound using | |
143 | various forms, op==, op!= and op bool. */ | |
144 | ||
145 | /* op== */ | |
146 | static_assert (null_func_view_2 == nullptr, ""); | |
147 | static_assert (nullptr == null_func_view_2, ""); | |
148 | static_assert (null_func_view_2 == NULL, ""); | |
149 | static_assert (NULL == null_func_view_2, ""); | |
150 | ||
151 | /* op!= */ | |
152 | static_assert (!(null_func_view_2 != nullptr), ""); | |
153 | static_assert (!(nullptr != null_func_view_2), ""); | |
154 | static_assert (!(null_func_view_2 != NULL), ""); | |
155 | static_assert (!(NULL != null_func_view_2), ""); | |
156 | ||
157 | /* op bool */ | |
158 | static_assert (!null_func_view_2, ""); | |
159 | ||
160 | /* Check the nullptr_t ctor. */ | |
161 | constexpr gdb::function_view<int (int)> check_ctor_nullptr (nullptr); | |
162 | static_assert (!check_ctor_nullptr, ""); | |
163 | ||
164 | /* Check the nullptr_t op= */ | |
165 | gdb::function_view<int (int)> check_op_eq_null (plus_one_fn_int); | |
166 | SELF_CHECK (check_op_eq_null); | |
167 | check_op_eq_null = nullptr; | |
168 | SELF_CHECK (!check_op_eq_null); | |
169 | } | |
170 | ||
171 | } /* namespace function_view */ | |
172 | } /* namespace selftests */ | |
173 | ||
174 | void | |
175 | _initialize_function_view_selftests () | |
176 | { | |
1526853e SM |
177 | selftests::register_test ("function_view", |
178 | selftests::function_view::run_tests); | |
07e253aa | 179 | } |