Branch data Line data Source code
1 : : #include "mocks.h"
2 : : #include <stdarg.h>
3 : : #include <setjmp.h>
4 : : #include <cmocka.h>
5 : : #include <errno.h>
6 : : #include <stdio.h>
7 : : #include <string.h>
8 : :
9 : : static bool mock_fread_enabled = false;
10 : : static size_t mock_fread_calls = 0;
11 : : static const char *mock_fread_target_suffix = NULL;
12 : : static FILE *mock_fread_target_stream = NULL;
13 : : static bool mock_fread_error_seen = false;
14 : : static int mock_fread_errno = EIO;
15 : : static bool mock_remove_enabled = false;
16 : : static size_t mock_remove_calls = 0;
17 : : static const char *mock_remove_target_suffix = NULL;
18 : : static int mock_remove_errno = EACCES;
19 : :
20 : 14 : static bool mock_path_matches_suffix(const char *path,const char *suffix)
21 : : {
22 : 14 : size_t path_len = 0;
23 : 14 : size_t suffix_len = 0;
24 : :
25 [ + - - + ]: 14 : if(path == NULL || suffix == NULL)
26 : : {
27 : 0 : return false;
28 : : }
29 : :
30 [ - + ]: 14 : if(strcmp(path,suffix) == 0)
31 : : {
32 : 0 : return true;
33 : : }
34 : :
35 : 14 : path_len = strlen(path);
36 : 14 : suffix_len = strlen(suffix);
37 : :
38 [ - + ]: 14 : if(path_len < suffix_len + 1U)
39 : : {
40 : 0 : return false;
41 : : }
42 : :
43 [ + + ]: 14 : if(path[path_len - suffix_len - 1U] != '/')
44 : : {
45 : 8 : return false;
46 : : }
47 : :
48 : 6 : return strcmp(path + (path_len - suffix_len),suffix) == 0;
49 : : }
50 : :
51 : 1 : void mocks_fread_set_target_suffix(const char *suffix)
52 : : {
53 : 1 : mock_fread_target_suffix = suffix;
54 : 1 : }
55 : :
56 : 2 : void mocks_fread_enable(bool enabled)
57 : : {
58 : 2 : mock_fread_enabled = enabled;
59 : 2 : }
60 : :
61 : 2 : void mocks_fread_reset(void)
62 : : {
63 : 2 : mock_fread_enabled = false;
64 : 2 : mock_fread_calls = 0;
65 : 2 : mock_fread_target_suffix = NULL;
66 : 2 : mock_fread_target_stream = NULL;
67 : 2 : mock_fread_error_seen = false;
68 : 2 : mock_fread_errno = EIO;
69 : 2 : }
70 : :
71 : 1 : size_t mocks_fread_call_count(void)
72 : : {
73 : 1 : return mock_fread_calls;
74 : : }
75 : :
76 : : /**
77 : : * @brief Set errno returned by the simulated fread failure path
78 : : *
79 : : * @param[in] err Errno value to expose after the forced read failure
80 : : */
81 : 1 : void mocks_fread_set_errno(int err)
82 : : {
83 : 1 : mock_fread_errno = err;
84 : 1 : }
85 : :
86 : 2 : void mocks_remove_set_target_suffix(const char *suffix)
87 : : {
88 : 2 : mock_remove_target_suffix = suffix;
89 : 2 : }
90 : :
91 : 2 : void mocks_remove_enable(bool enabled)
92 : : {
93 : 2 : mock_remove_enabled = enabled;
94 : 2 : }
95 : :
96 : 4 : void mocks_remove_reset(void)
97 : : {
98 : 4 : mock_remove_enabled = false;
99 : 4 : mock_remove_calls = 0;
100 : 4 : mock_remove_target_suffix = NULL;
101 : 4 : mock_remove_errno = EACCES;
102 : 4 : }
103 : :
104 : 2 : size_t mocks_remove_call_count(void)
105 : : {
106 : 2 : return mock_remove_calls;
107 : : }
108 : :
109 : 2 : void mocks_remove_set_errno(int err)
110 : : {
111 : 2 : mock_remove_errno = err;
112 : 2 : }
113 : :
114 : : FILE *__real_fopen(const char *path,const char *mode);
115 : :
116 : 2044 : FILE *__wrap_fopen(const char *path,const char *mode)
117 : : {
118 : 2044 : FILE *stream = __real_fopen(path,mode);
119 : :
120 [ + + + + ]: 2044 : if(stream != NULL && mock_fread_target_suffix != NULL)
121 : : {
122 [ + + ]: 12 : if(mock_path_matches_suffix(path,mock_fread_target_suffix))
123 : : {
124 : 1 : mock_fread_target_stream = stream;
125 : : }
126 : : }
127 : :
128 : 2044 : return stream;
129 : : }
130 : :
131 : : size_t __real_fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
132 : :
133 : 2464 : size_t __wrap_fread(void *ptr,size_t size,size_t nmemb,FILE *stream)
134 : : {
135 [ + + ]: 2464 : if(mock_fread_enabled
136 [ + - ]: 23 : && stream != NULL
137 [ + + ]: 23 : && stream == mock_fread_target_stream
138 [ + - ]: 1 : && mock_fread_calls == 0)
139 : : {
140 : 1 : mock_fread_calls++;
141 : 1 : mock_fread_error_seen = true;
142 : 1 : errno = mock_fread_errno;
143 : 1 : return 0;
144 : : }
145 : :
146 : 2463 : return __real_fread(ptr,size,nmemb,stream);
147 : : }
148 : :
149 : : int __real_ferror(FILE *stream);
150 : :
151 : : /**
152 : : * @brief Report a pending mocked fread error exactly once for the tracked stream
153 : : *
154 : : * @param[in] stream Stream passed to `ferror()`
155 : : * @return `1` for the pending mocked error or the real `ferror()` result otherwise
156 : : */
157 : 1020 : int __wrap_ferror(FILE *stream)
158 : : {
159 [ + - + + : 1020 : if(stream != NULL && stream == mock_fread_target_stream && mock_fread_error_seen)
+ - ]
160 : : {
161 : : /*
162 : : * Clear the target once the error is observed to avoid matching a
163 : : * recycled FILE* address for unrelated files (seen in coverage builds).
164 : : */
165 : 1 : mock_fread_target_stream = NULL;
166 : 1 : mock_fread_error_seen = false;
167 : 1 : return 1;
168 : : }
169 : :
170 : 1019 : return __real_ferror(stream);
171 : : }
172 : :
173 : : int __real_remove(const char *path);
174 : :
175 : 4925 : int __wrap_remove(const char *path)
176 : : {
177 [ + + ]: 4925 : if(mock_remove_enabled
178 [ + - ]: 2 : && path != NULL
179 [ + - ]: 2 : && mock_remove_target_suffix != NULL
180 [ + - ]: 2 : && mock_remove_calls == 0
181 [ + - ]: 2 : && mock_path_matches_suffix(path,mock_remove_target_suffix))
182 : : {
183 : 2 : mock_remove_calls++;
184 : 2 : errno = mock_remove_errno;
185 : 2 : return -1;
186 : : }
187 : :
188 : 4923 : return __real_remove(path);
189 : : }
|