1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15- #ifdef _GNU_SOURCE
16- #undef _GNU_SOURCE
17- #include < string>
18- #else
19- #include < string>
20- #endif
21-
2215#include < gtest/gtest.h>
2316
2417#include < sys/types.h>
2821#include < dirent.h>
2922#endif
3023
24+ #include " rcutils/macros.h"
3125#include " rcutils/strerror.h"
3226
3327#include " ./mimick.h"
@@ -64,22 +58,74 @@ TEST(test_strerror, get_error) {
6458
6559/*
6660 Define the blueprint of a mock identified by `strerror_r_proto`
67- strerror_r signature:
68- int strerror_r(int errnum, char *buf, size_t buflen);
61+ strerror_r possible signatures:
62+
63+ * int strerror_r(int errnum, char *buf, size_t buflen); (Case 1)
64+ * char *strerror_r(int errnum, char *buf, size_t buflen); (Case 2)
65+ * errno_t strerror_s( char *buf, rsize_t bufsz, errno_t errnum ); (Case 3)
6966*/
70- mmk_mock_define (strerror_r_mock, int , char *, size_t );
67+
68+ #if defined(_WIN32)
69+ mmk_mock_define (strerror_s_mock, errno_t , char *, rsize_t , errno_t );
70+ #elif defined(_GNU_SOURCE) && (!defined(ANDROID) || __ANDROID_API__ >= 23)
71+ mmk_mock_define (strerror_r_mock, char *, int , char *, size_t );
72+ #else
73+ mmk_mock_define (strerror_r_mock, int , int , char *, size_t );
74+ #endif
75+
76+ const char expected_error_msg[] = " Failed to get error" ;
77+ #if defined(_WIN32)
78+ // Function to be called for (Case 3)
79+ errno_t mocked_windows_strerror (char * buf, rsize_t bufsz, errno_t errnum)
80+ {
81+ (void ) errnum;
82+ unsigned char index_err = 0 ;
83+
84+ while (buf && bufsz--) {
85+ buf[index_err] = expected_error_msg[index_err];
86+ index_err++;
87+ }
88+ return errnum;
89+ }
90+ #else
91+ // Function to be called for (Case 1)
92+ char * mocked_gnu_strerror (int errnum, char * buf, size_t buflen)
93+ {
94+ (void ) errnum;
95+ const char error_msg[] = " Failed to get error" ;
96+ unsigned char index_err = 0 ;
97+ while (buf && buflen--) {
98+ buf[index_err] = error_msg[index_err];
99+ index_err++;
100+ }
101+ return buf;
102+ }
103+ #endif
71104
72105/* Mocking test example */
73106TEST (test_strerror, test_mock) {
74107 /* Mock the strerror_r function in the current module using
75108 the `strerror_r_mock` blueprint. */
76- mmk_mock (" __xpg_strerror_r@lib:rcutils" , strerror_r_mock);
77-
109+ #if defined(_WIN32)
110+ mmk_mock (RCUTILS_STRINGIFY (strerror_s) " @lib:rcutils" , strerror_s_mock);
111+ #else
112+ mmk_mock (RCUTILS_STRINGIFY (strerror_r) " @lib:rcutils" , strerror_r_mock);
113+ #endif
78114 /* Tell the mock to return NULL and set errno to ENOMEM
79115 whatever the given parameter is. */
116+ #if defined(_WIN32)
117+ mmk_when (
118+ strerror_s (mmk_any (errno_t ), mmk_any (char *), mmk_any (rsize_t ), mmk_any (errno_t )),
119+ .then_call = (mmk_fn) mocked_windows_strerror);
120+ #elif defined(_GNU_SOURCE) && (!defined(ANDROID) || __ANDROID_API__ >= 23)
121+ mmk_when (
122+ strerror_r (mmk_any (int ), mmk_any (char *), mmk_any (size_t ) ),
123+ .then_call = (mmk_fn) mocked_gnu_strerror);
124+ #else
80125 mmk_when (
81126 strerror_r (mmk_any (int ), mmk_any (char *), mmk_any (size_t ) ),
82127 .then_return = mmk_val (int , EINVAL));
128+ #endif
83129
84130 // Now normal usage of the function returning unexpected EINVAL
85131 // error for the internal strerror_r
@@ -90,6 +136,9 @@ TEST(test_strerror, test_mock) {
90136 char error_string[1024 ];
91137 rcutils_strerror (error_string, sizeof (error_string));
92138 ASSERT_STREQ (error_string, " Failed to get error" );
93-
139+ #if defined(_WIN32)
140+ mmk_reset (strerror_s);
141+ #else
94142 mmk_reset (strerror_r);
143+ #endif
95144}
0 commit comments