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 147 148 149 150 151 152
|
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_
#define COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "net/dns/dns_client.h"
#include "net/dns/dns_config_service.h"
#include "net/socket/socket_test_util.h"
namespace certificate_transparency {
// Mocks DNS requests and responses for a Certificate Transparency (CT) log.
// This is implemented using mock sockets. Call the CreateDnsClient() method to
// get a net::DnsClient wired up to these mock sockets.
// The Expect*() methods must be called from within a GTest test case.
//
// Example Usage:
// // net::DnsClient requires an I/O message loop for async operations.
// base::MessageLoopForIO message_loop;
//
// // Create a mock NetworkChangeNotifier to propagate DNS config.
// std::unique_ptr<net::NetworkChangeNotifier> net_change_notifier(
// net::NetworkChangeNotifier::CreateMock());
//
// MockLogDnsTraffic mock_dns;
// mock_dns.InitializeDnsConfig();
// // Use the Expect* methods to define expected DNS requests and responses.
// mock_dns.ExpectLeafIndexRequestAndResponse(
// "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.",
// "123456");
//
// LogDnsClient log_client(mock_dns.CreateDnsClient(), ...);
// log_client.QueryAuditProof("ct.test", ..., base::Bind(...));
class MockLogDnsTraffic {
public:
MockLogDnsTraffic();
~MockLogDnsTraffic();
// Expect a CT DNS request for the domain |qname|.
// Such a request will receive a DNS response indicating that the error
// specified by |rcode| occurred. See RFC1035, Section 4.1.1 for |rcode|
// values.
// Returns false if any of the arguments are invalid.
WARN_UNUSED_RESULT
bool ExpectRequestAndErrorResponse(base::StringPiece qname, uint8_t rcode);
// Expect a CT DNS request for the domain |qname|.
// Such a request will trigger a socket error of type |error|.
// Returns false if any of the arguments are invalid.
WARN_UNUSED_RESULT
bool ExpectRequestAndSocketError(base::StringPiece qname, net::Error error);
// Expect a CT DNS request for the domain |qname|.
// Such a request will timeout.
// This will reduce the DNS timeout to minimize test duration.
// Returns false if |qname| is invalid.
WARN_UNUSED_RESULT
bool ExpectRequestAndTimeout(base::StringPiece qname);
// Expect a CT DNS request for the domain |qname|.
// Such a request will receive a DNS TXT response containing |txt_strings|.
// Returns false if any of the arguments are invalid.
WARN_UNUSED_RESULT
bool ExpectRequestAndResponse(
base::StringPiece qname,
const std::vector<base::StringPiece>& txt_strings);
// Expect a CT DNS request for the domain |qname|.
// Such a request will receive a DNS response containing |leaf_index|.
// A description of such a request and response can be seen here:
// https://github.com/google/certificate-transparency-rfcs/blob/c8844de6bd0b5d3d16bac79865e6edef533d760b/dns/draft-ct-over-dns.md#hash-query-hashquery
// Returns false if any of the arguments are invalid.
WARN_UNUSED_RESULT
bool ExpectLeafIndexRequestAndResponse(base::StringPiece qname,
uint64_t leaf_index);
// Expect a CT DNS request for the domain |qname|.
// Such a request will receive a DNS response containing the inclusion proof
// nodes between |audit_path_start| and |audit_path_end|.
// A description of such a request and response can be seen here:
// https://github.com/google/certificate-transparency-rfcs/blob/c8844de6bd0b5d3d16bac79865e6edef533d760b/dns/draft-ct-over-dns.md#tree-query-treequery
// Returns false if any of the arguments are invalid.
WARN_UNUSED_RESULT
bool ExpectAuditProofRequestAndResponse(
base::StringPiece qname,
std::vector<std::string>::const_iterator audit_path_start,
std::vector<std::string>::const_iterator audit_path_end);
// Sets the initial DNS config appropriate for testing.
// Requires that net::NetworkChangeNotifier is initialized first.
// The DNS config is propogated to NetworkChangeNotifier::DNSObservers
// asynchronously.
void InitializeDnsConfig();
// Sets the DNS config to |config|.
// Requires that net::NetworkChangeNotifier is initialized first.
// The DNS config is propogated to NetworkChangeNotifier::DNSObservers
// asynchronously.
void SetDnsConfig(const net::DnsConfig& config);
// Creates a DNS client that uses mock sockets.
// It is this DNS client that the expectations will be tested against.
std::unique_ptr<net::DnsClient> CreateDnsClient();
private:
// Allows tests to change socket read mode. Only the LogDnsClient tests should
// need to do so, to ensure consistent behaviour regardless of mode.
friend class LogDnsClientTest;
class MockSocketData;
// Sets whether mock reads should complete synchronously or asynchronously.
// By default, they complete asynchronously.
void SetSocketReadMode(net::IoMode read_mode) {
socket_read_mode_ = read_mode;
}
// Constructs MockSocketData from |args| and adds it to |socket_factory_|.
template <typename... Args>
void EmplaceMockSocketData(Args&&... args);
// Sets the timeout used for DNS queries.
// Requires that net::NetworkChangeNotifier is initialized first.
// The new timeout is propogated to NetworkChangeNotifier::DNSObservers
// asynchronously.
void SetDnsTimeout(const base::TimeDelta& timeout);
// One MockSocketData for each socket that is created. This corresponds to one
// for each DNS request sent.
std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_;
// Provides as many mock sockets as there are entries in |mock_socket_data_|.
net::MockClientSocketFactory socket_factory_;
// Controls whether mock socket reads are asynchronous.
net::IoMode socket_read_mode_;
DISALLOW_COPY_AND_ASSIGN(MockLogDnsTraffic);
};
} // namespace certificate_transparency
#endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_
|