1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146

content / browser / network_service_instance_impl_unittest.cc [blame]

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

#include "content/browser/network_service_instance_impl.h"

#include <stdint.h>

#include "base/command_line.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_task_environment.h"
#include "content/test/test_content_browser_client.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

namespace {

// A leaky class that overrides Content Browser Client to say that shutdown has
// started.
class EarlyShutdownTestContentBrowserClient : public TestContentBrowserClient {
 public:
  static EarlyShutdownTestContentBrowserClient* GetInstance() {
    static base::NoDestructor<EarlyShutdownTestContentBrowserClient> instance;
    return instance.get();
  }

 private:
  bool IsShuttingDown() override { return true; }
};

}  // namespace

// This test exists as a regression test for https://crbug.com/1369808.
class NetworkServiceShutdownRaceTest : public testing::Test {
 public:
  NetworkServiceShutdownRaceTest() = default;

  NetworkServiceShutdownRaceTest(const NetworkServiceShutdownRaceTest&) =
      delete;
  NetworkServiceShutdownRaceTest& operator=(
      const NetworkServiceShutdownRaceTest&) = delete;

 protected:
  // Trigger a NetworkContext creation using default parameters. This posts a
  // background thread with a reply to the UI thread. This reply will race
  // shutdown.
  void CreateNetworkContext() {
    mojo::Remote<network::mojom::NetworkContext> network_context;
    network::mojom::NetworkContextParamsPtr context_params =
        network::mojom::NetworkContextParams::New();
    context_params->cert_verifier_params = GetCertVerifierParams(
        cert_verifier::mojom::CertVerifierCreationParams::New());
    CreateNetworkContextInNetworkService(
        network_context.BindNewPipeAndPassReceiver(),
        std::move(context_params));
  }

 private:
  BrowserTaskEnvironment task_environment_;
};

// This should not crash.
TEST_F(NetworkServiceShutdownRaceTest, CreateNetworkContextDuringShutdown) {
  // Set browser as shutting down. Note: this never gets reset back to the old
  // client and will intentionally leak, because the pending UI tasks that cause
  // issue 1369808 are run after the test fixture has been completely torn down,
  // and require IsShuttingDown() to still return true at that point to
  // reproduce the bug.
  std::ignore = SetBrowserClientForTesting(
      EarlyShutdownTestContentBrowserClient::GetInstance());
  // Trigger the network context creation.
  CreateNetworkContext();
}

TEST(NetworkServiceInstanceImplParseCommandLineTest,
     ParseNetLogMaximumFileNoSwitch) {
  base::CommandLine command_line{base::CommandLine::NO_PROGRAM};
  EXPECT_EQ(GetNetLogMaximumFileSizeFromCommandLineForTesting(command_line),
            std::numeric_limits<uint64_t>::max());
}

TEST(NetworkServiceInstanceImplParseCommandLineTest,
     ParseNetLogMaximumFileSizeZero) {
  base::CommandLine command_line{base::CommandLine::NO_PROGRAM};
  command_line.AppendSwitchASCII("net-log-max-size-mb", "0");
  EXPECT_EQ(GetNetLogMaximumFileSizeFromCommandLineForTesting(command_line),
            0u);
}

TEST(NetworkServiceInstanceImplParseCommandLineTest,
     ParseNetLogMaximumFileSizeSmall) {
  base::CommandLine command_line{base::CommandLine::NO_PROGRAM};
  command_line.AppendSwitchASCII("net-log-max-size-mb", "42");
  EXPECT_EQ(GetNetLogMaximumFileSizeFromCommandLineForTesting(command_line),
            42u * 1024 * 1024);
}

// Regression test for <https://crbug.com/352496169>.
TEST(NetworkServiceInstanceImplParseCommandLineTest,
     ParseNetLogMaximumFileSizeLargeButInRange) {
  constexpr uint64_t kTestCases[] = {
      1 << 12,
      std::numeric_limits<uint32_t>::max(),
  };

  for (uint64_t test_case : kTestCases) {
    base::CommandLine command_line{base::CommandLine::NO_PROGRAM};
    command_line.AppendSwitchASCII("net-log-max-size-mb",
                                   base::NumberToString(test_case));
    EXPECT_EQ(GetNetLogMaximumFileSizeFromCommandLineForTesting(command_line),
              test_case * 1024 * 1024);
  }
}

TEST(NetworkServiceInstanceImplParseCommandLineTest,
     ParseNetLogMaximumFileSizeTooLarge) {
  constexpr uint64_t kTooLarge =
      uint64_t{std::numeric_limits<uint32_t>::max()} + 1;
  base::CommandLine command_line{base::CommandLine::NO_PROGRAM};
  command_line.AppendSwitchASCII("net-log-max-size-mb",
                                 base::NumberToString(kTooLarge));
  EXPECT_EQ(GetNetLogMaximumFileSizeFromCommandLineForTesting(command_line),
            std::numeric_limits<uint64_t>::max());
}

TEST(NetworkServiceInstanceImplParseCommandLineTest,
     ParseNetLogMaximumFileSizeNotNumeric) {
  constexpr std::string_view kTestCases[] = {"",    " ",     "-", "-0",
                                             "-42", "hello", "\a"};
  for (std::string_view test_case : kTestCases) {
    SCOPED_TRACE(testing::Message() << "Test case: " << test_case);
    base::CommandLine command_line{base::CommandLine::NO_PROGRAM};
    command_line.AppendSwitchASCII("net-log-max-size-mb", test_case);
    EXPECT_EQ(GetNetLogMaximumFileSizeFromCommandLineForTesting(command_line),
              std::numeric_limits<uint64_t>::max());
  }
}

}  // namespace content