The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
strerror_tests.c
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /** Tests for a generic string buffer structure for string printing and parsing
18  *
19  * @file src/lib/util/strerror_tests.c
20  *
21  * @copyright 2020 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
22  */
23 #include <freeradius-devel/util/acutest.h>
24 #include <freeradius-devel/util/acutest_helpers.h>
25 #include <freeradius-devel/util/time.h>
26 
27 static void strerror_uninit(void)
28 {
29  char const *error;
30 
31  error = fr_strerror();
32 
33  TEST_CHECK(error != NULL);
34  TEST_CHECK(error && (error[0] == '\0'));
35 }
36 
37 static void strerror_pop_uninit(void)
38 {
39  char const *error;
40 
41  error = fr_strerror_pop();
42 
43  TEST_CHECK(error == NULL);
44 }
45 
46 static void strerror_perror_null(void)
47 {
48  /*
49  * Just a smoke test, can't check output
50  */
51  fr_perror(NULL);
52  fr_perror("Foo");
53 
54  fr_strerror_const("Test");
55  fr_perror("Bar");
56 }
57 
58 static void strerror_printf(void)
59 {
60  char const *error;
61 
62  fr_strerror_printf("Testing %i", 123);
63 
64  error = fr_strerror();
65 
66  TEST_CHECK(error != NULL);
67  TEST_CHECK_STRCMP(error, "Testing 123");
68 
69  error = fr_strerror();
70  TEST_CHECK(error != NULL);
71  TEST_CHECK(error && (error[0] == '\0'));
72 }
73 
74 static void strerror_printf_push_pop(void)
75 {
76  char const *error;
77 
78  fr_strerror_printf_push("Testing %i", 1);
79 
80  error = fr_strerror_pop();
81  TEST_CHECK(error != NULL);
82  TEST_CHECK_STRCMP(error, "Testing 1");
83 
84  error = fr_strerror_pop();
85  TEST_CHECK(error == NULL);
86 
87  error = fr_strerror();
88  TEST_CHECK(error != NULL);
89  TEST_CHECK(error && (error[0] == '\0'));
90 }
91 
93 {
94  char const *error;
95 
96  fr_strerror_printf_push("Testing %i", 1);
97 
98  error = fr_strerror();
99  TEST_CHECK(error != NULL);
100  TEST_CHECK_STRCMP(error, "Testing 1");
101 
102  error = fr_strerror_pop();
103  TEST_CHECK(error == NULL);
104 }
105 
107 {
108  char const *error;
109 
110  fr_strerror_printf_push("Testing %i", 1);
111  fr_strerror_printf_push("Testing %i", 2);
112 
113  error = fr_strerror_pop();
114  TEST_CHECK(error != NULL);
115  TEST_CHECK_STRCMP(error, "Testing 1");
116 
117  error = fr_strerror_pop();
118  TEST_CHECK(error != NULL);
119  TEST_CHECK_STRCMP(error, "Testing 2");
120 
121  error = fr_strerror_pop();
122  TEST_CHECK(error == NULL);
123 
124  error = fr_strerror();
125  TEST_CHECK(error != NULL);
126  TEST_CHECK(error && (error[0] == '\0'));
127 }
128 
130 {
131  char const *error;
132 
133  fr_strerror_printf_push("Testing %i", 1);
134  fr_strerror_printf_push("Testing %i", 2);
135 
136  error = fr_strerror();
137  TEST_CHECK(error != NULL);
138  TEST_CHECK_STRCMP(error, "Testing 2");
139 
140  error = fr_strerror_pop();
141  TEST_CHECK(error == NULL);
142 }
143 
145 {
146  char const *error;
147 
148  fr_strerror_printf("Testing %i", 1);
149  fr_strerror_printf("%s Testing %i", fr_strerror(), 2);
150 
151  error = fr_strerror();
152  TEST_CHECK(error != NULL);
153  TEST_CHECK_STRCMP(error, "Testing 1 Testing 2");
154 
155  error = fr_strerror();
156  TEST_CHECK(error != NULL);
157  TEST_CHECK(error && (error[0] == '\0'));
158 }
159 
161 {
162  char const *error;
163 
164  fr_strerror_printf_push("Testing %i", 1);
165  fr_strerror_printf("%s Testing %i", fr_strerror(), 2);
166 
167  error = fr_strerror();
168  TEST_CHECK(error != NULL);
169  TEST_CHECK_STRCMP(error, "Testing 1 Testing 2");
170 
171  error = fr_strerror();
172  TEST_CHECK(error != NULL);
173  TEST_CHECK(error && (error[0] == '\0'));
174 }
175 
177 {
178  char const *error;
179 
180  fr_strerror_printf_push("Testing %i", 1);
181  fr_strerror_printf("%s Testing %i", fr_strerror_pop(), 2);
182 
183  error = fr_strerror();
184  TEST_CHECK(error != NULL);
185  TEST_CHECK_STRCMP(error, "Testing 1 Testing 2");
186 
187  error = fr_strerror();
188  TEST_CHECK(error != NULL);
189  TEST_CHECK(error && (error[0] == '\0'));
190 }
191 
192 static void strerror_printf_benchmark(void)
193 {
194  int i;
195  fr_time_t start, stop;
196  uint64_t rate;
197 
198  fr_strerror_const("pre-allocate buffers");
200 
201  start = fr_time();
202  for (i = 0; i < 100000; i++) {
203  fr_strerror_printf("I am a test %u string %u %s", i, i, "benchmark");
204  fr_strerror_clear(); /* Clear */
205  }
206  stop = fr_time();
207 
208  rate = (uint64_t)((float)NSEC / (fr_time_delta_unwrap(fr_time_sub(stop, start)) / 100000));
209  printf("printf pop rate %" PRIu64 "\n", rate);
210 
211  /* shared runners are terrible for performance tests */
212  if (!getenv("NO_PERFORMANCE_TESTS")) TEST_CHECK(rate > 200000);
213 }
214 
215 
216 static void strerror_const_benchmark(void)
217 {
218  int i;
219  fr_time_t start, stop;
220  uint64_t rate;
221 
222  fr_strerror_const("pre-allocate buffers");
224 
225  start = fr_time();
226  for (i = 0; i < 100000; i++) {
227  fr_strerror_const("I am a test string");
228  fr_strerror_clear(); /* Clear */
229  }
230  stop = fr_time();
231 
232  rate = (uint64_t)((float)NSEC / (fr_time_delta_unwrap(fr_time_sub(stop, start)) / 100000));
233  printf("const pop rate %" PRIu64 "\n", rate);
234 
235  /* shared runners are terrible for performance tests */
236  if (!getenv("NO_PERFORMANCE_TESTS")) TEST_CHECK(rate > 1000000);
237 }
238 
239 
241  { "strerror_uninit", strerror_uninit },
242  { "strerror_pop_uninit", strerror_pop_uninit },
243  { "strerror_perror_null", strerror_perror_null },
244 
245  { "strerror_printf", strerror_printf },
246  { "strerror_printf_push_pop", strerror_printf_push_pop },
247 
248  { "strerror_printf_push_strerror", strerror_printf_push_strerror },
249  { "strerror_printf_push_pop_multi", strerror_printf_push_pop_multi },
250  { "strerror_printf_push_strerror_multi",strerror_printf_push_strerror_multi },
251  { "strerror_printf_strerror_append", strerror_printf_strerror_append },
252  { "strerror_printf_push_append", strerror_printf_push_append },
253  { "strerror_printf_push_append2", strerror_printf_push_append2 },
254 
255  { "strerror_printf_benchmark", strerror_printf_benchmark },
256  { "strerror_const_benchmark", strerror_const_benchmark },
257 
258  { 0 }
259 };
#define TEST_CHECK(cond)
Definition: acutest.h:85
#define TEST_CHECK_STRCMP(_got, _exp)
static bool stop
Definition: radmin.c:70
#define fr_time()
Allow us to arbitrarily manipulate time.
Definition: state_test.c:8
TEST_LIST
static void strerror_const_benchmark(void)
static void strerror_printf_push_strerror(void)
static void strerror_perror_null(void)
static void strerror_printf(void)
static void strerror_printf_push_pop(void)
static void strerror_printf_push_append2(void)
static void strerror_printf_benchmark(void)
static void strerror_uninit(void)
static void strerror_printf_push_pop_multi(void)
static void strerror_printf_push_strerror_multi(void)
static void strerror_printf_push_append(void)
static void strerror_pop_uninit(void)
static void strerror_printf_strerror_append(void)
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition: time.h:154
#define NSEC
Definition: time.h:379
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition: time.h:229
"server local" time.
Definition: time.h:69
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition: strerror.c:733
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
Definition: strerror.c:577
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
char const * fr_strerror_pop(void)
Pop the last library error.
Definition: strerror.c:681
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition: strerror.h:64
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
Definition: strerror.h:84
#define fr_strerror_const(_msg)
Definition: strerror.h:223