Branch data Line data Source code
1 : : #include "testmocking.h"
2 : :
3 : : #include <limits.h>
4 : : #include <stdarg.h>
5 : : #include <stddef.h>
6 : : #include <stdio.h>
7 : :
8 : : static size_t testmocking_snprintf_fail_remaining = 0;
9 : : static size_t testmocking_snprintf_truncate_remaining = 0;
10 : :
11 : : /**
12 : : * @brief Arm snprintf mock to fail for the next n calls
13 : : *
14 : : * @param[in] n Number of consecutive snprintf calls that must fail
15 : : */
16 : 5 : void testmocking_snprintf_fail_next(size_t n)
17 : : {
18 : 5 : testmocking_snprintf_fail_remaining = n;
19 : 5 : }
20 : :
21 : : /**
22 : : * @brief Arm snprintf mock to report truncation for the next n calls
23 : : *
24 : : * @param[in] n Number of consecutive snprintf calls that must report truncation
25 : : */
26 : 3 : void testmocking_snprintf_truncate_next(size_t n)
27 : : {
28 : 3 : testmocking_snprintf_truncate_remaining = n;
29 : 3 : }
30 : :
31 : : /**
32 : : * @brief Disable snprintf mock unconditionally
33 : : */
34 : 9 : void testmocking_snprintf_disable(void)
35 : : {
36 : 9 : testmocking_snprintf_fail_remaining = 0;
37 : 9 : testmocking_snprintf_truncate_remaining = 0;
38 : 9 : }
39 : :
40 : : #ifndef EVIL_EMPIRE_OS
41 : : int __wrap_snprintf(
42 : : char *str,
43 : : size_t size,
44 : : const char *format,
45 : : ...) __attribute__((format(printf,3,4)));
46 : :
47 : : /**
48 : : * @brief Linker-redirected entry point for snprintf
49 : : *
50 : : * When the mock is armed, it can inject either a formatting failure or a
51 : : * truncation result. Otherwise the call is forwarded to libc through
52 : : * vsnprintf, which is the standard way to pass a collected variadic argument
53 : : * list to a printf-family implementation
54 : : *
55 : : * @param[out] str Destination buffer passed by the caller
56 : : * @param[in] size Destination buffer size
57 : : * @param[in] format printf-style format string
58 : : * @return snprintf-compatible result
59 : : */
60 : 4441 : int __wrap_snprintf(
61 : : char *str,
62 : : size_t size,
63 : : const char *format,
64 : : ...)
65 : : {
66 [ + + ]: 4441 : if(testmocking_snprintf_fail_remaining > 0U)
67 : : {
68 : 5 : testmocking_snprintf_fail_remaining--;
69 : 5 : return(-1);
70 : : }
71 : :
72 [ + + ]: 4436 : if(testmocking_snprintf_truncate_remaining > 0U)
73 : : {
74 : 3 : testmocking_snprintf_truncate_remaining--;
75 : :
76 [ + - + - ]: 3 : if(str != NULL && size > 0U)
77 : : {
78 : 3 : str[0] = 'T';
79 : :
80 [ + - ]: 3 : if(size > 1U)
81 : : {
82 : 3 : str[1] = '\0';
83 : : }
84 : : }
85 : :
86 : 3 : int reported_length = 1;
87 : :
88 [ + - ]: 3 : if(size < (size_t)INT_MAX)
89 : : {
90 : 3 : reported_length = (int)size;
91 : : } else {
92 : 0 : reported_length = INT_MAX;
93 : : }
94 : :
95 [ - + ]: 3 : if(reported_length == 0)
96 : : {
97 : 0 : reported_length = 1;
98 : : }
99 : :
100 : 3 : return(reported_length);
101 : : }
102 : :
103 : : va_list args;
104 : 4433 : va_start(args,format);
105 : 4433 : const int result = vsnprintf(str,size,format,args);
106 : 4433 : va_end(args);
107 : :
108 : 4433 : return(result);
109 : : }
110 : : #endif
|