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.
4
5#include "net/http/disk_cache_based_quic_server_info.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/compiler_specific.h"
10#include "base/message_loop/message_loop.h"
11#include "net/base/net_errors.h"
12#include "net/http/mock_http_cache.h"
13#include "net/quic/crypto/quic_server_info.h"
14#include "net/quic/quic_server_id.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace net {
18namespace {
19
20// This is an empty transaction, needed to register the URL and the test mode.
21const MockTransaction kHostInfoTransaction1 = {
22  "quicserverinfo:https://www.google.com:443",
23  "",
24  base::Time(),
25  "",
26  LOAD_NORMAL,
27  "",
28  "",
29  base::Time(),
30  "",
31  TEST_MODE_NORMAL,
32  NULL,
33  0
34};
35
36const MockTransaction kHostInfoTransaction2 = {
37  "quicserverinfo:http://www.google.com:80",
38  "",
39  base::Time(),
40  "",
41  LOAD_NORMAL,
42  "",
43  "",
44  base::Time(),
45  "",
46  TEST_MODE_NORMAL,
47  NULL,
48  0
49};
50
51}  // namespace
52
53// Tests that we can delete a DiskCacheBasedQuicServerInfo object in a
54// completion callback for DiskCacheBasedQuicServerInfo::WaitForDataReady.
55TEST(DiskCacheBasedQuicServerInfo, DeleteInCallback) {
56  // Use the blocking mock backend factory to force asynchronous completion
57  // of quic_server_info->WaitForDataReady(), so that the callback will run.
58  MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
59  MockHttpCache cache(factory);
60  QuicServerId server_id("www.verisign.com", 443, true, PRIVACY_MODE_DISABLED);
61  scoped_ptr<QuicServerInfo> quic_server_info(
62      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
63  quic_server_info->Start();
64  TestCompletionCallback callback;
65  int rv = quic_server_info->WaitForDataReady(callback.callback());
66  EXPECT_EQ(ERR_IO_PENDING, rv);
67  // Now complete the backend creation and let the callback run.
68  factory->FinishCreation();
69  EXPECT_EQ(OK, callback.GetResult(rv));
70}
71
72// Tests the basic logic of storing, retrieving and updating data.
73TEST(DiskCacheBasedQuicServerInfo, Update) {
74  MockHttpCache cache;
75  AddMockTransaction(&kHostInfoTransaction1);
76  TestCompletionCallback callback;
77
78  QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
79  scoped_ptr<QuicServerInfo> quic_server_info(
80      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
81  quic_server_info->Start();
82  int rv = quic_server_info->WaitForDataReady(callback.callback());
83  EXPECT_EQ(OK, callback.GetResult(rv));
84
85  QuicServerInfo::State* state = quic_server_info->mutable_state();
86  EXPECT_TRUE(state->certs.empty());
87  const string server_config_a = "server_config_a";
88  const string source_address_token_a = "source_address_token_a";
89  const string server_config_sig_a = "server_config_sig_a";
90  const string cert_a = "cert_a";
91  const string cert_b = "cert_b";
92
93  state->server_config = server_config_a;
94  state->source_address_token = source_address_token_a;
95  state->server_config_sig = server_config_sig_a;
96  state->certs.push_back(cert_a);
97  quic_server_info->Persist();
98
99  // Wait until Persist() does the work.
100  base::MessageLoop::current()->RunUntilIdle();
101
102  // Open the stored QuicServerInfo.
103  quic_server_info.reset(
104      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
105  quic_server_info->Start();
106  rv = quic_server_info->WaitForDataReady(callback.callback());
107  EXPECT_EQ(OK, callback.GetResult(rv));
108
109  // And now update the data.
110  state = quic_server_info->mutable_state();
111  state->certs.push_back(cert_b);
112
113  // Fail instead of DCHECKing double creates.
114  cache.disk_cache()->set_double_create_check(false);
115  quic_server_info->Persist();
116  base::MessageLoop::current()->RunUntilIdle();
117
118  // Verify that the state was updated.
119  quic_server_info.reset(
120      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
121  quic_server_info->Start();
122  rv = quic_server_info->WaitForDataReady(callback.callback());
123  EXPECT_EQ(OK, callback.GetResult(rv));
124  EXPECT_TRUE(quic_server_info->IsDataReady());
125
126  const QuicServerInfo::State& state1 = quic_server_info->state();
127  EXPECT_EQ(server_config_a, state1.server_config);
128  EXPECT_EQ(source_address_token_a, state1.source_address_token);
129  EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
130  EXPECT_EQ(2U, state1.certs.size());
131  EXPECT_EQ(cert_a, state1.certs[0]);
132  EXPECT_EQ(cert_b, state1.certs[1]);
133
134  RemoveMockTransaction(&kHostInfoTransaction1);
135}
136
137// Test that demonstrates different info is returned when the ports differ.
138TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) {
139  MockHttpCache cache;
140  AddMockTransaction(&kHostInfoTransaction1);
141  AddMockTransaction(&kHostInfoTransaction2);
142  TestCompletionCallback callback;
143
144  // Persist data for port 443.
145  QuicServerId server_id1("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
146  scoped_ptr<QuicServerInfo> quic_server_info1(
147      new DiskCacheBasedQuicServerInfo(server_id1, cache.http_cache()));
148  quic_server_info1->Start();
149  int rv = quic_server_info1->WaitForDataReady(callback.callback());
150  EXPECT_EQ(OK, callback.GetResult(rv));
151
152  QuicServerInfo::State* state1 = quic_server_info1->mutable_state();
153  EXPECT_TRUE(state1->certs.empty());
154  const string server_config_a = "server_config_a";
155  const string source_address_token_a = "source_address_token_a";
156  const string server_config_sig_a = "server_config_sig_a";
157  const string cert_a = "cert_a";
158
159  state1->server_config = server_config_a;
160  state1->source_address_token = source_address_token_a;
161  state1->server_config_sig = server_config_sig_a;
162  state1->certs.push_back(cert_a);
163  quic_server_info1->Persist();
164
165  // Wait until Persist() does the work.
166  base::MessageLoop::current()->RunUntilIdle();
167
168  // Persist data for port 80.
169  QuicServerId server_id2("www.google.com", 80, false, PRIVACY_MODE_DISABLED);
170  scoped_ptr<QuicServerInfo> quic_server_info2(
171      new DiskCacheBasedQuicServerInfo(server_id2, cache.http_cache()));
172  quic_server_info2->Start();
173  rv = quic_server_info2->WaitForDataReady(callback.callback());
174  EXPECT_EQ(OK, callback.GetResult(rv));
175
176  QuicServerInfo::State* state2 = quic_server_info2->mutable_state();
177  EXPECT_TRUE(state2->certs.empty());
178  const string server_config_b = "server_config_b";
179  const string source_address_token_b = "source_address_token_b";
180  const string server_config_sig_b = "server_config_sig_b";
181  const string cert_b = "cert_b";
182
183  state2->server_config = server_config_b;
184  state2->source_address_token = source_address_token_b;
185  state2->server_config_sig = server_config_sig_b;
186  state2->certs.push_back(cert_b);
187  quic_server_info2->Persist();
188
189  // Wait until Persist() does the work.
190  base::MessageLoop::current()->RunUntilIdle();
191
192  // Verify the stored QuicServerInfo for port 443.
193  scoped_ptr<QuicServerInfo> quic_server_info(
194      new DiskCacheBasedQuicServerInfo(server_id1, cache.http_cache()));
195  quic_server_info->Start();
196  rv = quic_server_info->WaitForDataReady(callback.callback());
197  EXPECT_EQ(OK, callback.GetResult(rv));
198  EXPECT_TRUE(quic_server_info->IsDataReady());
199
200  const QuicServerInfo::State& state_a = quic_server_info->state();
201  EXPECT_EQ(server_config_a, state_a.server_config);
202  EXPECT_EQ(source_address_token_a, state_a.source_address_token);
203  EXPECT_EQ(server_config_sig_a, state_a.server_config_sig);
204  EXPECT_EQ(1U, state_a.certs.size());
205  EXPECT_EQ(cert_a, state_a.certs[0]);
206
207  // Verify the stored QuicServerInfo for port 80.
208  quic_server_info.reset(
209      new DiskCacheBasedQuicServerInfo(server_id2, cache.http_cache()));
210  quic_server_info->Start();
211  rv = quic_server_info->WaitForDataReady(callback.callback());
212  EXPECT_EQ(OK, callback.GetResult(rv));
213  EXPECT_TRUE(quic_server_info->IsDataReady());
214
215  const QuicServerInfo::State& state_b = quic_server_info->state();
216  EXPECT_EQ(server_config_b, state_b.server_config);
217  EXPECT_EQ(source_address_token_b, state_b.source_address_token);
218  EXPECT_EQ(server_config_sig_b, state_b.server_config_sig);
219  EXPECT_EQ(1U, state_b.certs.size());
220  EXPECT_EQ(cert_b, state_b.certs[0]);
221
222  RemoveMockTransaction(&kHostInfoTransaction2);
223  RemoveMockTransaction(&kHostInfoTransaction1);
224}
225
226// Test IsReadyToPersist when there is a pending write.
227TEST(DiskCacheBasedQuicServerInfo, IsReadyToPersist) {
228  MockHttpCache cache;
229  AddMockTransaction(&kHostInfoTransaction1);
230  TestCompletionCallback callback;
231
232  QuicServerId server_id("www.google.com", 443, true, PRIVACY_MODE_DISABLED);
233  scoped_ptr<QuicServerInfo> quic_server_info(
234      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
235  EXPECT_FALSE(quic_server_info->IsDataReady());
236  quic_server_info->Start();
237  int rv = quic_server_info->WaitForDataReady(callback.callback());
238  EXPECT_EQ(OK, callback.GetResult(rv));
239  EXPECT_TRUE(quic_server_info->IsDataReady());
240
241  QuicServerInfo::State* state = quic_server_info->mutable_state();
242  EXPECT_TRUE(state->certs.empty());
243  const string server_config_a = "server_config_a";
244  const string source_address_token_a = "source_address_token_a";
245  const string server_config_sig_a = "server_config_sig_a";
246  const string cert_a = "cert_a";
247
248  state->server_config = server_config_a;
249  state->source_address_token = source_address_token_a;
250  state->server_config_sig = server_config_sig_a;
251  state->certs.push_back(cert_a);
252  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
253  quic_server_info->Persist();
254
255  // Once we call Persist, IsReadyToPersist should return false until Persist
256  // has completed.
257  EXPECT_FALSE(quic_server_info->IsReadyToPersist());
258
259  // Wait until Persist() does the work.
260  base::MessageLoop::current()->RunUntilIdle();
261
262  EXPECT_TRUE(quic_server_info->IsReadyToPersist());
263
264  // Verify that the state was updated.
265  quic_server_info.reset(
266      new DiskCacheBasedQuicServerInfo(server_id, cache.http_cache()));
267  quic_server_info->Start();
268  rv = quic_server_info->WaitForDataReady(callback.callback());
269  EXPECT_EQ(OK, callback.GetResult(rv));
270  EXPECT_TRUE(quic_server_info->IsDataReady());
271
272  const QuicServerInfo::State& state1 = quic_server_info->state();
273  EXPECT_EQ(server_config_a, state1.server_config);
274  EXPECT_EQ(source_address_token_a, state1.source_address_token);
275  EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
276  EXPECT_EQ(1U, state1.certs.size());
277  EXPECT_EQ(cert_a, state1.certs[0]);
278
279  RemoveMockTransaction(&kHostInfoTransaction1);
280}
281
282}  // namespace net
283