Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(310)

Side by Side Diff: chrome/browser/chromeos/login/login_utils_browsertest.cc

Issue 11358160: Fixed shutdown of LoginUtilsTest. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/login/login_utils.h" 5 #include "chrome/browser/chromeos/login/login_utils.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/path_service.h" 11 #include "base/path_service.h"
12 #include "base/scoped_temp_dir.h" 12 #include "base/scoped_temp_dir.h"
13 #include "base/string_util.h" 13 #include "base/string_util.h"
14 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/sequenced_worker_pool.h" 15 #include "base/threading/sequenced_worker_pool.h"
16 #include "base/threading/thread.h"
15 #include "chrome/browser/chromeos/cros/cros_library.h" 17 #include "chrome/browser/chromeos/cros/cros_library.h"
16 #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h" 18 #include "chrome/browser/chromeos/cros/mock_cryptohome_library.h"
17 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h" 19 #include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
18 #include "chrome/browser/chromeos/login/authenticator.h" 20 #include "chrome/browser/chromeos/login/authenticator.h"
19 #include "chrome/browser/chromeos/login/login_status_consumer.h" 21 #include "chrome/browser/chromeos/login/login_status_consumer.h"
20 #include "chrome/browser/chromeos/login/user_manager.h" 22 #include "chrome/browser/chromeos/login/user_manager.h"
21 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h" 23 #include "chrome/browser/chromeos/settings/device_settings_test_helper.h"
22 #include "chrome/browser/io_thread.h" 24 #include "chrome/browser/io_thread.h"
23 #include "chrome/browser/net/predictor.h" 25 #include "chrome/browser/net/predictor.h"
24 #include "chrome/browser/policy/browser_policy_connector.h" 26 #include "chrome/browser/policy/browser_policy_connector.h"
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 "http://server/device_management?request=policy"; 89 "http://server/device_management?request=policy";
88 90
89 const char kDMToken[] = "1234"; 91 const char kDMToken[] = "1234";
90 92
91 // Used to mark |flag|, indicating that RefreshPolicies() has executed its 93 // Used to mark |flag|, indicating that RefreshPolicies() has executed its
92 // callback. 94 // callback.
93 void SetFlag(bool* flag) { 95 void SetFlag(bool* flag) {
94 *flag = true; 96 *flag = true;
95 } 97 }
96 98
99 // Single task of the fake IO loop used in the test, that just waits until
100 // it is signaled to quit or perform some work.
101 // |completion| is the event to wait for, and |work| is the task to invoke
102 // when signaled. If the task returns false then this quits the IO loop.
103 void BlockLoop(base::WaitableEvent* completion, base::Callback<bool()> work) {
104 do {
105 completion->Wait();
Nikita (slow) 2012/11/13 10:11:33 Is this a recommended way to handle fake IO look l
Joao da Silva 2012/11/13 13:11:04 This is not common at all, as you suspected. Othe
106 } while (work.Run());
107 MessageLoop::current()->QuitNow();
108 }
109
97 ACTION_P(MockSessionManagerClientRetrievePolicyCallback, policy) { 110 ACTION_P(MockSessionManagerClientRetrievePolicyCallback, policy) {
98 arg0.Run(*policy); 111 arg0.Run(*policy);
99 } 112 }
100 113
101 ACTION_P(MockSessionManagerClientStorePolicyCallback, success) { 114 ACTION_P(MockSessionManagerClientStorePolicyCallback, success) {
102 arg1.Run(success); 115 arg1.Run(success);
103 } 116 }
104 117
105 class LoginUtilsTest : public testing::Test, 118 class LoginUtilsTest : public testing::Test,
106 public LoginUtils::Delegate, 119 public LoginUtils::Delegate,
107 public LoginStatusConsumer { 120 public LoginStatusConsumer {
108 public: 121 public:
109 // Initialization here is important. The UI thread gets the test's 122 // Initialization here is important. The UI thread gets the test's
110 // message loop, as does the file thread (which never actually gets 123 // message loop, as does the file thread (which never actually gets
111 // started - so this is a way to fake multiple threads on a single 124 // started - so this is a way to fake multiple threads on a single
112 // test thread). The IO thread does not get the message loop set, 125 // test thread). The IO thread does not get the message loop set,
113 // and is never started. This is necessary so that we skip various 126 // and is never started. This is necessary so that we skip various
114 // bits of initialization that get posted to the IO thread. We do 127 // bits of initialization that get posted to the IO thread. We do
115 // however, at one point in the test, temporarily set the message 128 // however, at one point in the test, temporarily set the message
116 // loop for the IO thread. 129 // loop for the IO thread.
117 LoginUtilsTest() 130 LoginUtilsTest()
118 : loop_(MessageLoop::TYPE_IO), 131 : fake_io_thread_completion_(false, false),
132 fake_io_thread_("fake_io_thread"),
133 loop_(MessageLoop::TYPE_IO),
119 browser_process_( 134 browser_process_(
120 static_cast<TestingBrowserProcess*>(g_browser_process)), 135 static_cast<TestingBrowserProcess*>(g_browser_process)),
121 local_state_(browser_process_), 136 local_state_(browser_process_),
122 ui_thread_(content::BrowserThread::UI, &loop_), 137 ui_thread_(BrowserThread::UI, &loop_),
123 db_thread_(content::BrowserThread::DB), 138 db_thread_(BrowserThread::DB),
124 file_thread_(content::BrowserThread::FILE, &loop_), 139 file_thread_(BrowserThread::FILE, &loop_),
125 io_thread_(content::BrowserThread::IO),
126 mock_async_method_caller_(NULL), 140 mock_async_method_caller_(NULL),
127 connector_(NULL), 141 connector_(NULL),
128 cryptohome_(NULL), 142 cryptohome_(NULL),
129 prepared_profile_(NULL) {} 143 prepared_profile_(NULL) {}
130 144
131 virtual void SetUp() OVERRIDE { 145 virtual void SetUp() OVERRIDE {
146 // This test is not a full blown InProcessBrowserTest, and doesn't have
147 // all the usual threads running. However a lot of subsystems pulled from
148 // ProfileImpl post to IO (usually from ProfileIOData), and DCHECK that
149 // those tasks were posted. Those tasks in turn depend on a lot of other
150 // components that aren't there during this test, so this kludge is used to
151 // have a running IO loop that doesn't really execute any tasks.
152 //
153 // See InvokeOnIO() below for a way to perform specific tasks on IO, when
154 // that's necessary.
155
156 // A thread is needed to create a new MessageLoop, since there can be only
157 // one loop per thread.
158 fake_io_thread_.StartWithOptions(
159 base::Thread::Options(MessageLoop::TYPE_IO, 0));
160 MessageLoop* fake_io_loop = fake_io_thread_.message_loop();
161 // Make this loop enter the single task, BlockLoop(). Pass in the completion
162 // event and the work callback.
163 fake_io_loop->PostTask(
164 FROM_HERE,
165 base::Bind(
166 BlockLoop,
167 &fake_io_thread_completion_,
168 base::Bind(&LoginUtilsTest::DoIOWork, base::Unretained(this))));
169 // Map BrowserThread::IO to this loop. This allows posting to IO but nothing
170 // will be executed.
171 io_thread_.reset(
172 new content::TestBrowserThread(BrowserThread::IO, fake_io_loop));
173
132 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); 174 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
133 175
134 CommandLine* command_line = CommandLine::ForCurrentProcess(); 176 CommandLine* command_line = CommandLine::ForCurrentProcess();
135 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, kDMServer); 177 command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, kDMServer);
136 command_line->AppendSwitchASCII(switches::kLoginProfile, "user"); 178 command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
137 179
138 local_state_.Get()->RegisterStringPref(prefs::kApplicationLocale, ""); 180 local_state_.Get()->RegisterStringPref(prefs::kApplicationLocale, "");
139 181
140 // DBusThreadManager should be initialized before io_thread_state_, as 182 // DBusThreadManager should be initialized before io_thread_state_, as
141 // DBusThreadManager is used from chromeos::ProxyConfigServiceImpl, 183 // DBusThreadManager is used from chromeos::ProxyConfigServiceImpl,
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 connector_ = browser_process_->browser_policy_connector(); 262 connector_ = browser_process_->browser_policy_connector();
221 connector_->Init(); 263 connector_->Init();
222 264
223 RunUntilIdle(); 265 RunUntilIdle();
224 } 266 }
225 267
226 virtual void TearDown() OVERRIDE { 268 virtual void TearDown() OVERRIDE {
227 cryptohome::AsyncMethodCaller::Shutdown(); 269 cryptohome::AsyncMethodCaller::Shutdown();
228 mock_async_method_caller_ = NULL; 270 mock_async_method_caller_ = NULL;
229 271
230 RunUntilIdle(); 272 InvokeOnIO(
231 { 273 base::Bind(&LoginUtilsTest::TearDownOnIO, base::Unretained(this)));
232 // chrome_browser_net::Predictor usually skips its shutdown routines on
233 // unit_tests, but does the full thing when
234 // g_browser_process->profile_manager() is valid during initialization.
235 // Run a task on a temporary BrowserThread::IO that allows skipping
236 // these routines.
237 //
238 // It is important to not have a fake message loop on the IO
239 // thread for the whole test, see comment on LoginUtilsTest
240 // constructor for details.
241 io_thread_.DeprecatedSetMessageLoop(&loop_);
242 loop_.PostTask(FROM_HERE,
243 base::Bind(&LoginUtilsTest::TearDownOnIO,
244 base::Unretained(this)));
245 RunUntilIdle();
246 io_thread_.DeprecatedSetMessageLoop(NULL);
247 }
248 274
249 // These trigger some tasks that have to run while BrowserThread::UI 275 // These trigger some tasks that have to run while BrowserThread::UI
250 // exists. Delete all the profiles before deleting the connector. 276 // exists. Delete all the profiles before deleting the connector.
251 browser_process_->SetProfileManager(NULL); 277 browser_process_->SetProfileManager(NULL);
252 connector_ = NULL; 278 connector_ = NULL;
253 browser_process_->SetBrowserPolicyConnector(NULL); 279 browser_process_->SetBrowserPolicyConnector(NULL);
280 QuitIOLoop();
254 RunUntilIdle(); 281 RunUntilIdle();
255 } 282 }
256 283
257 void TearDownOnIO() { 284 void TearDownOnIO() {
285 // chrome_browser_net::Predictor usually skips its shutdown routines on
286 // unit_tests, but does the full thing when
287 // g_browser_process->profile_manager() is valid during initialization.
288 // That includes a WaitableEvent on UI waiting for a task on IO, so that
289 // task must execute. Do it directly from here now.
258 std::vector<Profile*> profiles = 290 std::vector<Profile*> profiles =
259 browser_process_->profile_manager()->GetLoadedProfiles(); 291 browser_process_->profile_manager()->GetLoadedProfiles();
260 for (size_t i = 0; i < profiles.size(); ++i) { 292 for (size_t i = 0; i < profiles.size(); ++i) {
261 chrome_browser_net::Predictor* predictor = 293 chrome_browser_net::Predictor* predictor =
262 profiles[i]->GetNetworkPredictor(); 294 profiles[i]->GetNetworkPredictor();
263 if (predictor) { 295 if (predictor) {
264 predictor->EnablePredictorOnIOThread(false); 296 predictor->EnablePredictorOnIOThread(false);
265 predictor->Shutdown(); 297 predictor->Shutdown();
266 } 298 }
267 } 299 }
268 } 300 }
269 301
270 void RunUntilIdle() { 302 void RunUntilIdle() {
271 loop_.RunUntilIdle(); 303 loop_.RunUntilIdle();
272 BrowserThread::GetBlockingPool()->FlushForTesting(); 304 BrowserThread::GetBlockingPool()->FlushForTesting();
273 loop_.RunUntilIdle(); 305 loop_.RunUntilIdle();
274 } 306 }
275 307
308 // Invokes |task| on the IO loop and returns after it has executed.
309 void InvokeOnIO(const base::Closure& task) {
310 fake_io_thread_work_ = task;
311 fake_io_thread_completion_.Signal();
312 content::RunMessageLoop();
313 }
314
315 // Makes the fake IO loop return.
316 void QuitIOLoop() {
317 fake_io_thread_completion_.Signal();
318 content::RunMessageLoop();
319 }
320
321 // Helper for BlockLoop, InvokeOnIO and QuitIOLoop.
322 bool DoIOWork() {
323 bool has_work = !fake_io_thread_work_.is_null();
324 if (has_work)
325 fake_io_thread_work_.Run();
326 fake_io_thread_work_.Reset();
327 BrowserThread::PostTask(
328 BrowserThread::UI, FROM_HERE,
329 MessageLoop::QuitWhenIdleClosure());
330 // If there was work then keep waiting for more work.
331 // If there was no work then quit the fake IO loop.
332 return has_work;
333 }
334
276 virtual void OnProfilePrepared(Profile* profile) OVERRIDE { 335 virtual void OnProfilePrepared(Profile* profile) OVERRIDE {
277 EXPECT_FALSE(prepared_profile_); 336 EXPECT_FALSE(prepared_profile_);
278 prepared_profile_ = profile; 337 prepared_profile_ = profile;
279 } 338 }
280 339
281 virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE { 340 virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE {
282 FAIL() << "OnLoginFailure not expected"; 341 FAIL() << "OnLoginFailure not expected";
283 } 342 }
284 343
285 virtual void OnLoginSuccess(const std::string& username, 344 virtual void OnLoginSuccess(const std::string& username,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 430
372 net::TestURLFetcher* PrepareDMPolicyFetcher() { 431 net::TestURLFetcher* PrepareDMPolicyFetcher() {
373 em::DeviceManagementResponse response; 432 em::DeviceManagementResponse response;
374 response.mutable_policy_response()->add_response(); 433 response.mutable_policy_response()->add_response();
375 return PrepareDMServiceFetcher(kDMPolicyRequest, response); 434 return PrepareDMServiceFetcher(kDMPolicyRequest, response);
376 } 435 }
377 436
378 protected: 437 protected:
379 ScopedStubCrosEnabler stub_cros_enabler_; 438 ScopedStubCrosEnabler stub_cros_enabler_;
380 439
440 base::Closure fake_io_thread_work_;
441 base::WaitableEvent fake_io_thread_completion_;
442 base::Thread fake_io_thread_;
443
381 MessageLoop loop_; 444 MessageLoop loop_;
382 TestingBrowserProcess* browser_process_; 445 TestingBrowserProcess* browser_process_;
383 ScopedTestingLocalState local_state_; 446 ScopedTestingLocalState local_state_;
384 447
385 content::TestBrowserThread ui_thread_; 448 content::TestBrowserThread ui_thread_;
386 content::TestBrowserThread db_thread_; 449 content::TestBrowserThread db_thread_;
387 content::TestBrowserThread file_thread_; 450 content::TestBrowserThread file_thread_;
388 content::TestBrowserThread io_thread_; 451 scoped_ptr<content::TestBrowserThread> io_thread_;
389 scoped_ptr<IOThread> io_thread_state_; 452 scoped_ptr<IOThread> io_thread_state_;
390 453
391 MockDBusThreadManager mock_dbus_thread_manager_; 454 MockDBusThreadManager mock_dbus_thread_manager_;
392 input_method::MockInputMethodManager mock_input_method_manager_; 455 input_method::MockInputMethodManager mock_input_method_manager_;
393 net::TestURLFetcherFactory test_url_fetcher_factory_; 456 net::TestURLFetcherFactory test_url_fetcher_factory_;
394 457
395 cryptohome::MockAsyncMethodCaller* mock_async_method_caller_; 458 cryptohome::MockAsyncMethodCaller* mock_async_method_caller_;
396 459
397 policy::BrowserPolicyConnector* connector_; 460 policy::BrowserPolicyConnector* connector_;
398 MockCryptohomeLibrary* cryptohome_; 461 MockCryptohomeLibrary* cryptohome_;
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 } 654 }
592 655
593 INSTANTIATE_TEST_CASE_P( 656 INSTANTIATE_TEST_CASE_P(
594 LoginUtilsBlockingLoginTestInstance, 657 LoginUtilsBlockingLoginTestInstance,
595 LoginUtilsBlockingLoginTest, 658 LoginUtilsBlockingLoginTest,
596 testing::Values(0, 1, 2, 3, 4, 5)); 659 testing::Values(0, 1, 2, 3, 4, 5));
597 660
598 } // namespace 661 } // namespace
599 662
600 } 663 }
OLDNEW
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698