chromium/net/dns/dns_transaction_unittest.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif

#include "net/dns/dns_transaction.h"

#include <stdint.h>

#include <algorithm>
#include <cstdlib>
#include <limits>
#include <memory>
#include <optional>
#include <string_view>
#include <utility>
#include <vector>

#include "base/base64url.h"
#include "base/containers/circular_deque.h"
#include "base/containers/span.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/numerics/safe_math.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/sys_byteorder.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/idempotency.h"
#include "net/base/ip_address.h"
#include "net/base/port_util.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/url_util.h"
#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_util.h"
#include "net/dns/dns_config.h"
#include "net/dns/dns_names_util.h"
#include "net/dns/dns_query.h"
#include "net/dns/dns_response.h"
#include "net/dns/dns_server_iterator.h"
#include "net/dns/dns_session.h"
#include "net/dns/dns_test_util.h"
#include "net/dns/public/dns_over_https_config.h"
#include "net/dns/public/dns_over_https_server_config.h"
#include "net/dns/public/dns_protocol.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/dns/resolve_context.h"
#include "net/http/http_util.h"
#include "net/log/net_log.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_with_source.h"
#include "net/proxy_resolution/proxy_config_service_fixed.h"
#include "net/socket/socket_test_util.h"
#include "net/test/gtest_util.h"
#include "net/test/test_with_task_environment.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/third_party/uri_template/uri_template.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

IsOk;

