Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / net / ssl / server_bound_cert_service_unittest.cc
1 // Copyright (c) 2012 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 #include "net/ssl/server_bound_cert_service.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/task_runner.h"
15 #include "crypto/ec_private_key.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/cert/asn1_util.h"
19 #include "net/cert/x509_certificate.h"
20 #include "net/ssl/default_server_bound_cert_store.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace net {
24
25 namespace {
26
27 void FailTest(int /* result */) {
28   FAIL();
29 }
30
31 // Simple task runner that refuses to actually post any tasks. This simulates
32 // a TaskRunner that has been shutdown, by returning false for any attempt to
33 // add new tasks.
34 class FailingTaskRunner : public base::TaskRunner {
35  public:
36   FailingTaskRunner() {}
37
38   virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
39                                const base::Closure& task,
40                                base::TimeDelta delay) OVERRIDE {
41     return false;
42   }
43
44   virtual bool RunsTasksOnCurrentThread() const OVERRIDE { return true; }
45
46  protected:
47   virtual ~FailingTaskRunner() {}
48
49  private:
50   DISALLOW_COPY_AND_ASSIGN(FailingTaskRunner);
51 };
52
53 class MockServerBoundCertStoreWithAsyncGet
54     : public DefaultServerBoundCertStore {
55  public:
56   MockServerBoundCertStoreWithAsyncGet()
57       : DefaultServerBoundCertStore(NULL), cert_count_(0) {}
58
59   virtual int GetServerBoundCert(const std::string& server_identifier,
60                                  base::Time* expiration_time,
61                                  std::string* private_key_result,
62                                  std::string* cert_result,
63                                  const GetCertCallback& callback) OVERRIDE;
64
65   virtual void SetServerBoundCert(const std::string& server_identifier,
66                                   base::Time creation_time,
67                                   base::Time expiration_time,
68                                   const std::string& private_key,
69                                   const std::string& cert) OVERRIDE {
70     cert_count_ = 1;
71   }
72
73   virtual int GetCertCount() OVERRIDE { return cert_count_; }
74
75   void CallGetServerBoundCertCallbackWithResult(int err,
76                                                 base::Time expiration_time,
77                                                 const std::string& private_key,
78                                                 const std::string& cert);
79
80  private:
81   GetCertCallback callback_;
82   std::string server_identifier_;
83   int cert_count_;
84 };
85
86 int MockServerBoundCertStoreWithAsyncGet::GetServerBoundCert(
87     const std::string& server_identifier,
88     base::Time* expiration_time,
89     std::string* private_key_result,
90     std::string* cert_result,
91     const GetCertCallback& callback) {
92   server_identifier_ = server_identifier;
93   callback_ = callback;
94   // Reset the cert count, it'll get incremented in either SetServerBoundCert or
95   // CallGetServerBoundCertCallbackWithResult.
96   cert_count_ = 0;
97   // Do nothing else: the results to be provided will be specified through
98   // CallGetServerBoundCertCallbackWithResult.
99   return ERR_IO_PENDING;
100 }
101
102 void
103 MockServerBoundCertStoreWithAsyncGet::CallGetServerBoundCertCallbackWithResult(
104     int err,
105     base::Time expiration_time,
106     const std::string& private_key,
107     const std::string& cert) {
108   if (err == OK)
109     cert_count_ = 1;
110   base::MessageLoop::current()->PostTask(FROM_HERE,
111                                          base::Bind(callback_,
112                                                     err,
113                                                     server_identifier_,
114                                                     expiration_time,
115                                                     private_key,
116                                                     cert));
117 }
118
119 class ServerBoundCertServiceTest : public testing::Test {
120  public:
121   ServerBoundCertServiceTest()
122       : service_(new ServerBoundCertService(
123             new DefaultServerBoundCertStore(NULL),
124             base::MessageLoopProxy::current())) {
125   }
126
127  protected:
128   scoped_ptr<ServerBoundCertService> service_;
129 };
130
131 TEST_F(ServerBoundCertServiceTest, GetDomainForHost) {
132   EXPECT_EQ("google.com",
133             ServerBoundCertService::GetDomainForHost("google.com"));
134   EXPECT_EQ("google.com",
135             ServerBoundCertService::GetDomainForHost("www.google.com"));
136   EXPECT_EQ("foo.appspot.com",
137             ServerBoundCertService::GetDomainForHost("foo.appspot.com"));
138   EXPECT_EQ("bar.appspot.com",
139             ServerBoundCertService::GetDomainForHost("foo.bar.appspot.com"));
140   EXPECT_EQ("appspot.com",
141             ServerBoundCertService::GetDomainForHost("appspot.com"));
142   EXPECT_EQ("google.com",
143             ServerBoundCertService::GetDomainForHost("www.mail.google.com"));
144   EXPECT_EQ("goto",
145             ServerBoundCertService::GetDomainForHost("goto"));
146   EXPECT_EQ("127.0.0.1",
147             ServerBoundCertService::GetDomainForHost("127.0.0.1"));
148 }
149
150 TEST_F(ServerBoundCertServiceTest, GetCacheMiss) {
151   std::string host("encrypted.google.com");
152
153   int error;
154   TestCompletionCallback callback;
155   ServerBoundCertService::RequestHandle request_handle;
156
157   // Synchronous completion, because the store is initialized.
158   std::string private_key, der_cert;
159   EXPECT_EQ(0, service_->cert_count());
160   error = service_->GetDomainBoundCert(
161       host, &private_key, &der_cert, callback.callback(), &request_handle);
162   EXPECT_EQ(ERR_FILE_NOT_FOUND, error);
163   EXPECT_FALSE(request_handle.is_active());
164   EXPECT_EQ(0, service_->cert_count());
165   EXPECT_TRUE(der_cert.empty());
166 }
167
168 TEST_F(ServerBoundCertServiceTest, CacheHit) {
169   std::string host("encrypted.google.com");
170
171   int error;
172   TestCompletionCallback callback;
173   ServerBoundCertService::RequestHandle request_handle;
174
175   // Asynchronous completion.
176   std::string private_key_info1, der_cert1;
177   EXPECT_EQ(0, service_->cert_count());
178   error = service_->GetOrCreateDomainBoundCert(
179       host, &private_key_info1, &der_cert1,
180       callback.callback(), &request_handle);
181   EXPECT_EQ(ERR_IO_PENDING, error);
182   EXPECT_TRUE(request_handle.is_active());
183   error = callback.WaitForResult();
184   EXPECT_EQ(OK, error);
185   EXPECT_EQ(1, service_->cert_count());
186   EXPECT_FALSE(private_key_info1.empty());
187   EXPECT_FALSE(der_cert1.empty());
188   EXPECT_FALSE(request_handle.is_active());
189
190   // Synchronous completion.
191   std::string private_key_info2, der_cert2;
192   error = service_->GetOrCreateDomainBoundCert(
193       host, &private_key_info2, &der_cert2,
194       callback.callback(), &request_handle);
195   EXPECT_FALSE(request_handle.is_active());
196   EXPECT_EQ(OK, error);
197   EXPECT_EQ(1, service_->cert_count());
198   EXPECT_EQ(private_key_info1, private_key_info2);
199   EXPECT_EQ(der_cert1, der_cert2);
200
201   // Synchronous get.
202   std::string private_key_info3, der_cert3;
203   error = service_->GetDomainBoundCert(
204       host, &private_key_info3, &der_cert3, callback.callback(),
205       &request_handle);
206   EXPECT_FALSE(request_handle.is_active());
207   EXPECT_EQ(OK, error);
208   EXPECT_EQ(1, service_->cert_count());
209   EXPECT_EQ(der_cert1, der_cert3);
210   EXPECT_EQ(private_key_info1, private_key_info3);
211
212   EXPECT_EQ(3u, service_->requests());
213   EXPECT_EQ(2u, service_->cert_store_hits());
214   EXPECT_EQ(0u, service_->inflight_joins());
215 }
216
217 TEST_F(ServerBoundCertServiceTest, StoreCerts) {
218   int error;
219   TestCompletionCallback callback;
220   ServerBoundCertService::RequestHandle request_handle;
221
222   std::string host1("encrypted.google.com");
223   std::string private_key_info1, der_cert1;
224   EXPECT_EQ(0, service_->cert_count());
225   error = service_->GetOrCreateDomainBoundCert(
226       host1, &private_key_info1, &der_cert1,
227       callback.callback(), &request_handle);
228   EXPECT_EQ(ERR_IO_PENDING, error);
229   EXPECT_TRUE(request_handle.is_active());
230   error = callback.WaitForResult();
231   EXPECT_EQ(OK, error);
232   EXPECT_EQ(1, service_->cert_count());
233
234   std::string host2("www.verisign.com");
235   std::string private_key_info2, der_cert2;
236   error = service_->GetOrCreateDomainBoundCert(
237       host2, &private_key_info2, &der_cert2,
238       callback.callback(), &request_handle);
239   EXPECT_EQ(ERR_IO_PENDING, error);
240   EXPECT_TRUE(request_handle.is_active());
241   error = callback.WaitForResult();
242   EXPECT_EQ(OK, error);
243   EXPECT_EQ(2, service_->cert_count());
244
245   std::string host3("www.twitter.com");
246   std::string private_key_info3, der_cert3;
247   error = service_->GetOrCreateDomainBoundCert(
248       host3, &private_key_info3, &der_cert3,
249       callback.callback(), &request_handle);
250   EXPECT_EQ(ERR_IO_PENDING, error);
251   EXPECT_TRUE(request_handle.is_active());
252   error = callback.WaitForResult();
253   EXPECT_EQ(OK, error);
254   EXPECT_EQ(3, service_->cert_count());
255
256   EXPECT_NE(private_key_info1, private_key_info2);
257   EXPECT_NE(der_cert1, der_cert2);
258   EXPECT_NE(private_key_info1, private_key_info3);
259   EXPECT_NE(der_cert1, der_cert3);
260   EXPECT_NE(private_key_info2, private_key_info3);
261   EXPECT_NE(der_cert2, der_cert3);
262 }
263
264 // Tests an inflight join.
265 TEST_F(ServerBoundCertServiceTest, InflightJoin) {
266   std::string host("encrypted.google.com");
267   int error;
268
269   std::string private_key_info1, der_cert1;
270   TestCompletionCallback callback1;
271   ServerBoundCertService::RequestHandle request_handle1;
272
273   std::string private_key_info2, der_cert2;
274   TestCompletionCallback callback2;
275   ServerBoundCertService::RequestHandle request_handle2;
276
277   error = service_->GetOrCreateDomainBoundCert(
278       host, &private_key_info1, &der_cert1,
279       callback1.callback(), &request_handle1);
280   EXPECT_EQ(ERR_IO_PENDING, error);
281   EXPECT_TRUE(request_handle1.is_active());
282   // Should join with the original request.
283   error = service_->GetOrCreateDomainBoundCert(
284       host, &private_key_info2, &der_cert2,
285       callback2.callback(), &request_handle2);
286   EXPECT_EQ(ERR_IO_PENDING, error);
287   EXPECT_TRUE(request_handle2.is_active());
288
289   error = callback1.WaitForResult();
290   EXPECT_EQ(OK, error);
291   error = callback2.WaitForResult();
292   EXPECT_EQ(OK, error);
293
294   EXPECT_EQ(2u, service_->requests());
295   EXPECT_EQ(0u, service_->cert_store_hits());
296   EXPECT_EQ(1u, service_->inflight_joins());
297   EXPECT_EQ(1u, service_->workers_created());
298 }
299
300 // Tests an inflight join of a Get request to a GetOrCreate request.
301 TEST_F(ServerBoundCertServiceTest, InflightJoinGetOrCreateAndGet) {
302   std::string host("encrypted.google.com");
303   int error;
304
305   std::string private_key_info1, der_cert1;
306   TestCompletionCallback callback1;
307   ServerBoundCertService::RequestHandle request_handle1;
308
309   std::string private_key_info2;
310   std::string der_cert2;
311   TestCompletionCallback callback2;
312   ServerBoundCertService::RequestHandle request_handle2;
313
314   error = service_->GetOrCreateDomainBoundCert(
315       host, &private_key_info1, &der_cert1,
316       callback1.callback(), &request_handle1);
317   EXPECT_EQ(ERR_IO_PENDING, error);
318   EXPECT_TRUE(request_handle1.is_active());
319   // Should join with the original request.
320   error = service_->GetDomainBoundCert(
321       host, &private_key_info2, &der_cert2, callback2.callback(),
322       &request_handle2);
323   EXPECT_EQ(ERR_IO_PENDING, error);
324   EXPECT_TRUE(request_handle2.is_active());
325
326   error = callback1.WaitForResult();
327   EXPECT_EQ(OK, error);
328   error = callback2.WaitForResult();
329   EXPECT_EQ(OK, error);
330   EXPECT_EQ(der_cert1, der_cert2);
331
332   EXPECT_EQ(2u, service_->requests());
333   EXPECT_EQ(0u, service_->cert_store_hits());
334   EXPECT_EQ(1u, service_->inflight_joins());
335   EXPECT_EQ(1u, service_->workers_created());
336 }
337
338 TEST_F(ServerBoundCertServiceTest, ExtractValuesFromBytesEC) {
339   std::string host("encrypted.google.com");
340   std::string private_key_info, der_cert;
341   int error;
342   TestCompletionCallback callback;
343   ServerBoundCertService::RequestHandle request_handle;
344
345   error = service_->GetOrCreateDomainBoundCert(
346       host, &private_key_info, &der_cert, callback.callback(),
347       &request_handle);
348   EXPECT_EQ(ERR_IO_PENDING, error);
349   EXPECT_TRUE(request_handle.is_active());
350   error = callback.WaitForResult();
351   EXPECT_EQ(OK, error);
352
353   base::StringPiece spki_piece;
354   ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(der_cert, &spki_piece));
355   std::vector<uint8> spki(
356       spki_piece.data(),
357       spki_piece.data() + spki_piece.size());
358
359   // Check that we can retrieve the key from the bytes.
360   std::vector<uint8> key_vec(private_key_info.begin(), private_key_info.end());
361   scoped_ptr<crypto::ECPrivateKey> private_key(
362       crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
363           ServerBoundCertService::kEPKIPassword, key_vec, spki));
364   EXPECT_TRUE(private_key != NULL);
365
366   // Check that we can retrieve the cert from the bytes.
367   scoped_refptr<X509Certificate> x509cert(
368       X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size()));
369   EXPECT_TRUE(x509cert.get() != NULL);
370 }
371
372 // Tests that the callback of a canceled request is never made.
373 TEST_F(ServerBoundCertServiceTest, CancelRequest) {
374   std::string host("encrypted.google.com");
375   std::string private_key_info, der_cert;
376   int error;
377   ServerBoundCertService::RequestHandle request_handle;
378
379   error = service_->GetOrCreateDomainBoundCert(host,
380                                                &private_key_info,
381                                                &der_cert,
382                                                base::Bind(&FailTest),
383                                                &request_handle);
384   EXPECT_EQ(ERR_IO_PENDING, error);
385   EXPECT_TRUE(request_handle.is_active());
386   request_handle.Cancel();
387   EXPECT_FALSE(request_handle.is_active());
388
389   // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
390   // ServerBoundCertService.
391   base::MessageLoop::current()->RunUntilIdle();
392
393   // Even though the original request was cancelled, the service will still
394   // store the result, it just doesn't call the callback.
395   EXPECT_EQ(1, service_->cert_count());
396 }
397
398 // Tests that destructing the RequestHandle cancels the request.
399 TEST_F(ServerBoundCertServiceTest, CancelRequestByHandleDestruction) {
400   std::string host("encrypted.google.com");
401   std::string private_key_info, der_cert;
402   int error;
403   {
404     ServerBoundCertService::RequestHandle request_handle;
405
406     error = service_->GetOrCreateDomainBoundCert(host,
407                                                  &private_key_info,
408                                                  &der_cert,
409                                                  base::Bind(&FailTest),
410                                                  &request_handle);
411     EXPECT_EQ(ERR_IO_PENDING, error);
412     EXPECT_TRUE(request_handle.is_active());
413   }
414
415   // Wait for reply from ServerBoundCertServiceWorker to be posted back to the
416   // ServerBoundCertService.
417   base::MessageLoop::current()->RunUntilIdle();
418
419   // Even though the original request was cancelled, the service will still
420   // store the result, it just doesn't call the callback.
421   EXPECT_EQ(1, service_->cert_count());
422 }
423
424 TEST_F(ServerBoundCertServiceTest, DestructionWithPendingRequest) {
425   std::string host("encrypted.google.com");
426   std::string private_key_info, der_cert;
427   int error;
428   ServerBoundCertService::RequestHandle request_handle;
429
430   error = service_->GetOrCreateDomainBoundCert(host,
431                                                &private_key_info,
432                                                &der_cert,
433                                                base::Bind(&FailTest),
434                                                &request_handle);
435   EXPECT_EQ(ERR_IO_PENDING, error);
436   EXPECT_TRUE(request_handle.is_active());
437
438   // Cancel request and destroy the ServerBoundCertService.
439   request_handle.Cancel();
440   service_.reset();
441
442   // ServerBoundCertServiceWorker should not post anything back to the
443   // non-existent ServerBoundCertService, but run the loop just to be sure it
444   // doesn't.
445   base::MessageLoop::current()->RunUntilIdle();
446
447   // If we got here without crashing or a valgrind error, it worked.
448 }
449
450 // Tests that shutting down the sequenced worker pool and then making new
451 // requests gracefully fails.
452 // This is a regression test for http://crbug.com/236387
453 TEST_F(ServerBoundCertServiceTest, RequestAfterPoolShutdown) {
454   scoped_refptr<FailingTaskRunner> task_runner(new FailingTaskRunner);
455   service_.reset(new ServerBoundCertService(
456       new DefaultServerBoundCertStore(NULL), task_runner));
457
458   // Make a request that will force synchronous completion.
459   std::string host("encrypted.google.com");
460   std::string private_key_info, der_cert;
461   int error;
462   ServerBoundCertService::RequestHandle request_handle;
463
464   error = service_->GetOrCreateDomainBoundCert(host,
465                                                &private_key_info,
466                                                &der_cert,
467                                                base::Bind(&FailTest),
468                                                &request_handle);
469   // If we got here without crashing or a valgrind error, it worked.
470   ASSERT_EQ(ERR_INSUFFICIENT_RESOURCES, error);
471   EXPECT_FALSE(request_handle.is_active());
472 }
473
474 // Tests that simultaneous creation of different certs works.
475 TEST_F(ServerBoundCertServiceTest, SimultaneousCreation) {
476   int error;
477
478   std::string host1("encrypted.google.com");
479   std::string private_key_info1, der_cert1;
480   TestCompletionCallback callback1;
481   ServerBoundCertService::RequestHandle request_handle1;
482
483   std::string host2("foo.com");
484   std::string private_key_info2, der_cert2;
485   TestCompletionCallback callback2;
486   ServerBoundCertService::RequestHandle request_handle2;
487
488   std::string host3("bar.com");
489   std::string private_key_info3, der_cert3;
490   TestCompletionCallback callback3;
491   ServerBoundCertService::RequestHandle request_handle3;
492
493   error = service_->GetOrCreateDomainBoundCert(host1,
494                                                &private_key_info1,
495                                                &der_cert1,
496                                                callback1.callback(),
497                                                &request_handle1);
498   EXPECT_EQ(ERR_IO_PENDING, error);
499   EXPECT_TRUE(request_handle1.is_active());
500
501   error = service_->GetOrCreateDomainBoundCert(host2,
502                                                &private_key_info2,
503                                                &der_cert2,
504                                                callback2.callback(),
505                                                &request_handle2);
506   EXPECT_EQ(ERR_IO_PENDING, error);
507   EXPECT_TRUE(request_handle2.is_active());
508
509   error = service_->GetOrCreateDomainBoundCert(host3,
510                                                &private_key_info3,
511                                                &der_cert3,
512                                                callback3.callback(),
513                                                &request_handle3);
514   EXPECT_EQ(ERR_IO_PENDING, error);
515   EXPECT_TRUE(request_handle3.is_active());
516
517   error = callback1.WaitForResult();
518   EXPECT_EQ(OK, error);
519   EXPECT_FALSE(private_key_info1.empty());
520   EXPECT_FALSE(der_cert1.empty());
521
522   error = callback2.WaitForResult();
523   EXPECT_EQ(OK, error);
524   EXPECT_FALSE(private_key_info2.empty());
525   EXPECT_FALSE(der_cert2.empty());
526
527   error = callback3.WaitForResult();
528   EXPECT_EQ(OK, error);
529   EXPECT_FALSE(private_key_info3.empty());
530   EXPECT_FALSE(der_cert3.empty());
531
532   EXPECT_NE(private_key_info1, private_key_info2);
533   EXPECT_NE(der_cert1, der_cert2);
534
535   EXPECT_NE(private_key_info1, private_key_info3);
536   EXPECT_NE(der_cert1, der_cert3);
537
538   EXPECT_NE(private_key_info2, private_key_info3);
539   EXPECT_NE(der_cert2, der_cert3);
540
541   EXPECT_EQ(3, service_->cert_count());
542 }
543
544 TEST_F(ServerBoundCertServiceTest, Expiration) {
545   ServerBoundCertStore* store = service_->GetCertStore();
546   base::Time now = base::Time::Now();
547   store->SetServerBoundCert("good",
548                             now,
549                             now + base::TimeDelta::FromDays(1),
550                             "a",
551                             "b");
552   store->SetServerBoundCert("expired",
553                             now - base::TimeDelta::FromDays(2),
554                             now - base::TimeDelta::FromDays(1),
555                             "c",
556                             "d");
557   EXPECT_EQ(2, service_->cert_count());
558
559   int error;
560   TestCompletionCallback callback;
561   ServerBoundCertService::RequestHandle request_handle;
562
563   // Cert is valid - synchronous completion.
564   std::string private_key_info1, der_cert1;
565   error = service_->GetOrCreateDomainBoundCert(
566       "good", &private_key_info1, &der_cert1,
567       callback.callback(), &request_handle);
568   EXPECT_EQ(OK, error);
569   EXPECT_FALSE(request_handle.is_active());
570   EXPECT_EQ(2, service_->cert_count());
571   EXPECT_STREQ("a", private_key_info1.c_str());
572   EXPECT_STREQ("b", der_cert1.c_str());
573
574   // Expired cert is valid as well - synchronous completion.
575   std::string private_key_info2, der_cert2;
576   error = service_->GetOrCreateDomainBoundCert(
577       "expired", &private_key_info2, &der_cert2,
578       callback.callback(), &request_handle);
579   EXPECT_EQ(OK, error);
580   EXPECT_FALSE(request_handle.is_active());
581   EXPECT_EQ(2, service_->cert_count());
582   EXPECT_STREQ("c", private_key_info2.c_str());
583   EXPECT_STREQ("d", der_cert2.c_str());
584 }
585
586 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOrCreateNoCertsInStore) {
587   MockServerBoundCertStoreWithAsyncGet* mock_store =
588       new MockServerBoundCertStoreWithAsyncGet();
589   service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService(
590       mock_store, base::MessageLoopProxy::current()));
591
592   std::string host("encrypted.google.com");
593
594   int error;
595   TestCompletionCallback callback;
596   ServerBoundCertService::RequestHandle request_handle;
597
598   // Asynchronous completion with no certs in the store.
599   std::string private_key_info, der_cert;
600   EXPECT_EQ(0, service_->cert_count());
601   error = service_->GetOrCreateDomainBoundCert(
602       host, &private_key_info, &der_cert, callback.callback(), &request_handle);
603   EXPECT_EQ(ERR_IO_PENDING, error);
604   EXPECT_TRUE(request_handle.is_active());
605
606   mock_store->CallGetServerBoundCertCallbackWithResult(
607       ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string());
608
609   error = callback.WaitForResult();
610   EXPECT_EQ(OK, error);
611   EXPECT_EQ(1, service_->cert_count());
612   EXPECT_FALSE(private_key_info.empty());
613   EXPECT_FALSE(der_cert.empty());
614   EXPECT_FALSE(request_handle.is_active());
615 }
616
617 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetNoCertsInStore) {
618   MockServerBoundCertStoreWithAsyncGet* mock_store =
619       new MockServerBoundCertStoreWithAsyncGet();
620   service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService(
621       mock_store, base::MessageLoopProxy::current()));
622
623   std::string host("encrypted.google.com");
624
625   int error;
626   TestCompletionCallback callback;
627   ServerBoundCertService::RequestHandle request_handle;
628
629   // Asynchronous completion with no certs in the store.
630   std::string private_key, der_cert;
631   EXPECT_EQ(0, service_->cert_count());
632   error = service_->GetDomainBoundCert(
633       host, &private_key, &der_cert, callback.callback(), &request_handle);
634   EXPECT_EQ(ERR_IO_PENDING, error);
635   EXPECT_TRUE(request_handle.is_active());
636
637   mock_store->CallGetServerBoundCertCallbackWithResult(
638       ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string());
639
640   error = callback.WaitForResult();
641   EXPECT_EQ(ERR_FILE_NOT_FOUND, error);
642   EXPECT_EQ(0, service_->cert_count());
643   EXPECT_EQ(0u, service_->workers_created());
644   EXPECT_TRUE(der_cert.empty());
645   EXPECT_FALSE(request_handle.is_active());
646 }
647
648 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOrCreateOneCertInStore) {
649   MockServerBoundCertStoreWithAsyncGet* mock_store =
650       new MockServerBoundCertStoreWithAsyncGet();
651   service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService(
652       mock_store, base::MessageLoopProxy::current()));
653
654   std::string host("encrypted.google.com");
655
656   int error;
657   TestCompletionCallback callback;
658   ServerBoundCertService::RequestHandle request_handle;
659
660   // Asynchronous completion with a cert in the store.
661   std::string private_key_info, der_cert;
662   EXPECT_EQ(0, service_->cert_count());
663   error = service_->GetOrCreateDomainBoundCert(
664       host, &private_key_info, &der_cert, callback.callback(), &request_handle);
665   EXPECT_EQ(ERR_IO_PENDING, error);
666   EXPECT_TRUE(request_handle.is_active());
667
668   mock_store->CallGetServerBoundCertCallbackWithResult(
669       OK, base::Time(), "ab", "cd");
670
671   error = callback.WaitForResult();
672   EXPECT_EQ(OK, error);
673   EXPECT_EQ(1, service_->cert_count());
674   EXPECT_EQ(1u, service_->requests());
675   EXPECT_EQ(1u, service_->cert_store_hits());
676   // Because the cert was found in the store, no new workers should have been
677   // created.
678   EXPECT_EQ(0u, service_->workers_created());
679   EXPECT_STREQ("ab", private_key_info.c_str());
680   EXPECT_STREQ("cd", der_cert.c_str());
681   EXPECT_FALSE(request_handle.is_active());
682 }
683
684 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetOneCertInStore) {
685   MockServerBoundCertStoreWithAsyncGet* mock_store =
686       new MockServerBoundCertStoreWithAsyncGet();
687   service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService(
688       mock_store, base::MessageLoopProxy::current()));
689
690   std::string host("encrypted.google.com");
691
692   int error;
693   TestCompletionCallback callback;
694   ServerBoundCertService::RequestHandle request_handle;
695
696   // Asynchronous completion with a cert in the store.
697   std::string private_key, der_cert;
698   EXPECT_EQ(0, service_->cert_count());
699   error = service_->GetDomainBoundCert(
700       host, &private_key, &der_cert, callback.callback(), &request_handle);
701   EXPECT_EQ(ERR_IO_PENDING, error);
702   EXPECT_TRUE(request_handle.is_active());
703
704   mock_store->CallGetServerBoundCertCallbackWithResult(
705       OK, base::Time(), "ab", "cd");
706
707   error = callback.WaitForResult();
708   EXPECT_EQ(OK, error);
709   EXPECT_EQ(1, service_->cert_count());
710   EXPECT_EQ(1u, service_->requests());
711   EXPECT_EQ(1u, service_->cert_store_hits());
712   // Because the cert was found in the store, no new workers should have been
713   // created.
714   EXPECT_EQ(0u, service_->workers_created());
715   EXPECT_STREQ("cd", der_cert.c_str());
716   EXPECT_FALSE(request_handle.is_active());
717 }
718
719 TEST_F(ServerBoundCertServiceTest, AsyncStoreGetThenCreateNoCertsInStore) {
720   MockServerBoundCertStoreWithAsyncGet* mock_store =
721       new MockServerBoundCertStoreWithAsyncGet();
722   service_ = scoped_ptr<ServerBoundCertService>(new ServerBoundCertService(
723       mock_store, base::MessageLoopProxy::current()));
724
725   std::string host("encrypted.google.com");
726
727   int error;
728
729   // Asynchronous get with no certs in the store.
730   TestCompletionCallback callback1;
731   ServerBoundCertService::RequestHandle request_handle1;
732   std::string private_key1, der_cert1;
733   EXPECT_EQ(0, service_->cert_count());
734   error = service_->GetDomainBoundCert(
735       host, &private_key1, &der_cert1, callback1.callback(), &request_handle1);
736   EXPECT_EQ(ERR_IO_PENDING, error);
737   EXPECT_TRUE(request_handle1.is_active());
738
739   // Asynchronous get/create with no certs in the store.
740   TestCompletionCallback callback2;
741   ServerBoundCertService::RequestHandle request_handle2;
742   std::string private_key2, der_cert2;
743   EXPECT_EQ(0, service_->cert_count());
744   error = service_->GetOrCreateDomainBoundCert(
745       host, &private_key2, &der_cert2, callback2.callback(), &request_handle2);
746   EXPECT_EQ(ERR_IO_PENDING, error);
747   EXPECT_TRUE(request_handle2.is_active());
748
749   mock_store->CallGetServerBoundCertCallbackWithResult(
750       ERR_FILE_NOT_FOUND, base::Time(), std::string(), std::string());
751
752   // Even though the first request didn't ask to create a cert, it gets joined
753   // by the second, which does, so both succeed.
754   error = callback1.WaitForResult();
755   EXPECT_EQ(OK, error);
756   error = callback2.WaitForResult();
757   EXPECT_EQ(OK, error);
758
759   // One cert is created, one request is joined.
760   EXPECT_EQ(2U, service_->requests());
761   EXPECT_EQ(1, service_->cert_count());
762   EXPECT_EQ(1u, service_->workers_created());
763   EXPECT_EQ(1u, service_->inflight_joins());
764   EXPECT_FALSE(der_cert1.empty());
765   EXPECT_EQ(der_cert1, der_cert2);
766   EXPECT_FALSE(private_key1.empty());
767   EXPECT_EQ(private_key1, private_key2);
768   EXPECT_FALSE(request_handle1.is_active());
769   EXPECT_FALSE(request_handle2.is_active());
770 }
771
772 }  // namespace
773
774 }  // namespace net