OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 "base/scoped_ptr.h" | |
6 #include "base/scoped_temp_dir.h" | |
7 #include "base/test/test_file_util.h" | |
8 #include "base/waitable_event.h" | |
9 #include "chrome/browser/password_manager/encryptor.h" | |
10 #include "chrome/browser/sync/engine/auth_watcher.h" | |
11 #include "chrome/browser/sync/engine/syncer_thread.h" | |
12 #include "chrome/browser/sync/util/user_settings.h" | |
13 #include "chrome/common/deprecated/event_sys-inl.h" | |
14 #include "chrome/common/net/http_return.h" | |
15 #include "chrome/common/net/gaia/gaia_authenticator.h" | |
16 #include "chrome/test/sync/engine/mock_connection_manager.h" | |
17 #include "chrome/test/sync/engine/test_directory_setter_upper.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 static FilePath::CharType kUserSettingsDB[] = | |
21 FILE_PATH_LITERAL("Settings.sqlite3"); | |
22 static const char* kTestUserAgent = "useragent"; | |
23 static const char* kTestServiceId = "serviceid"; | |
24 static const char* kTestGaiaURL = "http://gaia_url"; | |
25 static const char* kUserDisplayName = "Mr. Auth Watcher"; | |
26 static const char* kUserDisplayEmail = "authwatcherdisplay@gmail.com"; | |
27 static const char* kTestEmail = "authwatchertest@gmail.com"; | |
28 static const char* kWrongPassword = "wrongpassword"; | |
29 static const char* kCorrectPassword = "correctpassword"; | |
30 static const char* kValidSID = "validSID"; | |
31 static const char* kValidLSID = "validLSID"; | |
32 static const char* kInvalidAuthToken = "invalidAuthToken"; | |
33 static const char* kValidAuthToken = "validAuthToken"; | |
34 | |
35 namespace browser_sync { | |
36 | |
37 class GaiaAuthMockForAuthWatcher : public gaia::GaiaAuthenticator { | |
38 public: | |
39 GaiaAuthMockForAuthWatcher() : GaiaAuthenticator( | |
40 kTestUserAgent, kTestServiceId, kTestGaiaURL), | |
41 use_bad_auth_token_(false) {} | |
42 virtual ~GaiaAuthMockForAuthWatcher() {} | |
43 | |
44 virtual int GetBackoffDelaySeconds( | |
45 int current_backoff_delay) { | |
46 return SyncerThread::GetRecommendedDelaySeconds(current_backoff_delay); | |
47 } | |
48 | |
49 void SendBadAuthTokenForNextRequest() { use_bad_auth_token_ = true; } | |
50 | |
51 std::string renewed_token() { | |
52 return renewed_token_; | |
53 } | |
54 | |
55 protected: | |
56 bool PerformGaiaRequest(const AuthParams& params, AuthResults* results) { | |
57 if (params.password == kWrongPassword) { | |
58 results->auth_error = gaia::BadAuthentication; | |
59 return false; | |
60 } | |
61 if (params.password == kCorrectPassword) { | |
62 results->sid = kValidSID; | |
63 results->lsid = kValidLSID; | |
64 results->auth_token = kValidAuthToken; | |
65 } | |
66 if (use_bad_auth_token_) { | |
67 results->auth_token = kInvalidAuthToken; | |
68 use_bad_auth_token_ = false; | |
69 } | |
70 return true; | |
71 } | |
72 | |
73 void RenewAuthToken(const std::string& auth_token) { | |
74 renewed_token_ = auth_token; | |
75 } | |
76 | |
77 private: | |
78 // Whether we should send an invalid auth token on the next request. | |
79 bool use_bad_auth_token_; | |
80 std::string renewed_token_; | |
81 }; | |
82 | |
83 class AuthWatcherTest : public testing::Test { | |
84 public: | |
85 AuthWatcherTest() : metadb_(kUserDisplayEmail), | |
86 consumer_ready(false, false), | |
87 event_produced(false, false), | |
88 last_event_reason_(AuthWatcherEvent::ILLEGAL_VALUE) {} | |
89 virtual void SetUp() { | |
90 #if defined(OS_MACOSX) | |
91 // Need to mock the Keychain for unit tests on Mac to avoid possible | |
92 // blocking UI. |SetAuthTokenForService| uses Encryptor. | |
93 Encryptor::UseMockKeychain(true); | |
94 #endif | |
95 metadb_.SetUp(); | |
96 connection_.reset(new MockConnectionManager(metadb_.manager(), | |
97 metadb_.name())); | |
98 // Mock out data that would normally be sent back from a server. | |
99 connection()->SetAuthenticationResponseInfo(kValidAuthToken, | |
100 kUserDisplayName, kUserDisplayEmail, "ID"); | |
101 user_settings_.reset(new UserSettings()); | |
102 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); | |
103 FilePath user_settings_path = temp_dir_.path().Append(kUserSettingsDB); | |
104 user_settings_->Init(user_settings_path); | |
105 gaia_auth_ = new GaiaAuthMockForAuthWatcher(); | |
106 auth_watcher_ = new AuthWatcher(metadb_.manager(), connection_.get(), | |
107 kTestUserAgent, kTestServiceId, kTestGaiaURL, | |
108 user_settings_.get(), gaia_auth_); | |
109 authwatcher_hookup_.reset(NewEventListenerHookup(auth_watcher_->channel(), | |
110 this, &AuthWatcherTest::HandleAuthWatcherEvent)); | |
111 } | |
112 | |
113 virtual void TearDown() { | |
114 metadb_.TearDown(); | |
115 auth_watcher_->Shutdown(); | |
116 EXPECT_FALSE(auth_watcher()->message_loop()); | |
117 } | |
118 | |
119 void HandleAuthWatcherEvent(const AuthWatcherEvent& event) { | |
120 if (event.what_happened == AuthWatcherEvent::AUTHWATCHER_DESTROYED) | |
121 return; | |
122 consumer_ready.Wait(); // Block progress until the test is ready. | |
123 | |
124 last_event_reason_ = event.what_happened; | |
125 if (event.what_happened == AuthWatcherEvent::AUTH_SUCCEEDED) | |
126 user_email_ = event.user_email; | |
127 | |
128 event_produced.Signal(); | |
129 } | |
130 | |
131 AuthWatcherEvent::WhatHappened ConsumeNextEvent() { | |
132 consumer_ready.Signal(); | |
133 event_produced.Wait(); | |
134 return last_event_reason_; | |
135 } | |
136 | |
137 AuthWatcher* auth_watcher() { return auth_watcher_.get(); } | |
138 MockConnectionManager* connection() { return connection_.get(); } | |
139 GaiaAuthMockForAuthWatcher* gaia_auth() { return gaia_auth_; } | |
140 const std::string& user_email() { return user_email_; } | |
141 | |
142 private: | |
143 // Responsible for creating / deleting a temp dir containing user settings DB. | |
144 ScopedTempDir temp_dir_; | |
145 | |
146 // The event listener hookup registered for HandleAuthWatcherEvent. | |
147 scoped_ptr<EventListenerHookup> authwatcher_hookup_; | |
148 | |
149 // The sync engine pieces necessary to run an AuthWatcher. | |
150 TriggeredOpenTestDirectorySetterUpper metadb_; | |
151 scoped_ptr<MockConnectionManager> connection_; | |
152 scoped_ptr<UserSettings> user_settings_; | |
153 GaiaAuthMockForAuthWatcher* gaia_auth_; // Owned by auth_watcher_. | |
154 scoped_refptr<AuthWatcher> auth_watcher_; | |
155 | |
156 // This is used to block the AuthWatcherThread when it raises events until we | |
157 // are ready to read the event. It is not a manual-reset event, so it goes | |
158 // straight back to non-signaled after one thread (the main thread) is | |
159 // signaled (or "consumes" the signaled state). | |
160 base::WaitableEvent consumer_ready; | |
161 | |
162 // This is signaled by the AuthWatcherThread after it sets last_event_reason_ | |
163 // and possibly user_email_ for us to read. | |
164 base::WaitableEvent event_produced; | |
165 | |
166 // The 'WhatHappened' value from the last AuthWatcherEvent we handled. | |
167 AuthWatcherEvent::WhatHappened last_event_reason_; | |
168 | |
169 // Set when we receive an AUTH_SUCCEEDED event. | |
170 std::string user_email_; | |
171 | |
172 DISALLOW_COPY_AND_ASSIGN(AuthWatcherTest); | |
173 }; | |
174 | |
175 TEST_F(AuthWatcherTest, Construction) { | |
176 EXPECT_TRUE(auth_watcher()->message_loop()); | |
177 EXPECT_EQ("SyncEngine_AuthWatcherThread", | |
178 auth_watcher()->message_loop()->thread_name()); | |
179 EXPECT_TRUE(auth_watcher()->auth_backend_thread_.IsRunning()); | |
180 EXPECT_EQ(AuthWatcher::NOT_AUTHENTICATED, auth_watcher()->status()); | |
181 } | |
182 | |
183 TEST_F(AuthWatcherTest, AuthenticateGaiaAuthFailure) { | |
184 auth_watcher()->Authenticate(kTestEmail, kWrongPassword, | |
185 std::string(), // captcha_token | |
186 std::string()); // captcha_value | |
187 | |
188 EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent()); | |
189 EXPECT_EQ(AuthWatcherEvent::GAIA_AUTH_FAILED, ConsumeNextEvent()); | |
190 } | |
191 | |
192 TEST_F(AuthWatcherTest, AuthenticateBadAuthToken) { | |
193 gaia_auth()->SendBadAuthTokenForNextRequest(); | |
194 auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(), | |
195 std::string()); | |
196 EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent()); | |
197 EXPECT_EQ(AuthWatcherEvent::SERVICE_AUTH_FAILED, ConsumeNextEvent()); | |
198 } | |
199 | |
200 TEST_F(AuthWatcherTest, AuthenticateSuccess) { | |
201 auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(), | |
202 std::string()); | |
203 EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent()); | |
204 EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent()); | |
205 | |
206 // The server responds with a different email than what we used in the call | |
207 // to Authenticate, and the AuthWatcher should have told us about. | |
208 EXPECT_EQ(kUserDisplayEmail, user_email()); | |
209 } | |
210 | |
211 TEST_F(AuthWatcherTest, AuthenticateWithTokenBadAuthToken) { | |
212 auth_watcher()->AuthenticateWithToken(kTestEmail, kInvalidAuthToken); | |
213 EXPECT_EQ(AuthWatcherEvent::SERVICE_AUTH_FAILED, ConsumeNextEvent()); | |
214 } | |
215 | |
216 TEST_F(AuthWatcherTest, AuthenticateWithTokenSuccess) { | |
217 auth_watcher()->AuthenticateWithToken(kTestEmail, kValidAuthToken); | |
218 EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent()); | |
219 EXPECT_EQ(kUserDisplayEmail, user_email()); | |
220 } | |
221 | |
222 // Just check that the thread task was properly issued. | |
223 TEST_F(AuthWatcherTest, RenewAuthToken) { | |
224 auth_watcher()->Authenticate(kTestEmail, kCorrectPassword, std::string(), | |
225 std::string()); | |
226 EXPECT_EQ(AuthWatcherEvent::AUTHENTICATION_ATTEMPT_START, ConsumeNextEvent()); | |
227 EXPECT_EQ(AuthWatcherEvent::AUTH_SUCCEEDED, ConsumeNextEvent()); | |
228 | |
229 auth_watcher()->RenewAuthToken("updated_token"); | |
230 EXPECT_EQ(AuthWatcherEvent::AUTH_RENEWED, ConsumeNextEvent()); | |
231 EXPECT_EQ(gaia_auth()->renewed_token(), "updated_token"); | |
232 EXPECT_EQ(connection()->auth_token(), "updated_token"); | |
233 } | |
234 | |
235 } // namespace browser_sync | |
OLD | NEW |