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/http/disk_cache_based_quic_server_info.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_session_key.h"
15 #include "testing/gtest/include/gtest/gtest.h"
20 // This is an empty transaction, needed to register the URL and the test mode.
21 const MockTransaction kHostInfoTransaction1 = {
22 "quicserverinfo:https://www.google.com:443",
36 const MockTransaction kHostInfoTransaction2 = {
37 "quicserverinfo:http://www.google.com:80",
53 // Tests that we can delete a DiskCacheBasedQuicServerInfo object in a
54 // completion callback for DiskCacheBasedQuicServerInfo::WaitForDataReady.
55 TEST(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 QuicSessionKey server_key("www.verisign.com", 443, true,
61 kPrivacyModeDisabled);
62 scoped_ptr<QuicServerInfo> quic_server_info(
63 new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
64 quic_server_info->Start();
65 TestCompletionCallback callback;
66 int rv = quic_server_info->WaitForDataReady(callback.callback());
67 EXPECT_EQ(ERR_IO_PENDING, rv);
68 // Now complete the backend creation and let the callback run.
69 factory->FinishCreation();
70 EXPECT_EQ(OK, callback.GetResult(rv));
73 // Tests the basic logic of storing, retrieving and updating data.
74 TEST(DiskCacheBasedQuicServerInfo, Update) {
76 AddMockTransaction(&kHostInfoTransaction1);
77 TestCompletionCallback callback;
79 QuicSessionKey server_key("www.google.com", 443, true, kPrivacyModeDisabled);
80 scoped_ptr<QuicServerInfo> quic_server_info(
81 new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
82 quic_server_info->Start();
83 int rv = quic_server_info->WaitForDataReady(callback.callback());
84 EXPECT_EQ(OK, callback.GetResult(rv));
86 QuicServerInfo::State* state = quic_server_info->mutable_state();
87 EXPECT_TRUE(state->certs.empty());
88 const string server_config_a = "server_config_a";
89 const string source_address_token_a = "source_address_token_a";
90 const string server_config_sig_a = "server_config_sig_a";
91 const string cert_a = "cert_a";
92 const string cert_b = "cert_b";
94 state->server_config = server_config_a;
95 state->source_address_token = source_address_token_a;
96 state->server_config_sig = server_config_sig_a;
97 state->certs.push_back(cert_a);
98 quic_server_info->Persist();
100 // Wait until Persist() does the work.
101 base::MessageLoop::current()->RunUntilIdle();
103 // Open the stored QuicServerInfo.
104 quic_server_info.reset(
105 new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
106 quic_server_info->Start();
107 rv = quic_server_info->WaitForDataReady(callback.callback());
108 EXPECT_EQ(OK, callback.GetResult(rv));
110 // And now update the data.
111 state = quic_server_info->mutable_state();
112 state->certs.push_back(cert_b);
114 // Fail instead of DCHECKing double creates.
115 cache.disk_cache()->set_double_create_check(false);
116 quic_server_info->Persist();
117 base::MessageLoop::current()->RunUntilIdle();
119 // Verify that the state was updated.
120 quic_server_info.reset(
121 new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
122 quic_server_info->Start();
123 rv = quic_server_info->WaitForDataReady(callback.callback());
124 EXPECT_EQ(OK, callback.GetResult(rv));
125 EXPECT_TRUE(quic_server_info->IsDataReady());
127 const QuicServerInfo::State& state1 = quic_server_info->state();
128 EXPECT_EQ(server_config_a, state1.server_config);
129 EXPECT_EQ(source_address_token_a, state1.source_address_token);
130 EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
131 EXPECT_EQ(2U, state1.certs.size());
132 EXPECT_EQ(cert_a, state1.certs[0]);
133 EXPECT_EQ(cert_b, state1.certs[1]);
135 RemoveMockTransaction(&kHostInfoTransaction1);
138 // Test that demonstrates different info is returned when the ports differ.
139 TEST(DiskCacheBasedQuicServerInfo, UpdateDifferentPorts) {
141 AddMockTransaction(&kHostInfoTransaction1);
142 AddMockTransaction(&kHostInfoTransaction2);
143 TestCompletionCallback callback;
145 // Persist data for port 443.
146 QuicSessionKey server_key1("www.google.com", 443, true, kPrivacyModeDisabled);
147 scoped_ptr<QuicServerInfo> quic_server_info1(
148 new DiskCacheBasedQuicServerInfo(server_key1, cache.http_cache()));
149 quic_server_info1->Start();
150 int rv = quic_server_info1->WaitForDataReady(callback.callback());
151 EXPECT_EQ(OK, callback.GetResult(rv));
153 QuicServerInfo::State* state1 = quic_server_info1->mutable_state();
154 EXPECT_TRUE(state1->certs.empty());
155 const string server_config_a = "server_config_a";
156 const string source_address_token_a = "source_address_token_a";
157 const string server_config_sig_a = "server_config_sig_a";
158 const string cert_a = "cert_a";
160 state1->server_config = server_config_a;
161 state1->source_address_token = source_address_token_a;
162 state1->server_config_sig = server_config_sig_a;
163 state1->certs.push_back(cert_a);
164 quic_server_info1->Persist();
166 // Wait until Persist() does the work.
167 base::MessageLoop::current()->RunUntilIdle();
169 // Persist data for port 80.
170 QuicSessionKey server_key2("www.google.com", 80, false, kPrivacyModeDisabled);
171 scoped_ptr<QuicServerInfo> quic_server_info2(
172 new DiskCacheBasedQuicServerInfo(server_key2, cache.http_cache()));
173 quic_server_info2->Start();
174 rv = quic_server_info2->WaitForDataReady(callback.callback());
175 EXPECT_EQ(OK, callback.GetResult(rv));
177 QuicServerInfo::State* state2 = quic_server_info2->mutable_state();
178 EXPECT_TRUE(state2->certs.empty());
179 const string server_config_b = "server_config_b";
180 const string source_address_token_b = "source_address_token_b";
181 const string server_config_sig_b = "server_config_sig_b";
182 const string cert_b = "cert_b";
184 state2->server_config = server_config_b;
185 state2->source_address_token = source_address_token_b;
186 state2->server_config_sig = server_config_sig_b;
187 state2->certs.push_back(cert_b);
188 quic_server_info2->Persist();
190 // Wait until Persist() does the work.
191 base::MessageLoop::current()->RunUntilIdle();
193 // Verify the stored QuicServerInfo for port 443.
194 scoped_ptr<QuicServerInfo> quic_server_info(
195 new DiskCacheBasedQuicServerInfo(server_key1, cache.http_cache()));
196 quic_server_info->Start();
197 rv = quic_server_info->WaitForDataReady(callback.callback());
198 EXPECT_EQ(OK, callback.GetResult(rv));
199 EXPECT_TRUE(quic_server_info->IsDataReady());
201 const QuicServerInfo::State& state_a = quic_server_info->state();
202 EXPECT_EQ(server_config_a, state_a.server_config);
203 EXPECT_EQ(source_address_token_a, state_a.source_address_token);
204 EXPECT_EQ(server_config_sig_a, state_a.server_config_sig);
205 EXPECT_EQ(1U, state_a.certs.size());
206 EXPECT_EQ(cert_a, state_a.certs[0]);
208 // Verify the stored QuicServerInfo for port 80.
209 quic_server_info.reset(
210 new DiskCacheBasedQuicServerInfo(server_key2, cache.http_cache()));
211 quic_server_info->Start();
212 rv = quic_server_info->WaitForDataReady(callback.callback());
213 EXPECT_EQ(OK, callback.GetResult(rv));
214 EXPECT_TRUE(quic_server_info->IsDataReady());
216 const QuicServerInfo::State& state_b = quic_server_info->state();
217 EXPECT_EQ(server_config_b, state_b.server_config);
218 EXPECT_EQ(source_address_token_b, state_b.source_address_token);
219 EXPECT_EQ(server_config_sig_b, state_b.server_config_sig);
220 EXPECT_EQ(1U, state_b.certs.size());
221 EXPECT_EQ(cert_b, state_b.certs[0]);
223 RemoveMockTransaction(&kHostInfoTransaction2);
224 RemoveMockTransaction(&kHostInfoTransaction1);
227 // Test IsReadyToPersist when there is a pending write.
228 TEST(DiskCacheBasedQuicServerInfo, IsReadyToPersist) {
230 AddMockTransaction(&kHostInfoTransaction1);
231 TestCompletionCallback callback;
233 QuicSessionKey server_key("www.google.com", 443, true, kPrivacyModeDisabled);
234 scoped_ptr<QuicServerInfo> quic_server_info(
235 new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
236 EXPECT_FALSE(quic_server_info->IsDataReady());
237 quic_server_info->Start();
238 int rv = quic_server_info->WaitForDataReady(callback.callback());
239 EXPECT_EQ(OK, callback.GetResult(rv));
240 EXPECT_TRUE(quic_server_info->IsDataReady());
242 QuicServerInfo::State* state = quic_server_info->mutable_state();
243 EXPECT_TRUE(state->certs.empty());
244 const string server_config_a = "server_config_a";
245 const string source_address_token_a = "source_address_token_a";
246 const string server_config_sig_a = "server_config_sig_a";
247 const string cert_a = "cert_a";
249 state->server_config = server_config_a;
250 state->source_address_token = source_address_token_a;
251 state->server_config_sig = server_config_sig_a;
252 state->certs.push_back(cert_a);
253 EXPECT_TRUE(quic_server_info->IsReadyToPersist());
254 quic_server_info->Persist();
256 // Once we call Persist, IsReadyToPersist should return false until Persist
258 EXPECT_FALSE(quic_server_info->IsReadyToPersist());
260 // Wait until Persist() does the work.
261 base::MessageLoop::current()->RunUntilIdle();
263 EXPECT_TRUE(quic_server_info->IsReadyToPersist());
265 // Verify that the state was updated.
266 quic_server_info.reset(
267 new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
268 quic_server_info->Start();
269 rv = quic_server_info->WaitForDataReady(callback.callback());
270 EXPECT_EQ(OK, callback.GetResult(rv));
271 EXPECT_TRUE(quic_server_info->IsDataReady());
273 const QuicServerInfo::State& state1 = quic_server_info->state();
274 EXPECT_EQ(server_config_a, state1.server_config);
275 EXPECT_EQ(source_address_token_a, state1.source_address_token);
276 EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
277 EXPECT_EQ(1U, state1.certs.size());
278 EXPECT_EQ(cert_a, state1.certs[0]);
280 RemoveMockTransaction(&kHostInfoTransaction1);