| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <arpa/inet.h> |
| #include <fidl/fuchsia.netemul.sync/cpp/wire.h> |
| #include <lib/fdio/directory.h> |
| #include <netinet/in.h> |
| #include <sys/socket.h> |
| #include <zircon/assert.h> |
| |
| #include <fbl/unique_fd.h> |
| #include <gtest/gtest.h> |
| |
| #include "constants.h" |
| |
| namespace { |
| |
| constexpr char kBusName[] = "test-bus"; |
| constexpr char kTestClientName[] = "client"; |
| constexpr char kTestServerName[] = "server"; |
| |
| void TestUdpPing(int domain, const sockaddr* bind_addr, socklen_t bind_addr_len, |
| const sockaddr* connect_addr, socklen_t connect_addr_len) { |
| fbl::unique_fd s; |
| ASSERT_TRUE(s = fbl::unique_fd(socket(domain, SOCK_DGRAM, 0))) << strerror(errno); |
| |
| ASSERT_EQ(bind(s.get(), bind_addr, bind_addr_len), 0) << strerror(errno); |
| |
| ASSERT_EQ(connect(s.get(), connect_addr, connect_addr_len), 0) << strerror(errno); |
| |
| constexpr char kSendBuf[] = "Hello"; |
| ASSERT_EQ(send(s.get(), &kSendBuf, sizeof(kSendBuf), 0), static_cast<ssize_t>(sizeof(kSendBuf))) |
| << strerror(errno); |
| |
| constexpr char kExpectedRecvBuf[] = "Response: Hello"; |
| char recv_buf[sizeof(kExpectedRecvBuf) + 1]; |
| ASSERT_EQ(read(s.get(), &recv_buf, sizeof(recv_buf)), |
| static_cast<ssize_t>(sizeof(kExpectedRecvBuf))) |
| << strerror(errno); |
| EXPECT_STREQ(kExpectedRecvBuf, recv_buf); |
| } |
| |
| void TestIpv4UdpPing(const char* client_addr) { |
| sockaddr_in bind_addr{ |
| .sin_family = AF_INET, |
| }; |
| ASSERT_EQ(inet_pton(bind_addr.sin_family, client_addr, &bind_addr.sin_addr), 1); |
| |
| sockaddr_in connect_addr = { |
| .sin_family = AF_INET, |
| .sin_port = htons(kServerPort), |
| }; |
| ASSERT_EQ(inet_pton(connect_addr.sin_family, kServerIpv4Addr, &connect_addr.sin_addr), 1); |
| |
| ASSERT_NO_FATAL_FAILURE(TestUdpPing(AF_INET, reinterpret_cast<sockaddr*>(&bind_addr), |
| sizeof(bind_addr), reinterpret_cast<sockaddr*>(&connect_addr), |
| sizeof(connect_addr))); |
| } |
| |
| TEST(InfraTest, UdpPingFromIpv4Ep1) { ASSERT_NO_FATAL_FAILURE(TestIpv4UdpPing(kClientIpv4Addr1)); } |
| |
| TEST(InfraTest, UdpPingFromIpv4Ep2) { ASSERT_NO_FATAL_FAILURE(TestIpv4UdpPing(kClientIpv4Addr2)); } |
| |
| void TestIpv6UdpPing(const char* client_addr) { |
| sockaddr_in6 bind_addr{ |
| .sin6_family = AF_INET6, |
| }; |
| ASSERT_EQ(inet_pton(bind_addr.sin6_family, client_addr, &bind_addr.sin6_addr), 1); |
| |
| sockaddr_in6 connect_addr = { |
| .sin6_family = AF_INET6, |
| .sin6_port = htons(kServerPort), |
| }; |
| ASSERT_EQ(inet_pton(connect_addr.sin6_family, kServerIpv6Addr, &connect_addr.sin6_addr), 1); |
| |
| ASSERT_NO_FATAL_FAILURE(TestUdpPing(AF_INET6, reinterpret_cast<sockaddr*>(&bind_addr), |
| sizeof(bind_addr), reinterpret_cast<sockaddr*>(&connect_addr), |
| sizeof(connect_addr))); |
| } |
| |
| TEST(InfraTest, UdpPingFromIpv6Ep1) { ASSERT_NO_FATAL_FAILURE(TestIpv6UdpPing(kClientIpv6Addr1)); } |
| |
| TEST(InfraTest, UdpPingFromIpv6Ep2) { ASSERT_NO_FATAL_FAILURE(TestIpv6UdpPing(kClientIpv6Addr2)); } |
| |
| } // namespace |
| |
| int main(int argc, char** argv) { |
| // Make sure the server has come up before running any tests by waiting |
| // on the bus for its subscription. |
| auto sync_manager_endpoints = fidl::CreateEndpoints<fuchsia_netemul_sync::SyncManager>(); |
| if (sync_manager_endpoints.is_error()) { |
| ZX_PANIC("error creating sync manager endpoints: %s", |
| zx_status_get_string(sync_manager_endpoints.error_value())); |
| } |
| auto bus_endpoints = fidl::CreateEndpoints<fuchsia_netemul_sync::Bus>(); |
| if (bus_endpoints.is_error()) { |
| ZX_PANIC("error creating bus endpoints: %s", zx_status_get_string(bus_endpoints.error_value())); |
| } |
| |
| zx_status_t status = fdio_service_connect_by_name( |
| fidl::DiscoverableProtocolName<fuchsia_netemul_sync::SyncManager>, |
| sync_manager_endpoints->server.channel().release()); |
| ZX_ASSERT_MSG(status == ZX_OK, "error connecting to sync manager server: %s", |
| zx_status_get_string(status)); |
| |
| fidl::WireSyncClient sync_manager = |
| fidl::BindSyncClient(std::move(sync_manager_endpoints->client)); |
| { |
| fidl::Status result = |
| sync_manager->BusSubscribe(kBusName, kTestClientName, std::move(bus_endpoints->server)); |
| ZX_ASSERT_MSG(result.status() == ZX_OK, "error getting bus: %s", result.status_string()); |
| } |
| |
| fidl::WireSyncClient bus = fidl::BindSyncClient(std::move(bus_endpoints->client)); |
| { |
| std::array<fidl::StringView, 1> clients = {fidl::StringView(kTestServerName)}; |
| fidl::Status result = bus->WaitForClients( |
| fidl::VectorView<fidl::StringView>::FromExternal(clients), /* no timeout */ 0); |
| ZX_ASSERT_MSG(result.status() == ZX_OK, "error waiting for server to be ready: %s", |
| result.status_string()); |
| } |
| |
| testing::InitGoogleTest(&argc, argv); |
| return RUN_ALL_TESTS(); |
| } |