TestLibCoreStream.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Format.h>
  7. #include <LibCore/EventLoop.h>
  8. #include <LibCore/LocalServer.h>
  9. #include <LibCore/LocalSocket.h>
  10. #include <LibCore/Stream.h>
  11. #include <LibCore/TCPServer.h>
  12. #include <LibCore/TCPSocket.h>
  13. #include <LibCore/Timer.h>
  14. #include <LibCore/UDPServer.h>
  15. #include <LibCore/UDPSocket.h>
  16. #include <LibTest/TestCase.h>
  17. #include <LibThreading/BackgroundAction.h>
  18. #include <fcntl.h>
  19. #include <unistd.h>
  20. // File tests
  21. TEST_CASE(file_open)
  22. {
  23. auto maybe_file = Core::Stream::File::open("/tmp/file-open-test.txt", Core::Stream::OpenMode::Write);
  24. if (maybe_file.is_error()) {
  25. warnln("Failed to open the file: {}", strerror(maybe_file.error().code()));
  26. VERIFY_NOT_REACHED();
  27. }
  28. // Testing out some basic file properties.
  29. auto file = maybe_file.release_value();
  30. EXPECT(file->is_open());
  31. EXPECT(!file->is_readable());
  32. EXPECT(file->is_writable());
  33. EXPECT(!file->is_eof());
  34. auto maybe_size = file->size();
  35. EXPECT(!maybe_size.is_error());
  36. EXPECT_EQ(maybe_size.value(), 0);
  37. }
  38. TEST_CASE(file_write_bytes)
  39. {
  40. auto maybe_file = Core::Stream::File::open("/tmp/file-write-bytes-test.txt", Core::Stream::OpenMode::Write);
  41. auto file = maybe_file.release_value();
  42. constexpr auto some_words = "These are some words"sv;
  43. ReadonlyBytes buffer { some_words.characters_without_null_termination(), some_words.length() };
  44. auto result = file->write(buffer);
  45. EXPECT(!result.is_error());
  46. }
  47. constexpr auto expected_buffer_contents = "&lt;small&gt;(Please consider translating this message for the benefit of your fellow Wikimedians. Please also consider translating"sv;
  48. TEST_CASE(file_read_bytes)
  49. {
  50. auto maybe_file = Core::Stream::File::open("/usr/Tests/LibCore/long_lines.txt", Core::Stream::OpenMode::Read);
  51. EXPECT(!maybe_file.is_error());
  52. auto file = maybe_file.release_value();
  53. auto maybe_buffer = ByteBuffer::create_uninitialized(131);
  54. EXPECT(maybe_buffer.has_value());
  55. auto buffer = maybe_buffer.release_value();
  56. auto result = file->read(buffer);
  57. EXPECT(!result.is_error());
  58. EXPECT_EQ(result.value(), 131ul);
  59. StringView buffer_contents { buffer.bytes() };
  60. EXPECT_EQ(buffer_contents, expected_buffer_contents);
  61. }
  62. constexpr auto expected_seek_contents1 = "|Lleer esti mens"sv;
  63. constexpr auto expected_seek_contents2 = "s of advanced ad"sv;
  64. constexpr auto expected_seek_contents3 = "levels of advanc"sv;
  65. TEST_CASE(file_seeking_around)
  66. {
  67. auto maybe_file = Core::Stream::File::open("/usr/Tests/LibCore/long_lines.txt", Core::Stream::OpenMode::Read);
  68. EXPECT(!maybe_file.is_error());
  69. auto file = maybe_file.release_value();
  70. EXPECT_EQ(file->size().release_value(), 8702);
  71. auto maybe_buffer = ByteBuffer::create_uninitialized(16);
  72. EXPECT(maybe_buffer.has_value());
  73. auto buffer = maybe_buffer.release_value();
  74. StringView buffer_contents { buffer.bytes() };
  75. EXPECT(!file->seek(500, Core::Stream::SeekMode::SetPosition).is_error());
  76. EXPECT_EQ(file->tell().release_value(), 500);
  77. EXPECT(file->read_or_error(buffer));
  78. EXPECT_EQ(buffer_contents, expected_seek_contents1);
  79. EXPECT(!file->seek(234, Core::Stream::SeekMode::FromCurrentPosition).is_error());
  80. EXPECT_EQ(file->tell().release_value(), 750);
  81. EXPECT(file->read_or_error(buffer));
  82. EXPECT_EQ(buffer_contents, expected_seek_contents2);
  83. EXPECT(!file->seek(-105, Core::Stream::SeekMode::FromEndPosition).is_error());
  84. EXPECT_EQ(file->tell().release_value(), 8597);
  85. EXPECT(file->read_or_error(buffer));
  86. EXPECT_EQ(buffer_contents, expected_seek_contents3);
  87. }
  88. TEST_CASE(file_adopt_fd)
  89. {
  90. int rc = ::open("/usr/Tests/LibCore/long_lines.txt", O_RDONLY);
  91. EXPECT(rc >= 0);
  92. auto maybe_file = Core::Stream::File::adopt_fd(rc, Core::Stream::OpenMode::Read);
  93. EXPECT(!maybe_file.is_error());
  94. auto file = maybe_file.release_value();
  95. EXPECT_EQ(file->size().release_value(), 8702);
  96. auto maybe_buffer = ByteBuffer::create_uninitialized(16);
  97. EXPECT(maybe_buffer.has_value());
  98. auto buffer = maybe_buffer.release_value();
  99. StringView buffer_contents { buffer.bytes() };
  100. EXPECT(!file->seek(500, Core::Stream::SeekMode::SetPosition).is_error());
  101. EXPECT_EQ(file->tell().release_value(), 500);
  102. EXPECT(file->read_or_error(buffer));
  103. EXPECT_EQ(buffer_contents, expected_seek_contents1);
  104. // A single seek & read test should be fine for now.
  105. }
  106. TEST_CASE(file_adopt_invalid_fd)
  107. {
  108. auto maybe_file = Core::Stream::File::adopt_fd(-1, Core::Stream::OpenMode::Read);
  109. EXPECT(maybe_file.is_error());
  110. EXPECT_EQ(maybe_file.error().code(), EBADF);
  111. }
  112. // TCPSocket tests
  113. constexpr auto sent_data = "Mr. Watson, come here. I want to see you."sv;
  114. TEST_CASE(tcp_socket_read)
  115. {
  116. // NOTE: This is required here because Core::TCPServer requires
  117. // Core::EventLoop through Core::Notifier.
  118. Core::EventLoop event_loop;
  119. auto maybe_tcp_server = Core::TCPServer::try_create();
  120. EXPECT(!maybe_tcp_server.is_error());
  121. auto tcp_server = maybe_tcp_server.release_value();
  122. EXPECT(!tcp_server->listen({ 127, 0, 0, 1 }, 9090).is_error());
  123. EXPECT(!tcp_server->set_blocking(true).is_error());
  124. auto maybe_client_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 });
  125. EXPECT(!maybe_client_socket.is_error());
  126. auto client_socket = maybe_client_socket.release_value();
  127. EXPECT(client_socket->is_open());
  128. auto maybe_server_socket = tcp_server->accept();
  129. EXPECT(!maybe_server_socket.is_error());
  130. auto server_socket = maybe_server_socket.release_value();
  131. EXPECT(!server_socket->write({ sent_data.characters_without_null_termination(), sent_data.length() }).is_error());
  132. server_socket->close();
  133. EXPECT(client_socket->can_read_without_blocking(100).release_value());
  134. EXPECT_EQ(client_socket->pending_bytes().release_value(), sent_data.length());
  135. auto maybe_receive_buffer = ByteBuffer::create_uninitialized(64);
  136. auto receive_buffer = maybe_receive_buffer.release_value();
  137. auto maybe_nread = client_socket->read(receive_buffer);
  138. EXPECT(!maybe_nread.is_error());
  139. auto nread = maybe_nread.release_value();
  140. StringView received_data { receive_buffer.data(), nread };
  141. EXPECT_EQ(sent_data, received_data);
  142. }
  143. TEST_CASE(tcp_socket_write)
  144. {
  145. Core::EventLoop event_loop;
  146. auto maybe_tcp_server = Core::TCPServer::try_create();
  147. EXPECT(!maybe_tcp_server.is_error());
  148. auto tcp_server = maybe_tcp_server.release_value();
  149. EXPECT(!tcp_server->listen({ 127, 0, 0, 1 }, 9090).is_error());
  150. EXPECT(!tcp_server->set_blocking(true).is_error());
  151. auto maybe_client_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 });
  152. EXPECT(!maybe_client_socket.is_error());
  153. auto client_socket = maybe_client_socket.release_value();
  154. auto maybe_server_socket = tcp_server->accept();
  155. EXPECT(!maybe_server_socket.is_error());
  156. auto server_socket = maybe_server_socket.release_value();
  157. EXPECT(!server_socket->set_blocking(true).is_error());
  158. EXPECT(client_socket->write_or_error({ sent_data.characters_without_null_termination(), sent_data.length() }));
  159. client_socket->close();
  160. auto receive_buffer = ByteBuffer::create_uninitialized(64).release_value();
  161. auto maybe_nread = server_socket->read(receive_buffer);
  162. EXPECT(!maybe_nread.is_error());
  163. auto nread = maybe_nread.release_value();
  164. StringView received_data { receive_buffer.data(), nread };
  165. EXPECT_EQ(sent_data, received_data);
  166. }
  167. TEST_CASE(tcp_socket_eof)
  168. {
  169. Core::EventLoop event_loop;
  170. auto maybe_tcp_server = Core::TCPServer::try_create();
  171. EXPECT(!maybe_tcp_server.is_error());
  172. auto tcp_server = maybe_tcp_server.release_value();
  173. EXPECT(!tcp_server->listen({ 127, 0, 0, 1 }, 9090).is_error());
  174. EXPECT(!tcp_server->set_blocking(true).is_error());
  175. auto maybe_client_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 });
  176. EXPECT(!maybe_client_socket.is_error());
  177. auto client_socket = maybe_client_socket.release_value();
  178. EXPECT(client_socket->is_open());
  179. auto server_socket = tcp_server->accept().release_value();
  180. server_socket->close();
  181. // NOTE: This may seem unintuitive, but poll will mark a fd which has
  182. // reached EOF (i.e. in the case of the other side disconnecting) as
  183. // POLLIN.
  184. EXPECT(client_socket->can_read_without_blocking(100).release_value());
  185. EXPECT_EQ(client_socket->pending_bytes().release_value(), 0ul);
  186. auto maybe_receive_buffer = ByteBuffer::create_uninitialized(1);
  187. auto receive_buffer = maybe_receive_buffer.release_value();
  188. EXPECT_EQ(client_socket->read(receive_buffer).release_value(), 0ul);
  189. EXPECT(client_socket->is_eof());
  190. }
  191. // UDPSocket tests
  192. constexpr auto udp_reply_data = "Well hello friends!"sv;
  193. TEST_CASE(udp_socket_read_write)
  194. {
  195. // NOTE: This is required here because Core::UDPServer requires
  196. // Core::EventLoop through Core::Notifier.
  197. Core::EventLoop event_loop;
  198. auto udp_server = Core::UDPServer::construct();
  199. EXPECT(udp_server->bind({ 127, 0, 0, 1 }, 9090));
  200. auto maybe_client_socket = Core::Stream::UDPSocket::connect({ { 127, 0, 0, 1 }, 9090 });
  201. EXPECT(!maybe_client_socket.is_error());
  202. auto client_socket = maybe_client_socket.release_value();
  203. EXPECT(client_socket->is_open());
  204. EXPECT(client_socket->write_or_error({ sent_data.characters_without_null_termination(), sent_data.length() }));
  205. // FIXME: UDPServer::receive sadly doesn't give us a way to block on it,
  206. // currently.
  207. usleep(100000);
  208. struct sockaddr_in client_address;
  209. auto server_receive_buffer = udp_server->receive(64, client_address);
  210. EXPECT(!server_receive_buffer.is_empty());
  211. StringView server_received_data { server_receive_buffer.bytes() };
  212. EXPECT_EQ(server_received_data, sent_data);
  213. EXPECT(!udp_server->send({ udp_reply_data.characters_without_null_termination(), udp_reply_data.length() }, client_address).is_error());
  214. EXPECT(client_socket->can_read_without_blocking(100).release_value());
  215. EXPECT_EQ(client_socket->pending_bytes().release_value(), udp_reply_data.length());
  216. // Testing that supplying a smaller buffer than required causes a failure.
  217. auto small_buffer = ByteBuffer::create_uninitialized(8).release_value();
  218. EXPECT_EQ(client_socket->read(small_buffer).error().code(), EMSGSIZE);
  219. auto maybe_client_receive_buffer = ByteBuffer::create_uninitialized(64);
  220. auto client_receive_buffer = maybe_client_receive_buffer.release_value();
  221. auto maybe_nread = client_socket->read(client_receive_buffer);
  222. EXPECT(!maybe_nread.is_error());
  223. auto nread = maybe_nread.release_value();
  224. StringView client_received_data { client_receive_buffer.data(), nread };
  225. EXPECT_EQ(udp_reply_data, client_received_data);
  226. }
  227. // LocalSocket tests
  228. TEST_CASE(local_socket_read)
  229. {
  230. Core::EventLoop event_loop;
  231. auto local_server = Core::LocalServer::construct();
  232. EXPECT(local_server->listen("/tmp/test-socket"));
  233. local_server->on_accept = [&](NonnullRefPtr<Core::LocalSocket> server_socket) {
  234. EXPECT(server_socket->write(sent_data));
  235. event_loop.quit(0);
  236. event_loop.pump();
  237. };
  238. // NOTE: Doing this on another thread, because otherwise we're at an
  239. // impasse. LocalSocket::connect blocks because there's nobody to
  240. // accept, and LocalServer::accept blocks because there's nobody
  241. // connected.
  242. auto background_action = Threading::BackgroundAction<int>::construct(
  243. [](auto&) {
  244. auto maybe_client_socket = Core::Stream::LocalSocket::connect("/tmp/test-socket");
  245. EXPECT(!maybe_client_socket.is_error());
  246. auto client_socket = maybe_client_socket.release_value();
  247. EXPECT(client_socket->is_open());
  248. EXPECT(client_socket->can_read_without_blocking(100).release_value());
  249. EXPECT_EQ(client_socket->pending_bytes().release_value(), sent_data.length());
  250. auto maybe_receive_buffer = ByteBuffer::create_uninitialized(64);
  251. auto receive_buffer = maybe_receive_buffer.release_value();
  252. auto maybe_nread = client_socket->read(receive_buffer);
  253. EXPECT(!maybe_nread.is_error());
  254. auto nread = maybe_nread.release_value();
  255. StringView received_data { receive_buffer.data(), nread };
  256. EXPECT_EQ(sent_data, received_data);
  257. return 0;
  258. },
  259. nullptr);
  260. event_loop.exec();
  261. ::unlink("/tmp/test-socket");
  262. }
  263. TEST_CASE(local_socket_write)
  264. {
  265. Core::EventLoop event_loop;
  266. auto local_server = Core::LocalServer::construct();
  267. EXPECT(local_server->listen("/tmp/test-socket"));
  268. local_server->on_accept = [&](NonnullRefPtr<Core::LocalSocket> server_socket) {
  269. // NOTE: For some reason LocalServer gives us a nonblocking socket..?
  270. server_socket->set_blocking(true);
  271. auto receive_buffer = server_socket->read_all();
  272. EXPECT(!server_socket->error());
  273. StringView received_data { receive_buffer.bytes() };
  274. EXPECT_EQ(sent_data, received_data);
  275. event_loop.quit(0);
  276. event_loop.pump();
  277. };
  278. // NOTE: Same reason as in the local_socket_read test.
  279. auto background_action = Threading::BackgroundAction<int>::construct(
  280. [](auto&) {
  281. auto maybe_client_socket = Core::Stream::LocalSocket::connect("/tmp/test-socket");
  282. EXPECT(!maybe_client_socket.is_error());
  283. auto client_socket = maybe_client_socket.release_value();
  284. EXPECT(client_socket->write_or_error({ sent_data.characters_without_null_termination(), sent_data.length() }));
  285. client_socket->close();
  286. return 0;
  287. },
  288. nullptr);
  289. event_loop.exec();
  290. ::unlink("/tmp/test-socket");
  291. }
  292. // Buffered stream tests
  293. TEST_CASE(buffered_long_file_read)
  294. {
  295. auto maybe_file = Core::Stream::File::open("/usr/Tests/LibCore/long_lines.txt", Core::Stream::OpenMode::Read);
  296. EXPECT(!maybe_file.is_error());
  297. auto maybe_buffered_file = Core::Stream::BufferedFile::create(maybe_file.release_value());
  298. EXPECT(!maybe_buffered_file.is_error());
  299. auto file = maybe_buffered_file.release_value();
  300. auto buffer = ByteBuffer::create_uninitialized(4096).release_value();
  301. EXPECT(!file->seek(255, Core::Stream::SeekMode::SetPosition).is_error());
  302. EXPECT(file->can_read_line().release_value());
  303. auto maybe_nread = file->read_line(buffer);
  304. EXPECT(!maybe_nread.is_error());
  305. EXPECT_EQ(maybe_nread.value(), 4095ul); // 4095 bytes on the third line
  306. // Testing that buffering with seeking works properly
  307. EXPECT(!file->seek(365, Core::Stream::SeekMode::SetPosition).is_error());
  308. auto maybe_after_seek_nread = file->read_line(buffer);
  309. EXPECT(!maybe_after_seek_nread.is_error());
  310. EXPECT_EQ(maybe_after_seek_nread.value(), 3985ul); // 4095 - 110
  311. }
  312. TEST_CASE(buffered_small_file_read)
  313. {
  314. auto maybe_file = Core::Stream::File::open("/usr/Tests/LibCore/small.txt", Core::Stream::OpenMode::Read);
  315. EXPECT(!maybe_file.is_error());
  316. auto maybe_buffered_file = Core::Stream::BufferedFile::create(maybe_file.release_value());
  317. EXPECT(!maybe_buffered_file.is_error());
  318. auto file = maybe_buffered_file.release_value();
  319. static constexpr StringView expected_lines[] {
  320. "Well"sv,
  321. "hello"sv,
  322. "friends!"sv,
  323. ":^)"sv
  324. };
  325. // Testing that we don't read out of bounds when the entire file fits into the buffer
  326. auto buffer = ByteBuffer::create_uninitialized(4096).release_value();
  327. for (auto const& line : expected_lines) {
  328. VERIFY(file->can_read_line().release_value());
  329. auto maybe_nread = file->read_line(buffer);
  330. EXPECT(!maybe_nread.is_error());
  331. EXPECT_EQ(maybe_nread.value(), line.length());
  332. EXPECT_EQ(StringView(buffer.span().trim(maybe_nread.value())), line);
  333. }
  334. EXPECT(!file->can_read_line().is_error());
  335. EXPECT(!file->can_read_line().value());
  336. }
  337. constexpr auto buffered_sent_data = "Well hello friends!\n:^)\nThis shouldn't be present. :^("sv;
  338. constexpr auto first_line = "Well hello friends!"sv;
  339. constexpr auto second_line = ":^)"sv;
  340. TEST_CASE(buffered_tcp_socket_read)
  341. {
  342. Core::EventLoop event_loop;
  343. auto maybe_tcp_server = Core::TCPServer::try_create();
  344. EXPECT(!maybe_tcp_server.is_error());
  345. auto tcp_server = maybe_tcp_server.release_value();
  346. EXPECT(!tcp_server->listen({ 127, 0, 0, 1 }, 9090).is_error());
  347. EXPECT(!tcp_server->set_blocking(true).is_error());
  348. auto maybe_client_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 });
  349. EXPECT(!maybe_client_socket.is_error());
  350. auto maybe_buffered_socket = Core::Stream::BufferedTCPSocket::create(maybe_client_socket.release_value());
  351. EXPECT(!maybe_buffered_socket.is_error());
  352. auto client_socket = maybe_buffered_socket.release_value();
  353. EXPECT(client_socket->is_open());
  354. auto maybe_server_socket = tcp_server->accept();
  355. EXPECT(!maybe_server_socket.is_error());
  356. auto server_socket = maybe_server_socket.release_value();
  357. EXPECT(!server_socket->write({ buffered_sent_data.characters_without_null_termination(), sent_data.length() }).is_error());
  358. EXPECT(client_socket->can_read_without_blocking(100).release_value());
  359. auto receive_buffer = ByteBuffer::create_uninitialized(64).release_value();
  360. auto maybe_first_nread = client_socket->read_line(receive_buffer);
  361. EXPECT(!maybe_first_nread.is_error());
  362. StringView first_received_line { receive_buffer.data(), maybe_first_nread.value() };
  363. EXPECT_EQ(first_received_line, first_line);
  364. auto maybe_second_nread = client_socket->read_line(receive_buffer);
  365. EXPECT(!maybe_second_nread.is_error());
  366. StringView second_received_line { receive_buffer.data(), maybe_second_nread.value() };
  367. EXPECT_EQ(second_received_line, second_line);
  368. }