chromium/net/socket/socket_test_util.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/socket/socket_test_util.h"

#include <inttypes.h>  // For SCNx64
#include <stdint.h>
#include <stdio.h>

#include <memory>
#include <ostream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "base/compiler_specific.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "net/base/address_family.h"
#include "net/base/address_list.h"
#include "net/base/auth.h"
#include "net/base/completion_once_callback.h"
#include "net/base/hex_utils.h"
#include "net/base/ip_address.h"
#include "net/base/load_timing_info.h"
#include "net/base/proxy_server.h"
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/log/net_log_source.h"
#include "net/log/net_log_source_type.h"
#include "net/socket/connect_job.h"
#include "net/socket/socket.h"
#include "net/socket/stream_socket.h"
#include "net/socket/websocket_endpoint_lock_manager.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/strings/ascii.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/android/build_info.h"
#endif

#define NET_TRACE(level, s)

namespace net {
namespace {

inline char AsciifyHigh(char x) {}

inline char AsciifyLow(char x) {}

inline char Asciify(char x) {}

void DumpData(const char* data, int data_len) {}

template <MockReadWriteType type>
void DumpMockReadWrite(const MockReadWrite<type>& r) {}

void RunClosureIfNonNull(base::OnceClosure closure) {}

}  // namespace

MockConnectCompleter::MockConnectCompleter() = default;

MockConnectCompleter::~MockConnectCompleter() = default;

void MockConnectCompleter::SetCallback(CompletionOnceCallback callback) {}

void MockConnectCompleter::Complete(int result) {}

MockConnect::MockConnect() :{}

MockConnect::MockConnect(IoMode io_mode, int r) :{}

MockConnect::MockConnect(IoMode io_mode, int r, IPEndPoint addr)
    :{}

MockConnect::MockConnect(IoMode io_mode,
                         int r,
                         IPEndPoint addr,
                         bool first_attempt_fails)
    :{}

MockConnect::MockConnect(MockConnectCompleter* completer)
    :{}

MockConnect::~MockConnect() = default;

MockConfirm::MockConfirm() :{}

MockConfirm::MockConfirm(IoMode io_mode, int r) :{}

MockConfirm::~MockConfirm() = default;

bool SocketDataProvider::IsIdle() const {}

void SocketDataProvider::Initialize(AsyncSocket* socket) {}

void SocketDataProvider::DetachSocket() {}

SocketDataProvider::SocketDataProvider() = default;

SocketDataProvider::~SocketDataProvider() {}

StaticSocketDataHelper::StaticSocketDataHelper(
    base::span<const MockRead> reads,
    base::span<const MockWrite> writes)
    :{}

StaticSocketDataHelper::~StaticSocketDataHelper() = default;

const MockRead& StaticSocketDataHelper::PeekRead() const {}

const MockWrite& StaticSocketDataHelper::PeekWrite() const {}

const MockRead& StaticSocketDataHelper::AdvanceRead() {}

const MockWrite& StaticSocketDataHelper::AdvanceWrite() {}

void StaticSocketDataHelper::Reset() {}

bool StaticSocketDataHelper::VerifyWriteData(const std::string& data,
                                             SocketDataPrinter* printer) {}

void StaticSocketDataHelper::ExpectAllReadDataConsumed(
    SocketDataPrinter* printer) const {}

void StaticSocketDataHelper::ExpectAllWriteDataConsumed(
    SocketDataPrinter* printer) const {}

const MockWrite& StaticSocketDataHelper::PeekRealWrite() const {}

StaticSocketDataProvider::StaticSocketDataProvider()
    :{}

StaticSocketDataProvider::StaticSocketDataProvider(
    base::span<const MockRead> reads,
    base::span<const MockWrite> writes)
    :{}

StaticSocketDataProvider::~StaticSocketDataProvider() = default;

void StaticSocketDataProvider::Pause() {}

void StaticSocketDataProvider::Resume() {}

MockRead StaticSocketDataProvider::OnRead() {}

MockWriteResult StaticSocketDataProvider::OnWrite(const std::string& data) {}

bool StaticSocketDataProvider::AllReadDataConsumed() const {}

bool StaticSocketDataProvider::AllWriteDataConsumed() const {}

void StaticSocketDataProvider::Reset() {}

SSLSocketDataProvider::SSLSocketDataProvider(IoMode mode, int result)
    :{}

SSLSocketDataProvider::SSLSocketDataProvider(MockConnectCompleter* completer)
    :{}

SSLSocketDataProvider::SSLSocketDataProvider(
    const SSLSocketDataProvider& other) = default;

SSLSocketDataProvider::~SSLSocketDataProvider() = default;

SequencedSocketData::SequencedSocketData()
    :{}

SequencedSocketData::SequencedSocketData(base::span<const MockRead> reads,
                                         base::span<const MockWrite> writes)
    :{}

SequencedSocketData::SequencedSocketData(const MockConnect& connect,
                                         base::span<const MockRead> reads,
                                         base::span<const MockWrite> writes)
    :{}
MockRead SequencedSocketData::OnRead() {}

MockWriteResult SequencedSocketData::OnWrite(const std::string& data) {}

bool SequencedSocketData::AllReadDataConsumed() const {}

void SequencedSocketData::CancelPendingRead() {}

bool SequencedSocketData::AllWriteDataConsumed() const {}

void SequencedSocketData::ExpectAllReadDataConsumed() const {}

void SequencedSocketData::ExpectAllWriteDataConsumed() const {}

bool SequencedSocketData::IsIdle() const {}

bool SequencedSocketData::IsPaused() const {}

void SequencedSocketData::Resume() {}

void SequencedSocketData::RunUntilPaused() {}

void SequencedSocketData::MaybePostReadCompleteTask() {}

void SequencedSocketData::MaybePostWriteCompleteTask() {}

void SequencedSocketData::Reset() {}

void SequencedSocketData::OnReadComplete() {}

void SequencedSocketData::OnWriteComplete() {}

SequencedSocketData::~SequencedSocketData() = default;

MockClientSocketFactory::MockClientSocketFactory() = default;

MockClientSocketFactory::~MockClientSocketFactory() = default;

void MockClientSocketFactory::AddSocketDataProvider(SocketDataProvider* data) {}

void MockClientSocketFactory::AddTcpSocketDataProvider(
    SocketDataProvider* data) {}

void MockClientSocketFactory::AddSSLSocketDataProvider(
    SSLSocketDataProvider* data) {}

void MockClientSocketFactory::ResetNextMockIndexes() {}

std::unique_ptr<DatagramClientSocket>
MockClientSocketFactory::CreateDatagramClientSocket(
    DatagramSocket::BindType bind_type,
    NetLog* net_log,
    const NetLogSource& source) {}

std::unique_ptr<TransportClientSocket>
MockClientSocketFactory::CreateTransportClientSocket(
    const AddressList& addresses,
    std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
    NetworkQualityEstimator* network_quality_estimator,
    NetLog* net_log,
    const NetLogSource& source) {}

std::unique_ptr<SSLClientSocket> MockClientSocketFactory::CreateSSLClientSocket(
    SSLClientContext* context,
    std::unique_ptr<StreamSocket> stream_socket,
    const HostPortPair& host_and_port,
    const SSLConfig& ssl_config) {}

MockClientSocket::MockClientSocket(const NetLogWithSource& net_log)
    :{}

int MockClientSocket::SetReceiveBufferSize(int32_t size) {}

int MockClientSocket::SetSendBufferSize(int32_t size) {}

int MockClientSocket::Bind(const net::IPEndPoint& local_addr) {}

bool MockClientSocket::SetNoDelay(bool no_delay) {}

bool MockClientSocket::SetKeepAlive(bool enable, int delay) {}

void MockClientSocket::Disconnect() {}

bool MockClientSocket::IsConnected() const {}

bool MockClientSocket::IsConnectedAndIdle() const {}

int MockClientSocket::GetPeerAddress(IPEndPoint* address) const {}

int MockClientSocket::GetLocalAddress(IPEndPoint* address) const {}

const NetLogWithSource& MockClientSocket::NetLog() const {}

NextProto MockClientSocket::GetNegotiatedProtocol() const {}

MockClientSocket::~MockClientSocket() = default;

void MockClientSocket::RunCallbackAsync(CompletionOnceCallback callback,
                                        int result) {}

void MockClientSocket::RunCallback(CompletionOnceCallback callback,
                                   int result) {}

MockTCPClientSocket::MockTCPClientSocket(const AddressList& addresses,
                                         net::NetLog* net_log,
                                         SocketDataProvider* data)
    :{}

MockTCPClientSocket::~MockTCPClientSocket() {}

int MockTCPClientSocket::Read(IOBuffer* buf,
                              int buf_len,
                              CompletionOnceCallback callback) {}

int MockTCPClientSocket::ReadIfReady(IOBuffer* buf,
                                     int buf_len,
                                     CompletionOnceCallback callback) {}

int MockTCPClientSocket::CancelReadIfReady() {}

int MockTCPClientSocket::Write(
    IOBuffer* buf,
    int buf_len,
    CompletionOnceCallback callback,
    const NetworkTrafficAnnotationTag& /* traffic_annotation */) {}

int MockTCPClientSocket::SetReceiveBufferSize(int32_t size) {}

int MockTCPClientSocket::SetSendBufferSize(int32_t size) {}

bool MockTCPClientSocket::SetNoDelay(bool no_delay) {}

bool MockTCPClientSocket::SetKeepAlive(bool enable, int delay) {}

void MockTCPClientSocket::SetBeforeConnectCallback(
    const BeforeConnectCallback& before_connect_callback) {}

int MockTCPClientSocket::Connect(CompletionOnceCallback callback) {}

void MockTCPClientSocket::Disconnect() {}

bool MockTCPClientSocket::IsConnected() const {}

bool MockTCPClientSocket::IsConnectedAndIdle() const {}

int MockTCPClientSocket::GetPeerAddress(IPEndPoint* address) const {}

bool MockTCPClientSocket::WasEverUsed() const {}

bool MockTCPClientSocket::GetSSLInfo(SSLInfo* ssl_info) {}

void MockTCPClientSocket::OnReadComplete(const MockRead& data) {}

void MockTCPClientSocket::OnWriteComplete(int rv) {}

void MockTCPClientSocket::OnConnectComplete(const MockConnect& data) {}

void MockTCPClientSocket::OnDataProviderDestroyed() {}

void MockTCPClientSocket::RetryRead(int rv) {}

int MockTCPClientSocket::ReadIfReadyImpl(IOBuffer* buf,
                                         int buf_len,
                                         CompletionOnceCallback callback) {}

void MockTCPClientSocket::RunReadIfReadyCallback(int result) {}

// static
void MockSSLClientSocket::ConnectCallback(
    MockSSLClientSocket* ssl_client_socket,
    CompletionOnceCallback callback,
    int rv) {}

MockSSLClientSocket::MockSSLClientSocket(
    std::unique_ptr<StreamSocket> stream_socket,
    const HostPortPair& host_and_port,
    const SSLConfig& ssl_config,
    SSLSocketDataProvider* data)
    :{}

MockSSLClientSocket::~MockSSLClientSocket() {}

int MockSSLClientSocket::Read(IOBuffer* buf,
                              int buf_len,
                              CompletionOnceCallback callback) {}

int MockSSLClientSocket::ReadIfReady(IOBuffer* buf,
                                     int buf_len,
                                     CompletionOnceCallback callback) {}

int MockSSLClientSocket::Write(
    IOBuffer* buf,
    int buf_len,
    CompletionOnceCallback callback,
    const NetworkTrafficAnnotationTag& traffic_annotation) {}

int MockSSLClientSocket::CancelReadIfReady() {}

int MockSSLClientSocket::Connect(CompletionOnceCallback callback) {}

void MockSSLClientSocket::Disconnect() {}

void MockSSLClientSocket::RunConfirmHandshakeCallback(
    CompletionOnceCallback callback,
    int result) {}

int MockSSLClientSocket::ConfirmHandshake(CompletionOnceCallback callback) {}

bool MockSSLClientSocket::IsConnected() const {}

bool MockSSLClientSocket::IsConnectedAndIdle() const {}

bool MockSSLClientSocket::WasEverUsed() const {}

int MockSSLClientSocket::GetLocalAddress(IPEndPoint* address) const {}

int MockSSLClientSocket::GetPeerAddress(IPEndPoint* address) const {}

NextProto MockSSLClientSocket::GetNegotiatedProtocol() const {}

std::optional<std::string_view>
MockSSLClientSocket::GetPeerApplicationSettings() const {}

bool MockSSLClientSocket::GetSSLInfo(SSLInfo* requested_ssl_info) {}

void MockSSLClientSocket::ApplySocketTag(const SocketTag& tag) {}

const NetLogWithSource& MockSSLClientSocket::NetLog() const {}

int64_t MockSSLClientSocket::GetTotalReceivedBytes() const {}

int64_t MockClientSocket::GetTotalReceivedBytes() const {}

int MockSSLClientSocket::SetReceiveBufferSize(int32_t size) {}

int MockSSLClientSocket::SetSendBufferSize(int32_t size) {}

void MockSSLClientSocket::GetSSLCertRequestInfo(
    SSLCertRequestInfo* cert_request_info) const {}

int MockSSLClientSocket::ExportKeyingMaterial(std::string_view label,
                                              bool has_context,
                                              std::string_view context,
                                              unsigned char* out,
                                              unsigned int outlen) {}

std::vector<uint8_t> MockSSLClientSocket::GetECHRetryConfigs() {}

void MockSSLClientSocket::RunCallbackAsync(CompletionOnceCallback callback,
                                           int result) {}

void MockSSLClientSocket::RunCallback(CompletionOnceCallback callback,
                                      int result) {}

void MockSSLClientSocket::OnReadComplete(const MockRead& data) {}

void MockSSLClientSocket::OnWriteComplete(int rv) {}

void MockSSLClientSocket::OnConnectComplete(const MockConnect& data) {}

MockUDPClientSocket::MockUDPClientSocket(SocketDataProvider* data,
                                         net::NetLog* net_log)
    :{}

MockUDPClientSocket::~MockUDPClientSocket() {}

int MockUDPClientSocket::Read(IOBuffer* buf,
                              int buf_len,
                              CompletionOnceCallback callback) {}

int MockUDPClientSocket::Write(
    IOBuffer* buf,
    int buf_len,
    CompletionOnceCallback callback,
    const NetworkTrafficAnnotationTag& /* traffic_annotation */) {}

int MockUDPClientSocket::SetReceiveBufferSize(int32_t size) {}

int MockUDPClientSocket::SetSendBufferSize(int32_t size) {}

int MockUDPClientSocket::SetDoNotFragment() {}

int MockUDPClientSocket::SetRecvTos() {}

int MockUDPClientSocket::SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) {}