namespace net {

namespace {

base::TimeDelta kFallbackPeriod =;

const char kMockHostname[] =;

std::vector<uint8_t> DomainFromDot(std::string_view dotted_name) {}

enum class Transport {};

class NetLogCountingObserver : public net::NetLog::ThreadSafeObserver {};

// A SocketDataProvider builder.
class DnsSocketData {};

class TestSocketFactory;

// A variant of MockUDPClientSocket which always fails to Connect.
class FailingUDPClientSocket : public MockUDPClientSocket {};

// A variant of MockUDPClientSocket which notifies the factory OnConnect.
class TestUDPClientSocket : public MockUDPClientSocket {};

// Creates TestUDPClientSockets and keeps endpoints reported via OnConnect.
class TestSocketFactory : public MockClientSocketFactory {};

int TestUDPClientSocket::Connect(const IPEndPoint& endpoint) {}

int TestUDPClientSocket::ConnectAsync(const IPEndPoint& address,
                                      CompletionOnceCallback callback) {}

// Helper class that holds a DnsTransaction and handles OnTransactionComplete.
class TransactionHelper {};

// Callback that allows a test to modify HttpResponseinfo
// before the response is sent to the requester. This allows
// response headers to be changed.
ResponseModifierCallback;

// Callback that allows the test to substitute its own implementation
// of URLRequestJob to handle the request.
DohJobMakerCallback;

// Callback to notify that URLRequestJob::Start has been called.
UrlRequestStartedCallback;

// Subclass of URLRequestJob which takes a SocketDataProvider with data
// representing both a DNS over HTTPS query and response.
class URLRequestMockDohJob : public URLRequestJob, public AsyncSocket {};

class DnsTransactionTestBase : public testing::Test {};

class DnsTransactionTest : public DnsTransactionTestBase,
                           public WithTaskEnvironment {};

class DnsTransactionTestWithMockTime : public DnsTransactionTestBase,
                                       public WithTaskEnvironment {};

TEST_F(DnsTransactionTest, Lookup) {}

TEST_F(DnsTransactionTest, LookupWithLog) {}

TEST_F(DnsTransactionTest, LookupWithEDNSOption) {}

TEST_F(DnsTransactionTest, LookupWithMultipleEDNSOptions) {}

// Concurrent lookup tests assume that DnsTransaction::Start immediately
// consumes a socket from ClientSocketFactory.
TEST_F(DnsTransactionTest, ConcurrentLookup) {}

TEST_F(DnsTransactionTest, CancelLookup) {}

TEST_F(DnsTransactionTest, DestroyFactory) {}

TEST_F(DnsTransactionTest, CancelFromCallback) {}

TEST_F(DnsTransactionTest, MismatchedResponseSync) {}

TEST_F(DnsTransactionTest, MismatchedResponseAsync) {}

// Test that responses are not accepted when only the response ID mismatches.
// Tests against incorrect transaction ID validation, which is anti-pattern #1
// from the "NAME:WRECK" report:
// https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST_F(DnsTransactionTest, MismatchedResponseFail) {}

TEST_F(DnsTransactionTest, MismatchedResponseNxdomain) {}

// This is a regression test for https://crbug.com/1410442.
TEST_F(DnsTransactionTest, ZeroSizeResponseAsync) {}

TEST_F(DnsTransactionTest, ServerFail) {}

TEST_F(DnsTransactionTest, NoDomain) {}

TEST_F(DnsTransactionTestWithMockTime, Timeout_FastTimeout) {}

TEST_F(DnsTransactionTestWithMockTime, ServerFallbackAndRotate) {}

TEST_F(DnsTransactionTest, SuffixSearchAboveNdots) {}

TEST_F(DnsTransactionTest, SuffixSearchBelowNdots) {}

TEST_F(DnsTransactionTest, EmptySuffixSearch) {}

TEST_F(DnsTransactionTest, DontAppendToMultiLabelName) {}

const uint8_t kResponseNoData[] =;

TEST_F(DnsTransactionTest, SuffixSearchStop) {}

TEST_F(DnsTransactionTest, SyncFirstQuery) {}

TEST_F(DnsTransactionTest, SyncFirstQueryWithSearch) {}

TEST_F(DnsTransactionTest, SyncSearchQuery) {}

TEST_F(DnsTransactionTest, ConnectFailure) {}

TEST_F(DnsTransactionTest, ConnectFailure_SocketLimitReached) {}

TEST_F(DnsTransactionTest, ConnectFailureFollowedBySuccess) {}

TEST_F(DnsTransactionTest, HttpsGetLookup) {}

TEST_F(DnsTransactionTest, HttpsGetFailure) {}

TEST_F(DnsTransactionTest, HttpsGetMalformed) {}

TEST_F(DnsTransactionTest, HttpsPostLookup) {}

TEST_F(DnsTransactionTest, HttpsPostFailure) {}

TEST_F(DnsTransactionTest, HttpsPostMalformed) {}

TEST_F(DnsTransactionTest, HttpsPostLookupAsync) {}

std::unique_ptr<URLRequestJob> DohJobMakerCallbackFailLookup(
    URLRequest* request,
    SocketDataProvider* data) {}

TEST_F(DnsTransactionTest, HttpsPostLookupFailDohServerLookup) {}

std::unique_ptr<URLRequestJob> DohJobMakerCallbackFailStart(
    URLRequest* request,
    SocketDataProvider* data) {}

TEST_F(DnsTransactionTest, HttpsPostLookupFailStart) {}

std::unique_ptr<URLRequestJob> DohJobMakerCallbackFailSync(
    URLRequest* request,
    SocketDataProvider* data) {}

TEST_F(DnsTransactionTest, HttpsPostLookupFailSync) {}

std::unique_ptr<URLRequestJob> DohJobMakerCallbackFailAsync(
    URLRequest* request,
    SocketDataProvider* data) {}

TEST_F(DnsTransactionTest, HttpsPostLookupFailAsync) {}

TEST_F(DnsTransactionTest, HttpsPostLookup2Sync) {}

TEST_F(DnsTransactionTest, HttpsPostLookup2Async) {}

TEST_F(DnsTransactionTest, HttpsPostLookupAsyncWithAsyncZeroRead) {}

TEST_F(DnsTransactionTest, HttpsPostLookupSyncWithAsyncZeroRead) {}

TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenSync) {}

TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenSyncError) {}

TEST_F(DnsTransactionTest, HttpsPostLookupAsyncThenAsyncError) {}

TEST_F(DnsTransactionTest, HttpsPostLookupSyncThenAsyncError) {}

TEST_F(DnsTransactionTest, HttpsPostLookupSyncThenSyncError) {}

TEST_F(DnsTransactionTest, HttpsNotAvailable) {}

TEST_F(DnsTransactionTest, HttpsMarkHttpsBad) {}

TEST_F(DnsTransactionTest, HttpsPostFailThenHTTPFallback) {}

TEST_F(DnsTransactionTest, HttpsPostFailTwice) {}

TEST_F(DnsTransactionTest, HttpsNotAvailableThenHttpFallback) {}

// Fail first DoH server, then no fallbacks marked available in AUTOMATIC mode.
TEST_F(DnsTransactionTest, HttpsFailureThenNotAvailable_Automatic) {}

