Mercurial > code
view C++/Tests/Sockets/main.cpp @ 275:d945fa44f601
Socket: update tests
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 23 Oct 2014 12:25:43 +0200 |
parents | 46ccfbee84d9 |
children | 05f0a3e09cbf |
line wrap: on
line source
#include <chrono> #include <sstream> #include <string> #include <thread> #include <gtest/gtest.h> #include <Socket.h> #include <SocketListener.h> #include <SocketAddress.h> using namespace std::literals::chrono_literals; using namespace address; /* -------------------------------------------------------- * Miscellaneous * -------------------------------------------------------- */ TEST(Misc, set) { try { Socket s(AF_INET6, SOCK_STREAM, 0); s.set(IPPROTO_IPV6, IPV6_V6ONLY, false); ASSERT_FALSE(s.get<bool>(IPPROTO_IPV6, IPV6_V6ONLY)); s.set(IPPROTO_IPV6, IPV6_V6ONLY, true); ASSERT_TRUE(s.get<bool>(IPPROTO_IPV6, IPV6_V6ONLY)); } catch (const std::exception &ex) { } } /* -------------------------------------------------------- * Select tests * -------------------------------------------------------- */ TEST(ListenerMethodSelect, add) { try { Socket s(AF_INET, SOCK_STREAM, 0); Socket s2(AF_INET, SOCK_STREAM, 0); SocketListener listener(SocketMethod::Select); listener.add(s, SocketDirection::Read); listener.add(s2, SocketDirection::Read); ASSERT_EQ(2UL, listener.size()); } catch (const std::exception &ex) { } } TEST(ListenerMethodSelect, remove) { try { Socket s(AF_INET, SOCK_STREAM, 0); Socket s2(AF_INET, SOCK_STREAM, 0); SocketListener listener(SocketMethod::Select); listener.add(s, SocketDirection::Read); listener.add(s2, SocketDirection::Read); listener.remove(s, SocketDirection::Read); listener.remove(s2, SocketDirection::Read); ASSERT_EQ(0UL, listener.size()); } catch (const std::exception &ex) { } } /* * Add two sockets for both reading and writing, them remove only reading and then * move only writing. */ TEST(ListenerMethodSelect, inOut) { try { Socket s(AF_INET, SOCK_STREAM, 0); Socket s2(AF_INET, SOCK_STREAM, 0); SocketListener listener(SocketMethod::Select); listener.add(s, SocketDirection::Read | SocketDirection::Write); listener.add(s2, SocketDirection::Read | SocketDirection::Write); listener.list([&] (Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s || si == s2); ASSERT_EQ(0x03, static_cast<int>(dir)); }); listener.remove(s, SocketDirection::Write); listener.remove(s2, SocketDirection::Write); ASSERT_EQ(2UL, listener.size()); listener.list([&] (Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s || si == s2); ASSERT_EQ(SocketDirection::Read, dir); }); listener.remove(s, SocketDirection::Read); listener.remove(s2, SocketDirection::Read); ASSERT_EQ(0UL, listener.size()); } catch (const std::exception &ex) { } } TEST(ListenerMethodSelect, addSame) { try { Socket s(AF_INET, SOCK_STREAM, 0); SocketListener listener(SocketMethod::Select); listener.add(s, SocketDirection::Read); ASSERT_EQ(1UL, listener.size()); listener.list([&] (const Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s); ASSERT_EQ(SocketDirection::Read, dir); }); listener.add(s, SocketDirection::Write); ASSERT_EQ(1UL, listener.size()); listener.list([&] (const Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s); ASSERT_EQ(0x03, static_cast<int>(dir)); }); // Oops, added the same listener.add(s, SocketDirection::Read); listener.add(s, SocketDirection::Write); listener.add(s, SocketDirection::Read | SocketDirection::Write); ASSERT_EQ(1UL, listener.size()); listener.list([&] (const Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s); ASSERT_EQ(0x03, static_cast<int>(dir)); }); } catch (const std::exception &ex) { } } /* -------------------------------------------------------- * Poll tests * -------------------------------------------------------- */ TEST(ListenerMethodPoll, add) { try { Socket s(AF_INET, SOCK_STREAM, 0); Socket s2(AF_INET, SOCK_STREAM, 0); SocketListener listener(SocketMethod::Poll); listener.add(s, SocketDirection::Read); listener.add(s2, SocketDirection::Read); ASSERT_EQ(2UL, listener.size()); } catch (const std::exception &ex) { } } TEST(ListenerMethodPoll, remove) { try { Socket s(AF_INET, SOCK_STREAM, 0); Socket s2(AF_INET, SOCK_STREAM, 0); SocketListener listener(SocketMethod::Poll); listener.add(s, SocketDirection::Read); listener.add(s2, SocketDirection::Read); listener.remove(s, SocketDirection::Read); listener.remove(s2, SocketDirection::Read); ASSERT_EQ(0UL, listener.size()); } catch (const std::exception &ex) { } } TEST(ListenerMethodPoll, inOut) { try { Socket s(AF_INET, SOCK_STREAM, 0); Socket s2(AF_INET, SOCK_STREAM, 0); SocketListener listener(SocketMethod::Poll); listener.add(s, SocketDirection::Read | SocketDirection::Write); listener.add(s2, SocketDirection::Read | SocketDirection::Write); listener.list([&] (Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s || si == s2); ASSERT_EQ(0x03, static_cast<int>(dir)); }); listener.remove(s, SocketDirection::Write); listener.remove(s2, SocketDirection::Write); ASSERT_EQ(2UL, listener.size()); listener.list([&] (Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s || si == s2); ASSERT_EQ(SocketDirection::Read, dir); }); listener.remove(s, SocketDirection::Read); listener.remove(s2, SocketDirection::Read); ASSERT_EQ(0UL, listener.size()); } catch (const std::exception &ex) { } } TEST(ListenerMethodPoll, addSame) { try { Socket s(AF_INET, SOCK_STREAM, 0); SocketListener listener(SocketMethod::Poll); listener.add(s, SocketDirection::Read); ASSERT_EQ(1UL, listener.size()); listener.list([&] (const Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s); ASSERT_EQ(SocketDirection::Read, dir); }); listener.add(s, SocketDirection::Write); ASSERT_EQ(1UL, listener.size()); listener.list([&] (const Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s); ASSERT_EQ(0x03, static_cast<int>(dir)); }); // Oops, added the same listener.add(s, SocketDirection::Read); listener.add(s, SocketDirection::Write); listener.add(s, SocketDirection::Read | SocketDirection::Write); ASSERT_EQ(1UL, listener.size()); listener.list([&] (const Socket &si, SocketDirection dir) { ASSERT_TRUE(si == s); ASSERT_EQ(0x03, static_cast<int>(dir)); }); } catch (const std::exception &ex) { } } /* -------------------------------------------------------- * Socket listener class * -------------------------------------------------------- */ TEST(Listener, connection) { std::thread client([] () { Socket client; std::this_thread::sleep_for(3s); try { client = Socket(AF_INET, SOCK_STREAM, 0); client.connect(Internet("localhost", 10000, AF_INET)); } catch (const std::exception &ex) { } client.close(); }); Socket s; SocketListener listener; try { s = Socket(AF_INET, SOCK_STREAM, 0); s.bind(Internet("localhost", 10000, AF_INET)); s.listen(8); listener.add(s, SocketDirection::Read); auto client = listener.select(10s); ASSERT_TRUE(client.direction == SocketDirection::Read); ASSERT_TRUE(client.socket == s); } catch (const std::exception &ex) { } s.close(); client.join(); } TEST(Listener, connectionAndRead) { std::thread thread([] () { Socket client; std::this_thread::sleep_for(3s); try { client = Socket(AF_INET, SOCK_STREAM, 0); client.connect(Internet("localhost", 10000, AF_INET)); client.send("hello world"); } catch (const std::exception &ex) { } client.close(); }); Socket s; SocketListener listener; try { s = Socket(AF_INET, SOCK_STREAM, 0); s.bind(Internet("localhost", 10000, AF_INET)); s.listen(8); // Read for master listener.add(s, SocketDirection::Read); auto result = listener.select(10s); ASSERT_TRUE(result.direction == SocketDirection::Read); ASSERT_TRUE(result.socket == s); // Wait for client auto client = s.accept(); listener.add(client, SocketDirection::Read); result = listener.select(10s); ASSERT_TRUE(result.direction == SocketDirection::Read); ASSERT_TRUE(result.socket == client); char data[512]; auto nb = client.recv(data, sizeof (data) - 1); data[nb] = '\0'; client.close(); ASSERT_STREQ("hello world", data); } catch (const std::exception &ex) { } s.close(); thread.join(); } TEST(Listener, bigData) { auto producer = [] () { std::string data; data.reserve(9000000); for (int i = 0; i < 9000000; ++i) data.push_back('a'); data.push_back('\r'); data.push_back('\n'); std::this_thread::sleep_for(3s); Socket client; SocketListener listener; try { client = Socket(AF_INET, SOCK_STREAM, 0); client.connect(Internet("localhost", 10000, AF_INET)); client.blockMode(false); listener.add(client, SocketDirection::Write); while (data.size() > 0) { auto s = listener.select(30s).socket; auto nb = s.send(data.data(), data.size()); data.erase(0, nb); } } catch (const std::exception &ex) { } client.close(); }; auto consumer = [] () { std::ostringstream out; Socket server; SocketListener listener; bool finished(false); try { server = Socket(AF_INET, SOCK_STREAM, 0); server.bind(Internet("*", 10000, AF_INET)); server.listen(10); listener.add(server, SocketDirection::Read); while (!finished) { auto s = listener.select(60s).socket; if (s == server) { listener.add(s.accept(), SocketDirection::Read); } else { char data[512]; auto nb = s.recv(data, sizeof (data) - 1); if (nb == 0) finished = true; else { data[nb] = '\0'; out << data; } } } ASSERT_EQ(9000002UL, out.str().size()); } catch (const std::exception &ex) { } server.close(); }; std::thread tconsumer(consumer); std::thread tproducer(producer); tconsumer.join(); tproducer.join(); } /* -------------------------------------------------------- * Multiple selection tests * -------------------------------------------------------- */ TEST(MultipleSelection, select) { /* * Normally, 3 sockets added for writing should be marked ready immediately * as there are no data being currently queued to be sent. */ std::thread tester([] () { try { SocketListener masterListener, clientListener; Socket master(AF_INET, SOCK_STREAM, 0); master.bind(Internet("*", 10000, AF_INET)); master.listen(8); masterListener.add(master, SocketDirection::Read); while (clientListener.size() != 3) { masterListener.select(3s); clientListener.add(master.accept(), SocketDirection::Write); } // Now do the test of writing auto result = clientListener.selectMultiple(3s); ASSERT_EQ(3UL, result.size()); clientListener.list([] (auto s, auto) { s.close(); }); master.close(); } catch (const std::exception &ex) { } }); try { Socket s1(AF_INET, SOCK_STREAM, 0); Socket s2(AF_INET, SOCK_STREAM, 0); Socket s3(AF_INET, SOCK_STREAM, 0); s1.connect(Internet("localhost", 10000, AF_INET)); s2.connect(Internet("localhost", 10000, AF_INET)); s3.connect(Internet("localhost", 10000, AF_INET)); s1.close(); s2.close(); s3.close(); } catch (const std::exception &ex) { } tester.join(); } #if defined(SOCKET_LISTENER_HAVE_POLL) TEST(MultipleSelection, poll) { /* * Normally, 3 sockets added for writing should be marked ready immediately * as there are no data being currently queued to be sent. */ std::thread tester([] () { try { SocketListener masterListener(SocketMethod::Poll), clientListener(SocketMethod::Poll); Socket master(AF_INET, SOCK_STREAM, 0); master.bind(Internet("*", 10000, AF_INET)); master.listen(8); masterListener.add(master, SocketDirection::Read); while (clientListener.size() != 3) { masterListener.select(3s); clientListener.add(master.accept(), SocketDirection::Write); } // Now do the test of writing auto result = clientListener.selectMultiple(3s); ASSERT_EQ(3UL, result.size()); clientListener.list([] (auto s, auto) { s.close(); }); master.close(); } catch (const std::exception &ex) { } }); try { Socket s1(AF_INET, SOCK_STREAM, 0); Socket s2(AF_INET, SOCK_STREAM, 0); Socket s3(AF_INET, SOCK_STREAM, 0); s1.connect(Internet("localhost", 10000, AF_INET)); s2.connect(Internet("localhost", 10000, AF_INET)); s3.connect(Internet("localhost", 10000, AF_INET)); s1.close(); s2.close(); s3.close(); } catch (const std::exception &ex) { } tester.join(); } #endif /* -------------------------------------------------------- * Basic TCP tests * -------------------------------------------------------- */ TEST(BasicTcp, sendipv4) { std::thread client([] () { Socket s; std::this_thread::sleep_for(3s); try { s = Socket(AF_INET, SOCK_STREAM, 0); s.connect(Internet("localhost", 10000, AF_INET)); s.send("hello"); } catch (const std::exception &ex) { } s.close(); }); Socket server; try { server = Socket(AF_INET, SOCK_STREAM, 0); server.bind(Internet("*", 10000, SOCK_STREAM)); server.listen(8); auto client = server.accept(); char data[512]; auto nb = client.recv(data, sizeof (data) - 1); data[nb] = '\0'; ASSERT_STREQ("hello", data); } catch (const std::exception &ex) { } server.close(); client.join(); } TEST(BasicTcp, sendipv6) { std::thread client([] () { Socket s; std::this_thread::sleep_for(3s); try { s = Socket(AF_INET6, SOCK_STREAM, 0); s.connect(Internet("localhost", 10000, AF_INET6)); s.send("hello"); } catch (const std::exception &ex) { } s.close(); }); Socket server; try { server = Socket(AF_INET6, SOCK_STREAM, 0); server.bind(Internet("*", 10000, SOCK_STREAM)); server.listen(8); auto client = server.accept(); char data[512]; auto nb = client.recv(data, sizeof (data) - 1); data[nb] = '\0'; ASSERT_STREQ("hello", data); } catch (const std::exception &ex) { } server.close(); client.join(); } #if !defined(_WIN32) TEST(BasicTcp, sendunix) { std::thread client([] () { Socket s; std::this_thread::sleep_for(3s); try { s = Socket(AF_UNIX, SOCK_STREAM, 0); s.connect(Unix("/tmp/gtest-send-tcp-unix.sock")); s.send("hello"); } catch (const std::exception &ex) { } s.close(); }); Socket server; try { server = Socket(AF_UNIX, SOCK_STREAM, 0); server.bind(Unix("/tmp/gtest-send-tcp-unix.sock", true)); server.listen(8); auto client = server.accept(); char data[512]; auto nb = client.recv(data, sizeof (data) - 1); data[nb] = '\0'; ASSERT_STREQ("hello", data); } catch (const std::exception &ex) { } server.close(); client.join(); } #endif TEST(BasicUdp, sendipv4) { std::thread client([] () { Socket s; std::this_thread::sleep_for(3s); try { s = Socket(AF_INET, SOCK_DGRAM, 0); s.sendto("hello", Internet("localhost", 10000, AF_INET)); } catch (const std::exception &ex) { } s.close(); }); Socket server; try { server = Socket(AF_INET, SOCK_DGRAM, 0); server.bind(Internet("*", 10000, SOCK_DGRAM)); char data[512]; auto nb = server.recvfrom(data, sizeof (data) - 1); data[nb] = '\0'; ASSERT_STREQ("hello", data); } catch (const std::exception &ex) { } server.close(); client.join(); } TEST(BasicUdp, sendipv6) { std::thread client([] () { Socket s; std::this_thread::sleep_for(3s); try { s = Socket(AF_INET6, SOCK_DGRAM, 0); s.sendto("hello", Internet("localhost", 10000, AF_INET6)); } catch (const std::exception &ex) { } s.close(); }); Socket server; try { server = Socket(AF_INET6, SOCK_DGRAM, 0); server.bind(Internet("*", 10000, SOCK_DGRAM)); char data[512]; auto nb = server.recvfrom(data, sizeof (data) - 1); data[nb] = '\0'; ASSERT_STREQ("hello", data); } catch (const std::exception &ex) { } server.close(); client.join(); } #if !defined(_WIN32) TEST(BasicUdp, sendunix) { std::thread client([] () { Socket s; std::this_thread::sleep_for(3s); try { s = Socket(AF_UNIX, SOCK_DGRAM, 0); s.sendto("hello", Unix("/tmp/gtest-send-udp-unix.sock")); } catch (const std::exception &ex) { } s.close(); }); Socket server; try { server = Socket(AF_UNIX, SOCK_DGRAM, 0); server.bind(Unix("/tmp/gtest-send-udp-unix.sock", true)); char data[512]; auto nb = server.recvfrom(data, sizeof (data) - 1); data[nb] = '\0'; ASSERT_STREQ("hello", data); } catch (const std::exception &ex) { } server.close(); client.join(); } #endif int main(int argc, char **argv) { Socket::init(); testing::InitGoogleTest(&argc, argv); auto ret = RUN_ALL_TESTS(); Socket::finish(); return ret; }