1 // Copyright (c) 2011 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.
7 #include "base/strings/string16.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "net/base/net_errors.h"
12 #include "net/http/http_auth_cache.h"
13 #include "net/http/http_auth_handler.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using base::ASCIIToUTF16
;
22 class MockAuthHandler
: public HttpAuthHandler
{
24 MockAuthHandler(HttpAuth::Scheme scheme
,
25 const std::string
& realm
,
26 HttpAuth::Target target
) {
27 // Can't use initializer list since these are members of the base class.
28 auth_scheme_
= scheme
;
35 virtual HttpAuth::AuthorizationResult
HandleAnotherChallenge(
36 HttpAuth::ChallengeTokenizer
* challenge
) OVERRIDE
{
37 return HttpAuth::AUTHORIZATION_RESULT_REJECT
;
41 virtual bool Init(HttpAuth::ChallengeTokenizer
* challenge
) OVERRIDE
{
42 return false; // Unused.
45 virtual int GenerateAuthTokenImpl(const AuthCredentials
*,
46 const HttpRequestInfo
*,
47 const CompletionCallback
& callback
,
48 std::string
* auth_token
) OVERRIDE
{
49 *auth_token
= "mock-credentials";
55 virtual ~MockAuthHandler() {}
58 const char* kRealm1
= "Realm1";
59 const char* kRealm2
= "Realm2";
60 const char* kRealm3
= "Realm3";
61 const char* kRealm4
= "Realm4";
62 const char* kRealm5
= "Realm5";
63 const base::string16
k123(ASCIIToUTF16("123"));
64 const base::string16
k1234(ASCIIToUTF16("1234"));
65 const base::string16
kAdmin(ASCIIToUTF16("admin"));
66 const base::string16
kAlice(ASCIIToUTF16("alice"));
67 const base::string16
kAlice2(ASCIIToUTF16("alice2"));
68 const base::string16
kPassword(ASCIIToUTF16("password"));
69 const base::string16
kRoot(ASCIIToUTF16("root"));
70 const base::string16
kUsername(ASCIIToUTF16("username"));
71 const base::string16
kWileCoyote(ASCIIToUTF16("wilecoyote"));
73 AuthCredentials
CreateASCIICredentials(const char* username
,
74 const char* password
) {
75 return AuthCredentials(ASCIIToUTF16(username
), ASCIIToUTF16(password
));
80 // Test adding and looking-up cache entries (both by realm and by path).
81 TEST(HttpAuthCacheTest
, Basic
) {
82 GURL
origin("http://www.google.com");
84 HttpAuthCache::Entry
* entry
;
86 // Add cache entries for 4 realms: "Realm1", "Realm2", "Realm3" and
89 scoped_ptr
<HttpAuthHandler
> realm1_handler(
90 new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC
,
92 HttpAuth::AUTH_SERVER
));
93 cache
.Add(origin
, realm1_handler
->realm(), realm1_handler
->auth_scheme(),
95 CreateASCIICredentials("realm1-user", "realm1-password"),
96 "/foo/bar/index.html");
98 scoped_ptr
<HttpAuthHandler
> realm2_handler(
99 new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC
,
101 HttpAuth::AUTH_SERVER
));
102 cache
.Add(origin
, realm2_handler
->realm(), realm2_handler
->auth_scheme(),
103 "Basic realm=Realm2",
104 CreateASCIICredentials("realm2-user", "realm2-password"),
107 scoped_ptr
<HttpAuthHandler
> realm3_basic_handler(
108 new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC
,
110 HttpAuth::AUTH_PROXY
));
113 realm3_basic_handler
->realm(),
114 realm3_basic_handler
->auth_scheme(),
115 "Basic realm=Realm3",
116 CreateASCIICredentials("realm3-basic-user", "realm3-basic-password"),
119 scoped_ptr
<HttpAuthHandler
> realm3_digest_handler(
120 new MockAuthHandler(HttpAuth::AUTH_SCHEME_DIGEST
,
122 HttpAuth::AUTH_PROXY
));
123 cache
.Add(origin
, realm3_digest_handler
->realm(),
124 realm3_digest_handler
->auth_scheme(), "Digest realm=Realm3",
125 CreateASCIICredentials("realm3-digest-user",
126 "realm3-digest-password"),
129 scoped_ptr
<HttpAuthHandler
> realm4_basic_handler(
130 new MockAuthHandler(HttpAuth::AUTH_SCHEME_BASIC
,
132 HttpAuth::AUTH_SERVER
));
133 cache
.Add(origin
, realm4_basic_handler
->realm(),
134 realm4_basic_handler
->auth_scheme(), "Basic realm=Realm4",
135 CreateASCIICredentials("realm4-basic-user",
136 "realm4-basic-password"),
139 // There is no Realm5
140 entry
= cache
.Lookup(origin
, kRealm5
, HttpAuth::AUTH_SCHEME_BASIC
);
141 EXPECT_TRUE(NULL
== entry
);
143 // While Realm3 does exist, the origin scheme is wrong.
144 entry
= cache
.Lookup(GURL("https://www.google.com"), kRealm3
,
145 HttpAuth::AUTH_SCHEME_BASIC
);
146 EXPECT_TRUE(NULL
== entry
);
148 // Realm, origin scheme ok, authentication scheme wrong
150 (GURL("http://www.google.com"), kRealm1
, HttpAuth::AUTH_SCHEME_DIGEST
);
151 EXPECT_TRUE(NULL
== entry
);
153 // Valid lookup by origin, realm, scheme.
154 entry
= cache
.Lookup(
155 GURL("http://www.google.com:80"), kRealm3
, HttpAuth::AUTH_SCHEME_BASIC
);
156 ASSERT_FALSE(NULL
== entry
);
157 EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC
, entry
->scheme());
158 EXPECT_EQ(kRealm3
, entry
->realm());
159 EXPECT_EQ("Basic realm=Realm3", entry
->auth_challenge());
160 EXPECT_EQ(ASCIIToUTF16("realm3-basic-user"), entry
->credentials().username());
161 EXPECT_EQ(ASCIIToUTF16("realm3-basic-password"),
162 entry
->credentials().password());
164 // Valid lookup by origin, realm, scheme when there's a duplicate
165 // origin, realm in the cache
166 entry
= cache
.Lookup(
167 GURL("http://www.google.com:80"), kRealm3
, HttpAuth::AUTH_SCHEME_DIGEST
);
168 ASSERT_FALSE(NULL
== entry
);
169 EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST
, entry
->scheme());
170 EXPECT_EQ(kRealm3
, entry
->realm());
171 EXPECT_EQ("Digest realm=Realm3", entry
->auth_challenge());
172 EXPECT_EQ(ASCIIToUTF16("realm3-digest-user"),
173 entry
->credentials().username());
174 EXPECT_EQ(ASCIIToUTF16("realm3-digest-password"),
175 entry
->credentials().password());
177 // Valid lookup by realm.
178 entry
= cache
.Lookup(origin
, kRealm2
, HttpAuth::AUTH_SCHEME_BASIC
);
179 ASSERT_FALSE(NULL
== entry
);
180 EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC
, entry
->scheme());
181 EXPECT_EQ(kRealm2
, entry
->realm());
182 EXPECT_EQ("Basic realm=Realm2", entry
->auth_challenge());
183 EXPECT_EQ(ASCIIToUTF16("realm2-user"), entry
->credentials().username());
184 EXPECT_EQ(ASCIIToUTF16("realm2-password"), entry
->credentials().password());
186 // Check that subpaths are recognized.
187 HttpAuthCache::Entry
* realm2_entry
= cache
.Lookup(
188 origin
, kRealm2
, HttpAuth::AUTH_SCHEME_BASIC
);
189 HttpAuthCache::Entry
* realm4_entry
= cache
.Lookup(
190 origin
, kRealm4
, HttpAuth::AUTH_SCHEME_BASIC
);
191 EXPECT_FALSE(NULL
== realm2_entry
);
192 EXPECT_FALSE(NULL
== realm4_entry
);
193 // Realm4 applies to '/' and Realm2 applies to '/foo2/'.
194 // LookupByPath() should return the closest enclosing path.
196 entry
= cache
.LookupByPath(origin
, "/foo2/index.html");
197 EXPECT_TRUE(realm2_entry
== entry
);
198 entry
= cache
.LookupByPath(origin
, "/foo2/foobar.html");
199 EXPECT_TRUE(realm2_entry
== entry
);
200 entry
= cache
.LookupByPath(origin
, "/foo2/bar/index.html");
201 EXPECT_TRUE(realm2_entry
== entry
);
202 entry
= cache
.LookupByPath(origin
, "/foo2/");
203 EXPECT_TRUE(realm2_entry
== entry
);
204 entry
= cache
.LookupByPath(origin
, "/foo2");
205 EXPECT_TRUE(realm4_entry
== entry
);
206 entry
= cache
.LookupByPath(origin
, "/");
207 EXPECT_TRUE(realm4_entry
== entry
);
210 entry
= cache
.LookupByPath(origin
, "/foo3/index.html");
211 EXPECT_FALSE(realm2_entry
== entry
);
212 entry
= cache
.LookupByPath(origin
, std::string());
213 EXPECT_FALSE(realm2_entry
== entry
);
215 // Confirm we find the same realm, different auth scheme by path lookup
216 HttpAuthCache::Entry
* realm3_digest_entry
=
217 cache
.Lookup(origin
, kRealm3
, HttpAuth::AUTH_SCHEME_DIGEST
);
218 EXPECT_FALSE(NULL
== realm3_digest_entry
);
219 entry
= cache
.LookupByPath(origin
, "/baz/index.html");
220 EXPECT_TRUE(realm3_digest_entry
== entry
);
221 entry
= cache
.LookupByPath(origin
, "/baz/");
222 EXPECT_TRUE(realm3_digest_entry
== entry
);
223 entry
= cache
.LookupByPath(origin
, "/baz");
224 EXPECT_FALSE(realm3_digest_entry
== entry
);
226 // Confirm we find the same realm, different auth scheme by path lookup
227 HttpAuthCache::Entry
* realm3DigestEntry
=
228 cache
.Lookup(origin
, kRealm3
, HttpAuth::AUTH_SCHEME_DIGEST
);
229 EXPECT_FALSE(NULL
== realm3DigestEntry
);
230 entry
= cache
.LookupByPath(origin
, "/baz/index.html");
231 EXPECT_TRUE(realm3DigestEntry
== entry
);
232 entry
= cache
.LookupByPath(origin
, "/baz/");
233 EXPECT_TRUE(realm3DigestEntry
== entry
);
234 entry
= cache
.LookupByPath(origin
, "/baz");
235 EXPECT_FALSE(realm3DigestEntry
== entry
);
237 // Lookup using empty path (may be used for proxy).
238 entry
= cache
.LookupByPath(origin
, std::string());
239 EXPECT_FALSE(NULL
== entry
);
240 EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC
, entry
->scheme());
241 EXPECT_EQ(kRealm3
, entry
->realm());
244 TEST(HttpAuthCacheTest
, AddPath
) {
245 HttpAuthCache::Entry entry
;
247 // All of these paths have a common root /1/2/2/4/5/
248 entry
.AddPath("/1/2/3/4/5/x.txt");
249 entry
.AddPath("/1/2/3/4/5/y.txt");
250 entry
.AddPath("/1/2/3/4/5/z.txt");
252 EXPECT_EQ(1U, entry
.paths_
.size());
253 EXPECT_EQ("/1/2/3/4/5/", entry
.paths_
.front());
255 // Add a new entry (not a subpath).
256 entry
.AddPath("/1/XXX/q");
257 EXPECT_EQ(2U, entry
.paths_
.size());
258 EXPECT_EQ("/1/XXX/", entry
.paths_
.front());
259 EXPECT_EQ("/1/2/3/4/5/", entry
.paths_
.back());
261 // Add containing paths of /1/2/3/4/5/ -- should swallow up the deeper paths.
262 entry
.AddPath("/1/2/3/4/x.txt");
263 EXPECT_EQ(2U, entry
.paths_
.size());
264 EXPECT_EQ("/1/2/3/4/", entry
.paths_
.front());
265 EXPECT_EQ("/1/XXX/", entry
.paths_
.back());
266 entry
.AddPath("/1/2/3/x");
267 EXPECT_EQ(2U, entry
.paths_
.size());
268 EXPECT_EQ("/1/2/3/", entry
.paths_
.front());
269 EXPECT_EQ("/1/XXX/", entry
.paths_
.back());
271 entry
.AddPath("/index.html");
272 EXPECT_EQ(1U, entry
.paths_
.size());
273 EXPECT_EQ("/", entry
.paths_
.front());
276 // Calling Add when the realm entry already exists, should append that
278 TEST(HttpAuthCacheTest
, AddToExistingEntry
) {
280 GURL
origin("http://www.foobar.com:70");
281 const std::string auth_challenge
= "Basic realm=MyRealm";
283 scoped_ptr
<HttpAuthHandler
> handler(
285 HttpAuth::AUTH_SCHEME_BASIC
, "MyRealm", HttpAuth::AUTH_SERVER
));
286 HttpAuthCache::Entry
* orig_entry
= cache
.Add(
287 origin
, handler
->realm(), handler
->auth_scheme(), auth_challenge
,
288 CreateASCIICredentials("user1", "password1"), "/x/y/z/");
289 cache
.Add(origin
, handler
->realm(), handler
->auth_scheme(), auth_challenge
,
290 CreateASCIICredentials("user2", "password2"), "/z/y/x/");
291 cache
.Add(origin
, handler
->realm(), handler
->auth_scheme(), auth_challenge
,
292 CreateASCIICredentials("user3", "password3"), "/z/y");
294 HttpAuthCache::Entry
* entry
= cache
.Lookup(
295 origin
, "MyRealm", HttpAuth::AUTH_SCHEME_BASIC
);
297 EXPECT_TRUE(entry
== orig_entry
);
298 EXPECT_EQ(ASCIIToUTF16("user3"), entry
->credentials().username());
299 EXPECT_EQ(ASCIIToUTF16("password3"), entry
->credentials().password());
301 EXPECT_EQ(2U, entry
->paths_
.size());
302 EXPECT_EQ("/z/", entry
->paths_
.front());
303 EXPECT_EQ("/x/y/z/", entry
->paths_
.back());
306 TEST(HttpAuthCacheTest
, Remove
) {
307 GURL
origin("http://foobar2.com");
309 scoped_ptr
<HttpAuthHandler
> realm1_handler(
311 HttpAuth::AUTH_SCHEME_BASIC
, kRealm1
, HttpAuth::AUTH_SERVER
));
313 scoped_ptr
<HttpAuthHandler
> realm2_handler(
315 HttpAuth::AUTH_SCHEME_BASIC
, kRealm2
, HttpAuth::AUTH_SERVER
));
317 scoped_ptr
<HttpAuthHandler
> realm3_basic_handler(
319 HttpAuth::AUTH_SCHEME_BASIC
, kRealm3
, HttpAuth::AUTH_SERVER
));
321 scoped_ptr
<HttpAuthHandler
> realm3_digest_handler(
323 HttpAuth::AUTH_SCHEME_DIGEST
, kRealm3
, HttpAuth::AUTH_SERVER
));
326 cache
.Add(origin
, realm1_handler
->realm(), realm1_handler
->auth_scheme(),
327 "basic realm=Realm1", AuthCredentials(kAlice
, k123
), "/");
328 cache
.Add(origin
, realm2_handler
->realm(), realm2_handler
->auth_scheme(),
329 "basic realm=Realm2", CreateASCIICredentials("bob", "princess"),
331 cache
.Add(origin
, realm3_basic_handler
->realm(),
332 realm3_basic_handler
->auth_scheme(), "basic realm=Realm3",
333 AuthCredentials(kAdmin
, kPassword
), "/");
334 cache
.Add(origin
, realm3_digest_handler
->realm(),
335 realm3_digest_handler
->auth_scheme(), "digest realm=Realm3",
336 AuthCredentials(kRoot
, kWileCoyote
), "/");
338 // Fails, because there is no realm "Realm5".
339 EXPECT_FALSE(cache
.Remove(
340 origin
, kRealm5
, HttpAuth::AUTH_SCHEME_BASIC
,
341 AuthCredentials(kAlice
, k123
)));
343 // Fails because the origin is wrong.
344 EXPECT_FALSE(cache
.Remove(GURL("http://foobar2.com:100"),
346 HttpAuth::AUTH_SCHEME_BASIC
,
347 AuthCredentials(kAlice
, k123
)));
349 // Fails because the username is wrong.
350 EXPECT_FALSE(cache
.Remove(
351 origin
, kRealm1
, HttpAuth::AUTH_SCHEME_BASIC
,
352 AuthCredentials(kAlice2
, k123
)));
354 // Fails because the password is wrong.
355 EXPECT_FALSE(cache
.Remove(
356 origin
, kRealm1
, HttpAuth::AUTH_SCHEME_BASIC
,
357 AuthCredentials(kAlice
, k1234
)));
359 // Fails because the authentication type is wrong.
360 EXPECT_FALSE(cache
.Remove(
361 origin
, kRealm1
, HttpAuth::AUTH_SCHEME_DIGEST
,
362 AuthCredentials(kAlice
, k123
)));
365 EXPECT_TRUE(cache
.Remove(
366 origin
, kRealm1
, HttpAuth::AUTH_SCHEME_BASIC
,
367 AuthCredentials(kAlice
, k123
)));
369 // Fails because we just deleted the entry!
370 EXPECT_FALSE(cache
.Remove(
371 origin
, kRealm1
, HttpAuth::AUTH_SCHEME_BASIC
,
372 AuthCredentials(kAlice
, k123
)));
374 // Succeed when there are two authentication types for the same origin,realm.
375 EXPECT_TRUE(cache
.Remove(
376 origin
, kRealm3
, HttpAuth::AUTH_SCHEME_DIGEST
,
377 AuthCredentials(kRoot
, kWileCoyote
)));
379 // Succeed as above, but when entries were added in opposite order
380 cache
.Add(origin
, realm3_digest_handler
->realm(),
381 realm3_digest_handler
->auth_scheme(), "digest realm=Realm3",
382 AuthCredentials(kRoot
, kWileCoyote
), "/");
383 EXPECT_TRUE(cache
.Remove(
384 origin
, kRealm3
, HttpAuth::AUTH_SCHEME_BASIC
,
385 AuthCredentials(kAdmin
, kPassword
)));
387 // Make sure that removing one entry still leaves the other available for
389 HttpAuthCache::Entry
* entry
= cache
.Lookup(
390 origin
, kRealm3
, HttpAuth::AUTH_SCHEME_DIGEST
);
391 EXPECT_FALSE(NULL
== entry
);
394 TEST(HttpAuthCacheTest
, UpdateStaleChallenge
) {
396 GURL
origin("http://foobar2.com");
397 scoped_ptr
<HttpAuthHandler
> digest_handler(
399 HttpAuth::AUTH_SCHEME_DIGEST
, kRealm1
, HttpAuth::AUTH_PROXY
));
400 HttpAuthCache::Entry
* entry_pre
= cache
.Add(
402 digest_handler
->realm(),
403 digest_handler
->auth_scheme(),
404 "Digest realm=Realm1,"
405 "nonce=\"s3MzvFhaBAA=4c520af5acd9d8d7ae26947529d18c8eae1e98f4\"",
406 CreateASCIICredentials("realm-digest-user", "realm-digest-password"),
408 ASSERT_TRUE(entry_pre
!= NULL
);
410 EXPECT_EQ(2, entry_pre
->IncrementNonceCount());
411 EXPECT_EQ(3, entry_pre
->IncrementNonceCount());
412 EXPECT_EQ(4, entry_pre
->IncrementNonceCount());
414 bool update_success
= cache
.UpdateStaleChallenge(
416 digest_handler
->realm(),
417 digest_handler
->auth_scheme(),
418 "Digest realm=Realm1,"
419 "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\","
421 EXPECT_TRUE(update_success
);
423 // After the stale update, the entry should still exist in the cache and
424 // the nonce count should be reset to 0.
425 HttpAuthCache::Entry
* entry_post
= cache
.Lookup(
427 digest_handler
->realm(),
428 digest_handler
->auth_scheme());
429 ASSERT_TRUE(entry_post
!= NULL
);
430 EXPECT_EQ(2, entry_post
->IncrementNonceCount());
432 // UpdateStaleChallenge will fail if an entry doesn't exist in the cache.
433 bool update_failure
= cache
.UpdateStaleChallenge(
436 digest_handler
->auth_scheme(),
437 "Digest realm=Realm2,"
438 "nonce=\"claGgoRXBAA=7583377687842fdb7b56ba0555d175baa0b800e3\","
440 EXPECT_FALSE(update_failure
);
443 TEST(HttpAuthCacheTest
, UpdateAllFrom
) {
444 GURL
origin("http://example.com");
445 std::string
path("/some/path");
446 std::string
another_path("/another/path");
448 scoped_ptr
<HttpAuthHandler
> realm1_handler(
450 HttpAuth::AUTH_SCHEME_BASIC
, kRealm1
, HttpAuth::AUTH_SERVER
));
452 scoped_ptr
<HttpAuthHandler
> realm2_handler(
454 HttpAuth::AUTH_SCHEME_BASIC
, kRealm2
, HttpAuth::AUTH_PROXY
));
456 scoped_ptr
<HttpAuthHandler
> realm3_digest_handler(
458 HttpAuth::AUTH_SCHEME_DIGEST
, kRealm3
, HttpAuth::AUTH_SERVER
));
460 scoped_ptr
<HttpAuthHandler
> realm4_handler(
462 HttpAuth::AUTH_SCHEME_BASIC
, kRealm4
, HttpAuth::AUTH_SERVER
));
464 HttpAuthCache first_cache
;
465 HttpAuthCache::Entry
* entry
;
467 first_cache
.Add(origin
, realm1_handler
->realm(),
468 realm1_handler
->auth_scheme(), "basic realm=Realm1",
469 AuthCredentials(kAlice
, k123
), path
);
470 first_cache
.Add(origin
, realm2_handler
->realm(),
471 realm2_handler
->auth_scheme(), "basic realm=Realm2",
472 AuthCredentials(kAlice2
, k1234
), path
);
473 first_cache
.Add(origin
, realm3_digest_handler
->realm(),
474 realm3_digest_handler
->auth_scheme(), "digest realm=Realm3",
475 AuthCredentials(kRoot
, kWileCoyote
), path
);
476 entry
= first_cache
.Add(
477 origin
, realm3_digest_handler
->realm(),
478 realm3_digest_handler
->auth_scheme(), "digest realm=Realm3",
479 AuthCredentials(kRoot
, kWileCoyote
), another_path
);
481 EXPECT_EQ(2, entry
->IncrementNonceCount());
483 HttpAuthCache second_cache
;
484 // Will be overwritten by kRoot:kWileCoyote.
485 second_cache
.Add(origin
, realm3_digest_handler
->realm(),
486 realm3_digest_handler
->auth_scheme(), "digest realm=Realm3",
487 AuthCredentials(kAlice2
, k1234
), path
);
488 // Should be left intact.
489 second_cache
.Add(origin
, realm4_handler
->realm(),
490 realm4_handler
->auth_scheme(), "basic realm=Realm4",
491 AuthCredentials(kAdmin
, kRoot
), path
);
493 second_cache
.UpdateAllFrom(first_cache
);
495 // Copied from first_cache.
496 entry
= second_cache
.Lookup(origin
, kRealm1
, HttpAuth::AUTH_SCHEME_BASIC
);
497 EXPECT_TRUE(NULL
!= entry
);
498 EXPECT_EQ(kAlice
, entry
->credentials().username());
499 EXPECT_EQ(k123
, entry
->credentials().password());
501 // Copied from first_cache.
502 entry
= second_cache
.Lookup(origin
, kRealm2
, HttpAuth::AUTH_SCHEME_BASIC
);
503 EXPECT_TRUE(NULL
!= entry
);
504 EXPECT_EQ(kAlice2
, entry
->credentials().username());
505 EXPECT_EQ(k1234
, entry
->credentials().password());
507 // Overwritten from first_cache.
508 entry
= second_cache
.Lookup(origin
, kRealm3
, HttpAuth::AUTH_SCHEME_DIGEST
);
509 EXPECT_TRUE(NULL
!= entry
);
510 EXPECT_EQ(kRoot
, entry
->credentials().username());
511 EXPECT_EQ(kWileCoyote
, entry
->credentials().password());
512 // Nonce count should get copied.
513 EXPECT_EQ(3, entry
->IncrementNonceCount());
515 // All paths should get copied.
516 entry
= second_cache
.LookupByPath(origin
, another_path
);
517 EXPECT_TRUE(NULL
!= entry
);
518 EXPECT_EQ(kRoot
, entry
->credentials().username());
519 EXPECT_EQ(kWileCoyote
, entry
->credentials().password());
521 // Left intact in second_cache.
522 entry
= second_cache
.Lookup(origin
, kRealm4
, HttpAuth::AUTH_SCHEME_BASIC
);
523 EXPECT_TRUE(NULL
!= entry
);
524 EXPECT_EQ(kAdmin
, entry
->credentials().username());
525 EXPECT_EQ(kRoot
, entry
->credentials().password());
528 // Test fixture class for eviction tests (contains helpers for bulk
529 // insertion and existence testing).
530 class HttpAuthCacheEvictionTest
: public testing::Test
{
532 HttpAuthCacheEvictionTest() : origin_("http://www.google.com") { }
534 std::string
GenerateRealm(int realm_i
) {
535 return base::StringPrintf("Realm %d", realm_i
);
538 std::string
GeneratePath(int realm_i
, int path_i
) {
539 return base::StringPrintf("/%d/%d/x/y", realm_i
, path_i
);
542 void AddRealm(int realm_i
) {
543 AddPathToRealm(realm_i
, 0);
546 void AddPathToRealm(int realm_i
, int path_i
) {
548 GenerateRealm(realm_i
),
549 HttpAuth::AUTH_SCHEME_BASIC
,
551 AuthCredentials(kUsername
, kPassword
),
552 GeneratePath(realm_i
, path_i
));
555 void CheckRealmExistence(int realm_i
, bool exists
) {
556 const HttpAuthCache::Entry
* entry
=
558 origin_
, GenerateRealm(realm_i
), HttpAuth::AUTH_SCHEME_BASIC
);
560 EXPECT_FALSE(entry
== NULL
);
561 EXPECT_EQ(GenerateRealm(realm_i
), entry
->realm());
563 EXPECT_TRUE(entry
== NULL
);
567 void CheckPathExistence(int realm_i
, int path_i
, bool exists
) {
568 const HttpAuthCache::Entry
* entry
=
569 cache_
.LookupByPath(origin_
, GeneratePath(realm_i
, path_i
));
571 EXPECT_FALSE(entry
== NULL
);
572 EXPECT_EQ(GenerateRealm(realm_i
), entry
->realm());
574 EXPECT_TRUE(entry
== NULL
);
579 HttpAuthCache cache_
;
581 static const int kMaxPaths
= HttpAuthCache::kMaxNumPathsPerRealmEntry
;
582 static const int kMaxRealms
= HttpAuthCache::kMaxNumRealmEntries
;
585 // Add the maxinim number of realm entries to the cache. Each of these entries
586 // must still be retrievable. Next add three more entries -- since the cache is
587 // full this causes FIFO eviction of the first three entries.
588 TEST_F(HttpAuthCacheEvictionTest
, RealmEntryEviction
) {
589 for (int i
= 0; i
< kMaxRealms
; ++i
)
592 for (int i
= 0; i
< kMaxRealms
; ++i
)
593 CheckRealmExistence(i
, true);
595 for (int i
= 0; i
< 3; ++i
)
596 AddRealm(i
+ kMaxRealms
);
598 for (int i
= 0; i
< 3; ++i
)
599 CheckRealmExistence(i
, false);
601 for (int i
= 0; i
< kMaxRealms
; ++i
)
602 CheckRealmExistence(i
+ 3, true);
605 // Add the maximum number of paths to a single realm entry. Each of these
606 // paths should be retrievable. Next add 3 more paths -- since the cache is
607 // full this causes FIFO eviction of the first three paths.
608 TEST_F(HttpAuthCacheEvictionTest
, RealmPathEviction
) {
609 for (int i
= 0; i
< kMaxPaths
; ++i
)
610 AddPathToRealm(0, i
);
612 for (int i
= 1; i
< kMaxRealms
; ++i
)
615 for (int i
= 0; i
< 3; ++i
)
616 AddPathToRealm(0, i
+ kMaxPaths
);
618 for (int i
= 0; i
< 3; ++i
)
619 CheckPathExistence(0, i
, false);
621 for (int i
= 0; i
< kMaxPaths
; ++i
)
622 CheckPathExistence(0, i
+ 3, true);
624 for (int i
= 0; i
< kMaxRealms
; ++i
)
625 CheckRealmExistence(i
, true);