void MockUDPClientSocket::Close() {}

int MockUDPClientSocket::GetPeerAddress(IPEndPoint* address) const {}

int MockUDPClientSocket::GetLocalAddress(IPEndPoint* address) const {}

void MockUDPClientSocket::UseNonBlockingIO() {}

int MockUDPClientSocket::SetMulticastInterface(uint32_t interface_index) {}

const NetLogWithSource& MockUDPClientSocket::NetLog() const {}

int MockUDPClientSocket::Connect(const IPEndPoint& address) {}

int MockUDPClientSocket::ConnectUsingNetwork(handles::NetworkHandle network,
                                             const IPEndPoint& address) {}

int MockUDPClientSocket::ConnectUsingDefaultNetwork(const IPEndPoint& address) {}

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

int MockUDPClientSocket::ConnectUsingNetworkAsync(
    handles::NetworkHandle network,
    const IPEndPoint& address,
    CompletionOnceCallback callback) {}

int MockUDPClientSocket::ConnectUsingDefaultNetworkAsync(
    const IPEndPoint& address,
    CompletionOnceCallback callback) {}

handles::NetworkHandle MockUDPClientSocket::GetBoundNetwork() const {}

void MockUDPClientSocket::ApplySocketTag(const SocketTag& tag) {}

DscpAndEcn MockUDPClientSocket::GetLastTos() const {}

