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 17 namespace net { 18 namespace { 19 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", 23 "", 24 base::Time(), 25 "", 26 LOAD_NORMAL, 27 "", 28 "", 29 base::Time(), 30 "", 31 TEST_MODE_NORMAL, 32 NULL, 33 0 34 }; 35 36 const 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. 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 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. 73 TEST(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. 138 TEST(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. 227 TEST(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