// Test a secure transaction failure in SECURE mode when other DoH servers are
// only available for fallback because of
TEST_F(DnsTransactionTest, HttpsFailureThenNotAvailable_Secure) {}

TEST_F(DnsTransactionTest, MaxHttpsFailures_NonConsecutive) {}

TEST_F(DnsTransactionTest, MaxHttpsFailures_Consecutive) {}

// Test that a secure transaction started before a DoH server becomes
// unavailable can complete and make the server available again.
TEST_F(DnsTransactionTest, SuccessfulTransactionStartedBeforeUnavailable) {}

void MakeResponseWithCookie(URLRequest* request, HttpResponseInfo* info) {}

class CookieCallback {};

TEST_F(DnsTransactionTest, HttpsPostTestNoCookies) {}

void MakeResponseWithoutLength(URLRequest* request, HttpResponseInfo* info) {}

TEST_F(DnsTransactionTest, HttpsPostNoContentLength) {}

void MakeResponseWithBadRequestResponse(URLRequest* request,
                                        HttpResponseInfo* info) {}

TEST_F(DnsTransactionTest, HttpsPostWithBadRequestResponse) {}

void MakeResponseWrongType(URLRequest* request, HttpResponseInfo* info) {}

TEST_F(DnsTransactionTest, HttpsPostWithWrongType) {}

void MakeResponseRedirect(URLRequest* request, HttpResponseInfo* info) {}

TEST_F(DnsTransactionTest, HttpsGetRedirect) {}

void MakeResponseInsecureRedirect(URLRequest* request, HttpResponseInfo* info) {}

TEST_F(DnsTransactionTest, HttpsGetRedirectToInsecureProtocol) {}

TEST_F(DnsTransactionTest, HttpsGetContentLengthTooLarge) {}

TEST_F(DnsTransactionTest, HttpsGetResponseTooLargeWithoutContentLength) {}

void MakeResponseNoType(URLRequest* request, HttpResponseInfo* info) {}

TEST_F(DnsTransactionTest, HttpsPostWithNoType) {}

TEST_F(DnsTransactionTest, CanLookupDohServerName) {}

TEST_F(DnsTransactionTest, HttpsPostLookupWithLog) {}

// Test for when a slow DoH response is delayed until after the initial fallback
// period (but succeeds before the full timeout period).
TEST_F(DnsTransactionTestWithMockTime, SlowHttpsResponse_SingleAttempt) {}

// Test for when a slow DoH response is delayed until after the initial fallback
// period but fast timeout is enabled, resulting in timeout failure.
TEST_F(DnsTransactionTestWithMockTime,
       SlowHttpsResponse_SingleAttempt_FastTimeout) {}

// Test for when a slow DoH response is delayed until after the initial fallback
// period but a retry is configured.
TEST_F(DnsTransactionTestWithMockTime, SlowHttpsResponse_TwoAttempts) {}

// Test for when a slow DoH response is delayed until after the full timeout
// period.
TEST_F(DnsTransactionTestWithMockTime, HttpsTimeout) {}

// Test for when two slow DoH responses are delayed until after the full timeout
// period.
TEST_F(DnsTransactionTestWithMockTime, HttpsTimeout2) {}

// Test for when attempt fallback periods go beyond the full timeout period.
TEST_F(DnsTransactionTestWithMockTime, LongHttpsTimeouts) {}

// Test for when the last of multiple HTTPS attempts fails (SERVFAIL) before
// a previous attempt succeeds.
TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFails) {}

// Test for when the last of multiple HTTPS attempts fails (SERVFAIL), and a
// previous attempt never completes.
TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFails_Timeout) {}

// Test for when the last of multiple HTTPS attempts fails (SERVFAIL) before
// a previous attempt can complete, but fast timeouts is enabled.
TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFails_FastTimeout) {}

// Test for when the last of multiple HTTPS attempts fails (SERVFAIL) before
// a previous attempt later fails as well.
TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFailsFirst) {}

// Test for when multiple HTTPS attempts fail (SERVFAIL) in order, making the
// last started attempt also the last attempt to be pending.
TEST_F(DnsTransactionTestWithMockTime, LastHttpsAttemptFailsLast) {}

TEST_F(DnsTransactionTest, TcpLookup_UdpRetry) {}

