Skip to content

Commit 77d1f52

Browse files
committed
improvements
1 parent 621d24e commit 77d1f52

File tree

5 files changed

+177
-50
lines changed

5 files changed

+177
-50
lines changed

src/application/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ int main(void) // NOLINT
9595
USB_task(husb);
9696

9797
// Output logs
98-
LOG_task();
98+
LOG_task(8);
9999

100100
// Log system status periodically (optional)
101101
static uint32_t log_counter = 0;

src/system/system.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ void SYSTEM_init(void)
1818
{
1919
PLATFORM_init();
2020
// Read any logs that were generated during platform initialization
21-
LOG_task();
21+
unsigned const max_log_entries = 32;
22+
LOG_task(max_log_entries);
2223
LED_init();
2324
}

src/util/logging.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88

99
#include "logging.h"
10-
#include "error.h"
1110
#include "util.h"
1211
#include <assert.h>
1312
#include <stdarg.h>
@@ -47,6 +46,10 @@ LOG_Handle *LOG_init(void)
4746
"LOG_MAX_MESSAGE_SIZE must be reasonable (1-511)"
4847
);
4948

49+
if (g_log_handle.initialized) {
50+
return &g_log_handle; // Already initialized
51+
}
52+
5053
circular_buffer_init(
5154
&g_log_handle.buffer, g_log_handle.buffer_data, LOG_BUFFER_SIZE
5255
);
@@ -55,6 +58,16 @@ LOG_Handle *LOG_init(void)
5558
return &g_log_handle;
5659
}
5760

