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 "chrome/browser/net/http_server_properties_manager.h"
6
7#include "base/basictypes.h"
8#include "base/message_loop/message_loop.h"
9#include "base/prefs/pref_registry_simple.h"
10#include "base/prefs/testing_pref_service.h"
11#include "base/values.h"
12#include "chrome/common/pref_names.h"
13#include "content/public/test/test_browser_thread.h"
14#include "testing/gmock/include/gmock/gmock.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "url/gurl.h"
17
18namespace chrome_browser_net {
19
20namespace {
21
22using ::testing::_;
23using ::testing::Invoke;
24using ::testing::Mock;
25using ::testing::StrictMock;
26using content::BrowserThread;
27
28class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager {
29 public:
30  explicit TestingHttpServerPropertiesManager(PrefService* pref_service)
31      : HttpServerPropertiesManager(pref_service) {
32    InitializeOnIOThread();
33  }
34
35  virtual ~TestingHttpServerPropertiesManager() {
36  }
37
38  // Make these methods public for testing.
39  using HttpServerPropertiesManager::ScheduleUpdateCacheOnUI;
40  using HttpServerPropertiesManager::ScheduleUpdatePrefsOnIO;
41
42  // Post tasks without a delay during tests.
43  virtual void StartPrefsUpdateTimerOnIO(base::TimeDelta delay) OVERRIDE {
44    HttpServerPropertiesManager::StartPrefsUpdateTimerOnIO(
45        base::TimeDelta());
46  }
47
48  void UpdateCacheFromPrefsOnUIConcrete() {
49    HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI();
50  }
51
52  // Post tasks without a delay during tests.
53  virtual void StartCacheUpdateTimerOnUI(base::TimeDelta delay) OVERRIDE {
54    HttpServerPropertiesManager::StartCacheUpdateTimerOnUI(
55        base::TimeDelta());
56  }
57
58  void UpdatePrefsFromCacheOnIOConcrete(const base::Closure& callback) {
59    HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO(callback);
60  }
61
62  MOCK_METHOD0(UpdateCacheFromPrefsOnUI, void());
63  MOCK_METHOD1(UpdatePrefsFromCacheOnIO, void(const base::Closure&));
64  MOCK_METHOD5(UpdateCacheFromPrefsOnIO,
65               void(std::vector<std::string>* spdy_servers,
66                    net::SpdySettingsMap* spdy_settings_map,
67                    net::AlternateProtocolMap* alternate_protocol_map,
68                    net::PipelineCapabilityMap* pipeline_capability_map,
69                    bool detected_corrupted_prefs));
70  MOCK_METHOD4(UpdatePrefsOnUI,
71               void(base::ListValue* spdy_server_list,
72                    net::SpdySettingsMap* spdy_settings_map,
73                    net::AlternateProtocolMap* alternate_protocol_map,
74                    net::PipelineCapabilityMap* pipeline_capability_map));
75
76 private:
77  DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager);
78};
79
80class HttpServerPropertiesManagerTest : public testing::Test {
81 protected:
82  HttpServerPropertiesManagerTest()
83      : ui_thread_(BrowserThread::UI, &loop_),
84        io_thread_(BrowserThread::IO, &loop_) {
85  }
86
87  virtual void SetUp() OVERRIDE {
88    pref_service_.registry()->RegisterDictionaryPref(
89        prefs::kHttpServerProperties);
90    http_server_props_manager_.reset(
91        new StrictMock<TestingHttpServerPropertiesManager>(&pref_service_));
92    ExpectCacheUpdate();
93    loop_.RunUntilIdle();
94  }
95
96  virtual void TearDown() OVERRIDE {
97    if (http_server_props_manager_.get())
98      http_server_props_manager_->ShutdownOnUIThread();
99    loop_.RunUntilIdle();
100    // Delete |http_server_props_manager_| while |io_thread_| is mapping IO to
101    // |loop_|.
102    http_server_props_manager_.reset();
103  }
104
105  void ExpectCacheUpdate() {
106    EXPECT_CALL(*http_server_props_manager_, UpdateCacheFromPrefsOnUI())
107        .WillOnce(
108            Invoke(http_server_props_manager_.get(),
109                   &TestingHttpServerPropertiesManager::
110                   UpdateCacheFromPrefsOnUIConcrete));
111  }
112
113  void ExpectPrefsUpdate() {
114    EXPECT_CALL(*http_server_props_manager_, UpdatePrefsFromCacheOnIO(_))
115        .WillOnce(
116            Invoke(http_server_props_manager_.get(),
117                   &TestingHttpServerPropertiesManager::
118                   UpdatePrefsFromCacheOnIOConcrete));
119  }
120
121  void ExpectPrefsUpdateRepeatedly() {
122    EXPECT_CALL(*http_server_props_manager_, UpdatePrefsFromCacheOnIO(_))
123        .WillRepeatedly(
124            Invoke(http_server_props_manager_.get(),
125                   &TestingHttpServerPropertiesManager::
126                   UpdatePrefsFromCacheOnIOConcrete));
127  }
128
129  base::MessageLoop loop_;
130  TestingPrefServiceSimple pref_service_;
131  scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_;
132
133 private:
134  content::TestBrowserThread ui_thread_;
135  content::TestBrowserThread io_thread_;
136
137  DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerTest);
138};
139
140TEST_F(HttpServerPropertiesManagerTest,
141       SingleUpdateForTwoSpdyServerPrefChanges) {
142  ExpectCacheUpdate();
143
144  // Set up the prefs for www.google.com:80 and mail.google.com:80 and then set
145  // it twice. Only expect a single cache update.
146
147  base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
148
149  // Set supports_spdy for www.google.com:80.
150  server_pref_dict->SetBoolean("supports_spdy", true);
151
152  // Set up alternate_protocol for www.google.com:80.
153  base::DictionaryValue* alternate_protocol = new base::DictionaryValue;
154  alternate_protocol->SetInteger("port", 443);
155  alternate_protocol->SetString("protocol_str", "npn-spdy/3");
156  server_pref_dict->SetWithoutPathExpansion(
157      "alternate_protocol", alternate_protocol);
158
159  // Set pipeline capability for www.google.com:80.
160  server_pref_dict->SetInteger("pipeline_capability", net::PIPELINE_CAPABLE);
161
162  // Set the server preference for www.google.com:80.
163  base::DictionaryValue* servers_dict = new base::DictionaryValue;
164  servers_dict->SetWithoutPathExpansion(
165      "www.google.com:80", server_pref_dict);
166
167  // Set the preference for mail.google.com server.
168  base::DictionaryValue* server_pref_dict1 = new base::DictionaryValue;
169
170  // Set supports_spdy for mail.google.com:80
171  server_pref_dict1->SetBoolean("supports_spdy", true);
172
173  // Set up alternate_protocol for mail.google.com:80
174  base::DictionaryValue* alternate_protocol1 = new base::DictionaryValue;
175  alternate_protocol1->SetInteger("port", 444);
176  alternate_protocol1->SetString("protocol_str", "npn-spdy/3.1");
177
178  server_pref_dict1->SetWithoutPathExpansion(
179      "alternate_protocol", alternate_protocol1);
180
181  // Set pipelining capability for mail.google.com:80
182  server_pref_dict1->SetInteger("pipeline_capability", net::PIPELINE_INCAPABLE);
183
184  // Set the server preference for mail.google.com:80.
185  servers_dict->SetWithoutPathExpansion(
186      "mail.google.com:80", server_pref_dict1);
187
188  base::DictionaryValue* http_server_properties_dict =
189      new base::DictionaryValue;
190  HttpServerPropertiesManager::SetVersion(http_server_properties_dict, -1);
191  http_server_properties_dict->SetWithoutPathExpansion("servers", servers_dict);
192
193  // Set the same value for kHttpServerProperties multiple times.
194  pref_service_.SetManagedPref(prefs::kHttpServerProperties,
195                               http_server_properties_dict);
196  base::DictionaryValue* http_server_properties_dict2 =
197      http_server_properties_dict->DeepCopy();
198  pref_service_.SetManagedPref(prefs::kHttpServerProperties,
199                               http_server_properties_dict2);
200
201  loop_.RunUntilIdle();
202  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
203
204  // Verify SupportsSpdy.
205  EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(
206      net::HostPortPair::FromString("www.google.com:80")));
207  EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(
208      net::HostPortPair::FromString("mail.google.com:80")));
209  EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(
210      net::HostPortPair::FromString("foo.google.com:1337")));
211
212  // Verify AlternateProtocol.
213  ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
214      net::HostPortPair::FromString("www.google.com:80")));
215  ASSERT_TRUE(http_server_props_manager_->HasAlternateProtocol(
216      net::HostPortPair::FromString("mail.google.com:80")));
217  net::PortAlternateProtocolPair port_alternate_protocol =
218      http_server_props_manager_->GetAlternateProtocol(
219          net::HostPortPair::FromString("www.google.com:80"));
220  EXPECT_EQ(443, port_alternate_protocol.port);
221  EXPECT_EQ(net::NPN_SPDY_3, port_alternate_protocol.protocol);
222  port_alternate_protocol =
223      http_server_props_manager_->GetAlternateProtocol(
224          net::HostPortPair::FromString("mail.google.com:80"));
225  EXPECT_EQ(444, port_alternate_protocol.port);
226  EXPECT_EQ(net::NPN_SPDY_3_1, port_alternate_protocol.protocol);
227
228  // Verify pipeline capability.
229  EXPECT_EQ(net::PIPELINE_CAPABLE,
230            http_server_props_manager_->GetPipelineCapability(
231                net::HostPortPair::FromString("www.google.com:80")));
232  EXPECT_EQ(net::PIPELINE_INCAPABLE,
233            http_server_props_manager_->GetPipelineCapability(
234                net::HostPortPair::FromString("mail.google.com:80")));
235}
236
237TEST_F(HttpServerPropertiesManagerTest, SupportsSpdy) {
238  ExpectPrefsUpdate();
239
240  // Post an update task to the IO thread. SetSupportsSpdy calls
241  // ScheduleUpdatePrefsOnIO.
242
243  // Add mail.google.com:443 as a supporting spdy server.
244  net::HostPortPair spdy_server_mail("mail.google.com", 443);
245  EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
246  http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
247
248  // Run the task.
249  loop_.RunUntilIdle();
250
251  EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
252  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
253}
254
255TEST_F(HttpServerPropertiesManagerTest, SetSpdySetting) {
256  ExpectPrefsUpdate();
257
258  // Add SpdySetting for mail.google.com:443.
259  net::HostPortPair spdy_server_mail("mail.google.com", 443);
260  const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
261  const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
262  const uint32 value1 = 31337;
263  http_server_props_manager_->SetSpdySetting(
264      spdy_server_mail, id1, flags1, value1);
265
266  // Run the task.
267  loop_.RunUntilIdle();
268
269  const net::SettingsMap& settings_map1_ret =
270      http_server_props_manager_->GetSpdySettings(spdy_server_mail);
271  ASSERT_EQ(1U, settings_map1_ret.size());
272  net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
273  EXPECT_TRUE(it1_ret != settings_map1_ret.end());
274  net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
275  EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
276  EXPECT_EQ(value1, flags_and_value1_ret.second);
277
278  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
279}
280
281TEST_F(HttpServerPropertiesManagerTest, ClearSpdySetting) {
282  ExpectPrefsUpdateRepeatedly();
283
284  // Add SpdySetting for mail.google.com:443.
285  net::HostPortPair spdy_server_mail("mail.google.com", 443);
286  const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
287  const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
288  const uint32 value1 = 31337;
289  http_server_props_manager_->SetSpdySetting(
290      spdy_server_mail, id1, flags1, value1);
291
292  // Run the task.
293  loop_.RunUntilIdle();
294
295  const net::SettingsMap& settings_map1_ret =
296      http_server_props_manager_->GetSpdySettings(spdy_server_mail);
297  ASSERT_EQ(1U, settings_map1_ret.size());
298  net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
299  EXPECT_TRUE(it1_ret != settings_map1_ret.end());
300  net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
301  EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
302  EXPECT_EQ(value1, flags_and_value1_ret.second);
303
304  // Clear SpdySetting for mail.google.com:443.
305  http_server_props_manager_->ClearSpdySettings(spdy_server_mail);
306
307  // Run the task.
308  loop_.RunUntilIdle();
309
310  // Verify that there are no entries in the settings map for
311  // mail.google.com:443.
312  const net::SettingsMap& settings_map2_ret =
313      http_server_props_manager_->GetSpdySettings(spdy_server_mail);
314  ASSERT_EQ(0U, settings_map2_ret.size());
315
316  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
317}
318
319TEST_F(HttpServerPropertiesManagerTest, ClearAllSpdySetting) {
320  ExpectPrefsUpdateRepeatedly();
321
322  // Add SpdySetting for mail.google.com:443.
323  net::HostPortPair spdy_server_mail("mail.google.com", 443);
324  const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
325  const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
326  const uint32 value1 = 31337;
327  http_server_props_manager_->SetSpdySetting(
328      spdy_server_mail, id1, flags1, value1);
329
330  // Run the task.
331  loop_.RunUntilIdle();
332
333  const net::SettingsMap& settings_map1_ret =
334      http_server_props_manager_->GetSpdySettings(spdy_server_mail);
335  ASSERT_EQ(1U, settings_map1_ret.size());
336  net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
337  EXPECT_TRUE(it1_ret != settings_map1_ret.end());
338  net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
339  EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
340  EXPECT_EQ(value1, flags_and_value1_ret.second);
341
342  // Clear All SpdySettings.
343  http_server_props_manager_->ClearAllSpdySettings();
344
345  // Run the task.
346  loop_.RunUntilIdle();
347
348  // Verify that there are no entries in the settings map.
349  const net::SpdySettingsMap& spdy_settings_map2_ret =
350      http_server_props_manager_->spdy_settings_map();
351  ASSERT_EQ(0U, spdy_settings_map2_ret.size());
352
353  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
354}
355
356TEST_F(HttpServerPropertiesManagerTest, HasAlternateProtocol) {
357  ExpectPrefsUpdate();
358
359  net::HostPortPair spdy_server_mail("mail.google.com", 80);
360  EXPECT_FALSE(
361      http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
362  http_server_props_manager_->SetAlternateProtocol(
363      spdy_server_mail, 443, net::NPN_SPDY_3);
364
365  // Run the task.
366  loop_.RunUntilIdle();
367  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
368
369  ASSERT_TRUE(
370      http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
371  net::PortAlternateProtocolPair port_alternate_protocol =
372      http_server_props_manager_->GetAlternateProtocol(spdy_server_mail);
373  EXPECT_EQ(443, port_alternate_protocol.port);
374  EXPECT_EQ(net::NPN_SPDY_3, port_alternate_protocol.protocol);
375}
376
377TEST_F(HttpServerPropertiesManagerTest, PipelineCapability) {
378  ExpectPrefsUpdate();
379
380  net::HostPortPair known_pipeliner("pipeline.com", 8080);
381  net::HostPortPair bad_pipeliner("wordpress.com", 80);
382  EXPECT_EQ(net::PIPELINE_UNKNOWN,
383            http_server_props_manager_->GetPipelineCapability(known_pipeliner));
384  EXPECT_EQ(net::PIPELINE_UNKNOWN,
385            http_server_props_manager_->GetPipelineCapability(bad_pipeliner));
386
387  // Post an update task to the IO thread. SetPipelineCapability calls
388  // ScheduleUpdatePrefsOnIO.
389  http_server_props_manager_->SetPipelineCapability(known_pipeliner,
390                                                    net::PIPELINE_CAPABLE);
391  http_server_props_manager_->SetPipelineCapability(bad_pipeliner,
392                                                    net::PIPELINE_INCAPABLE);
393
394  // Run the task.
395  loop_.RunUntilIdle();
396
397  EXPECT_EQ(net::PIPELINE_CAPABLE,
398            http_server_props_manager_->GetPipelineCapability(known_pipeliner));
399  EXPECT_EQ(net::PIPELINE_INCAPABLE,
400            http_server_props_manager_->GetPipelineCapability(bad_pipeliner));
401  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
402}
403
404TEST_F(HttpServerPropertiesManagerTest, Clear) {
405  ExpectPrefsUpdate();
406
407  net::HostPortPair spdy_server_mail("mail.google.com", 443);
408  http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true);
409  http_server_props_manager_->SetAlternateProtocol(
410      spdy_server_mail, 443, net::NPN_SPDY_3);
411
412  const net::SpdySettingsIds id1 = net::SETTINGS_UPLOAD_BANDWIDTH;
413  const net::SpdySettingsFlags flags1 = net::SETTINGS_FLAG_PLEASE_PERSIST;
414  const uint32 value1 = 31337;
415  http_server_props_manager_->SetSpdySetting(
416      spdy_server_mail, id1, flags1, value1);
417
418  net::HostPortPair known_pipeliner("pipeline.com", 8080);
419  http_server_props_manager_->SetPipelineCapability(known_pipeliner,
420                                                    net::PIPELINE_CAPABLE);
421
422  // Run the task.
423  loop_.RunUntilIdle();
424
425  EXPECT_TRUE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
426  EXPECT_TRUE(
427      http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
428
429  // Check SPDY settings values.
430  const net::SettingsMap& settings_map1_ret =
431      http_server_props_manager_->GetSpdySettings(spdy_server_mail);
432  ASSERT_EQ(1U, settings_map1_ret.size());
433  net::SettingsMap::const_iterator it1_ret = settings_map1_ret.find(id1);
434  EXPECT_TRUE(it1_ret != settings_map1_ret.end());
435  net::SettingsFlagsAndValue flags_and_value1_ret = it1_ret->second;
436  EXPECT_EQ(net::SETTINGS_FLAG_PERSISTED, flags_and_value1_ret.first);
437  EXPECT_EQ(value1, flags_and_value1_ret.second);
438
439  EXPECT_EQ(net::PIPELINE_CAPABLE,
440            http_server_props_manager_->GetPipelineCapability(known_pipeliner));
441
442  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
443
444  ExpectPrefsUpdate();
445
446  // Clear http server data, time out if we do not get a completion callback.
447  http_server_props_manager_->Clear(base::MessageLoop::QuitClosure());
448  loop_.Run();
449
450  EXPECT_FALSE(http_server_props_manager_->SupportsSpdy(spdy_server_mail));
451  EXPECT_FALSE(
452      http_server_props_manager_->HasAlternateProtocol(spdy_server_mail));
453
454  const net::SettingsMap& settings_map2_ret =
455      http_server_props_manager_->GetSpdySettings(spdy_server_mail);
456  EXPECT_EQ(0U, settings_map2_ret.size());
457
458  EXPECT_EQ(net::PIPELINE_UNKNOWN,
459            http_server_props_manager_->GetPipelineCapability(known_pipeliner));
460
461  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
462}
463
464TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) {
465  // Post an update task to the UI thread.
466  http_server_props_manager_->ScheduleUpdateCacheOnUI();
467  // Shutdown comes before the task is executed.
468  http_server_props_manager_->ShutdownOnUIThread();
469  http_server_props_manager_.reset();
470  // Run the task after shutdown and deletion.
471  loop_.RunUntilIdle();
472}
473
474TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache1) {
475  // Post an update task.
476  http_server_props_manager_->ScheduleUpdateCacheOnUI();
477  // Shutdown comes before the task is executed.
478  http_server_props_manager_->ShutdownOnUIThread();
479  // Run the task after shutdown, but before deletion.
480  loop_.RunUntilIdle();
481  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
482  http_server_props_manager_.reset();
483  loop_.RunUntilIdle();
484}
485
486TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache2) {
487  http_server_props_manager_->UpdateCacheFromPrefsOnUIConcrete();
488  // Shutdown comes before the task is executed.
489  http_server_props_manager_->ShutdownOnUIThread();
490  // Run the task after shutdown, but before deletion.
491  loop_.RunUntilIdle();
492  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
493  http_server_props_manager_.reset();
494  loop_.RunUntilIdle();
495}
496
497//
498// Tests for shutdown when updating prefs.
499//
500TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs0) {
501  // Post an update task to the IO thread.
502  http_server_props_manager_->ScheduleUpdatePrefsOnIO();
503  // Shutdown comes before the task is executed.
504  http_server_props_manager_->ShutdownOnUIThread();
505  http_server_props_manager_.reset();
506  // Run the task after shutdown and deletion.
507  loop_.RunUntilIdle();
508}
509
510TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs1) {
511  ExpectPrefsUpdate();
512  // Post an update task.
513  http_server_props_manager_->ScheduleUpdatePrefsOnIO();
514  // Shutdown comes before the task is executed.
515  http_server_props_manager_->ShutdownOnUIThread();
516  // Run the task after shutdown, but before deletion.
517  loop_.RunUntilIdle();
518  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
519  http_server_props_manager_.reset();
520  loop_.RunUntilIdle();
521}
522
523TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) {
524  // This posts a task to the UI thread.
525  http_server_props_manager_->UpdatePrefsFromCacheOnIOConcrete(base::Closure());
526  // Shutdown comes before the task is executed.
527  http_server_props_manager_->ShutdownOnUIThread();
528  // Run the task after shutdown, but before deletion.
529  loop_.RunUntilIdle();
530  Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
531  http_server_props_manager_.reset();
532  loop_.RunUntilIdle();
533}
534
535}  // namespace
536
537}  // namespace chrome_browser_net
538