1/* Self tests for function_view for GDB, the GNU debugger. 2 3 Copyright (C) 2017-2020 Free Software Foundation, Inc. 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" 21#include "gdbsupport/selftest.h" 22#include "gdbsupport/function-view.h" 23 24namespace selftests { 25namespace function_view { 26 27static int 28plus_one_fn_int (int val) 29{ 30 return ++val; 31} 32 33static short 34plus_one_fn_short (short val) 35{ 36 return ++val; 37} 38 39static int 40call_callback_int (int val, gdb::function_view <int (int)> callback) 41{ 42 return callback (val); 43} 44 45static void 46call_callback_void (int val, gdb::function_view <void (int)> callback) 47{ 48 callback (val); 49} 50 51struct 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 63static void 64run_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 174void _initialize_function_view_selftests (); 175void 176_initialize_function_view_selftests () 177{ 178 selftests::register_test ("function_view", 179 selftests::function_view::run_tests); 180} 181