robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_ |
| 6 | #define COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_ |
| 7 | |
| 8 | #include <stdint.h> |
| 9 | |
| 10 | #include <memory> |
| 11 | #include <string> |
| 12 | #include <vector> |
| 13 | |
robpercival | 7038ecd | 2016-10-20 17:05:49 | [diff] [blame] | 14 | #include "base/compiler_specific.h" |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 15 | #include "base/macros.h" |
| 16 | #include "base/strings/string_piece.h" |
| 17 | #include "net/dns/dns_client.h" |
| 18 | #include "net/dns/dns_config_service.h" |
| 19 | #include "net/socket/socket_test_util.h" |
| 20 | |
| 21 | namespace certificate_transparency { |
| 22 | |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 23 | // Mocks DNS requests and responses for a Certificate Transparency (CT) log. |
| 24 | // This is implemented using mock sockets. Call the CreateDnsClient() method to |
| 25 | // get a net::DnsClient wired up to these mock sockets. |
| 26 | // The Expect*() methods must be called from within a GTest test case. |
robpercival | 3106d3f | 2016-10-18 08:40:32 | [diff] [blame] | 27 | // |
| 28 | // Example Usage: |
| 29 | // // net::DnsClient requires an I/O message loop for async operations. |
| 30 | // base::MessageLoopForIO message_loop; |
| 31 | // |
| 32 | // // Create a mock NetworkChangeNotifier to propagate DNS config. |
| 33 | // std::unique_ptr<net::NetworkChangeNotifier> net_change_notifier( |
| 34 | // net::NetworkChangeNotifier::CreateMock()); |
| 35 | // |
| 36 | // MockLogDnsTraffic mock_dns; |
| 37 | // mock_dns.InitializeDnsConfig(); |
| 38 | // // Use the Expect* methods to define expected DNS requests and responses. |
| 39 | // mock_dns.ExpectLeafIndexRequestAndResponse( |
| 40 | // "D4S6DSV2J743QJZEQMH4UYHEYK7KRQ5JIQOCPMFUHZVJNFGHXACA.hash.ct.test.", |
| 41 | // "123456"); |
| 42 | // |
| 43 | // LogDnsClient log_client(mock_dns.CreateDnsClient(), ...); |
| 44 | // log_client.QueryAuditProof("ct.test", ..., base::Bind(...)); |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 45 | class MockLogDnsTraffic { |
| 46 | public: |
| 47 | MockLogDnsTraffic(); |
| 48 | ~MockLogDnsTraffic(); |
| 49 | |
| 50 | // Expect a CT DNS request for the domain |qname|. |
| 51 | // Such a request will receive a DNS response indicating that the error |
| 52 | // specified by |rcode| occurred. See RFC1035, Section 4.1.1 for |rcode| |
| 53 | // values. |
robpercival | 7038ecd | 2016-10-20 17:05:49 | [diff] [blame] | 54 | // Returns false if any of the arguments are invalid. |
| 55 | WARN_UNUSED_RESULT |
| 56 | bool ExpectRequestAndErrorResponse(base::StringPiece qname, uint8_t rcode); |
robpercival | 3106d3f | 2016-10-18 08:40:32 | [diff] [blame] | 57 | |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 58 | // Expect a CT DNS request for the domain |qname|. |
robpercival | 3106d3f | 2016-10-18 08:40:32 | [diff] [blame] | 59 | // Such a request will trigger a socket error of type |error|. |
robpercival | 7038ecd | 2016-10-20 17:05:49 | [diff] [blame] | 60 | // Returns false if any of the arguments are invalid. |
| 61 | WARN_UNUSED_RESULT |
| 62 | bool ExpectRequestAndSocketError(base::StringPiece qname, net::Error error); |
robpercival | 3106d3f | 2016-10-18 08:40:32 | [diff] [blame] | 63 | |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 64 | // Expect a CT DNS request for the domain |qname|. |
| 65 | // Such a request will timeout. |
| 66 | // This will reduce the DNS timeout to minimize test duration. |
robpercival | 7038ecd | 2016-10-20 17:05:49 | [diff] [blame] | 67 | // Returns false if |qname| is invalid. |
| 68 | WARN_UNUSED_RESULT |
| 69 | bool ExpectRequestAndTimeout(base::StringPiece qname); |
robpercival | 3106d3f | 2016-10-18 08:40:32 | [diff] [blame] | 70 | |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 71 | // Expect a CT DNS request for the domain |qname|. |
robpercival | 9dc75a8 | 2016-10-05 13:29:44 | [diff] [blame] | 72 | // Such a request will receive a DNS TXT response containing |txt_strings|. |
robpercival | 7038ecd | 2016-10-20 17:05:49 | [diff] [blame] | 73 | // Returns false if any of the arguments are invalid. |
| 74 | WARN_UNUSED_RESULT |
| 75 | bool ExpectRequestAndResponse( |
| 76 | base::StringPiece qname, |
| 77 | const std::vector<base::StringPiece>& txt_strings); |
| 78 | |
robpercival | 9dc75a8 | 2016-10-05 13:29:44 | [diff] [blame] | 79 | // Expect a CT DNS request for the domain |qname|. |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 80 | // Such a request will receive a DNS response containing |leaf_index|. |
| 81 | // A description of such a request and response can be seen here: |
| 82 | // https://github.com/google/certificate-transparency-rfcs/blob/c8844de6bd0b5d3d16bac79865e6edef533d760b/dns/draft-ct-over-dns.md#hash-query-hashquery |
robpercival | 7038ecd | 2016-10-20 17:05:49 | [diff] [blame] | 83 | // Returns false if any of the arguments are invalid. |
| 84 | WARN_UNUSED_RESULT |
| 85 | bool ExpectLeafIndexRequestAndResponse(base::StringPiece qname, |
robpercival | 9dc75a8 | 2016-10-05 13:29:44 | [diff] [blame] | 86 | uint64_t leaf_index); |
robpercival | 7038ecd | 2016-10-20 17:05:49 | [diff] [blame] | 87 | |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 88 | // Expect a CT DNS request for the domain |qname|. |
| 89 | // Such a request will receive a DNS response containing the inclusion proof |
| 90 | // nodes between |audit_path_start| and |audit_path_end|. |
| 91 | // A description of such a request and response can be seen here: |
| 92 | // https://github.com/google/certificate-transparency-rfcs/blob/c8844de6bd0b5d3d16bac79865e6edef533d760b/dns/draft-ct-over-dns.md#tree-query-treequery |
robpercival | 7038ecd | 2016-10-20 17:05:49 | [diff] [blame] | 93 | // Returns false if any of the arguments are invalid. |
| 94 | WARN_UNUSED_RESULT |
| 95 | bool ExpectAuditProofRequestAndResponse( |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 96 | base::StringPiece qname, |
| 97 | std::vector<std::string>::const_iterator audit_path_start, |
| 98 | std::vector<std::string>::const_iterator audit_path_end); |
| 99 | |
| 100 | // Sets the initial DNS config appropriate for testing. |
| 101 | // Requires that net::NetworkChangeNotifier is initialized first. |
| 102 | // The DNS config is propogated to NetworkChangeNotifier::DNSObservers |
| 103 | // asynchronously. |
| 104 | void InitializeDnsConfig(); |
| 105 | |
| 106 | // Sets the DNS config to |config|. |
| 107 | // Requires that net::NetworkChangeNotifier is initialized first. |
| 108 | // The DNS config is propogated to NetworkChangeNotifier::DNSObservers |
| 109 | // asynchronously. |
| 110 | void SetDnsConfig(const net::DnsConfig& config); |
| 111 | |
| 112 | // Creates a DNS client that uses mock sockets. |
| 113 | // It is this DNS client that the expectations will be tested against. |
| 114 | std::unique_ptr<net::DnsClient> CreateDnsClient(); |
| 115 | |
robpercival | 3106d3f | 2016-10-18 08:40:32 | [diff] [blame] | 116 | private: |
| 117 | // Allows tests to change socket read mode. Only the LogDnsClient tests should |
| 118 | // need to do so, to ensure consistent behaviour regardless of mode. |
| 119 | friend class LogDnsClientTest; |
| 120 | |
| 121 | class MockSocketData; |
| 122 | |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 123 | // Sets whether mock reads should complete synchronously or asynchronously. |
robpercival | 3106d3f | 2016-10-18 08:40:32 | [diff] [blame] | 124 | // By default, they complete asynchronously. |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 125 | void SetSocketReadMode(net::IoMode read_mode) { |
| 126 | socket_read_mode_ = read_mode; |
| 127 | } |
| 128 | |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 129 | // Constructs MockSocketData from |args| and adds it to |socket_factory_|. |
| 130 | template <typename... Args> |
| 131 | void EmplaceMockSocketData(Args&&... args); |
| 132 | |
| 133 | // Sets the timeout used for DNS queries. |
| 134 | // Requires that net::NetworkChangeNotifier is initialized first. |
| 135 | // The new timeout is propogated to NetworkChangeNotifier::DNSObservers |
| 136 | // asynchronously. |
| 137 | void SetDnsTimeout(const base::TimeDelta& timeout); |
| 138 | |
| 139 | // One MockSocketData for each socket that is created. This corresponds to one |
| 140 | // for each DNS request sent. |
robpercival | 3106d3f | 2016-10-18 08:40:32 | [diff] [blame] | 141 | std::vector<std::unique_ptr<MockSocketData>> mock_socket_data_; |
robpercival | 6e7096f | 2016-07-25 13:34:00 | [diff] [blame] | 142 | // Provides as many mock sockets as there are entries in |mock_socket_data_|. |
| 143 | net::MockClientSocketFactory socket_factory_; |
| 144 | // Controls whether mock socket reads are asynchronous. |
| 145 | net::IoMode socket_read_mode_; |
| 146 | |
| 147 | DISALLOW_COPY_AND_ASSIGN(MockLogDnsTraffic); |
| 148 | }; |
| 149 | |
| 150 | } // namespace certificate_transparency |
| 151 | |
| 152 | #endif // COMPONENTS_CERTIFICATE_TRANSPARENCY_MOCK_LOG_DNS_TRAFFIC_H_ |