void MockUDPClientSocket::OnReadComplete(const MockRead& data) {}

void MockUDPClientSocket::OnWriteComplete(int rv) {}

void MockUDPClientSocket::OnConnectComplete(const MockConnect& data) {}

void MockUDPClientSocket::OnDataProviderDestroyed() {}

int MockUDPClientSocket::CompleteRead() {}

void MockUDPClientSocket::RunCallbackAsync(CompletionOnceCallback callback,
                                           int result) {}

void MockUDPClientSocket::RunCallback(CompletionOnceCallback callback,
                                      int result) {}

TestSocketRequest::TestSocketRequest(
    std::vector<raw_ptr<TestSocketRequest, VectorExperimental>>* request_order,
    size_t* completion_count)
    :{}

TestSocketRequest::~TestSocketRequest() = default;

void TestSocketRequest::OnComplete(int result) {}

// static
const int ClientSocketPoolTest::kIndexOutOfBounds =;

// static
const int ClientSocketPoolTest::kRequestNotFound =;

ClientSocketPoolTest::ClientSocketPoolTest() = default;
ClientSocketPoolTest::~ClientSocketPoolTest() = default;

int ClientSocketPoolTest::GetOrderOfRequest(size_t index) const {}

bool ClientSocketPoolTest::ReleaseOneConnection(KeepAlive keep_alive) {}