61+
void LOG_deinit(LOG_Handle *handle)
62+
{
63+
if (handle != &g_log_handle) {
64+
return; // Only deinit the global handle
65+
}
66+
67+
circular_buffer_reset(&g_log_handle.buffer);
68+
g_log_handle.initialized = false;
69+
}
70+
5871
int LOG_write(LOG_Level level, char const *format, ...)
5972
{
6073
if (!g_log_handle.initialized) {
@@ -168,19 +181,18 @@ bool LOG_read_entry(LOG_Entry *entry)
168181
return true;
169182
}
170183

171-
void LOG_task(void)
184+
int LOG_task(uint32_t max_entries)
172185
{
173186
if (!g_log_handle.initialized) {
174-
return;
187+
return 0;
175188
}
176189

177190
/* Limit the number of entries processed per call to avoid blocking */
178-
enum { MAX_ENTRIES_PER_CALL = 8 };
179191
LOG_Entry entry;
180192
int processed = 0;
181193

182194
/* Process available log entries */
183-
while (processed < MAX_ENTRIES_PER_CALL && LOG_read_entry(&entry)) {
195+
while (processed < max_entries && LOG_read_entry(&entry)) {
184196
/* Format and output the message to stdout */
185197
printf("[%s] %s\r\n", g_LEVEL_NAMES[entry.level], entry.message);
186198
processed++;
@@ -190,4 +202,6 @@ void LOG_task(void)
190202
if (processed > 0) {
191203
(void)fflush(stdout);
192204
}
205+
206+
return processed;
193207
}

src/util/logging.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
* - Printf-style formatting
99
* - Configurable buffer size
1010
*
11-
* The logging system uses a circular buffer to store log messages, which
12-
* are written to stdout by the `LOG_task` function.
11+
* The logging system uses a circular buffer to store log messages, which can
12+
* be read back by the application using the `LOG_read_entry` function, or
13+
* written to stdout by the `LOG_task` function.
1314
*
1415
* @author PSLab Team
1516
* @date 2025-07-14
@@ -76,6 +77,16 @@ typedef struct {
7677
*/
7778
LOG_Handle *LOG_init(void);
7879

80+
/**
81+
* @brief Deinitialize the logging system
82+
*
83+
* This should be called when the logging system is no longer needed.
84+
* It resets the internal state and frees any resources.
85+
*
86+
* @param handle Pointer to the log handle to deinitialize
87+
*/
88+
void LOG_deinit(LOG_Handle *handle);
89+
7990
/**
8091
* @brief Write a log message
8192
*
@@ -111,8 +122,12 @@ bool LOG_read_entry(LOG_Entry *entry);
111122
*
112123
* The function processes up to a limited number of entries per call to avoid
113124
* blocking for too long in interrupt contexts.
125+
*
126+
* @param max_entries Maximum number of entries to process in this call
127+
*
128+
* @return Number of entries processed
114129
*/
115-
void LOG_task(void);
130+
int LOG_task(uint32_t max_entries);
116131

117132
/**
118133
* @brief Core logging macros with compile-time filtering

tests/test_logging.c

Lines changed: 137 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ void setUp(void)
2222
void tearDown(void)
2323
{
2424
// Reset logging state
25-
circular_buffer_reset(&g_log_handle->buffer);
25+
LOG_deinit(g_log_handle);
2626
}
2727

2828
void test_LOG_init(void)
@@ -34,6 +34,41 @@ void test_LOG_init(void)
3434
TEST_ASSERT_EQUAL(LOG_BUFFER_SIZE, g_log_handle->buffer.size);
3535
}
3636

37+
void test_LOG_init_already_initialized(void)
38+
{
39+
// Arrange - Call init again
40+
LOG_Handle *handle = LOG_init();
41+
42+
// Assert - Should return the same handle
43+
TEST_ASSERT_EQUAL_PTR(g_log_handle, handle);
44+
}
45+
46+
void test_LOG_deinit(void)
47+
{
48+
// Arrange
49+
LOG_Handle *handle = g_log_handle;
50+
51+
// Act
52+
LOG_deinit(handle);
53+
54+
// Assert - Check if handle is still valid after deinit
55+
TEST_ASSERT_NOT_NULL(handle);
56+
TEST_ASSERT_FALSE(handle->initialized);
57+
TEST_ASSERT_EQUAL(0, circular_buffer_available(&handle->buffer));
58+
}
59+
60+
void test_LOG_deinit_invalid_handle(void)
61+
{
62+
// Arrange
63+
LOG_Handle invalid_handle = { .initialized = true };
64+
65+
// Act - Attempt to deinitialize an invalid handle
66+
LOG_deinit(&invalid_handle);
67+
68+
// Assert - Should not crash, handle remains unchanged
69+
TEST_ASSERT_TRUE(invalid_handle.initialized);
70+
}
71+
3772
void test_LOG_write(void)
3873
{
3974
// Arrange
@@ -59,43 +94,6 @@ void test_LOG_write(void)
5994
TEST_ASSERT_EQUAL('\0', entry.message[entry.length]);
6095
}
6196

62-
void test_LOG_available(void)
63-
{
64-
// Arrange
65-
char const *test_message = "Test log message";
66-
67-
// Act
68-
int bytes_written = LOG_write(LOG_LEVEL_DEBUG, test_message);
69-
size_t available = LOG_available();
70-
71-
// Assert
72-
TEST_ASSERT_GREATER_THAN(0, bytes_written);
73-
TEST_ASSERT_EQUAL(available, bytes_written);
74-
}
75-
76-
// Test LOG_task processes at most 8 entries per call
77-
void test_LOG_task_partial_processing(void)
78-
{
79-
// Arrange: Write more than 8 entries
80-
const int total_entries = 12;
81-
for (int i = 0; i < total_entries; i++) {
82-
int bytes_written = LOG_write(LOG_LEVEL_INFO, "Test entry %d", i);
83-
TEST_ASSERT_GREATER_THAN(0, bytes_written);
84-
}
85-
86-
// Act: Call service once
87-
LOG_task();
88-
89-
// Assert: Only 8 processed, 4 remain
90-
TEST_ASSERT_GREATER_THAN(0, LOG_available());
91-
92-
// Act: Call service again
93-
LOG_task();
94-
95-
// Assert: Remaining 4 processed, buffer empty
96-
TEST_ASSERT_EQUAL(0, LOG_available());
97-
}
98-
9997
void test_LOG_write_multiple_entries(void)
10098
{
10199
// Arrange & Act
@@ -166,6 +164,24 @@ void test_LOG_write_long_message(void)
166164
TEST_ASSERT_EQUAL('\0', entry.message[entry.length]);
167165
}
168166

167+
void test_LOG_write_null_message(void)
168+
{
169+
// Act - Attempt to write a null message
170+
int bytes_written = LOG_write(LOG_LEVEL_INFO, NULL);
171+
172+
// Assert - Should return -1 for invalid format string
173+
TEST_ASSERT_EQUAL(-1, bytes_written);
174+
}
175+
176+
void test_LOG_write_invalid_level(void)
177+
{
178+
// Act - Attempt to write with an invalid log level
179+
int bytes_written = LOG_write((LOG_Level)999, "Invalid level test");
180+
181+
// Assert - Should return -1 for invalid log level
182+
TEST_ASSERT_EQUAL(-1, bytes_written);
183+
}
184+
169185
void test_LOG_read_entry_success(void)
170186
{
171187
// Arrange - Write a message first
@@ -194,7 +210,7 @@ void test_LOG_read_entry_empty_buffer(void)
194210
TEST_ASSERT_FALSE(result);
195211
}
196212

197-
void test_LOG_LOG_read_entry_null_pointer(void)
213+
void test_LOG_read_entry_null_pointer(void)
198214
{
199215
// Arrange
200216
int bytes_written = LOG_write(LOG_LEVEL_INFO, "Test message");
@@ -228,6 +244,54 @@ void test_LOG_buffer_overflow(void)
228244
TEST_ASSERT_EQUAL_STRING(final_entry_message_in_buffer, entry.message);
229245
}
230246

247+
void test_LOG_available(void)
248+
{
249+
// Arrange
250+
char const *test_message = "Test log message";
251+
252+
// Act
253+
int bytes_written = LOG_write(LOG_LEVEL_DEBUG, test_message);
254+
size_t available = LOG_available();
255+
256+
// Assert
257+
TEST_ASSERT_GREATER_THAN(0, bytes_written);
258+
TEST_ASSERT_EQUAL(available, bytes_written);
259+
}
260+
261+
void test_LOG_available_empty_buffer(void)
262+
{
263+
// Act
264+
size_t available = LOG_available();
265+
266+
// Assert - Should be 0 after setUp
267+
TEST_ASSERT_EQUAL(0, available);
268+
}
269+
270+
// Test LOG_task processes fewer entries than available
271+
void test_LOG_task_partial_processing(void)
272+
{
273+
// Arrange: Write several entries
274+
const int total_entries = 12;
275+
for (int i = 0; i < total_entries; i++) {
276+
int bytes_written = LOG_write(LOG_LEVEL_INFO, "Test entry %d", i);
277+
TEST_ASSERT_GREATER_THAN(0, bytes_written);
278+
}
279+
280+
// Act: Process fewer entries than available
281+
int processed = LOG_task(8);
282+
283+
// Assert: Only 8 processed, 4 remain
284+
TEST_ASSERT_EQUAL(8, processed);
285+
TEST_ASSERT_GREATER_THAN(0, LOG_available());
286+
287+
// Act: Call service again
288+
processed += LOG_task(8);
289+
290+
// Assert: Remaining 4 processed, buffer empty
291+
TEST_ASSERT_EQUAL(12, processed);
292+
TEST_ASSERT_EQUAL(0, LOG_available());
293+
}
294+
231295
void test_LOG_task_multiple_entries(void)
232296
{
233297
// Arrange - Write multiple entries
@@ -243,9 +307,20 @@ void test_LOG_task_multiple_entries(void)
243307
TEST_ASSERT_GREATER_THAN(0, bytes4);
244308

245309
// Act
246-
LOG_task();
310+
int processed = LOG_task(4);
247311

248312
// Assert - All entries should be processed and buffer empty
313+
TEST_ASSERT_EQUAL(4, processed);
314+
TEST_ASSERT_EQUAL(0, LOG_available());
315+
}
316+
317+
void test_LOG_task_no_entries(void)
318+
{
319+
// Act - Call task with no entries
320+
int processed = LOG_task(5);
321+
322+
// Assert - Should process 0 entries
323+
TEST_ASSERT_EQUAL(0, processed);
249324
TEST_ASSERT_EQUAL(0, LOG_available());
250325
}
251326

@@ -465,3 +540,25 @@ void test_LOG_buffer_data_integrity_after_wraparound(void)
465540
}
466541
}
467542
}
543+
544+
void test_LOG_consistent_state_on_multiple_initializations(void)
545+
{
546+
// Arrange - Write a message before reinitialization
547+
char const *test_message = "Consistent state test";
548+
int bytes_written = LOG_write(LOG_LEVEL_INFO, test_message);
549+
TEST_ASSERT_GREATER_THAN(0, bytes_written);
550+
551+
// Act - Reinitialize logging system
552+
LOG_Handle *handle_reinit = LOG_init();
553+
554+
// Assert - Should return the same handle, state should be consistent
555+
TEST_ASSERT_EQUAL_PTR(g_log_handle, handle_reinit);
556+
TEST_ASSERT_TRUE(handle_reinit->initialized);
557+
TEST_ASSERT_EQUAL(bytes_written, LOG_available());
558+
559+
// Verify we can still read the previously written message
560+
LOG_Entry entry;
561+
TEST_ASSERT_TRUE(LOG_read_entry(&entry));
562+
TEST_ASSERT_EQUAL(LOG_LEVEL_INFO, entry.level);
563+
TEST_ASSERT_EQUAL_STRING(test_message, entry.message);
564+
}

0 commit comments

Comments
 (0)