Skip to content

Commit 8338f9e

Browse files
committed
Add multi-platform support
Signed-off-by: Jorge Perez <[email protected]>
1 parent d3407d6 commit 8338f9e

File tree

1 file changed

+62
-13
lines changed

1 file changed

+62
-13
lines changed

test/test_strerror.cpp

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,6 @@
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>
@@ -28,6 +21,7 @@
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 */
73106
TEST(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

Comments
 (0)