void ClientSocketPoolTest::ReleaseAllConnections(KeepAlive keep_alive) {}

MockTransportClientSocketPool::MockConnectJob::MockConnectJob(
    std::unique_ptr<StreamSocket> socket,
    ClientSocketHandle* handle,
    const SocketTag& socket_tag,
    CompletionOnceCallback callback,
    RequestPriority priority)
    :{}

MockTransportClientSocketPool::MockConnectJob::~MockConnectJob() = default;

int MockTransportClientSocketPool::MockConnectJob::Connect() {}

bool MockTransportClientSocketPool::MockConnectJob::CancelHandle(
    const ClientSocketHandle* handle) {}

void MockTransportClientSocketPool::MockConnectJob::OnConnect(int rv) {}

MockTransportClientSocketPool::MockTransportClientSocketPool(
    int max_sockets,
    int max_sockets_per_group,
    const CommonConnectJobParams* common_connect_job_params)
    :{}

MockTransportClientSocketPool::~MockTransportClientSocketPool() = default;

int MockTransportClientSocketPool::RequestSocket(
    const ClientSocketPool::GroupId& group_id,
    scoped_refptr<ClientSocketPool::SocketParams> socket_params,
    const std::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
    RequestPriority priority,
    const SocketTag& socket_tag,
    RespectLimits respect_limits,
    ClientSocketHandle* handle,
    CompletionOnceCallback callback,
    const ProxyAuthCallback& on_auth_callback,
    const NetLogWithSource& net_log) {}

