The FreeRADIUS server $Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
log_tests.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program 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
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; 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 the rate limited logging macros
18 *
19 * @file src/lib/server/log_tests.c
20 *
21 * @copyright 2026 Network RADIUS SAS ("legal@networkradius.com")
22 */
23#include <freeradius-devel/util/test/acutest.h>
24#include <freeradius-devel/util/test/acutest_helpers.h>
25
26#include <freeradius-devel/server/log.h>
27
28/*
29 * The logging macro under test. Each call records the formatted
30 * message, and counts the call. RATE_LIMIT_LOCAL() wraps the macro
31 * in parentheses, which requires an expression.
32 */
33static char captured[256];
34static int logged;
35
36#define CAPTURE_LOG(_fmt, ...) \
37 ((void) snprintf(captured, sizeof(captured), _fmt, ## __VA_ARGS__), logged++)
38
39static void capture_reset(void)
40{
41 captured[0] = '\0';
42 logged = 0;
43 fr_log_rate_limit = true;
44}
45
46/** The first message from a fresh entry is logged, even in the first second of the process
47 *
48 * fr_time() counts from fr_time_start(). A fresh entry has last_complained of zero, which
49 * is second 0, and a message in second 0 of the process compared equal to it and was
50 * counted as a repeat instead of being logged.
51 */
53{
54 fr_rate_limit_t entry = {};
55
57 TEST_ASSERT(fr_time_start() == 0); /* Places fr_time() in second 0 */
58
59 RATE_LIMIT_LOCAL(&entry, CAPTURE_LOG, "first %d", 1);
60 TEST_CHECK(logged == 1);
61 TEST_MSG("logged %d, expected 1", logged);
62 TEST_CHECK(strcmp(captured, "first 1") == 0);
63 TEST_MSG("captured \"%s\"", captured);
64}
65
66/** A second message in the same second is counted, not logged
67 */
68static void test_repeat_suppressed(void)
69{
70 fr_rate_limit_t entry = {};
71
73 RATE_LIMIT_LOCAL(&entry, CAPTURE_LOG, "message");
74 RATE_LIMIT_LOCAL(&entry, CAPTURE_LOG, "message");
75 TEST_CHECK(logged == 1);
76 TEST_MSG("logged %d, expected 1", logged);
77 TEST_CHECK(entry.repeated == 1);
78 TEST_MSG("repeated %u, expected 1", entry.repeated);
79}
80
81/** A message one second after the last one reports the repeats suppressed in between
82 *
83 * The macro set last_complained to now before computing the time since the last
84 * complaint, which was then always zero, and the suffix never appeared.
85 */
87{
88 fr_rate_limit_t entry = {};
89
92 entry.repeated = 3;
93
94 RATE_LIMIT_LOCAL(&entry, CAPTURE_LOG, "message");
95 TEST_CHECK(logged == 1);
96 TEST_CHECK(strcmp(captured, "message - repeated 3 time(s)") == 0);
97 TEST_MSG("captured \"%s\"", captured);
98 TEST_CHECK(entry.repeated == 0);
99}
100
102 { "first_message_logged", test_first_message_logged },
103 { "repeat_suppressed", test_repeat_suppressed },
104 { "repeat_count_reported", test_repeat_count_reported },
106};
#define TEST_CHECK(cond)
Definition acutest.h:101
#define TEST_ASSERT(cond)
Definition acutest.h:125
#define TEST_TERMINATOR
Definition acutest.h:77
#define TEST_MSG(...)
Definition acutest.h:234
#define RATE_LIMIT_LOCAL(_entry, _log, _fmt,...)
Rate limit messages using a local limiting entry.
Definition log.h:586
unsigned int repeated
Number of "skipped" messages.
Definition log.h:567
fr_time_t last_complained
Last time we emitted a log message.
Definition log.h:566
Track when a log message was last repeated.
Definition log.h:564
#define fr_time()
Definition event.c:58
bool fr_log_rate_limit
Whether repeated log entries should be rate limited.
Definition log.c:76
static void test_first_message_logged(void)
The first message from a fresh entry is logged, even in the first second of the process.
Definition log_tests.c:52
TEST_LIST
Definition log_tests.c:101
static void test_repeat_suppressed(void)
A second message in the same second is counted, not logged.
Definition log_tests.c:68
#define CAPTURE_LOG(_fmt,...)
Definition log_tests.c:36
static void test_repeat_count_reported(void)
A message one second after the last one reports the repeats suppressed in between.
Definition log_tests.c:86
static void capture_reset(void)
Definition log_tests.c:39
static char captured[256]
Definition log_tests.c:33
static int logged
Definition log_tests.c:34
int fr_time_start(void)
Initialize the local time.
Definition time.c:157
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:599
#define fr_time_sub(_a, _b)
Subtract one time from another.
Definition time.h:229