| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/dns/dns_transaction.h" | 5 #include "net/dns/dns_transaction.h" |
| 6 | 6 |
| 7 #include <deque> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/bind.h" | 7 #include "base/bind.h" |
| 11 #include "base/test/test_timeouts.h" | 8 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/time.h" | 9 #include "net/base/big_endian.h" |
| 13 #include "net/dns/dns_protocol.h" | 10 #include "net/base/net_log.h" |
| 14 #include "net/dns/dns_query.h" | 11 #include "net/base/sys_addrinfo.h" |
| 15 #include "net/dns/dns_response.h" | 12 #include "net/dns/dns_response.h" |
| 16 #include "net/dns/dns_session.h" | 13 #include "net/dns/dns_session.h" |
| 17 #include "net/dns/dns_test_util.h" | 14 #include "net/dns/dns_test_util.h" |
| 18 #include "net/socket/socket_test_util.h" | 15 #include "net/socket/socket_test_util.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 17 |
| 18 // TODO(szym): test timeout. |
| 19 // TODO(szym): test server fallback. |
| 20 // TODO(szym): test suffix search. |
| 21 |
| 21 namespace net { | 22 namespace net { |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 // A mock for RandIntCallback that always returns 0. | |
| 26 int ReturnZero(int min, int max) { | |
| 27 return 0; | |
| 28 } | |
| 29 | |
| 30 class DnsTransactionTest : public testing::Test { | 26 class DnsTransactionTest : public testing::Test { |
| 27 public: |
| 28 class TestHelper { |
| 29 public: |
| 30 // If |answer_count| < 0, it is the expected error code. |
| 31 TestHelper(const char* name, |
| 32 uint16 type, |
| 33 const MockWrite& write, |
| 34 const MockRead& read, |
| 35 int answer_count) |
| 36 : qname(name), |
| 37 qtype(type), |
| 38 expected_answer_count(answer_count), |
| 39 completed(false) { |
| 40 writes.push_back(write); |
| 41 reads.push_back(read); |
| 42 ReadBigEndian<uint16>(write.data, &transaction_id); |
| 43 data.reset(new StaticSocketDataProvider(&reads[0], reads.size(), |
| 44 &writes[0], writes.size())); |
| 45 } |
| 46 |
| 47 void MakeRequest(DnsTransactionFactory* client) { |
| 48 EXPECT_EQ(NULL, transaction.get()); |
| 49 transaction = client->CreateTransaction( |
| 50 qname, |
| 51 qtype, |
| 52 base::Bind(&TestHelper::OnTransactionComplete, |
| 53 base::Unretained(this)), |
| 54 BoundNetLog()); |
| 55 EXPECT_EQ(qname, transaction->GetHostname()); |
| 56 EXPECT_EQ(qtype, transaction->GetType()); |
| 57 int rv = transaction->Start(); |
| 58 if (rv != ERR_IO_PENDING) { |
| 59 EXPECT_NE(OK, rv); |
| 60 EXPECT_EQ(expected_answer_count, rv); |
| 61 } |
| 62 } |
| 63 |
| 64 void Cancel() { |
| 65 ASSERT_TRUE(transaction.get() != NULL); |
| 66 transaction.reset(NULL); |
| 67 } |
| 68 |
| 69 void OnTransactionComplete(DnsTransaction* t, |
| 70 int rv, |
| 71 const DnsResponse* response) { |
| 72 EXPECT_FALSE(completed); |
| 73 EXPECT_EQ(transaction.get(), t); |
| 74 |
| 75 if (expected_answer_count >= 0) { |
| 76 EXPECT_EQ(OK, rv); |
| 77 EXPECT_EQ(expected_answer_count, response->answer_count()); |
| 78 |
| 79 DnsRecordParser parser = response->Parser(); |
| 80 DnsResourceRecord record; |
| 81 for (int i = 0; i < expected_answer_count; ++i) { |
| 82 EXPECT_TRUE(parser.ParseRecord(&record)); |
| 83 } |
| 84 EXPECT_TRUE(parser.AtEnd()); |
| 85 |
| 86 } else { |
| 87 EXPECT_EQ(expected_answer_count, rv); |
| 88 EXPECT_EQ(NULL, response); |
| 89 } |
| 90 |
| 91 completed = true; |
| 92 } |
| 93 |
| 94 void CancelOnTransactionComplete(DnsTransaction* req, |
| 95 int rv, |
| 96 const DnsResponse* response) { |
| 97 EXPECT_FALSE(completed); |
| 98 Cancel(); |
| 99 } |
| 100 |
| 101 std::string qname; |
| 102 uint16 qtype; |
| 103 std::vector<MockWrite> writes; |
| 104 std::vector<MockRead> reads; |
| 105 uint16 transaction_id; // Id from first write. |
| 106 scoped_ptr<StaticSocketDataProvider> data; |
| 107 scoped_ptr<DnsTransaction> transaction; |
| 108 int expected_answer_count; |
| 109 |
| 110 bool completed; |
| 111 }; |
| 112 |
| 113 virtual void SetUp() OVERRIDE { |
| 114 helpers_.push_back(new TestHelper( |
| 115 kT0HostName, |
| 116 kT0Qtype, |
| 117 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), |
| 118 arraysize(kT0QueryDatagram)), |
| 119 MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), |
| 120 arraysize(kT0ResponseDatagram)), |
| 121 arraysize(kT0IpAddresses) + 1)); // +1 for CNAME RR |
| 122 |
| 123 helpers_.push_back(new TestHelper( |
| 124 kT1HostName, |
| 125 kT1Qtype, |
| 126 MockWrite(true, reinterpret_cast<const char*>(kT1QueryDatagram), |
| 127 arraysize(kT1QueryDatagram)), |
| 128 MockRead(true, reinterpret_cast<const char*>(kT1ResponseDatagram), |
| 129 arraysize(kT1ResponseDatagram)), |
| 130 arraysize(kT1IpAddresses) + 1)); // +1 for CNAME RR |
| 131 |
| 132 helpers_.push_back(new TestHelper( |
| 133 kT2HostName, |
| 134 kT2Qtype, |
| 135 MockWrite(true, reinterpret_cast<const char*>(kT2QueryDatagram), |
| 136 arraysize(kT2QueryDatagram)), |
| 137 MockRead(true, reinterpret_cast<const char*>(kT2ResponseDatagram), |
| 138 arraysize(kT2ResponseDatagram)), |
| 139 arraysize(kT2IpAddresses) + 1)); // +1 for CNAME RR |
| 140 |
| 141 helpers_.push_back(new TestHelper( |
| 142 kT3HostName, |
| 143 kT3Qtype, |
| 144 MockWrite(true, reinterpret_cast<const char*>(kT3QueryDatagram), |
| 145 arraysize(kT3QueryDatagram)), |
| 146 MockRead(true, reinterpret_cast<const char*>(kT3ResponseDatagram), |
| 147 arraysize(kT3ResponseDatagram)), |
| 148 arraysize(kT3IpAddresses) + 2)); // +2 for CNAME RR |
| 149 |
| 150 CreateFactory(); |
| 151 } |
| 152 |
| 153 void CreateFactory() { |
| 154 MockClientSocketFactory* socket_factory = new MockClientSocketFactory(); |
| 155 |
| 156 transaction_ids_.clear(); |
| 157 for (unsigned i = 0; i < helpers_.size(); ++i) { |
| 158 socket_factory->AddSocketDataProvider(helpers_[i]->data.get()); |
| 159 transaction_ids_.push_back(static_cast<int>(helpers_[i]->transaction_id)); |
| 160 } |
| 161 |
| 162 DnsConfig config; |
| 163 |
| 164 IPEndPoint dns_server; |
| 165 { |
| 166 bool rv = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); |
| 167 EXPECT_TRUE(rv); |
| 168 } |
| 169 config.nameservers.push_back(dns_server); |
| 170 |
| 171 DnsSession* session = new DnsSession( |
| 172 config, |
| 173 socket_factory, |
| 174 base::Bind(&DnsTransactionTest::GetNextId, base::Unretained(this)), |
| 175 NULL /* NetLog */); |
| 176 |
| 177 factory_ = DnsTransactionFactory::CreateFactory(session); |
| 178 } |
| 179 |
| 180 virtual void TearDown() OVERRIDE { |
| 181 STLDeleteElements(&helpers_); |
| 182 } |
| 183 |
| 184 int GetNextId(int min, int max) { |
| 185 EXPECT_FALSE(transaction_ids_.empty()); |
| 186 int id = transaction_ids_.front(); |
| 187 transaction_ids_.pop_front(); |
| 188 EXPECT_GE(id, min); |
| 189 EXPECT_LE(id, max); |
| 190 return id; |
| 191 } |
| 192 |
| 31 protected: | 193 protected: |
| 32 virtual void SetUp() OVERRIDE { | 194 std::vector<TestHelper*> helpers_; |
| 33 callback_ = base::Bind(&DnsTransactionTest::OnTransactionComplete, | 195 std::deque<int> transaction_ids_; |
| 34 base::Unretained(this)); | 196 scoped_ptr<DnsTransactionFactory> factory_; |
| 35 qname_ = std::string(kT0DnsName, arraysize(kT0DnsName)); | |
| 36 // Use long timeout to prevent timing out on slow bots. | |
| 37 ConfigureSession(base::TimeDelta::FromMilliseconds( | |
| 38 TestTimeouts::action_timeout_ms())); | |
| 39 } | |
| 40 | |
| 41 void ConfigureSession(const base::TimeDelta& timeout) { | |
| 42 IPEndPoint dns_server; | |
| 43 bool rv = CreateDnsAddress(kDnsIp, kDnsPort, &dns_server); | |
| 44 ASSERT_TRUE(rv); | |
| 45 | |
| 46 DnsConfig config; | |
| 47 config.nameservers.push_back(dns_server); | |
| 48 config.attempts = 3; | |
| 49 config.timeout = timeout; | |
| 50 | |
| 51 session_ = new DnsSession(config, | |
| 52 new MockClientSocketFactory(), | |
| 53 base::Bind(&ReturnZero), | |
| 54 NULL /* NetLog */); | |
| 55 } | |
| 56 | |
| 57 void StartTransaction() { | |
| 58 transaction_.reset(new DnsTransaction(session_.get(), | |
| 59 qname_, | |
| 60 kT0Qtype, | |
| 61 callback_, | |
| 62 BoundNetLog())); | |
| 63 | |
| 64 int rv0 = transaction_->Start(); | |
| 65 EXPECT_EQ(ERR_IO_PENDING, rv0); | |
| 66 } | |
| 67 | |
| 68 void OnTransactionComplete(DnsTransaction* transaction, int rv) { | |
| 69 EXPECT_EQ(transaction_.get(), transaction); | |
| 70 EXPECT_EQ(qname_, transaction->query()->qname().as_string()); | |
| 71 EXPECT_EQ(kT0Qtype, transaction->query()->qtype()); | |
| 72 rv_ = rv; | |
| 73 MessageLoop::current()->Quit(); | |
| 74 } | |
| 75 | |
| 76 MockClientSocketFactory& factory() { | |
| 77 return *static_cast<MockClientSocketFactory*>(session_->socket_factory()); | |
| 78 } | |
| 79 | |
| 80 int rv() const { return rv_; } | |
| 81 | |
| 82 private: | |
| 83 DnsTransaction::ResultCallback callback_; | |
| 84 std::string qname_; | |
| 85 scoped_refptr<DnsSession> session_; | |
| 86 scoped_ptr<DnsTransaction> transaction_; | |
| 87 | |
| 88 int rv_; | |
| 89 }; | 197 }; |
| 90 | 198 |
| 91 TEST_F(DnsTransactionTest, NormalQueryResponseTest) { | 199 TEST_F(DnsTransactionTest, Lookup) { |
| 92 MockWrite writes0[] = { | 200 helpers_[0]->MakeRequest(factory_.get()); |
| 93 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), | 201 |
| 94 arraysize(kT0QueryDatagram)) | 202 // Wait until result. |
| 95 }; | 203 MessageLoop::current()->RunAllPending(); |
| 96 | 204 |
| 97 MockRead reads0[] = { | 205 EXPECT_TRUE(helpers_[0]->completed); |
| 98 MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), | 206 } |
| 99 arraysize(kT0ResponseDatagram)) | 207 |
| 100 }; | 208 TEST_F(DnsTransactionTest, ConcurrentLookup) { |
| 101 | 209 for (unsigned i = 0; i < helpers_.size(); ++i) { |
| 102 StaticSocketDataProvider data(reads0, arraysize(reads0), | 210 helpers_[i]->MakeRequest(factory_.get()); |
| 103 writes0, arraysize(writes0)); | 211 } |
| 104 factory().AddSocketDataProvider(&data); | 212 |
| 105 | 213 MessageLoop::current()->RunAllPending(); |
| 106 StartTransaction(); | 214 |
| 107 MessageLoop::current()->Run(); | 215 for (unsigned i = 0; i < helpers_.size(); ++i) { |
| 108 | 216 EXPECT_TRUE(helpers_[i]->completed); |
| 109 EXPECT_EQ(OK, rv()); | 217 } |
| 110 // TODO(szym): test fields of |transaction_->response()| | 218 } |
| 111 | 219 |
| 112 EXPECT_TRUE(data.at_read_eof()); | 220 TEST_F(DnsTransactionTest, CancelLookup) { |
| 113 EXPECT_TRUE(data.at_write_eof()); | 221 for (unsigned i = 0; i < helpers_.size(); ++i) { |
| 114 } | 222 helpers_[i]->MakeRequest(factory_.get()); |
| 115 | 223 } |
| 116 TEST_F(DnsTransactionTest, MismatchedQueryResponseTest) { | 224 |
| 117 MockWrite writes0[] = { | 225 helpers_[0]->Cancel(); |
| 118 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), | 226 helpers_[2]->Cancel(); |
| 119 arraysize(kT0QueryDatagram)) | 227 |
| 120 }; | 228 MessageLoop::current()->RunAllPending(); |
| 121 | 229 |
| 122 MockRead reads1[] = { | 230 EXPECT_FALSE(helpers_[0]->completed); |
| 123 MockRead(true, reinterpret_cast<const char*>(kT1ResponseDatagram), | 231 EXPECT_TRUE(helpers_[1]->completed); |
| 124 arraysize(kT1ResponseDatagram)) | 232 EXPECT_FALSE(helpers_[2]->completed); |
| 125 }; | 233 EXPECT_TRUE(helpers_[3]->completed); |
| 126 | 234 } |
| 127 StaticSocketDataProvider data(reads1, arraysize(reads1), | 235 |
| 128 writes0, arraysize(writes0)); | 236 TEST_F(DnsTransactionTest, DestroyClient) { |
| 129 factory().AddSocketDataProvider(&data); | 237 for (unsigned i = 0; i < helpers_.size(); ++i) { |
| 130 | 238 helpers_[i]->MakeRequest(factory_.get()); |
| 131 StartTransaction(); | 239 } |
| 132 MessageLoop::current()->Run(); | 240 |
| 133 | 241 // Destroying the client does not affect running requests. |
| 134 EXPECT_EQ(ERR_DNS_MALFORMED_RESPONSE, rv()); | 242 factory_.reset(NULL); |
| 135 | 243 |
| 136 EXPECT_TRUE(data.at_read_eof()); | 244 MessageLoop::current()->RunAllPending(); |
| 137 EXPECT_TRUE(data.at_write_eof()); | 245 |
| 138 } | 246 for (unsigned i = 0; i < helpers_.size(); ++i) { |
| 139 | 247 EXPECT_TRUE(helpers_[i]->completed); |
| 140 // Test that after the first timeout we do a fresh connection and if we get | 248 } |
| 141 // a response on the new connection, we return it. | 249 } |
| 142 TEST_F(DnsTransactionTest, FirstTimeoutTest) { | 250 |
| 143 MockWrite writes0[] = { | 251 TEST_F(DnsTransactionTest, DestroyRequestFromCallback) { |
| 144 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), | 252 // Custom callback to cancel the completing request. |
| 145 arraysize(kT0QueryDatagram)) | 253 helpers_[0]->transaction = factory_->CreateTransaction( |
| 146 }; | 254 helpers_[0]->qname, |
| 147 | 255 helpers_[0]->qtype, |
| 148 MockRead reads0[] = { | 256 base::Bind(&TestHelper::CancelOnTransactionComplete, |
| 149 MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), | 257 base::Unretained(helpers_[0])), |
| 150 arraysize(kT0ResponseDatagram)) | 258 BoundNetLog()); |
| 151 }; | 259 |
| 152 | 260 int rv = helpers_[0]->transaction->Start(); |
| 153 scoped_refptr<DelayedSocketData> socket0_data( | 261 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 154 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); | 262 |
| 155 scoped_refptr<DelayedSocketData> socket1_data( | 263 for (unsigned i = 1; i < helpers_.size(); ++i) { |
| 156 new DelayedSocketData(0, reads0, arraysize(reads0), | 264 helpers_[i]->MakeRequest(factory_.get()); |
| 157 writes0, arraysize(writes0))); | 265 } |
| 158 | 266 |
| 159 // Use short timeout to speed up the test. | 267 MessageLoop::current()->RunAllPending(); |
| 160 ConfigureSession(base::TimeDelta::FromMilliseconds( | 268 |
| 161 TestTimeouts::tiny_timeout_ms())); | 269 EXPECT_FALSE(helpers_[0]->completed); |
| 162 factory().AddSocketDataProvider(socket0_data.get()); | 270 for (unsigned i = 1; i < helpers_.size(); ++i) { |
| 163 factory().AddSocketDataProvider(socket1_data.get()); | 271 EXPECT_TRUE(helpers_[i]->completed); |
| 164 | 272 } |
| 165 StartTransaction(); | 273 } |
| 166 | 274 |
| 167 MessageLoop::current()->Run(); | 275 TEST_F(DnsTransactionTest, HandleFailure) { |
| 168 | 276 STLDeleteElements(&helpers_); |
| 169 EXPECT_EQ(OK, rv()); | 277 // Wrong question. |
| 170 | 278 helpers_.push_back(new TestHelper( |
| 171 EXPECT_TRUE(socket0_data->at_read_eof()); | 279 kT0HostName, |
| 172 EXPECT_TRUE(socket0_data->at_write_eof()); | 280 kT0Qtype, |
| 173 EXPECT_TRUE(socket1_data->at_read_eof()); | 281 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), |
| 174 EXPECT_TRUE(socket1_data->at_write_eof()); | 282 arraysize(kT0QueryDatagram)), |
| 175 EXPECT_EQ(2u, factory().udp_client_sockets().size()); | 283 MockRead(true, reinterpret_cast<const char*>(kT1ResponseDatagram), |
| 176 } | 284 arraysize(kT1ResponseDatagram)), |
| 177 | 285 ERR_DNS_MALFORMED_RESPONSE)); |
| 178 // Test that after the first timeout we do a fresh connection, and after | 286 |
| 179 // the second timeout we do another fresh connection, and if we get a | 287 // Response with NXDOMAIN. |
| 180 // response on the second connection, we return it. | 288 uint8 nxdomain_response[arraysize(kT0QueryDatagram)]; |
| 181 TEST_F(DnsTransactionTest, SecondTimeoutTest) { | 289 memcpy(nxdomain_response, kT0QueryDatagram, arraysize(nxdomain_response)); |
| 182 MockWrite writes0[] = { | 290 nxdomain_response[2] &= 0x80; // Response bit. |
| 183 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), | 291 nxdomain_response[3] &= 0x03; // NXDOMAIN bit. |
| 184 arraysize(kT0QueryDatagram)) | 292 helpers_.push_back(new TestHelper( |
| 185 }; | 293 kT0HostName, |
| 186 | 294 kT0Qtype, |
| 187 MockRead reads0[] = { | 295 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), |
| 188 MockRead(true, reinterpret_cast<const char*>(kT0ResponseDatagram), | 296 arraysize(kT0QueryDatagram)), |
| 189 arraysize(kT0ResponseDatagram)) | 297 MockRead(true, reinterpret_cast<const char*>(nxdomain_response), |
| 190 }; | 298 arraysize(nxdomain_response)), |
| 191 | 299 ERR_NAME_NOT_RESOLVED)); |
| 192 scoped_refptr<DelayedSocketData> socket0_data( | 300 |
| 193 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); | 301 CreateFactory(); |
| 194 scoped_refptr<DelayedSocketData> socket1_data( | 302 |
| 195 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); | 303 for (unsigned i = 0; i < helpers_.size(); ++i) { |
| 196 scoped_refptr<DelayedSocketData> socket2_data( | 304 helpers_[i]->MakeRequest(factory_.get()); |
| 197 new DelayedSocketData(0, reads0, arraysize(reads0), | 305 } |
| 198 writes0, arraysize(writes0))); | 306 |
| 199 | 307 MessageLoop::current()->RunAllPending(); |
| 200 // Use short timeout to speed up the test. | 308 |
| 201 ConfigureSession(base::TimeDelta::FromMilliseconds( | 309 for (unsigned i = 0; i < helpers_.size(); ++i) { |
| 202 TestTimeouts::tiny_timeout_ms())); | 310 EXPECT_TRUE(helpers_[i]->completed); |
| 203 factory().AddSocketDataProvider(socket0_data.get()); | 311 } |
| 204 factory().AddSocketDataProvider(socket1_data.get()); | |
| 205 factory().AddSocketDataProvider(socket2_data.get()); | |
| 206 | |
| 207 StartTransaction(); | |
| 208 | |
| 209 MessageLoop::current()->Run(); | |
| 210 | |
| 211 EXPECT_EQ(OK, rv()); | |
| 212 | |
| 213 EXPECT_TRUE(socket0_data->at_read_eof()); | |
| 214 EXPECT_TRUE(socket0_data->at_write_eof()); | |
| 215 EXPECT_TRUE(socket1_data->at_read_eof()); | |
| 216 EXPECT_TRUE(socket1_data->at_write_eof()); | |
| 217 EXPECT_TRUE(socket2_data->at_read_eof()); | |
| 218 EXPECT_TRUE(socket2_data->at_write_eof()); | |
| 219 EXPECT_EQ(3u, factory().udp_client_sockets().size()); | |
| 220 } | |
| 221 | |
| 222 // Test that after the first timeout we do a fresh connection, and after | |
| 223 // the second timeout we do another fresh connection and after the third | |
| 224 // timeout we give up and return a timeout error. | |
| 225 TEST_F(DnsTransactionTest, ThirdTimeoutTest) { | |
| 226 MockWrite writes0[] = { | |
| 227 MockWrite(true, reinterpret_cast<const char*>(kT0QueryDatagram), | |
| 228 arraysize(kT0QueryDatagram)) | |
| 229 }; | |
| 230 | |
| 231 scoped_refptr<DelayedSocketData> socket0_data( | |
| 232 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); | |
| 233 scoped_refptr<DelayedSocketData> socket1_data( | |
| 234 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); | |
| 235 scoped_refptr<DelayedSocketData> socket2_data( | |
| 236 new DelayedSocketData(2, NULL, 0, writes0, arraysize(writes0))); | |
| 237 | |
| 238 // Use short timeout to speed up the test. | |
| 239 ConfigureSession(base::TimeDelta::FromMilliseconds( | |
| 240 TestTimeouts::tiny_timeout_ms())); | |
| 241 factory().AddSocketDataProvider(socket0_data.get()); | |
| 242 factory().AddSocketDataProvider(socket1_data.get()); | |
| 243 factory().AddSocketDataProvider(socket2_data.get()); | |
| 244 | |
| 245 StartTransaction(); | |
| 246 | |
| 247 MessageLoop::current()->Run(); | |
| 248 | |
| 249 EXPECT_EQ(ERR_DNS_TIMED_OUT, rv()); | |
| 250 | |
| 251 EXPECT_TRUE(socket0_data->at_read_eof()); | |
| 252 EXPECT_TRUE(socket0_data->at_write_eof()); | |
| 253 EXPECT_TRUE(socket1_data->at_read_eof()); | |
| 254 EXPECT_TRUE(socket1_data->at_write_eof()); | |
| 255 EXPECT_TRUE(socket2_data->at_read_eof()); | |
| 256 EXPECT_TRUE(socket2_data->at_write_eof()); | |
| 257 EXPECT_EQ(3u, factory().udp_client_sockets().size()); | |
| 258 } | 312 } |
| 259 | 313 |
| 260 } // namespace | 314 } // namespace |
| 261 | 315 |
| 262 } // namespace net | 316 } // namespace net |
| 317 |
| OLD | NEW |