Skip to content

Commit 740e588

Browse files
Merge pull request #35 from SaridakisStamatisChristos/codex/expand-test-coverage-to-90-percent
Add logging and metrics coverage tests
2 parents f59e244 + f2c2427 commit 740e588

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ if(BUILD_TESTING)
8787
target_compile_options(test_statistics PRIVATE -Wall -Wextra)
8888
add_test(NAME statistics COMMAND test_statistics)
8989

90+
add_executable(test_logging_metrics tests/test_logging_metrics.c)
91+
target_link_libraries(test_logging_metrics PRIVATE thermal_simd_core_tests pthread)
92+
target_compile_options(test_logging_metrics PRIVATE -Wall -Wextra -pthread)
93+
add_test(NAME logging_metrics COMMAND test_logging_metrics)
94+
9095
add_executable(test_thermal_simd
9196
tests/test_thermal_simd.c
9297
src/thermal_simd.c)

tests/test_logging_metrics.c

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#include <thermal/simd/logging.h>
2+
#include <thermal/simd/metrics.h>
3+
#include <thermal/simd/simd_width.h>
4+
5+
#include <errno.h>
6+
#include <stdint.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <string.h>
10+
#include <unistd.h>
11+
12+
static void check_true(int condition, const char *message) {
13+
if (!condition) {
14+
fprintf(stderr, "test failure: %s\n", message);
15+
exit(1);
16+
}
17+
}
18+
19+
static void check_nonneg(int value, const char *message) {
20+
if (value < 0) {
21+
fprintf(stderr, "test failure: %s (errno=%d)\n", message, errno);
22+
exit(1);
23+
}
24+
}
25+
26+
static void check_zero(int rc, const char *message) {
27+
if (rc != 0) {
28+
fprintf(stderr, "test failure: %s (errno=%d)\n", message, errno);
29+
exit(1);
30+
}
31+
}
32+
33+
static ssize_t read_into_buffer(int fd, char *buffer, size_t buffer_len) {
34+
ssize_t total = 0;
35+
while ((size_t)total < buffer_len - 1) {
36+
ssize_t n = read(fd, buffer + total, buffer_len - 1 - (size_t)total);
37+
if (n <= 0) {
38+
break;
39+
}
40+
total += n;
41+
}
42+
buffer[total >= 0 ? (size_t)total : 0] = '\0';
43+
return total;
44+
}
45+
46+
typedef void (*capture_fn)(void *arg);
47+
48+
static void capture_stream(FILE *stream, int fd, capture_fn fn, void *arg, char *buffer, size_t buffer_len) {
49+
int pipefd[2];
50+
check_zero(pipe(pipefd), "pipe");
51+
fflush(stream);
52+
int saved_fd = dup(fd);
53+
check_nonneg(saved_fd, "dup");
54+
check_nonneg(dup2(pipefd[1], fd), "dup2 redirect");
55+
close(pipefd[1]);
56+
fn(arg);
57+
fflush(stream);
58+
check_zero(close(fd), "close stream fd");
59+
read_into_buffer(pipefd[0], buffer, buffer_len);
60+
close(pipefd[0]);
61+
check_nonneg(dup2(saved_fd, fd), "restore dup2");
62+
check_zero(close(saved_fd), "close saved fd");
63+
}
64+
65+
static void log_message(void *arg) {
66+
const char *message = (const char *)arg;
67+
tsd_log_info("test_component", "%s", message);
68+
}
69+
70+
static void log_warning(void *arg) {
71+
const char *message = (const char *)arg;
72+
tsd_log_warn("test_component", "%s", message);
73+
}
74+
75+
static void verify_logging_outputs(void) {
76+
tsd_log_set_level(TSD_LOG_LEVEL_DEBUG);
77+
char buffer[1024];
78+
79+
const char *info_message = "informational payload";
80+
capture_stream(stdout, STDOUT_FILENO, log_message, (void *)info_message, buffer, sizeof(buffer));
81+
check_true(strstr(buffer, "test_component") != NULL, "info log missing component");
82+
check_true(strstr(buffer, info_message) != NULL, "info log missing payload");
83+
84+
const char *warn_message = "warning payload";
85+
capture_stream(stderr, STDERR_FILENO, log_warning, (void *)warn_message, buffer, sizeof(buffer));
86+
check_true(strstr(buffer, "test_component") != NULL, "warn log missing component");
87+
check_true(strstr(buffer, warn_message) != NULL, "warn log missing payload");
88+
89+
char long_message[600];
90+
memset(long_message, 'A', sizeof(long_message) - 1);
91+
long_message[sizeof(long_message) - 1] = '\0';
92+
capture_stream(stdout, STDOUT_FILENO, log_message, long_message, buffer, sizeof(buffer));
93+
check_true(strstr(buffer, long_message) != NULL, "long message not emitted");
94+
}
95+
96+
static void verify_log_level_controls(void) {
97+
tsd_log_set_level(TSD_LOG_LEVEL_INFO);
98+
check_true(tsd_log_get_level() == TSD_LOG_LEVEL_INFO, "info level clamp");
99+
check_true(tsd_log_should_log(TSD_LOG_LEVEL_ERROR), "error should log");
100+
check_true(tsd_log_should_log(TSD_LOG_LEVEL_WARN), "warn should log");
101+
check_true(tsd_log_should_log(TSD_LOG_LEVEL_INFO), "info should log");
102+
check_true(!tsd_log_should_log(TSD_LOG_LEVEL_DEBUG), "debug should not log");
103+
104+
tsd_log_set_level(TSD_LOG_LEVEL_ERROR);
105+
check_true(tsd_log_get_level() == TSD_LOG_LEVEL_ERROR, "error clamp lower bound");
106+
check_true(!tsd_log_should_log(TSD_LOG_LEVEL_INFO), "info suppressed at error");
107+
108+
tsd_log_set_level((tsd_log_level_t)100);
109+
check_true(tsd_log_get_level() == TSD_LOG_LEVEL_DEBUG, "high level clamps to debug");
110+
}
111+
112+
static void verify_log_level_conversion(void) {
113+
tsd_log_level_t level = TSD_LOG_LEVEL_ERROR;
114+
check_true(tsd_log_level_from_string("warn", &level) == 0, "parse warn");
115+
check_true(level == TSD_LOG_LEVEL_WARN, "warn level value");
116+
check_true(tsd_log_level_from_string("INFO", &level) == 0, "parse info");
117+
check_true(level == TSD_LOG_LEVEL_INFO, "info level value");
118+
check_true(tsd_log_level_from_string("debug", &level) == 0, "parse debug");
119+
check_true(level == TSD_LOG_LEVEL_DEBUG, "debug level value");
120+
check_true(tsd_log_level_from_string("error", &level) == 0, "parse error");
121+
check_true(level == TSD_LOG_LEVEL_ERROR, "error level value");
122+
check_true(tsd_log_level_from_string("warning", &level) == 0, "parse warning alias");
123+
check_true(level == TSD_LOG_LEVEL_WARN, "warning alias level value");
124+
check_true(tsd_log_level_from_string(NULL, &level) != 0, "null string rejected");
125+
check_true(tsd_log_level_from_string("invalid", &level) != 0, "invalid string rejected");
126+
check_true(tsd_log_level_from_string("info", NULL) != 0, "null output rejected");
127+
128+
check_true(strcmp(tsd_log_level_to_string(TSD_LOG_LEVEL_ERROR), "ERROR") == 0, "level to string error");
129+
check_true(strcmp(tsd_log_level_to_string(TSD_LOG_LEVEL_WARN), "WARN") == 0, "level to string warn");
130+
check_true(strcmp(tsd_log_level_to_string(TSD_LOG_LEVEL_INFO), "INFO") == 0, "level to string info");
131+
check_true(strcmp(tsd_log_level_to_string(TSD_LOG_LEVEL_DEBUG), "DEBUG") == 0, "level to string debug");
132+
}
133+
134+
static void verify_strerror_wrapper(void) {
135+
char buffer[64];
136+
const char *msg = tsd_log_strerror(ENOENT, buffer, sizeof(buffer));
137+
check_true(msg != NULL, "strerror returned null");
138+
check_true(strlen(msg) > 0, "strerror empty message");
139+
140+
const char *empty = tsd_log_strerror(ENOENT, buffer, 0);
141+
check_true(empty != NULL, "strerror zero buffer null");
142+
check_true(strcmp(empty, "") == 0, "strerror zero buffer output");
143+
}
144+
145+
static void verify_metrics_counters(void) {
146+
tsd_metrics_snapshot_t before;
147+
tsd_metrics_snapshot(&before);
148+
149+
tsd_metrics_increment(TSD_METRIC_PERF_FALLBACKS);
150+
tsd_metrics_add(TSD_METRIC_PERF_FALLBACKS, 5);
151+
tsd_metrics_increment(TSD_METRIC_COUNT);
152+
tsd_metrics_add(TSD_METRIC_COUNT, 10);
153+
154+
tsd_metrics_snapshot_t after;
155+
tsd_metrics_snapshot(&after);
156+
157+
uint64_t perf_fallbacks_delta = after.counters[TSD_METRIC_PERF_FALLBACKS] -
158+
before.counters[TSD_METRIC_PERF_FALLBACKS];
159+
check_true(perf_fallbacks_delta == 6, "perf fallback counter delta");
160+
161+
for (int i = 0; i < TSD_METRIC_COUNT; ++i) {
162+
const char *name = tsd_metrics_counter_name((tsd_metric_counter_t)i);
163+
check_true(name != NULL, "metric name null");
164+
check_true(strlen(name) > 0, "metric name empty");
165+
}
166+
check_true(strcmp(tsd_metrics_counter_name((tsd_metric_counter_t)100), "invalid") == 0,
167+
"invalid metric name fallback");
168+
169+
tsd_metrics_snapshot_t mid;
170+
tsd_metrics_snapshot(&mid);
171+
tsd_metrics_record_width_transition(SIMD_SSE41, SIMD_AVX2, 0);
172+
tsd_metrics_record_width_transition(SIMD_AVX2, SIMD_AVX512, -1);
173+
tsd_metrics_snapshot_t end;
174+
tsd_metrics_snapshot(&end);
175+
176+
uint64_t transitions_delta = end.counters[TSD_METRIC_PATCH_TRANSITIONS] -
177+
mid.counters[TSD_METRIC_PATCH_TRANSITIONS];
178+
uint64_t failures_delta = end.counters[TSD_METRIC_PATCH_FAILURES] -
179+
mid.counters[TSD_METRIC_PATCH_FAILURES];
180+
check_true(transitions_delta == 1, "patch transitions delta");
181+
check_true(failures_delta == 1, "patch failures delta");
182+
}
183+
184+
int main(void) {
185+
verify_logging_outputs();
186+
verify_log_level_controls();
187+
verify_log_level_conversion();
188+
verify_strerror_wrapper();
189+
verify_metrics_counters();
190+
return 0;
191+
}

0 commit comments

Comments
 (0)