diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index 4085e934f5c..216b1daf853 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -512,6 +512,7 @@ if (BUILD_TESTING) AK LibCrypto LibCompress + LibDNS LibGC LibTest LibTextCodec diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index e3619abe14c..9127ba058b9 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(AK) add_subdirectory(LibCompress) add_subdirectory(LibCore) add_subdirectory(LibDiff) +add_subdirectory(LibDNS) add_subdirectory(LibGfx) add_subdirectory(LibJS) add_subdirectory(LibRegex) diff --git a/Tests/LibDNS/CMakeLists.txt b/Tests/LibDNS/CMakeLists.txt new file mode 100644 index 00000000000..f9b0b64735e --- /dev/null +++ b/Tests/LibDNS/CMakeLists.txt @@ -0,0 +1,7 @@ +set(TEST_SOURCES + TestDNSResolver.cpp +) + +foreach(source IN LISTS TEST_SOURCES) + serenity_test("${source}" LibDNS LIBS LibDNS LibTLS) +endforeach() diff --git a/Tests/LibDNS/TestDNSResolver.cpp b/Tests/LibDNS/TestDNSResolver.cpp new file mode 100644 index 00000000000..f22d2685cb8 --- /dev/null +++ b/Tests/LibDNS/TestDNSResolver.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2025, Altomani Gianluca + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +TEST_CASE(test_udp) +{ + Core::EventLoop loop; + + DNS::Resolver resolver { + [&] -> ErrorOr { + Core::SocketAddress addr = { IPv4Address::from_string("1.1.1.1"sv).value(), static_cast(53) }; + return DNS::Resolver::SocketResult { + MUST(Core::BufferedSocket::create(MUST(Core::UDPSocket::connect(addr)))), + DNS::Resolver::ConnectionMode::UDP, + }; + } + }; + + MUST(resolver.when_socket_ready()->await()); + + resolver.lookup("google.com", DNS::Messages::Class::IN, { DNS::Messages::ResourceType::A, DNS::Messages::ResourceType::AAAA }) + ->when_resolved([&](auto& result) { + EXPECT(!result->records().is_empty()); + loop.quit(0); + }) + .when_rejected([&](auto& error) { + outln("Failed to resolve: {}", error); + loop.quit(1); + }); + + EXPECT_EQ(0, loop.exec()); +} + +TEST_CASE(test_tcp) +{ + Core::EventLoop loop; + + DNS::Resolver resolver { + [&] -> ErrorOr { + Core::SocketAddress addr = { IPv4Address::from_string("1.1.1.1"sv).value(), static_cast(53) }; + return DNS::Resolver::SocketResult { + MUST(Core::BufferedSocket::create(MUST(Core::TCPSocket::connect(addr)))), + DNS::Resolver::ConnectionMode::TCP, + }; + } + }; + + MUST(resolver.when_socket_ready()->await()); + + resolver.lookup("google.com", DNS::Messages::Class::IN, { DNS::Messages::ResourceType::A, DNS::Messages::ResourceType::AAAA }) + ->when_resolved([&](auto& result) { + EXPECT(!result->records().is_empty()); + loop.quit(0); + }) + .when_rejected([&](auto& error) { + outln("Failed to resolve: {}", error); + loop.quit(1); + }); + + EXPECT_EQ(0, loop.exec()); +} + +static StringView ca_certs_file = "./cacert.pem"sv; +static Optional locate_ca_certs_file() +{ + if (FileSystem::exists(ca_certs_file)) { + return ca_certs_file; + } + auto on_target_path = ByteString("/etc/cacert.pem"); + if (FileSystem::exists(on_target_path)) { + return on_target_path; + } + return {}; +} + +TEST_CASE(test_tls) +{ + Core::EventLoop loop; + + DNS::Resolver resolver { + [&] -> ErrorOr { + Core::SocketAddress addr = { IPv4Address::from_string("1.1.1.1"sv).value(), static_cast(853) }; + + TLS::Options options; + options.set_root_certificates_path(locate_ca_certs_file()); + + return DNS::Resolver::SocketResult { + MaybeOwned(TRY(TLS::TLSv12::connect(addr, "1.1.1.1", move(options)))), + DNS::Resolver::ConnectionMode::TCP, + }; + } + }; + + MUST(resolver.when_socket_ready()->await()); + + resolver.lookup("google.com", DNS::Messages::Class::IN, { DNS::Messages::ResourceType::A, DNS::Messages::ResourceType::AAAA }) + ->when_resolved([&](auto& result) { + EXPECT(!result->records().is_empty()); + loop.quit(0); + }) + .when_rejected([&](auto& error) { + outln("Failed to resolve: {}", error); + loop.quit(1); + }); + + EXPECT_EQ(0, loop.exec()); +}