void MockTransportClientSocketPool::SetPriority(
    const ClientSocketPool::GroupId& group_id,
    ClientSocketHandle* handle,
    RequestPriority priority) {}

void MockTransportClientSocketPool::CancelRequest(
    const ClientSocketPool::GroupId& group_id,
    ClientSocketHandle* handle,
    bool cancel_connect_job) {}

void MockTransportClientSocketPool::ReleaseSocket(
    const ClientSocketPool::GroupId& group_id,
    std::unique_ptr<StreamSocket> socket,
    int64_t generation) {}

WrappedStreamSocket::WrappedStreamSocket(
    std::unique_ptr<StreamSocket> transport)
    :{}
WrappedStreamSocket::~WrappedStreamSocket() = default;

int WrappedStreamSocket::Bind(const net::IPEndPoint& local_addr) {}

int WrappedStreamSocket::Connect(CompletionOnceCallback callback) {}

void WrappedStreamSocket::Disconnect() {}

bool WrappedStreamSocket::IsConnected() const {}

bool WrappedStreamSocket::IsConnectedAndIdle() const {}

int WrappedStreamSocket::GetPeerAddress(IPEndPoint* address) const {}

int WrappedStreamSocket::GetLocalAddress(IPEndPoint* address) const {}

const NetLogWithSource& WrappedStreamSocket::NetLog() const {}

bool WrappedStreamSocket::WasEverUsed() const {}

NextProto WrappedStreamSocket::GetNegotiatedProtocol() const {}

bool WrappedStreamSocket::GetSSLInfo(SSLInfo* ssl_info) {}

int64_t WrappedStreamSocket::GetTotalReceivedBytes() const {}

void WrappedStreamSocket::ApplySocketTag(const SocketTag& tag) {}

int WrappedStreamSocket::Read(IOBuffer* buf,
                              int buf_len,
                              CompletionOnceCallback callback) {}

int WrappedStreamSocket::ReadIfReady(IOBuffer* buf,
                                     int buf_len,
                                     CompletionOnceCallback callback) {}