TEST_F(DnsTransactionTest, TcpLookup_UdpRetry_WithLog) {}

TEST_F(DnsTransactionTest, TcpLookup_LowEntropy) {}

TEST_F(DnsTransactionTest, TCPFailure) {}

TEST_F(DnsTransactionTest, TCPMalformed) {}

TEST_F(DnsTransactionTestWithMockTime, TcpTimeout_UdpRetry) {}

TEST_F(DnsTransactionTestWithMockTime, TcpTimeout_LowEntropy) {}

TEST_F(DnsTransactionTest, TCPReadReturnsZeroAsync) {}

TEST_F(DnsTransactionTest, TCPReadReturnsZeroSynchronous) {}

TEST_F(DnsTransactionTest, TCPConnectionClosedAsync) {}

TEST_F(DnsTransactionTest, TCPConnectionClosedSynchronous) {}

TEST_F(DnsTransactionTest, MismatchedThenNxdomainThenTCP) {}

TEST_F(DnsTransactionTest, MismatchedThenOkThenTCP) {}

TEST_F(DnsTransactionTest, MismatchedThenRefusedThenTCP) {}

TEST_F(DnsTransactionTest, InvalidQuery) {}

TEST_F(DnsTransactionTest, CheckAsync) {}

TEST_F(DnsTransactionTest, EarlyCancel) {}

TEST_F(DnsTransactionTestWithMockTime, ProbeUntilSuccess) {}

TEST_F(DnsTransactionTestWithMockTime, ProbeCreationTriggersSuccessMetric) {}

TEST_F(DnsTransactionTestWithMockTime,
       ProbeAttemptConnectionFailureAffectsHistograms) {}

TEST_F(DnsTransactionTestWithMockTime, ProbeAttemptServFailAffectsHistograms) {}

TEST_F(DnsTransactionTestWithMockTime,
       ProbeAttemptEmptyResponseAffectsHistograms) {}

// Test that if a probe attempt hangs, additional probes will still run on
// schedule
TEST_F(DnsTransactionTestWithMockTime, HungProbe) {}

TEST_F(DnsTransactionTestWithMockTime, ProbeMultipleServers) {}

TEST_F(DnsTransactionTestWithMockTime, MultipleProbeRunners) {}

TEST_F(DnsTransactionTestWithMockTime, MultipleProbeRunners_SeparateContexts) {}

TEST_F(DnsTransactionTestWithMockTime, CancelDohProbeOnDestruction) {}

TEST_F(DnsTransactionTestWithMockTime, CancelDohProbeOnContextDestruction) {}

TEST_F(DnsTransactionTestWithMockTime, CancelOneOfMultipleProbeRunners) {}

TEST_F(DnsTransactionTestWithMockTime, CancelAllOfMultipleProbeRunners) {}

TEST_F(DnsTransactionTestWithMockTime, CancelDohProbe_AfterSuccess) {}

TEST_F(DnsTransactionTestWithMockTime, DestroyFactoryAfterStartingDohProbe) {}

TEST_F(DnsTransactionTestWithMockTime, StartWhileRunning) {}

TEST_F(DnsTransactionTestWithMockTime, RestartFinishedProbe) {}

// Test that a probe runner keeps running on the same schedule if it completes
// but the server is marked unavailable again before the next scheduled probe.
TEST_F(DnsTransactionTestWithMockTime, FastProbeRestart) {}

// Test that queries cannot be sent when they contain a too-long name.
// Tests against incorrect name length validation, which is anti-pattern #3 from
// the "NAME:WRECK" report:
// https://www.forescout.com/company/resources/namewreck-breaking-and-fixing-dns-implementations/
TEST_F(DnsTransactionTestWithMockTime, RejectsQueryingLongNames) {}

// Test that ERR_CONNECTION_REFUSED error after fallback of DnsTCPAttempt
// should not cause DCHECK failure (https://crbug.com/1334250).
TEST_F(DnsTransactionTestWithMockTime, TcpConnectionRefusedAfterFallback) {}

// Test that ERR_CONNECTION_REFUSED error after fallback of DnsHTTPAttempt
// should not cause DCHECK failure (https://crbug.com/1334250).
TEST_F(DnsTransactionTestWithMockTime, HttpsConnectionRefusedAfterFallback) {}

}  // namespace

}  // namespace net