Issue
I have a function for example:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
The man page tell me "The argument addr is a pointer to a sockaddr structure. This structure is filled in with the address of the peer socket, as known to the communications layer." So I would call the function with:
struct sockaddr_storage clientAddr;
struct sockaddr* sa{(sockaddr*)&clientAddr};
clientLen = sizeof(clientAddr);;
accept_sock = accept(listen_sock, (struct sockaddr*)&clientAddr, &clientLen);
With mocking accept
I would like to fill clientAddr
with:
struct sockaddr_in* sa_in{(sockaddr_in*)&clientAddr};
sa_in->sin_family = AF_INET;
sa_in->sin_port = htons(50000);
inet_pton(AF_INET, "192.168.1.2", &sa_in->sin_addr);
To return a mocked pointer to a filled structure I would use:
EXPECT_CALL(mocked_sys_socket, accept(listen_sock, _, Pointee(clientLen)))
.WillOnce(DoAll(SetArgPointee<1>(*sa), Return(accept_sock)));
But that isn't what I need here. The clientAddr
structure is already given.
What action instead of SetArgPointee<1>(*sa)
I have to use to return with filling the provided structure clientAddr
?
Solution
IIUC, you want that as a result of a call to accept
, the second parameter of accept
, which is currently sa_int
to be set to the value of sa_next
.
If that's the case, I can think of two options:
struct sockaddr {
std::string name;
};
class MockedSysSocket {
public:
MOCK_METHOD(int, accept, (int, sockaddr *, socklen_t *addrlen), ());
};
TEST(MockedSysSocketTest, SideEffect1) {
MockedSysSocket mocked_sys_socket;
int accept_sock = 1;
int listen_sock = 2;
sockaddr sa_in{"initial"};
sockaddr sa_next{"next"};
socklen_t clientLen = sizeof(sockaddr);
EXPECT_CALL(mocked_sys_socket, accept(listen_sock, &sa_in, &clientLen))
.WillOnce(DoAll(SetArgPointee<1>(sa_next), Return(accept_sock)));
auto actual = mocked_sys_socket.accept(listen_sock, &sa_in, &clientLen);
EXPECT_EQ(sa_in.name, sa_next.name);
EXPECT_EQ(actual, accept_sock);
}
TEST(MockedSysSocketTest, SideEffect2) {
MockedSysSocket mocked_sys_socket;
int accept_sock = 1;
int listen_sock = 2;
sockaddr sa_in{"initial"};
sockaddr sa_next{"next"};
socklen_t clientLen = sizeof(sockaddr);
EXPECT_CALL(mocked_sys_socket, accept(listen_sock, &sa_in, &clientLen))
.WillOnce(WithArg<1>(Invoke([&sa_next, accept_sock](sockaddr *in) {
*in = sa_next;
return accept_sock;
})));
auto actual = mocked_sys_socket.accept(listen_sock, &sa_in, &clientLen);
EXPECT_EQ(sa_in.name, sa_next.name);
EXPECT_EQ(actual, accept_sock);
}
Live example: https://godbolt.org/z/3h4ffcnd7
Answered By - Ari Answer Checked By - Candace Johnson (WPSolving Volunteer)