int WrappedStreamSocket::Write(
    IOBuffer* buf,
    int buf_len,
    CompletionOnceCallback callback,
    const NetworkTrafficAnnotationTag& traffic_annotation) {}

int WrappedStreamSocket::SetReceiveBufferSize(int32_t size) {}

int WrappedStreamSocket::SetSendBufferSize(int32_t size) {}

int MockTaggingStreamSocket::Connect(CompletionOnceCallback callback) {}

void MockTaggingStreamSocket::ApplySocketTag(const SocketTag& tag) {}

std::unique_ptr<TransportClientSocket>
MockTaggingClientSocketFactory::CreateTransportClientSocket(
    const AddressList& addresses,
    std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
    NetworkQualityEstimator* network_quality_estimator,
    NetLog* net_log,
    const NetLogSource& source) {}

std::unique_ptr<DatagramClientSocket>
MockTaggingClientSocketFactory::CreateDatagramClientSocket(
    DatagramSocket::BindType bind_type,
    NetLog* net_log,
    const NetLogSource& source) {}

const char kSOCKS4TestHost[] =;
const int kSOCKS4TestPort =;

const char kSOCKS4OkRequestLocalHostPort80[] =;
const int kSOCKS4OkRequestLocalHostPort80Length =;

const char kSOCKS4OkReply[] =;
const int kSOCKS4OkReplyLength =;

const char kSOCKS5TestHost[] =;
const int kSOCKS5TestPort =;

const char kSOCKS5GreetRequest[] =;
const int kSOCKS5GreetRequestLength =;

const char kSOCKS5GreetResponse[] =;
const int kSOCKS5GreetResponseLength =;

const char kSOCKS5OkRequest[] =;
const int kSOCKS5OkRequestLength =;

const char kSOCKS5OkResponse[] =;
const int kSOCKS5OkResponseLength =;

int64_t CountReadBytes(base::span<const MockRead> reads) {}

int64_t CountWriteBytes(base::span<const MockWrite> writes) {}

#if BUILDFLAG(IS_ANDROID)
bool CanGetTaggedBytes() {
  // In Android P, /proc/net/xt_qtaguid/stats is no longer guaranteed to be
  // present, and has been replaced with eBPF Traffic Monitoring in netd. See:
  // https://source.android.com/devices/tech/datausage/ebpf-traffic-monitor
  //
  // To read traffic statistics from netd, apps should use the API
  // NetworkStatsManager.queryDetailsForUidTag(). But this API does not provide
  // statistics for local traffic, only mobile and WiFi traffic, so it would not
  // work in tests that spin up a local server. So for now, GetTaggedBytes is
  // only supported on Android releases older than P.
  return base::android::BuildInfo::GetInstance()->sdk_int() <
         base::android::SDK_VERSION_P;
}

uint64_t GetTaggedBytes(int32_t expected_tag) {
  EXPECT_TRUE(CanGetTaggedBytes());

  // To determine how many bytes the system saw with a particular tag read
  // the /proc/net/xt_qtaguid/stats file which contains the kernel's
  // dump of all the UIDs and their tags sent and received bytes.
  uint64_t bytes = 0;
  std::string contents;
  EXPECT_TRUE(base::ReadFileToString(
      base::FilePath::FromUTF8Unsafe("/proc/net/xt_qtaguid/stats"), &contents));
  for (size_t i = contents.find('\n');  // Skip first line which is headers.
       i != std::string::npos && i < contents.length();) {
    uint64_t tag, rx_bytes;
    uid_t uid;
    int n;
    // Parse out the numbers we care about. For reference here's the column
    // headers:
    // idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes
    // tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets
    // rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes
    // tx_udp_packets tx_other_bytes tx_other_packets
    EXPECT_EQ(sscanf(contents.c_str() + i,
                     "%*d %*s 0x%" SCNx64 " %d %*d %" SCNu64
                     " %*d %*d %*d %*d %*d %*d %*d %*d "
                     "%*d %*d %*d %*d %*d %*d %*d%n",
                     &tag, &uid, &rx_bytes, &n),
              3);
    // If this line matches our UID and |expected_tag| then add it to the total.
    if (uid == getuid() && (int32_t)(tag >> 32) == expected_tag) {
      bytes += rx_bytes;
    }
    // Move |i| to the next line.
    i += n + 1;
  }
  return bytes;
}
#endif

}  // namespace net