diff --git a/src/cares_wrap.h b/src/cares_wrap.h index fd66a67164b3d3..cb5cc29ba2a5b2 100644 --- a/src/cares_wrap.h +++ b/src/cares_wrap.h @@ -186,7 +186,9 @@ class ChannelWrap final : public AsyncWrap { private: uv_timer_t* timer_handle_ = nullptr; ares_channel channel_ = nullptr; - bool query_last_ok_ = true; + // Start pessimistically so the first query validates whether c-ares fell + // back to a loopback resolver while using the system DNS configuration. + bool query_last_ok_ = false; bool is_servers_default_ = true; bool library_inited_ = false; int timeout_; diff --git a/test/cctest/test_cares_wrap.cc b/test/cctest/test_cares_wrap.cc new file mode 100644 index 00000000000000..963a6def47bd85 --- /dev/null +++ b/test/cctest/test_cares_wrap.cc @@ -0,0 +1,50 @@ +#include "cares_wrap.h" + +#include "gtest/gtest.h" +#include "node.h" +#include "node_test_fixture.h" +#include "v8.h" + +#include + +class CaresWrapTest : public EnvironmentTestFixture {}; + +TEST_F(CaresWrapTest, FreshChannelChecksServersBeforeFirstQuery) { + v8::HandleScope handle_scope(isolate_); + const Argv argv; + Env env{handle_scope, argv}; + + v8::Local templ = + node::BaseObject::MakeLazilyInitializedJSTemplate(*env); + v8::Local object = templ->GetFunction(env.context()) + .ToLocalChecked() + ->NewInstance(env.context()) + .ToLocalChecked(); + + node::cares_wrap::ChannelWrap channel(*env, object, -1, 4, 0); + + ares_addr_port_node server{}; + server.family = AF_INET; + server.addr.addr4.s_addr = htonl(INADDR_LOOPBACK); + server.tcp_port = 12345; + server.udp_port = 12345; + + ASSERT_EQ(ares_set_servers_ports(channel.cares_channel(), &server), + ARES_SUCCESS); + channel.set_is_servers_default(true); + + channel.EnsureServers(); + + ares_addr_port_node* current = nullptr; + ares_get_servers_ports(channel.cares_channel(), ¤t); + ASSERT_NE(current, nullptr); + + const bool still_using_test_loopback = + current->next == nullptr && current->family == AF_INET && + current->addr.addr4.s_addr == htonl(INADDR_LOOPBACK) && + current->tcp_port == 12345 && current->udp_port == 12345; + + ares_free_data(current); + + EXPECT_FALSE(still_using_test_loopback); +}