TEST(SocketAddress, SetFromSocketUnixExplicit) { // Pick two temporary path names. // We use mkstemp() just to avoid warnings about mktemp, // but we need to remove the file to let the socket code bind to it. char serverPath[] = "/tmp/TSocketAddressTest.server.XXXXXX"; int serverPathFd = mkstemp(serverPath); EXPECT_GE(serverPathFd, 0); char clientPath[] = "/tmp/TSocketAddressTest.client.XXXXXX"; int clientPathFd = mkstemp(clientPath); EXPECT_GE(clientPathFd, 0); int rc = unlink(serverPath); EXPECT_EQ(rc, 0); rc = unlink(clientPath); EXPECT_EQ(rc, 0); TSocketAddress serverBindAddr; TSocketAddress clientBindAddr; TSocketAddress listenAddr; TSocketAddress acceptAddr; TSocketAddress serverAddr; TSocketAddress serverPeerAddr; TSocketAddress clientAddr; TSocketAddress clientPeerAddr; try { serverBindAddr.setFromPath(serverPath); clientBindAddr.setFromPath(clientPath); testSetFromSocket(&serverBindAddr, &clientBindAddr, &listenAddr, &acceptAddr, &serverAddr, &serverPeerAddr, &clientAddr, &clientPeerAddr); } catch (...) { // Remove the socket files after we are done unlink(serverPath); unlink(clientPath); throw; } unlink(serverPath); unlink(clientPath); // The server socket's local address should be the same as the listen // address. EXPECT_EQ(serverAddr, listenAddr); // The client's peer address should always be the same as the server // socket's address. EXPECT_EQ(clientPeerAddr, serverAddr); EXPECT_EQ(serverPeerAddr, clientAddr); EXPECT_EQ(serverPeerAddr, acceptAddr); EXPECT_EQ(acceptAddr, clientAddr); }
/* * Note this test exercises Linux-specific Unix socket behavior */ TEST(SocketAddress, SetFromSocketUnixAbstract) { // Explicitly binding to an empty path results in an abstract socket // name being picked for us automatically. TSocketAddress serverBindAddr; string path(1, 0); path.append("test address"); serverBindAddr.setFromPath(path); TSocketAddress clientBindAddr; clientBindAddr.setFromPath(""); TSocketAddress listenAddr; TSocketAddress acceptAddr; TSocketAddress serverAddr; TSocketAddress serverPeerAddr; TSocketAddress clientAddr; TSocketAddress clientPeerAddr; testSetFromSocket(&serverBindAddr, &clientBindAddr, &listenAddr, &acceptAddr, &serverAddr, &serverPeerAddr, &clientAddr, &clientPeerAddr); // The server socket's local address should be the same as the listen // address. EXPECT_EQ(serverAddr, listenAddr); // The client's peer address should always be the same as the server // socket's address. EXPECT_EQ(clientPeerAddr, serverAddr); EXPECT_EQ(serverPeerAddr, clientAddr); // Oddly, the address returned by accept() does not seem to match the address // returned by getpeername() on the server socket or getsockname() on the // client socket. // EXPECT_EQ(serverPeerAddr, acceptAddr); // EXPECT_EQ(acceptAddr, clientAddr); }
TEST(SocketAddress, SetFromSocketUnixAnonymous) { // Test an anonymous client talking to a fixed-path unix socket. char serverPath[] = "/tmp/TSocketAddressTest.server.XXXXXX"; int serverPathFd = mkstemp(serverPath); EXPECT_GE(serverPathFd, 0); int rc = unlink(serverPath); EXPECT_EQ(rc, 0); TSocketAddress serverBindAddr; TSocketAddress listenAddr; TSocketAddress acceptAddr; TSocketAddress serverAddr; TSocketAddress serverPeerAddr; TSocketAddress clientAddr; TSocketAddress clientPeerAddr; try { serverBindAddr.setFromPath(serverPath); testSetFromSocket(&serverBindAddr, nullptr, &listenAddr, &acceptAddr, &serverAddr, &serverPeerAddr, &clientAddr, &clientPeerAddr); } catch (...) { // Remove the socket file after we are done unlink(serverPath); throw; } unlink(serverPath); // The server socket's local address should be the same as the listen // address. EXPECT_EQ(serverAddr, listenAddr); // The client's peer address should always be the same as the server // socket's address. EXPECT_EQ(clientPeerAddr, serverAddr); // Since the client is using an anonymous address, it won't compare equal to // any other anonymous addresses. Make sure the addresses are anonymous. EXPECT_EQ(serverPeerAddr.getPath(), ""); EXPECT_EQ(clientAddr.getPath(), ""); EXPECT_EQ(acceptAddr.getPath(), ""); }
TEST(SocketAddress, Unix) { TSocketAddress addr; // Test a small path addr.setFromPath("foo"); EXPECT_EQ(addr.getFamily(), AF_UNIX); EXPECT_EQ(addr.describe(), "foo"); EXPECT_THROW(addr.getAddressStr(), TTransportException); EXPECT_THROW(addr.getPort(), TTransportException); EXPECT_TRUE(addr.isPrivateAddress()); EXPECT_TRUE(addr.isLoopbackAddress()); // Test a path that is too large const char longPath[] = "abcdefghijklmnopqrstuvwxyz0123456789" "abcdefghijklmnopqrstuvwxyz0123456789" "abcdefghijklmnopqrstuvwxyz0123456789" "abcdefghijklmnopqrstuvwxyz0123456789"; EXPECT_THROW(addr.setFromPath(longPath), TTransportException); // The original address should still be the same EXPECT_EQ(addr.getFamily(), AF_UNIX); EXPECT_EQ(addr.describe(), "foo"); // Test a path that exactly fits in sockaddr_un // (not including the NUL terminator) const char exactLengthPath[] = "abcdefghijklmnopqrstuvwxyz0123456789" "abcdefghijklmnopqrstuvwxyz0123456789" "abcdefghijklmnopqrstuvwxyz0123456789"; addr.setFromPath(exactLengthPath); EXPECT_EQ(addr.describe(), exactLengthPath); // Test converting a unix socket address to an IPv4 one, then back addr.setFromHostPort("127.0.0.1", 1234); EXPECT_EQ(addr.getFamily(), AF_INET); EXPECT_EQ(addr.describe(), "127.0.0.1:1234"); addr.setFromPath("/i/am/a/unix/address"); EXPECT_EQ(addr.getFamily(), AF_UNIX); EXPECT_EQ(addr.describe(), "/i/am/a/unix/address"); // Test copy constructor and assignment operator { TSocketAddress copy(addr); EXPECT_EQ(copy, addr); copy.setFromPath("/abc"); EXPECT_NE(copy, addr); copy = addr; EXPECT_EQ(copy, addr); copy.setFromIpPort("127.0.0.1", 80); EXPECT_NE(copy, addr); copy = addr; EXPECT_EQ(copy, addr); } { TSocketAddress copy(addr); EXPECT_EQ(copy, addr); EXPECT_EQ(copy.describe(), "/i/am/a/unix/address"); EXPECT_EQ(copy.getPath(), "/i/am/a/unix/address"); TSocketAddress other("127.0.0.1", 80); EXPECT_NE(other, addr); other = copy; EXPECT_EQ(other, copy); EXPECT_EQ(other, addr); EXPECT_EQ(copy, addr); } #if __GXX_EXPERIMENTAL_CXX0X__ { TSocketAddress copy; { // move a unix address into a non-unix address TSocketAddress tmpCopy(addr); copy = std::move(tmpCopy); } EXPECT_EQ(copy, addr); copy.setFromPath("/another/path"); { // move a unix address into a unix address TSocketAddress tmpCopy(addr); copy = std::move(tmpCopy); } EXPECT_EQ(copy, addr); { // move a non-unix address into a unix address TSocketAddress tmp("127.0.0.1", 80); copy = std::move(tmp); } EXPECT_EQ(copy.getAddressStr(), "127.0.0.1"); EXPECT_EQ(copy.getPort(), 80); copy = addr; // move construct a unix address TSocketAddress other(std::move(copy)); EXPECT_EQ(other, addr); EXPECT_EQ(other.getPath(), addr.getPath()); } #endif }
TEST(SocketAddress, EqualityAndHash) { // IPv4 TSocketAddress local1("127.0.0.1", 1234); EXPECT_EQ(local1, local1); EXPECT_EQ(local1.hash(), local1.hash()); TSocketAddress local2("127.0.0.1", 1234); EXPECT_EQ(local1, local2); EXPECT_EQ(local1.hash(), local2.hash()); TSocketAddress local3("127.0.0.1", 4321); EXPECT_NE(local1, local3); EXPECT_NE(local1.hash(), local3.hash()); TSocketAddress other1("1.2.3.4", 1234); EXPECT_EQ(other1, other1); EXPECT_EQ(other1.hash(), other1.hash()); EXPECT_NE(local1, other1); EXPECT_NE(local1.hash(), other1.hash()); TSocketAddress other2("4.3.2.1", 1234); EXPECT_NE(other1.hash(), other2.hash()); EXPECT_NE(other1.hash(), other2.hash()); other2.setFromIpPort("1.2.3.4", 0); EXPECT_NE(other1.hash(), other2.hash()); EXPECT_NE(other1.hash(), other2.hash()); other2.setPort(1234); EXPECT_EQ(other1.hash(), other2.hash()); EXPECT_EQ(other1.hash(), other2.hash()); // IPv6 TSocketAddress v6_1("2620:0:1c00:face:b00c:0:0:abcd", 1234); TSocketAddress v6_2("2620:0:1c00:face:b00c::abcd", 1234); TSocketAddress v6_3("2620:0:1c00:face:b00c::bcda", 1234); EXPECT_EQ(v6_1, v6_2); EXPECT_EQ(v6_1.hash(), v6_2.hash()); EXPECT_NE(v6_1, v6_3); EXPECT_NE(v6_1.hash(), v6_3.hash()); // IPv4 versus IPv6 comparison TSocketAddress localIPv6("::1", 1234); // Even though these both refer to localhost, // IPv4 and IPv6 addresses are never treated as the same address EXPECT_NE(local1, localIPv6); EXPECT_NE(local1.hash(), localIPv6.hash()); // IPv4-mapped IPv6 addresses are not treated as equal // to the equivalent IPv4 address TSocketAddress v4("10.0.0.3", 99); TSocketAddress v6_mapped1("::ffff:10.0.0.3", 99); TSocketAddress v6_mapped2("::ffff:0a00:0003", 99); EXPECT_NE(v4, v6_mapped1); EXPECT_NE(v4, v6_mapped2); EXPECT_EQ(v6_mapped1, v6_mapped2); // However, after calling convertToIPv4(), the mapped address should now be // equal to the v4 version. EXPECT_TRUE(v6_mapped1.isIPv4Mapped()); v6_mapped1.convertToIPv4(); EXPECT_EQ(v6_mapped1, v4); EXPECT_NE(v6_mapped1, v6_mapped2); // Unix TSocketAddress unix1; unix1.setFromPath("/foo"); TSocketAddress unix2; unix2.setFromPath("/foo"); TSocketAddress unix3; unix3.setFromPath("/bar"); TSocketAddress unixAnon; unixAnon.setFromPath(""); EXPECT_EQ(unix1, unix2); EXPECT_EQ(unix1.hash(), unix2.hash()); EXPECT_NE(unix1, unix3); EXPECT_NE(unix1, unixAnon); EXPECT_NE(unix2, unix3); EXPECT_NE(unix2, unixAnon); // anonymous addresses aren't equal to any other address, // including themselves EXPECT_NE(unixAnon, unixAnon); // It isn't strictly required that hashes for different addresses be // different, but we should have very few collisions. It generally indicates // a problem if these collide EXPECT_NE(unix1.hash(), unix3.hash()); EXPECT_NE(unix1.hash(), unixAnon.hash()); EXPECT_NE(unix3.hash(), unixAnon.hash()); }