GDB (xrefs)
function-view-selftests.c
Go to the documentation of this file.
1 /* Self tests for function_view for GDB, the GNU debugger.
2 
3  Copyright (C) 2017-2018 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 "selftest.h"
22 #include "common/function-view.h"
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 
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
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. */
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. */
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);
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= */
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
176 {
177  selftests::register_test ("function_view",
179 }
void _initialize_function_view_selftests()
static void call_callback_void(int val, gdb::function_view< void(int)> callback)
static short plus_one_fn_short(short val)
static int call_callback_int(int val, gdb::function_view< int(int)> callback)
Definition: value.c:169
static int plus_one_fn_int(int val)
void register_test(const std::string &name, selftest *test)
Definition: selftest.c:52
#define SELF_CHECK(VALUE)
Definition: selftest.h:67