Skip to content

Commit 470636c

Browse files
committed
Handle printf error
1 parent 7b7c1da commit 470636c

File tree

7 files changed

+115
-10
lines changed

7 files changed

+115
-10
lines changed

.clang-tidy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
# SPDX-License-Identifier: MIT
44

55
WarningsAsErrors: '*'
6+
7+
Checks: >
8+
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling

include/perfect-helloworld.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,38 @@
77
#pragma once
88

99
/**
10-
* @brief Print "Hello, World!\n" and exit
10+
* @brief
11+
* Result of the library function.
1112
*/
12-
void print_hello(void);
13+
enum PERFECT_HELLOWORLD_RESULT {
14+
PERFECT_HELLOWORLD_RESULT_OK = 0, //!< Success.
15+
PERFECT_HELLOWORLD_RESULT_STDOUT_IO_ERROR, //!< Failure.
16+
};
17+
18+
/**
19+
* @brief
20+
* Return a human-readable description of a PERFECT_HELLOWORLD_RESULT.
21+
*
22+
* @param res
23+
* A result code returned by a function of this library.
24+
*
25+
* @return
26+
* A pointer to a null-terminated, immutable string describing @p res.
27+
*
28+
* @note
29+
* - The returned string has static storage duration and must not be freed or
30+
* modified by the caller.
31+
*
32+
* - This function is thread-safe.
33+
*
34+
* - For unknown or unsupported values of @p res, a generic "Unknown error" string
35+
* is returned.
36+
*/
37+
const char *perfect_helloworld_strerror(enum PERFECT_HELLOWORLD_RESULT res);
38+
39+
/**
40+
* @brief
41+
* Print "Hello, World!\n".
42+
*/
43+
enum PERFECT_HELLOWORLD_RESULT
44+
perfect_helloworld_print_hello(void);

src/cli/main.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@
22
//
33
// SPDX-License-Identifier: MIT
44

5+
#include <stdio.h>
56
#include <stdlib.h>
67

78
#include "perfect-helloworld.h"
89

910
int main(void) {
10-
print_hello();
11+
enum PERFECT_HELLOWORLD_RESULT res = perfect_helloworld_print_hello();
12+
if (res != PERFECT_HELLOWORLD_RESULT_OK) {
13+
fprintf(
14+
stderr,
15+
"perfect_helloworld_print_hello failed: %s\n",
16+
perfect_helloworld_strerror(res));
17+
return EXIT_FAILURE;
18+
}
19+
1120
return EXIT_SUCCESS;
1221
}

src/lib/perfect-helloworld.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,22 @@
66

77
#include "perfect-helloworld.h"
88

9-
void print_hello(void) { printf("Hello, World!\n"); }
9+
const char *
10+
perfect_helloworld_strerror(enum PERFECT_HELLOWORLD_RESULT res) {
11+
switch (res) {
12+
case PERFECT_HELLOWORLD_RESULT_OK:
13+
return "Success";
14+
case PERFECT_HELLOWORLD_RESULT_STDOUT_IO_ERROR:
15+
return "I/O error while writing to standard output";
16+
default:
17+
return "Unknown perfect_helloworld error";
18+
}
19+
}
20+
21+
enum PERFECT_HELLOWORLD_RESULT perfect_helloworld_print_hello(void) {
22+
if (fputs("Hello, World!\n", stdout) == EOF) {
23+
return PERFECT_HELLOWORLD_RESULT_STDOUT_IO_ERROR;
24+
}
25+
26+
return PERFECT_HELLOWORLD_RESULT_OK;
27+
}

tests/meson.build

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,21 @@ if get_option('tests').enabled()
66
unity = dependency('unity', required: get_option('tests'))
77

88
test(
9-
'test-perfect-helloworld',
9+
'test-perfect-helloworld-print-hello-ok',
1010
executable(
11-
'test-perfect-helloworld',
12-
sources: files('test-perfect-helloworld.c'),
11+
'test-perfect-helloworld-print-hello-ok',
12+
sources: files('test-perfect-helloworld-print-hello-ok.c'),
13+
link_with: lib,
14+
dependencies: unity,
15+
include_directories: inc,
16+
),
17+
)
18+
19+
test(
20+
'test-perfect-helloworld-print-hello-err',
21+
executable(
22+
'test-perfect-helloworld-print-hello-err',
23+
sources: files('test-perfect-helloworld-print-hello-err.c'),
1324
link_with: lib,
1425
dependencies: unity,
1526
include_directories: inc,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-FileCopyrightText: © 2026 Nikita Krasnov <nikita.nikita.krasnov@gmail.com>
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
#include <stdio.h>
6+
#include <unity.h>
7+
#include <unity_internals.h>
8+
9+
#include "perfect-helloworld.h"
10+
11+
void setUp(void) {
12+
// set stuff up here
13+
}
14+
15+
void tearDown(void) {
16+
// clean stuff up here
17+
}
18+
19+
static void test_perfect_helloworld_print_hello_err(void) {
20+
fclose(stdout);
21+
enum PERFECT_HELLOWORLD_RESULT res = perfect_helloworld_print_hello();
22+
TEST_ASSERT_EQUAL(PERFECT_HELLOWORLD_RESULT_STDOUT_IO_ERROR, res);
23+
}
24+
25+
int main(void) {
26+
UNITY_BEGIN();
27+
28+
RUN_TEST(test_perfect_helloworld_print_hello_err);
29+
30+
return UNITY_END();
31+
}

tests/test-perfect-helloworld.c renamed to tests/test-perfect-helloworld-print-hello-ok.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@ void tearDown(void) {
1515
// clean stuff up here
1616
}
1717

18-
static void test_print_hello(void) {
19-
print_hello();
18+
static void test_perfect_helloworld_print_hello_ok(void) {
19+
enum PERFECT_HELLOWORLD_RESULT res = perfect_helloworld_print_hello();
20+
TEST_ASSERT_EQUAL(PERFECT_HELLOWORLD_RESULT_OK, res);
2021
}
2122

2223
int main(void) {
2324
UNITY_BEGIN();
2425

25-
RUN_TEST(test_print_hello);
26+
RUN_TEST(test_perfect_helloworld_print_hello_ok);
2627

2728
return UNITY_END();
2829
}

0 commit comments

Comments
 (0)