Skip to content

Commit

Permalink
WIP: SB16 POSIX socket test cases update
Browse files Browse the repository at this point in the history
Added more POSIX Socket tests cover more IPv4 and IPv6 cases.
Convered host byte to network byte order for port numbers.
Added wrapper layer in starboard/shared/moduler for sockaddr
definition differences on certain platform.

b/330771976
  • Loading branch information
maxz-lab committed Apr 11, 2024
1 parent 7798507 commit d81c4fc
Show file tree
Hide file tree
Showing 17 changed files with 686 additions and 85 deletions.
10 changes: 10 additions & 0 deletions starboard/elf_loader/exported_symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#if SB_API_VERSION >= 16
#include "starboard/shared/modular/starboard_layer_posix_mmap_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_pthread_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_socket_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_stat_abi_wrappers.h"
#include "starboard/shared/modular/starboard_layer_posix_time_abi_wrappers.h"
#endif // SB_API_VERSION >= 16
Expand Down Expand Up @@ -517,6 +518,15 @@ ExportedSymbols::ExportedSymbols() {
reinterpret_cast<const void*>(&__abi_wrap_pthread_self);
map_["stat"] = reinterpret_cast<const void*>(&__abi_wrap_stat);
map_["time"] = reinterpret_cast<const void*>(&__abi_wrap_time);
map_["accept"] = reinterpret_cast<const void*>(&__abi_wrap_socket_accept);
map_["bind"] = reinterpret_cast<const void*>(&__abi_wrap_socket_bind);
map_["connect"] = reinterpret_cast<const void*>(&__abi_wrap_socket_connect);
map_["getaddrinfo"] =
reinterpret_cast<const void*>(&__abi_wrap_socket_getaddrinfo);
map_["getifaddrs"] =
reinterpret_cast<const void*>(&__abi_wrap_socket_getifaddrs);
map_["setsockopt"] =
reinterpret_cast<const void*>(&__abi_wrap_socket_setsockopt);

#if defined(_MSC_VER)
// MSVC provides a template with the same name.
Expand Down
46 changes: 31 additions & 15 deletions starboard/nplb/posix_compliance/posix_socket_accept_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// Here we are not trying to do anything fancy, just to really sanity check that
// this is hooked up to something.

#include <fcntl.h>
#include "starboard/nplb/posix_compliance/posix_socket_helpers.h"

namespace starboard {
Expand All @@ -32,6 +33,9 @@ TEST(PosixSocketAcceptTest, RainyDayNoConnection) {
int result = -1;
ASSERT_TRUE(socket_listen_fd >= 0);

// set socket non-blocking
fcntl(socket_listen_fd, F_SETFL, O_NONBLOCK);

// set socket reuseable
const int on = 1;
result =
Expand All @@ -43,16 +47,20 @@ TEST(PosixSocketAcceptTest, RainyDayNoConnection) {
}

// bind socket with local address
struct sockaddr_in address = {};
result =
PosixGetLocalAddressiIPv4(reinterpret_cast<struct sockaddr*>(&address));
address.sin_port = GetPortNumberForTests();
address.sin_family = AF_INET;
EXPECT_TRUE(result == 0);
if (result != 0) {
close(socket_listen_fd);
return;
}
#if SB_HAS(IPV6)
sockaddr_in6 address = {};
sockaddr_in6* address_ptr = reinterpret_cast<sockaddr_in6*>(&address);
EXPECT_TRUE(
PosixGetLocalAddressIPv4(reinterpret_cast<sockaddr*>(&address)) == 0 ||
PosixGetLocalAddressIPv6(reinterpret_cast<sockaddr*>(&address)) == 0);
address.sin6_port = htons(GetPortNumberForTests());
#else
sockaddr address = {0};
EXPECT_TRUE(PosixGetLocalAddressIPv4(&address) == 0);
sockaddr_in* address_ptr = reinterpret_cast<sockaddr_in*>(&address);
address_ptr->sin_port = htons(GetPortNumberForTests());
#endif

result = bind(socket_listen_fd, reinterpret_cast<sockaddr*>(&address),
sizeof(sockaddr));
EXPECT_TRUE(result == 0);
Expand Down Expand Up @@ -124,11 +132,19 @@ TEST(PosixSocketAcceptTest, RainyDayNotListening) {
}

// bind socket with local address
struct sockaddr_in address = {};
result =
PosixGetLocalAddressiIPv4(reinterpret_cast<struct sockaddr*>(&address));
address.sin_port = GetPortNumberForTests();
address.sin_family = AF_INET;
#if SB_HAS(IPV6)
sockaddr_in6 address = {};
sockaddr_in6* address_ptr = reinterpret_cast<sockaddr_in6*>(&address);
EXPECT_TRUE(
PosixGetLocalAddressIPv4(reinterpret_cast<sockaddr*>(&address)) == 0 ||
PosixGetLocalAddressIPv6(reinterpret_cast<sockaddr*>(&address)) == 0);
address.sin6_port = htons(GetPortNumberForTests());
#else
sockaddr address = {0};
EXPECT_TRUE(PosixGetLocalAddressIPv4(&address) == 0);
sockaddr_in* address_ptr = reinterpret_cast<sockaddr_in*>(&address);
address_ptr->sin_port = htons(GetPortNumberForTests());
#endif
EXPECT_TRUE(result == 0);
if (result != 0) {
close(socket_fd);
Expand Down
199 changes: 179 additions & 20 deletions starboard/nplb/posix_compliance/posix_socket_bind_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@

namespace starboard {
namespace nplb {

namespace {

TEST(PosixSocketBindTest, RainyDayNullSocket) {
int port = GetPortNumberForTests();
int port = htons(GetPortNumberForTests());
sockaddr_in address = {};
address.sin_family = AF_INET;
int invalid_socket_fd = -1;
Expand All @@ -37,15 +36,6 @@ TEST(PosixSocketBindTest, RainyDayNullAddress) {

// Binding with a NULL address should fail.
EXPECT_FALSE(bind(socket_fd, NULL, 0) == 0);

// Even though that failed, binding the same socket now with 0.0.0.0:2048
// should work.
sockaddr_in address = {};
address.sin_family = AF_INET;
address.sin_port = GetPortNumberForTests();

EXPECT_TRUE(bind(socket_fd, reinterpret_cast<sockaddr*>(&address),
sizeof(sockaddr_in)) == 0);
EXPECT_TRUE(close(socket_fd) == 0);
}

Expand All @@ -62,15 +52,15 @@ TEST(PosixSocketBindTest, RainyDayWrongAddressType) {
// Binding with the wrong address type should fail.
sockaddr_in client_address = {};
client_address.sin_family = AF_INET6;
client_address.sin_port = GetPortNumberForTests();
client_address.sin_port = htons(GetPortNumberForTests());
EXPECT_FALSE(bind(socket_fd, reinterpret_cast<sockaddr*>(&client_address),
sizeof(sockaddr_in)) == 0);

// Even though that failed, binding the same socket now with the server
// address type should work.
sockaddr_in server_address = {};
server_address.sin_family = AF_INET;
server_address.sin_port = GetPortNumberForTests();
server_address.sin_port = htons(GetPortNumberForTests());
EXPECT_TRUE(bind(socket_fd, reinterpret_cast<sockaddr*>(&server_address),
sizeof(sockaddr_in)) == 0);
EXPECT_TRUE(close(socket_fd) == 0);
Expand All @@ -92,14 +82,18 @@ TEST(PosixSocketBindTest, RainyDayBadInterface) {
}

TEST(PosixSocketBindTest, SunnyDayLocalInterface) {
sockaddr_in6 address = {};
#if SB_HAS(IPV6)
EXPECT_TRUE(PosixGetLocalAddressiIPv4(
reinterpret_cast<struct sockaddr*>(&address)) == 0 ||
PosixGetLocalAddressiIPv6(&address) == 0);
#else
sockaddr_in6 address = {};
sockaddr_in6* address_ptr = reinterpret_cast<sockaddr_in6*>(&address);
EXPECT_TRUE(
PosixGetLocalAddressiIPv4(reinterpret_cast<sockaddr*>(&address)) == 0);
PosixGetLocalAddressIPv4(reinterpret_cast<sockaddr*>(&address)) == 0 ||
PosixGetLocalAddressIPv6(reinterpret_cast<sockaddr*>(&address)) == 0);
address.sin6_port = htons(GetPortNumberForTests());
#else
sockaddr address = {0};
EXPECT_TRUE(PosixGetLocalAddressIPv4(&address) == 0);
sockaddr_in* address_ptr = reinterpret_cast<sockaddr_in*>(&address);
address_ptr->sin_port = htons(GetPortNumberForTests());
#endif

int socket_domain = AF_INET;
Expand All @@ -108,11 +102,176 @@ TEST(PosixSocketBindTest, SunnyDayLocalInterface) {

int socket_fd = socket(socket_domain, socket_type, socket_protocol);
ASSERT_TRUE(socket_fd > 0);

EXPECT_TRUE(bind(socket_fd, reinterpret_cast<struct sockaddr*>(&address),
sizeof(struct sockaddr)) == 0);
sizeof(address)) == 0);
EXPECT_TRUE(close(socket_fd) == 0);
}

TEST(PosixSocketBindTest, SunnyDayAnyAddr) {
// Even though that failed, binding the same socket now with 0.0.0.0:2048
// should work.
sockaddr_in address = {};
address.sin_family = AF_INET;
address.sin_port = htons(GetPortNumberForTests());
address.sin_addr.s_addr = INADDR_ANY;

int socket_domain = AF_INET;
int socket_type = SOCK_STREAM;
int socket_protocol = IPPROTO_TCP;
int socket_fd = socket(socket_domain, socket_type, socket_protocol);
ASSERT_TRUE(socket_fd > 0);
EXPECT_TRUE(bind(socket_fd, reinterpret_cast<sockaddr*>(&address),
sizeof(sockaddr_in)) == 0);
EXPECT_TRUE(close(socket_fd) == 0);
}

// Pair data input test
std::string GetPosixSocketAddressTypeFilterPairName(
::testing::TestParamInfo<std::pair<int, int>> info) {
return FormatString("type_%d_filter_%d", info.param.first, info.param.second);
}

class PosixSocketBindPairFilterTest
: public ::testing::TestWithParam<std::pair<int, int>> {
public:
int GetAddressType() { return GetParam().first; }
int GetFilterType() { return GetParam().second; }
};

#if SB_HAS(IPV6)
class PosixSocketBindPairCSTest
: public ::testing::TestWithParam<std::pair<int, int>> {
public:
int GetServerAddressType() { return GetParam().first; }
int GetClientAddressType() { return GetParam().second; }
};
#endif

// This is to use NULL in asserts, which otherwise complain about long
// vs. pointer type.
const void* kNull = NULL;

TEST_P(PosixSocketBindPairFilterTest, RainyDayNullSocketPair) {
sockaddr_in address = {};
address.sin_family = GetAddressType();
address.sin_port = htons(GetPortNumberForTests());

int invalid_socket_fd = -1;

EXPECT_FALSE(bind(invalid_socket_fd, reinterpret_cast<sockaddr*>(&address),
sizeof(sockaddr_in)) == 0);
}

TEST_P(PosixSocketBindPairFilterTest, RainyDayNullAddressPair) {
return;
int socket_fd = socket(GetAddressType(), SOCK_STREAM, IPPROTO_TCP);
ASSERT_TRUE(socket_fd > 0);

// Binding with a NULL address should fail.
EXPECT_FALSE(bind(socket_fd, NULL, 0) == 0);

// Even though that failed, binding the same socket now with 0.0.0.0:2048
// should work.
sockaddr_in address = {};
address.sin_family = GetAddressType();
address.sin_port = htons(GetPortNumberForTests());

EXPECT_TRUE(bind(socket_fd, reinterpret_cast<sockaddr*>(&address),
sizeof(sockaddr_in)) == 0);
EXPECT_TRUE(close(socket_fd) == 0);
}

TEST_P(PosixSocketBindPairFilterTest, RainyDayBadInterfacePair) {
return;
int socket_fd = socket(GetAddressType(), SOCK_STREAM, IPPROTO_TCP);
ASSERT_TRUE(socket_fd > 0);

// Binding with an interface that doesn't exist on this device should fail, so
// let's find an address of a well-known public website that we shouldn't be
// able to bind to.
const char* kTestHostName = "www.yahoo.com";

struct addrinfo* ai = nullptr;
struct addrinfo hints = {0};
hints.ai_family = GetFilterType();
hints.ai_flags = AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;

// Most likely success since it is a well known website
int result = getaddrinfo(kTestHostName, nullptr, &hints, &ai);
EXPECT_TRUE(result == 0);
if (result < 0) {
close(socket_fd);
return;
}

int address_count = 0;
for (struct addrinfo* i = ai; i != nullptr; i = i->ai_next) {
++address_count;
}
EXPECT_LT(0, address_count);

// Extract the address out of the addrinfo structure
struct sockaddr server_address = {};

int index = 0;
for (struct addrinfo* i = ai; i != nullptr; i = i->ai_next, ++index) {
// Skip over any addresses we can't parse.
if (i->ai_addr != NULL) {
memcpy(&server_address, i->ai_addr, i->ai_addrlen);
break;
}
}

freeaddrinfo(ai);

EXPECT_FALSE(bind(socket_fd, &server_address, sizeof(sockaddr_in)) == 0);
EXPECT_TRUE(close(socket_fd) == 0);
}

#if SB_HAS(IPV6)
TEST_P(PosixSocketBindPairCSTest, RainyDayWrongAddressTypePair) {
return;
int socket_fd = socket(GetServerAddressType(), SOCK_STREAM, IPPROTO_TCP);
ASSERT_TRUE(socket_fd > 0);

// Binding with the wrong address type should fail.
sockaddr_in client_address = {};
client_address.sin_family = GetClientAddressType();
client_address.sin_port = htons(GetPortNumberForTests());
EXPECT_FALSE(bind(socket_fd, reinterpret_cast<sockaddr*>(&client_address),
sizeof(sockaddr_in)) == 0);

// Even though that failed, binding the same socket now with the server
// address type should work.
sockaddr_in server_address = {};
server_address.sin_family = GetServerAddressType();
server_address.sin_port = htons(GetPortNumberForTests());
EXPECT_TRUE(bind(socket_fd, reinterpret_cast<sockaddr*>(&server_address),
sizeof(sockaddr_in)) == 0);
EXPECT_TRUE(close(socket_fd) == 0);
}
#endif

#if SB_HAS(IPV6)
INSTANTIATE_TEST_SUITE_P(PosixSocketBindTest,
PosixSocketBindPairFilterTest,
::testing::Values(std::make_pair(AF_INET, AF_INET),
std::make_pair(AF_INET6, AF_INET6)),
GetPosixSocketAddressTypeFilterPairName);
INSTANTIATE_TEST_SUITE_P(PosixSocketBindTest,
PosixSocketBindPairCSTest,
::testing::Values(std::make_pair(AF_INET, AF_INET6),
std::make_pair(AF_INET6, AF_INET)),
GetPosixSocketAddressTypeFilterPairName);
#else
INSTANTIATE_TEST_SUITE_P(PosixSocketBindTest,
PosixSocketBindPairFilterTest,
::testing::Values(std::make_pair(AF_INET, AF_INET)),
GetPosixSocketAddressTypeFilterPairName);
#endif

} // namespace
} // namespace nplb
} // namespace starboard
22 changes: 22 additions & 0 deletions starboard/nplb/posix_compliance/posix_socket_connect_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ TEST(PosixSocketConnectTest, RainyDayNullAddress) {
EXPECT_TRUE(close(socket_fd) == 0);
}

TEST(PosixSocketConnectTest, SunnyDayConnectToServer) {
int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1;
int result = PosixSocketCreateAndConnect(
AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout,
&listen_socket_fd, &client_socket_fd, &server_socket_fd);
ASSERT_TRUE(result == 0);
EXPECT_TRUE(close(listen_socket_fd) == 0);
EXPECT_TRUE(close(client_socket_fd) == 0);
EXPECT_TRUE(close(server_socket_fd) == 0);
}

TEST(PosixSocketConnectTest, SunnyDayConnectToServerAgain) {
int listen_socket_fd = -1, client_socket_fd = -1, server_socket_fd = -1;
int result = PosixSocketCreateAndConnect(
AF_INET, AF_INET, htons(GetPortNumberForTests()), kSocketTimeout,
&listen_socket_fd, &client_socket_fd, &server_socket_fd);
ASSERT_TRUE(result == 0);
EXPECT_TRUE(close(listen_socket_fd) == 0);
EXPECT_TRUE(close(client_socket_fd) == 0);
EXPECT_TRUE(close(server_socket_fd) == 0);
}

} // namespace
} // namespace nplb
} // namespace starboard
Loading

0 comments on commit d81c4fc

Please sign in to comment.