2020#include <unistd.h>
2121#include <fcntl.h>
2222#include <assert.h>
23+ #include <time.h>
24+ #include <sys/stat.h>
2325
2426// Test utilities
2527static int test_passed = 0 ;
@@ -36,29 +38,68 @@ static int test_failed = 0;
3638 } \
3739 } while (0)
3840
39- // Capture stderr output
41+ // Capture stderr output - simple file-based approach
4042static char captured_stderr [8192 ];
4143static size_t captured_len = 0 ;
42- static int stderr_fd = -1 ;
43- static int stderr_backup = -1 ;
44+ static char stderr_file_path [256 ];
45+ static int stderr_backup_fd = -1 ;
46+ static int stderr_file_fd = -1 ;
4447
4548static void capture_stderr_start (void ) {
4649 fflush (stderr );
47- stderr_backup = dup (STDERR_FILENO );
48- stderr_fd = open ("/tmp/dsmil_test_stderr" , O_RDWR | O_CREAT | O_TRUNC , 0644 );
49- dup2 (stderr_fd , STDERR_FILENO );
50+ stderr_backup_fd = dup (STDERR_FILENO );
51+
52+ // Create unique temp file
53+ snprintf (stderr_file_path , sizeof (stderr_file_path ), "/tmp/dsmil_stderr_%d_%lu" , getpid (), (unsigned long )time (NULL ));
54+ stderr_file_fd = open (stderr_file_path , O_WRONLY | O_CREAT | O_TRUNC , 0644 );
55+ if (stderr_file_fd < 0 ) {
56+ dup2 (stderr_backup_fd , STDERR_FILENO );
57+ return ;
58+ }
59+
60+ // Redirect stderr to file
61+ dup2 (stderr_file_fd , STDERR_FILENO );
62+
63+ // Make unbuffered
64+ setvbuf (stderr , NULL , _IONBF , 0 );
65+
5066 captured_len = 0 ;
5167 memset (captured_stderr , 0 , sizeof (captured_stderr ));
5268}
5369
5470static void capture_stderr_stop (void ) {
71+ // Flush and sync
5572 fflush (stderr );
56- lseek (stderr_fd , 0 , SEEK_SET );
57- captured_len = read (stderr_fd , captured_stderr , sizeof (captured_stderr ) - 1 );
58- close (stderr_fd );
59- dup2 (stderr_backup , STDERR_FILENO );
60- close (stderr_backup );
61- unlink ("/tmp/dsmil_test_stderr" );
73+ fsync (STDERR_FILENO );
74+
75+ // Restore stderr immediately
76+ if (stderr_backup_fd >= 0 ) {
77+ dup2 (stderr_backup_fd , STDERR_FILENO );
78+ close (stderr_backup_fd );
79+ stderr_backup_fd = -1 ;
80+ }
81+
82+ // Close write fd
83+ if (stderr_file_fd >= 0 ) {
84+ close (stderr_file_fd );
85+ stderr_file_fd = -1 ;
86+ }
87+
88+ // Reset buffering
89+ setvbuf (stderr , NULL , _IOLBF , 0 );
90+
91+ // Now read the file
92+ FILE * f = fopen (stderr_file_path , "r" );
93+ if (f ) {
94+ captured_len = fread (captured_stderr , 1 , sizeof (captured_stderr ) - 1 , f );
95+ if (captured_len > 0 ) {
96+ captured_stderr [captured_len ] = '\0' ;
97+ }
98+ fclose (f );
99+ }
100+
101+ // Clean up
102+ unlink (stderr_file_path );
62103}
63104
64105// Test 1: Basic initialization
@@ -117,6 +158,9 @@ static void test_env_enable(void) {
117158static void test_event_logging (void ) {
118159 printf ("\n=== Test 4: Basic Event Logging ===\n" );
119160
161+ // Ensure telemetry is enabled (reset from previous tests)
162+ unsetenv ("DSMIL_OT_TELEMETRY" );
163+ dsmil_ot_telemetry_shutdown (); // Reset state
120164 dsmil_ot_telemetry_init ();
121165
122166 capture_stderr_start ();
@@ -141,6 +185,7 @@ static void test_event_logging(void) {
141185 };
142186
143187 dsmil_telemetry_event (& ev );
188+ fflush (stderr ); // Ensure runtime's write is flushed
144189
145190 capture_stderr_stop ();
146191
@@ -157,6 +202,9 @@ static void test_event_logging(void) {
157202static void test_all_event_types (void ) {
158203 printf ("\n=== Test 5: All Event Types ===\n" );
159204
205+ // Ensure telemetry is enabled
206+ unsetenv ("DSMIL_OT_TELEMETRY" );
207+ dsmil_ot_telemetry_shutdown ();
160208 dsmil_ot_telemetry_init ();
161209
162210 dsmil_telemetry_event_type_t types [] = {
@@ -203,8 +251,14 @@ static void test_all_event_types(void) {
203251 };
204252
205253 dsmil_telemetry_event (& ev );
254+ fflush (stderr );
206255 capture_stderr_stop ();
207256
257+ // Debug first failure
258+ if (i == 0 && captured_len > 0 && strstr (captured_stderr , expected_strings [i ]) == NULL ) {
259+ printf ("DEBUG Test 5[%zu]: Captured: %.200s\n" , i , captured_stderr );
260+ }
261+
208262 TEST_ASSERT (strstr (captured_stderr , expected_strings [i ]) != NULL ,
209263 expected_strings [i ]);
210264 }
@@ -217,6 +271,9 @@ static void test_all_event_types(void) {
217271static void test_safety_signal_update (void ) {
218272 printf ("\n=== Test 6: Safety Signal Update ===\n" );
219273
274+ // Ensure telemetry is enabled
275+ unsetenv ("DSMIL_OT_TELEMETRY" );
276+ dsmil_ot_telemetry_shutdown ();
220277 dsmil_ot_telemetry_init ();
221278
222279 capture_stderr_start ();
@@ -294,6 +351,9 @@ static void test_safety_signal_no_name(void) {
294351static void test_event_null_strings (void ) {
295352 printf ("\n=== Test 9: Event with NULL Strings ===\n" );
296353
354+ // Ensure telemetry is enabled
355+ unsetenv ("DSMIL_OT_TELEMETRY" );
356+ dsmil_ot_telemetry_shutdown ();
297357 dsmil_ot_telemetry_init ();
298358
299359 capture_stderr_start ();
@@ -323,6 +383,9 @@ static void test_event_null_strings(void) {
323383static void test_multiple_events (void ) {
324384 printf ("\n=== Test 10: Multiple Events ===\n" );
325385
386+ // Ensure telemetry is enabled
387+ unsetenv ("DSMIL_OT_TELEMETRY" );
388+ dsmil_ot_telemetry_shutdown ();
326389 dsmil_ot_telemetry_init ();
327390
328391 capture_stderr_start ();
@@ -339,7 +402,7 @@ static void test_multiple_events(void) {
339402 };
340403 dsmil_telemetry_event (& ev );
341404 }
342-
405+ fflush ( stderr );
343406 capture_stderr_stop ();
344407
345408 // Count occurrences of "ot_path_entry"
@@ -406,6 +469,9 @@ static void test_shutdown_reinit(void) {
406469static void test_complete_event (void ) {
407470 printf ("\n=== Test 13: Complete Event ===\n" );
408471
472+ // Ensure telemetry is enabled
473+ unsetenv ("DSMIL_OT_TELEMETRY" );
474+ dsmil_ot_telemetry_shutdown ();
409475 dsmil_ot_telemetry_init ();
410476
411477 capture_stderr_start ();
@@ -442,7 +508,7 @@ static void test_complete_event(void) {
442508 };
443509
444510 dsmil_telemetry_event (& ev );
445-
511+ fflush ( stderr );
446512 capture_stderr_stop ();
447513
448514 TEST_ASSERT (captured_len > 0 , "Complete event logged" );
0 commit comments