Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0d27faa authored by Mike Yu's avatar Mike Yu
Browse files

Add one more Revalidation unit test

The test checks that the revalidation can retry probing until
it succeeds. To do that, Private DNS validation backoff time
is changable in PrivateDnsConfigurationTest.

Original change: https://android-review.googlesource.com/c/platform/packages/modules/DnsResolver/+/1708171

Bug: 79727473
Bug: 188153519
Test: Test: cd packages/modules/DnsResolver && atest
Change-Id: I11fc8d9ee963dc54d051667971b51bfecd852a93
Merged-In: I11fc8d9ee963dc54d051667971b51bfecd852a93
parent 4b30ae6e
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@
#include "DnsTlsTransport.h"
#include "ResolverEventReporter.h"
#include "netd_resolv/resolv.h"
#include "netdutils/BackoffSequence.h"
#include "util.h"

using aidl::android::net::resolv::aidl::IDnsResolverUnsolicitedEventListener;
@@ -209,10 +208,7 @@ void PrivateDnsConfiguration::startValidation(const ServerIdentity& identity, un
        // such validation passes per day is about ~30MB per month, in the
        // worst case. Otherwise, this will cost ~600 SYNs per month
        // (6 SYNs per ip, 4 ips per validation pass, 24 passes per day).
        auto backoff = netdutils::BackoffSequence<>::Builder()
                               .withInitialRetransmissionTime(std::chrono::seconds(60))
                               .withMaximumRetransmissionTime(std::chrono::seconds(3600))
                               .build();
        auto backoff = mBackoffBuilder.build();

        while (true) {
            // ::validate() is a blocking call that performs network operations.
+8 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@

#include <android-base/result.h>
#include <android-base/thread_annotations.h>
#include <netdutils/BackoffSequence.h>
#include <netdutils/DumpWriter.h>
#include <netdutils/InternetAddresses.h>

@@ -139,6 +140,13 @@ class PrivateDnsConfiguration {

    friend class PrivateDnsConfigurationTest;

    // It's not const because PrivateDnsConfigurationTest needs to override it.
    // TODO: make it const by dependency injection.
    netdutils::BackoffSequence<>::Builder mBackoffBuilder =
            netdutils::BackoffSequence<>::Builder()
                    .withInitialRetransmissionTime(std::chrono::seconds(60))
                    .withMaximumRetransmissionTime(std::chrono::seconds(3600));

    struct RecordEntry {
        RecordEntry(uint32_t netId, const ServerIdentity& identity, Validation state)
            : netId(netId), serverIdentity(identity), state(state) {}
+47 −1
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ class PrivateDnsConfigurationTest : public ::testing::Test {

    void SetUp() {
        mPdc.setObserver(&mObserver);
        mPdc.mBackoffBuilder.withInitialRetransmissionTime(std::chrono::seconds(1))
                .withMaximumRetransmissionTime(std::chrono::seconds(1));

        // The default and sole action when the observer is notified of onValidationStateUpdate.
        // Don't override the action. In other words, don't use WillOnce() or WillRepeatedly()
@@ -51,7 +53,17 @@ class PrivateDnsConfigurationTest : public ::testing::Test {
        ON_CALL(mObserver, onValidationStateUpdate)
                .WillByDefault([&](const std::string& server, Validation validation, uint32_t) {
                    if (validation == Validation::in_process) {
                        std::lock_guard guard(mObserver.lock);
                        auto it = mObserver.serverStateMap.find(server);
                        if (it == mObserver.serverStateMap.end() ||
                            it->second != Validation::in_process) {
                            // Increment runningThreads only when receive the first in_process
                            // notification. The rest of the continuous in_process notifications
                            // are due to probe retry which runs on the same thread.
                            // TODO: consider adding onValidationThreadStart() and
                            // onValidationThreadEnd() callbacks.
                            mObserver.runningThreads++;
                        }
                    } else if (validation == Validation::success ||
                               validation == Validation::fail) {
                        mObserver.runningThreads--;
@@ -148,6 +160,40 @@ TEST_F(PrivateDnsConfigurationTest, ValidationFail_Opportunistic) {
    ASSERT_TRUE(backend.startServer());
}

TEST_F(PrivateDnsConfigurationTest, Revalidation_Opportunistic) {
    const DnsTlsServer server(netdutils::IPSockAddr::toIPSockAddr(kServer1, 853));

    // Step 1: Set up and wait for validation complete.
    testing::InSequence seq;
    EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::in_process, kNetId));
    EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::success, kNetId));

    EXPECT_EQ(mPdc.set(kNetId, kMark, {kServer1}, {}, {}), 0);
    expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
    ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 0; }));

    // Step 2: Simulate the DNS is temporarily broken, and then request a validation.
    // Expect the validation to run as follows:
    //   1. DnsResolver notifies of Validation::in_process when the validation is about to run.
    //   2. The first probing fails. DnsResolver notifies of Validation::in_process.
    //   3. One second later, the second probing begins and succeeds. DnsResolver notifies of
    //      Validation::success.
    EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::in_process, kNetId))
            .Times(2);
    EXPECT_CALL(mObserver, onValidationStateUpdate(kServer1, Validation::success, kNetId));

    std::thread t([] {
        std::this_thread::sleep_for(1000ms);
        backend.startServer();
    });
    backend.stopServer();
    EXPECT_TRUE(mPdc.requestValidation(kNetId, ServerIdentity(server), kMark).ok());

    t.join();
    expectPrivateDnsStatus(PrivateDnsMode::OPPORTUNISTIC);
    ASSERT_TRUE(PollForCondition([&]() { return mObserver.runningThreads == 0; }));
}

TEST_F(PrivateDnsConfigurationTest, ValidationBlock) {
    backend.setDeferredResp(true);