Landing Recent QUIC changes until 8/19/2015 17:00 UTC.
[chromium-blink-merge.git] / net / ssl / channel_id_service_unittest.cc
blob2a2ec962d50a2fa3d41f059bb826ee6a2390e020
1 // Copyright 2014 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.
5 #include "net/ssl/channel_id_service.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/location.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/task_runner.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "crypto/ec_private_key.h"
19 #include "net/base/net_errors.h"
20 #include "net/base/test_completion_callback.h"
21 #include "net/cert/asn1_util.h"
22 #include "net/cert/x509_certificate.h"
23 #include "net/ssl/default_channel_id_store.h"
24 #include "net/test/channel_id_test_util.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 namespace net {
29 namespace {
31 void FailTest(int /* result */) {
32 FAIL();
35 // Simple task runner that refuses to actually post any tasks. This simulates
36 // a TaskRunner that has been shutdown, by returning false for any attempt to
37 // add new tasks.
38 class FailingTaskRunner : public base::TaskRunner {
39 public:
40 FailingTaskRunner() {}
42 bool PostDelayedTask(const tracked_objects::Location& from_here,
43 const base::Closure& task,
44 base::TimeDelta delay) override {
45 return false;
48 bool RunsTasksOnCurrentThread() const override { return true; }
50 protected:
51 ~FailingTaskRunner() override {}
53 private:
54 DISALLOW_COPY_AND_ASSIGN(FailingTaskRunner);
57 class MockChannelIDStoreWithAsyncGet
58 : public DefaultChannelIDStore {
59 public:
60 MockChannelIDStoreWithAsyncGet()
61 : DefaultChannelIDStore(NULL), channel_id_count_(0) {}
63 int GetChannelID(const std::string& server_identifier,
64 scoped_ptr<crypto::ECPrivateKey>* key_result,
65 const GetChannelIDCallback& callback) override;
67 void SetChannelID(scoped_ptr<ChannelID> channel_id) override {
68 channel_id_count_ = 1;
71 int GetChannelIDCount() override { return channel_id_count_; }
73 void CallGetChannelIDCallbackWithResult(int err, crypto::ECPrivateKey* key);
75 private:
76 GetChannelIDCallback callback_;
77 std::string server_identifier_;
78 int channel_id_count_;
81 int MockChannelIDStoreWithAsyncGet::GetChannelID(
82 const std::string& server_identifier,
83 scoped_ptr<crypto::ECPrivateKey>* key_result,
84 const GetChannelIDCallback& callback) {
85 server_identifier_ = server_identifier;
86 callback_ = callback;
87 // Reset the cert count, it'll get incremented in either SetChannelID or
88 // CallGetChannelIDCallbackWithResult.
89 channel_id_count_ = 0;
90 // Do nothing else: the results to be provided will be specified through
91 // CallGetChannelIDCallbackWithResult.
92 return ERR_IO_PENDING;
95 void MockChannelIDStoreWithAsyncGet::CallGetChannelIDCallbackWithResult(
96 int err,
97 crypto::ECPrivateKey* key) {
98 if (err == OK)
99 channel_id_count_ = 1;
100 base::ThreadTaskRunnerHandle::Get()->PostTask(
101 FROM_HERE,
102 base::Bind(callback_, err, server_identifier_,
103 base::Passed(make_scoped_ptr(key ? key->Copy() : nullptr))));
106 class ChannelIDServiceTest : public testing::Test {
107 public:
108 ChannelIDServiceTest()
109 : service_(new ChannelIDService(new DefaultChannelIDStore(NULL),
110 base::ThreadTaskRunnerHandle::Get())) {}
112 protected:
113 scoped_ptr<ChannelIDService> service_;
116 TEST_F(ChannelIDServiceTest, GetDomainForHost) {
117 EXPECT_EQ("google.com",
118 ChannelIDService::GetDomainForHost("google.com"));
119 EXPECT_EQ("google.com",
120 ChannelIDService::GetDomainForHost("www.google.com"));
121 EXPECT_EQ("foo.appspot.com",
122 ChannelIDService::GetDomainForHost("foo.appspot.com"));
123 EXPECT_EQ("bar.appspot.com",
124 ChannelIDService::GetDomainForHost("foo.bar.appspot.com"));
125 EXPECT_EQ("appspot.com",
126 ChannelIDService::GetDomainForHost("appspot.com"));
127 EXPECT_EQ("google.com",
128 ChannelIDService::GetDomainForHost("www.mail.google.com"));
129 EXPECT_EQ("goto",
130 ChannelIDService::GetDomainForHost("goto"));
131 EXPECT_EQ("127.0.0.1",
132 ChannelIDService::GetDomainForHost("127.0.0.1"));
135 TEST_F(ChannelIDServiceTest, GetCacheMiss) {
136 std::string host("encrypted.google.com");
138 int error;
139 TestCompletionCallback callback;
140 ChannelIDService::Request request;
142 // Synchronous completion, because the store is initialized.
143 scoped_ptr<crypto::ECPrivateKey> key;
144 EXPECT_EQ(0, service_->channel_id_count());
145 error = service_->GetChannelID(host, &key, callback.callback(), &request);
146 EXPECT_EQ(ERR_FILE_NOT_FOUND, error);
147 EXPECT_FALSE(request.is_active());
148 EXPECT_EQ(0, service_->channel_id_count());
149 EXPECT_FALSE(key);
152 TEST_F(ChannelIDServiceTest, CacheHit) {
153 std::string host("encrypted.google.com");
155 int error;
156 TestCompletionCallback callback;
157 ChannelIDService::Request request;
159 // Asynchronous completion.
160 scoped_ptr<crypto::ECPrivateKey> key1;
161 EXPECT_EQ(0, service_->channel_id_count());
162 error = service_->GetOrCreateChannelID(host, &key1, callback.callback(),
163 &request);
164 EXPECT_EQ(ERR_IO_PENDING, error);
165 EXPECT_TRUE(request.is_active());
166 error = callback.WaitForResult();
167 EXPECT_EQ(OK, error);
168 EXPECT_EQ(1, service_->channel_id_count());
169 EXPECT_TRUE(key1);
170 EXPECT_FALSE(request.is_active());
172 // Synchronous completion.
173 scoped_ptr<crypto::ECPrivateKey> key2;
174 error = service_->GetOrCreateChannelID(host, &key2, callback.callback(),
175 &request);
176 EXPECT_FALSE(request.is_active());
177 EXPECT_EQ(OK, error);
178 EXPECT_EQ(1, service_->channel_id_count());
179 EXPECT_TRUE(KeysEqual(key1.get(), key2.get()));
181 // Synchronous get.
182 scoped_ptr<crypto::ECPrivateKey> key3;
183 error = service_->GetChannelID(host, &key3, callback.callback(), &request);
184 EXPECT_FALSE(request.is_active());
185 EXPECT_EQ(OK, error);
186 EXPECT_EQ(1, service_->channel_id_count());
187 EXPECT_TRUE(KeysEqual(key1.get(), key3.get()));
189 EXPECT_EQ(3u, service_->requests());
190 EXPECT_EQ(2u, service_->key_store_hits());
191 EXPECT_EQ(0u, service_->inflight_joins());
194 TEST_F(ChannelIDServiceTest, StoreChannelIDs) {
195 int error;
196 TestCompletionCallback callback;
197 ChannelIDService::Request request;
199 std::string host1("encrypted.google.com");
200 scoped_ptr<crypto::ECPrivateKey> key1;
201 EXPECT_EQ(0, service_->channel_id_count());
202 error = service_->GetOrCreateChannelID(host1, &key1, callback.callback(),
203 &request);
204 EXPECT_EQ(ERR_IO_PENDING, error);
205 EXPECT_TRUE(request.is_active());
206 error = callback.WaitForResult();
207 EXPECT_EQ(OK, error);
208 EXPECT_EQ(1, service_->channel_id_count());
210 std::string host2("www.verisign.com");
211 scoped_ptr<crypto::ECPrivateKey> key2;
212 error = service_->GetOrCreateChannelID(host2, &key2, callback.callback(),
213 &request);
214 EXPECT_EQ(ERR_IO_PENDING, error);
215 EXPECT_TRUE(request.is_active());
216 error = callback.WaitForResult();
217 EXPECT_EQ(OK, error);
218 EXPECT_EQ(2, service_->channel_id_count());
220 std::string host3("www.twitter.com");
221 scoped_ptr<crypto::ECPrivateKey> key3;
222 error = service_->GetOrCreateChannelID(host3, &key3, callback.callback(),
223 &request);
224 EXPECT_EQ(ERR_IO_PENDING, error);
225 EXPECT_TRUE(request.is_active());
226 error = callback.WaitForResult();
227 EXPECT_EQ(OK, error);
228 EXPECT_EQ(3, service_->channel_id_count());
230 EXPECT_FALSE(KeysEqual(key1.get(), key2.get()));
231 EXPECT_FALSE(KeysEqual(key1.get(), key3.get()));
232 EXPECT_FALSE(KeysEqual(key2.get(), key3.get()));
235 // Tests an inflight join.
236 TEST_F(ChannelIDServiceTest, InflightJoin) {
237 std::string host("encrypted.google.com");
238 int error;
240 scoped_ptr<crypto::ECPrivateKey> key1;
241 TestCompletionCallback callback1;
242 ChannelIDService::Request request1;
244 scoped_ptr<crypto::ECPrivateKey> key2;
245 TestCompletionCallback callback2;
246 ChannelIDService::Request request2;
248 error = service_->GetOrCreateChannelID(host, &key1, callback1.callback(),
249 &request1);
250 EXPECT_EQ(ERR_IO_PENDING, error);
251 EXPECT_TRUE(request1.is_active());
252 // Should join with the original request.
253 error = service_->GetOrCreateChannelID(host, &key2, callback2.callback(),
254 &request2);
255 EXPECT_EQ(ERR_IO_PENDING, error);
256 EXPECT_TRUE(request2.is_active());
258 error = callback1.WaitForResult();
259 EXPECT_EQ(OK, error);
260 error = callback2.WaitForResult();
261 EXPECT_EQ(OK, error);
263 EXPECT_EQ(2u, service_->requests());
264 EXPECT_EQ(0u, service_->key_store_hits());
265 EXPECT_EQ(1u, service_->inflight_joins());
266 EXPECT_EQ(1u, service_->workers_created());
269 // Tests an inflight join of a Get request to a GetOrCreate request.
270 TEST_F(ChannelIDServiceTest, InflightJoinGetOrCreateAndGet) {
271 std::string host("encrypted.google.com");
272 int error;
274 scoped_ptr<crypto::ECPrivateKey> key1;
275 TestCompletionCallback callback1;
276 ChannelIDService::Request request1;
278 scoped_ptr<crypto::ECPrivateKey> key2;
279 TestCompletionCallback callback2;
280 ChannelIDService::Request request2;
282 error = service_->GetOrCreateChannelID(host, &key1, callback1.callback(),
283 &request1);
284 EXPECT_EQ(ERR_IO_PENDING, error);
285 EXPECT_TRUE(request1.is_active());
286 // Should join with the original request.
287 error = service_->GetChannelID(host, &key2, callback2.callback(), &request2);
288 EXPECT_EQ(ERR_IO_PENDING, error);
289 EXPECT_TRUE(request2.is_active());
291 error = callback1.WaitForResult();
292 EXPECT_EQ(OK, error);
293 error = callback2.WaitForResult();
294 EXPECT_EQ(OK, error);
295 EXPECT_TRUE(KeysEqual(key1.get(), key2.get()));
297 EXPECT_EQ(2u, service_->requests());
298 EXPECT_EQ(0u, service_->key_store_hits());
299 EXPECT_EQ(1u, service_->inflight_joins());
300 EXPECT_EQ(1u, service_->workers_created());
303 // Tests that the callback of a canceled request is never made.
304 TEST_F(ChannelIDServiceTest, CancelRequest) {
305 std::string host("encrypted.google.com");
306 scoped_ptr<crypto::ECPrivateKey> key;
307 int error;
308 ChannelIDService::Request request;
310 error = service_->GetOrCreateChannelID(host, &key, base::Bind(&FailTest),
311 &request);
312 EXPECT_EQ(ERR_IO_PENDING, error);
313 EXPECT_TRUE(request.is_active());
314 request.Cancel();
315 EXPECT_FALSE(request.is_active());
317 // Wait for reply from ChannelIDServiceWorker to be posted back to the
318 // ChannelIDService.
319 base::MessageLoop::current()->RunUntilIdle();
321 // Even though the original request was cancelled, the service will still
322 // store the result, it just doesn't call the callback.
323 EXPECT_EQ(1, service_->channel_id_count());
326 // Tests that destructing the Request cancels the request.
327 TEST_F(ChannelIDServiceTest, CancelRequestByHandleDestruction) {
328 std::string host("encrypted.google.com");
329 scoped_ptr<crypto::ECPrivateKey> key;
330 int error;
331 scoped_ptr<ChannelIDService::Request> request(
332 new ChannelIDService::Request());
334 error = service_->GetOrCreateChannelID(host, &key, base::Bind(&FailTest),
335 request.get());
336 EXPECT_EQ(ERR_IO_PENDING, error);
337 EXPECT_TRUE(request->is_active());
339 // Delete the Request object.
340 request.reset();
342 // Wait for reply from ChannelIDServiceWorker to be posted back to the
343 // ChannelIDService.
344 base::MessageLoop::current()->RunUntilIdle();
346 // Even though the original request was cancelled, the service will still
347 // store the result, it just doesn't call the callback.
348 EXPECT_EQ(1, service_->channel_id_count());
351 TEST_F(ChannelIDServiceTest, DestructionWithPendingRequest) {
352 std::string host("encrypted.google.com");
353 scoped_ptr<crypto::ECPrivateKey> key;
354 int error;
355 ChannelIDService::Request request;
357 error = service_->GetOrCreateChannelID(host, &key, base::Bind(&FailTest),
358 &request);
359 EXPECT_EQ(ERR_IO_PENDING, error);
360 EXPECT_TRUE(request.is_active());
362 // Cancel request and destroy the ChannelIDService.
363 request.Cancel();
364 service_.reset();
366 // ChannelIDServiceWorker should not post anything back to the
367 // non-existent ChannelIDService, but run the loop just to be sure it
368 // doesn't.
369 base::MessageLoop::current()->RunUntilIdle();
371 // If we got here without crashing or a valgrind error, it worked.
374 // Tests that shutting down the sequenced worker pool and then making new
375 // requests gracefully fails.
376 // This is a regression test for http://crbug.com/236387
377 TEST_F(ChannelIDServiceTest, RequestAfterPoolShutdown) {
378 scoped_refptr<FailingTaskRunner> task_runner(new FailingTaskRunner);
379 service_.reset(new ChannelIDService(
380 new DefaultChannelIDStore(NULL), task_runner));
382 // Make a request that will force synchronous completion.
383 std::string host("encrypted.google.com");
384 scoped_ptr<crypto::ECPrivateKey> key;
385 int error;
386 ChannelIDService::Request request;
388 error = service_->GetOrCreateChannelID(host, &key, base::Bind(&FailTest),
389 &request);
390 // If we got here without crashing or a valgrind error, it worked.
391 ASSERT_EQ(ERR_INSUFFICIENT_RESOURCES, error);
392 EXPECT_FALSE(request.is_active());
395 // Tests that simultaneous creation of different certs works.
396 TEST_F(ChannelIDServiceTest, SimultaneousCreation) {
397 int error;
399 std::string host1("encrypted.google.com");
400 scoped_ptr<crypto::ECPrivateKey> key1;
401 TestCompletionCallback callback1;
402 ChannelIDService::Request request1;
404 std::string host2("foo.com");
405 scoped_ptr<crypto::ECPrivateKey> key2;
406 TestCompletionCallback callback2;
407 ChannelIDService::Request request2;
409 std::string host3("bar.com");
410 scoped_ptr<crypto::ECPrivateKey> key3;
411 TestCompletionCallback callback3;
412 ChannelIDService::Request request3;
414 error = service_->GetOrCreateChannelID(host1, &key1, callback1.callback(),
415 &request1);
416 EXPECT_EQ(ERR_IO_PENDING, error);
417 EXPECT_TRUE(request1.is_active());
419 error = service_->GetOrCreateChannelID(host2, &key2, callback2.callback(),
420 &request2);
421 EXPECT_EQ(ERR_IO_PENDING, error);
422 EXPECT_TRUE(request2.is_active());
424 error = service_->GetOrCreateChannelID(host3, &key3, callback3.callback(),
425 &request3);
426 EXPECT_EQ(ERR_IO_PENDING, error);
427 EXPECT_TRUE(request3.is_active());
429 error = callback1.WaitForResult();
430 EXPECT_EQ(OK, error);
431 EXPECT_TRUE(key1);
433 error = callback2.WaitForResult();
434 EXPECT_EQ(OK, error);
435 EXPECT_TRUE(key2);
437 error = callback3.WaitForResult();
438 EXPECT_EQ(OK, error);
439 EXPECT_TRUE(key3);
441 EXPECT_FALSE(KeysEqual(key1.get(), key2.get()));
442 EXPECT_FALSE(KeysEqual(key1.get(), key3.get()));
443 EXPECT_FALSE(KeysEqual(key2.get(), key3.get()));
445 EXPECT_EQ(3, service_->channel_id_count());
448 TEST_F(ChannelIDServiceTest, AsyncStoreGetOrCreateNoChannelIDsInStore) {
449 MockChannelIDStoreWithAsyncGet* mock_store =
450 new MockChannelIDStoreWithAsyncGet();
451 service_ = scoped_ptr<ChannelIDService>(
452 new ChannelIDService(mock_store, base::ThreadTaskRunnerHandle::Get()));
454 std::string host("encrypted.google.com");
456 int error;
457 TestCompletionCallback callback;
458 ChannelIDService::Request request;
460 // Asynchronous completion with no certs in the store.
461 scoped_ptr<crypto::ECPrivateKey> key;
462 EXPECT_EQ(0, service_->channel_id_count());
463 error =
464 service_->GetOrCreateChannelID(host, &key, callback.callback(), &request);
465 EXPECT_EQ(ERR_IO_PENDING, error);
466 EXPECT_TRUE(request.is_active());
468 mock_store->CallGetChannelIDCallbackWithResult(ERR_FILE_NOT_FOUND, nullptr);
470 error = callback.WaitForResult();
471 EXPECT_EQ(OK, error);
472 EXPECT_EQ(1, service_->channel_id_count());
473 EXPECT_TRUE(key);
474 EXPECT_FALSE(request.is_active());
477 TEST_F(ChannelIDServiceTest, AsyncStoreGetNoChannelIDsInStore) {
478 MockChannelIDStoreWithAsyncGet* mock_store =
479 new MockChannelIDStoreWithAsyncGet();
480 service_ = scoped_ptr<ChannelIDService>(
481 new ChannelIDService(mock_store, base::ThreadTaskRunnerHandle::Get()));
483 std::string host("encrypted.google.com");
485 int error;
486 TestCompletionCallback callback;
487 ChannelIDService::Request request;
489 // Asynchronous completion with no certs in the store.
490 scoped_ptr<crypto::ECPrivateKey> key;
491 EXPECT_EQ(0, service_->channel_id_count());
492 error = service_->GetChannelID(host, &key, callback.callback(), &request);
493 EXPECT_EQ(ERR_IO_PENDING, error);
494 EXPECT_TRUE(request.is_active());
496 mock_store->CallGetChannelIDCallbackWithResult(ERR_FILE_NOT_FOUND, nullptr);
498 error = callback.WaitForResult();
499 EXPECT_EQ(ERR_FILE_NOT_FOUND, error);
500 EXPECT_EQ(0, service_->channel_id_count());
501 EXPECT_EQ(0u, service_->workers_created());
502 EXPECT_FALSE(key);
503 EXPECT_FALSE(request.is_active());
506 TEST_F(ChannelIDServiceTest, AsyncStoreGetOrCreateOneCertInStore) {
507 MockChannelIDStoreWithAsyncGet* mock_store =
508 new MockChannelIDStoreWithAsyncGet();
509 service_ = scoped_ptr<ChannelIDService>(
510 new ChannelIDService(mock_store, base::ThreadTaskRunnerHandle::Get()));
512 std::string host("encrypted.google.com");
514 int error;
515 TestCompletionCallback callback;
516 ChannelIDService::Request request;
518 // Asynchronous completion with a cert in the store.
519 scoped_ptr<crypto::ECPrivateKey> key;
520 EXPECT_EQ(0, service_->channel_id_count());
521 error =
522 service_->GetOrCreateChannelID(host, &key, callback.callback(), &request);
523 EXPECT_EQ(ERR_IO_PENDING, error);
524 EXPECT_TRUE(request.is_active());
526 scoped_ptr<crypto::ECPrivateKey> expected_key(crypto::ECPrivateKey::Create());
527 mock_store->CallGetChannelIDCallbackWithResult(OK, expected_key.get());
529 error = callback.WaitForResult();
530 EXPECT_EQ(OK, error);
531 EXPECT_EQ(1, service_->channel_id_count());
532 EXPECT_EQ(1u, service_->requests());
533 EXPECT_EQ(1u, service_->key_store_hits());
534 // Because the cert was found in the store, no new workers should have been
535 // created.
536 EXPECT_EQ(0u, service_->workers_created());
537 EXPECT_TRUE(key);
538 EXPECT_TRUE(KeysEqual(expected_key.get(), key.get()));
539 EXPECT_FALSE(request.is_active());
542 TEST_F(ChannelIDServiceTest, AsyncStoreGetOneCertInStore) {
543 MockChannelIDStoreWithAsyncGet* mock_store =
544 new MockChannelIDStoreWithAsyncGet();
545 service_ = scoped_ptr<ChannelIDService>(
546 new ChannelIDService(mock_store, base::ThreadTaskRunnerHandle::Get()));
548 std::string host("encrypted.google.com");
550 int error;
551 TestCompletionCallback callback;
552 ChannelIDService::Request request;
554 // Asynchronous completion with a cert in the store.
555 scoped_ptr<crypto::ECPrivateKey> key;
556 std::string private_key, spki;
557 EXPECT_EQ(0, service_->channel_id_count());
558 error = service_->GetChannelID(host, &key, callback.callback(), &request);
559 EXPECT_EQ(ERR_IO_PENDING, error);
560 EXPECT_TRUE(request.is_active());
562 scoped_ptr<crypto::ECPrivateKey> expected_key(crypto::ECPrivateKey::Create());
563 mock_store->CallGetChannelIDCallbackWithResult(OK, expected_key.get());
565 error = callback.WaitForResult();
566 EXPECT_EQ(OK, error);
567 EXPECT_EQ(1, service_->channel_id_count());
568 EXPECT_EQ(1u, service_->requests());
569 EXPECT_EQ(1u, service_->key_store_hits());
570 // Because the cert was found in the store, no new workers should have been
571 // created.
572 EXPECT_EQ(0u, service_->workers_created());
573 EXPECT_TRUE(KeysEqual(expected_key.get(), key.get()));
574 EXPECT_FALSE(request.is_active());
577 TEST_F(ChannelIDServiceTest, AsyncStoreGetThenCreateNoCertsInStore) {
578 MockChannelIDStoreWithAsyncGet* mock_store =
579 new MockChannelIDStoreWithAsyncGet();
580 service_ = scoped_ptr<ChannelIDService>(
581 new ChannelIDService(mock_store, base::ThreadTaskRunnerHandle::Get()));
583 std::string host("encrypted.google.com");
585 int error;
587 // Asynchronous get with no certs in the store.
588 TestCompletionCallback callback1;
589 ChannelIDService::Request request1;
590 scoped_ptr<crypto::ECPrivateKey> key1;
591 EXPECT_EQ(0, service_->channel_id_count());
592 error = service_->GetChannelID(host, &key1, callback1.callback(), &request1);
593 EXPECT_EQ(ERR_IO_PENDING, error);
594 EXPECT_TRUE(request1.is_active());
596 // Asynchronous get/create with no certs in the store.
597 TestCompletionCallback callback2;
598 ChannelIDService::Request request2;
599 scoped_ptr<crypto::ECPrivateKey> key2;
600 EXPECT_EQ(0, service_->channel_id_count());
601 error = service_->GetOrCreateChannelID(host, &key2, callback2.callback(),
602 &request2);
603 EXPECT_EQ(ERR_IO_PENDING, error);
604 EXPECT_TRUE(request2.is_active());
606 mock_store->CallGetChannelIDCallbackWithResult(ERR_FILE_NOT_FOUND, nullptr);
608 // Even though the first request didn't ask to create a cert, it gets joined
609 // by the second, which does, so both succeed.
610 error = callback1.WaitForResult();
611 EXPECT_EQ(OK, error);
612 error = callback2.WaitForResult();
613 EXPECT_EQ(OK, error);
615 // One cert is created, one request is joined.
616 EXPECT_EQ(2U, service_->requests());
617 EXPECT_EQ(1, service_->channel_id_count());
618 EXPECT_EQ(1u, service_->workers_created());
619 EXPECT_EQ(1u, service_->inflight_joins());
620 EXPECT_TRUE(key1);
621 EXPECT_TRUE(KeysEqual(key1.get(), key2.get()));
622 EXPECT_FALSE(request1.is_active());
623 EXPECT_FALSE(request2.is_active());
626 } // namespace
628 } // namespace net