Chromium Code Reviews| Index: net/cookies/cookie_monster_unittest.cc |
| diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc |
| index 5a485992d8ad56ea6e8533afae25e4c75e8f15df..8c38de507a980097ba7143fc9f9c3f092762f322 100644 |
| --- a/net/cookies/cookie_monster_unittest.cc |
| +++ b/net/cookies/cookie_monster_unittest.cc |
| @@ -353,11 +353,12 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { |
| // Instantiates a CookieMonster, adds multiple cookies (to http_www_google_) |
| // with priorities specified by |coded_priority_str|, and tests priority-aware |
| // domain cookie eviction. |
| - // |coded_priority_str| specifies a run-length-encoded string of priorities. |
| - // Example: "2M 3L M 4H" means "MMLLLMHHHH", and speicifies sequential (i.e., |
| - // from least- to most-recently accessed) insertion of 2 medium-priority |
| - // cookies, 3 low-priority cookies, 1 medium-priority cookie, and 4 |
| - // high-priority cookies. |
| + // |
| + // Example: |coded_priority_string| of "2MN 3LS MN 4HN" specifies sequential |
| + // (i.e., from least- to most-recently accessed) insertion of 2 |
| + // medium-priority non-secure cookies, 3 low-priority secure cookies, 1 |
| + // medium-priority non-secure cookie, and 4 high-priority non-secure cookies. |
| + // |
| // Within each priority, only the least-accessed cookies should be evicted. |
| // Thus, to describe expected suriving cookies, it suffices to specify the |
| // expected population of surviving cookies per priority, i.e., |
| @@ -366,41 +367,57 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { |
| const std::string& coded_priority_str, |
| size_t expected_low_count, |
| size_t expected_medium_count, |
| - size_t expected_high_count) { |
| + size_t expected_high_count, |
| + size_t expected_nonsecure, |
| + size_t expected_secure) { |
| + SCOPED_TRACE(coded_priority_str.c_str()); |
| this->DeleteAll(cm); |
| int next_cookie_id = 0; |
| - std::vector<CookiePriority> priority_list; |
| - std::vector<int> id_list[3]; // Indexed by CookiePriority. |
| + // A list of cookie IDs, indexed by secure status, then by priority. |
| + std::vector<std::vector<std::vector<int>>> id_list{{{}, {}, {}}, |
| + {{}, {}, {}}}; |
| + // A list of all the cookies stored, along with their properties. |
| + std::vector<std::pair<bool, CookiePriority>> cookie_data; |
| // Parse |coded_priority_str| and add cookies. |
| for (const std::string& token : |
| base::SplitString(coded_priority_str, " ", base::TRIM_WHITESPACE, |
| base::SPLIT_WANT_ALL)) { |
| DCHECK(!token.empty()); |
| - // Take last character as priority. |
| - CookiePriority priority = CharToPriority(token.back()); |
| - std::string priority_str = CookiePriorityToString(priority); |
| + |
| + // Take last character as security status, then discard it. |
| + bool is_secure = token[token.size() - 1] == 'S'; |
| + |
| + // The second-to-last character is the priority. Grab and discard it. |
| + CookiePriority priority = CharToPriority(token[token.size() - 2]); |
| + |
| // The rest of the string (possibly empty) specifies repetition. |
| int rep = 1; |
| if (!token.empty()) { |
| bool result = base::StringToInt( |
| - base::StringPiece(token.begin(), token.end() - 1), &rep); |
| + base::StringPiece(token.begin(), token.end() - 2), &rep); |
| DCHECK(result); |
| } |
| for (; rep > 0; --rep, ++next_cookie_id) { |
| - std::string cookie = base::StringPrintf( |
| - "a%d=b;priority=%s", next_cookie_id, priority_str.c_str()); |
| - EXPECT_TRUE(SetCookie(cm, http_www_google_.url(), cookie)); |
| - priority_list.push_back(priority); |
| - id_list[priority].push_back(next_cookie_id); |
| + std::string cookie = |
| + base::StringPrintf("a%d=b;priority=%s;%s", next_cookie_id, |
| + CookiePriorityToString(priority).c_str(), |
| + is_secure ? "secure" : ""); |
| + EXPECT_TRUE(SetCookie(cm, https_www_google_.url(), cookie)); |
| + cookie_data.push_back(std::make_pair(is_secure, priority)); |
| + id_list[is_secure][priority].push_back(next_cookie_id); |
| } |
| } |
| - int num_cookies = static_cast<int>(priority_list.size()); |
| - std::vector<int> surviving_id_list[3]; // Indexed by CookiePriority. |
| + int num_cookies = static_cast<int>(cookie_data.size()); |
| + // A list of cookie IDs, indexed by secure status, then by priority. |
| + std::vector<std::vector<std::vector<int>>> surviving_id_list{{{}, {}, {}}, |
| + {{}, {}, {}}}; |
| // Parse the list of cookies |
| - std::string cookie_str = this->GetCookies(cm, http_www_google_.url()); |
| + std::string cookie_str = this->GetCookies(cm, https_www_google_.url()); |
| + size_t num_nonsecure = 0; |
| + size_t num_secure = 0; |
| for (const std::string& token : base::SplitString( |
| cookie_str, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { |
| // Assuming *it is "a#=b", so extract and parse "#" portion. |
| @@ -410,22 +427,40 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { |
| DCHECK(result); |
| DCHECK_GE(id, 0); |
| DCHECK_LT(id, num_cookies); |
| - surviving_id_list[priority_list[id]].push_back(id); |
| + surviving_id_list[cookie_data[id].first][cookie_data[id].second] |
| + .push_back(id); |
| + if (cookie_data[id].first) |
| + num_secure += 1; |
| + else |
| + num_nonsecure += 1; |
| } |
| + EXPECT_EQ(expected_nonsecure, num_nonsecure); |
| + EXPECT_EQ(expected_secure, num_secure); |
| + |
| // Validate each priority. |
| size_t expected_count[3] = { |
| expected_low_count, expected_medium_count, expected_high_count}; |
| for (int i = 0; i < 3; ++i) { |
| - DCHECK_LE(surviving_id_list[i].size(), id_list[i].size()); |
| - EXPECT_EQ(expected_count[i], surviving_id_list[i].size()); |
| + size_t num_for_priority = |
| + surviving_id_list[0][i].size() + surviving_id_list[1][i].size(); |
| + EXPECT_EQ(expected_count[i], num_for_priority); |
| // Verify that the remaining cookies are the most recent among those |
| // with the same priorities. |
| - if (expected_count[i] == surviving_id_list[i].size()) { |
| - std::sort(surviving_id_list[i].begin(), surviving_id_list[i].end()); |
| - EXPECT_TRUE(std::equal(surviving_id_list[i].begin(), |
| - surviving_id_list[i].end(), |
| - id_list[i].end() - expected_count[i])); |
| + if (expected_count[i] == num_for_priority) { |
| + // Non-secure: |
| + std::sort(surviving_id_list[0][i].begin(), |
| + surviving_id_list[0][i].end()); |
| + EXPECT_TRUE(std::equal( |
| + surviving_id_list[0][i].begin(), surviving_id_list[0][i].end(), |
| + id_list[0][i].end() - surviving_id_list[0][i].size())); |
| + |
| + // Secure: |
| + std::sort(surviving_id_list[1][i].begin(), |
| + surviving_id_list[1][i].end()); |
| + EXPECT_TRUE(std::equal( |
| + surviving_id_list[1][i].begin(), surviving_id_list[1][i].end(), |
| + id_list[1][i].end() - surviving_id_list[1][i].size())); |
| } |
| } |
| } |
| @@ -492,54 +527,152 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { |
| EXPECT_EQ(expected_non_secure_cookies, total_non_secure_cookies); |
| } |
| - void TestPriorityAwareGarbageCollectHelper() { |
| + void TestPriorityAwareGarbageCollectHelperNonSecure() { |
| + // Hard-coding limits in the test, but use DCHECK_EQ to enforce constraint. |
| + DCHECK_EQ(180U, CookieMonster::kDomainMaxCookies); |
| + DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - |
| + CookieMonster::kDomainPurgeCookies); |
| + |
| + scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); |
| + |
| + // Each test case adds 181 cookies, so 31 cookies are evicted. |
| + // Cookie same priority, repeated for each priority. |
| + TestPriorityCookieCase(cm.get(), "181LN", 150U, 0U, 0U, 150U, 0U); |
| + TestPriorityCookieCase(cm.get(), "181MN", 0U, 150U, 0U, 150U, 0U); |
| + TestPriorityCookieCase(cm.get(), "181HN", 0U, 0U, 150U, 150U, 0U); |
| + |
| + // Pairwise scenarios. |
| + // Round 1 => none; round2 => 31M; round 3 => none. |
| + TestPriorityCookieCase(cm.get(), "10HN 171MN", 0U, 140U, 10U, 150U, 0U); |
| + // Round 1 => 10L; round2 => 21M; round 3 => none. |
| + TestPriorityCookieCase(cm.get(), "141MN 40LN", 30U, 120U, 0U, 150U, 0U); |
| + // Round 1 => none; round2 => none; round 3 => 31H. |
| + TestPriorityCookieCase(cm.get(), "101HN 80MN", 0U, 80U, 70U, 150U, 0U); |
| + |
| + // For {low, medium} priorities right on quota, different orders. |
| + // Round 1 => 1L; round 2 => none, round3 => 30L. |
| + TestPriorityCookieCase(cm.get(), "31LN 50MN 100HN", 0U, 50U, 100U, 150U, |
| + 0U); |
| + // Round 1 => none; round 2 => 1M, round3 => 30M. |
| + TestPriorityCookieCase(cm.get(), "51MN 100HN 30LN", 30U, 20U, 100U, 150U, |
| + 0U); |
| + // Round 1 => none; round 2 => none; round3 => 31H. |
| + TestPriorityCookieCase(cm.get(), "101HN 50MN 30LN", 30U, 50U, 70U, 150U, |
| + 0U); |
| + |
| + // Round 1 => 10L; round 2 => 10M; round3 => 11H. |
| + TestPriorityCookieCase(cm.get(), "81HN 60MN 40LN", 30U, 50U, 70U, 150U, 0U); |
| + |
| + // More complex scenarios. |
| + // Round 1 => 10L; round 2 => 10M; round 3 => 11H. |
| + TestPriorityCookieCase(cm.get(), "21HN 60MN 40LN 60HN", 30U, 50U, 70U, 150U, |
| + 0U); |
| + // Round 1 => 10L; round 2 => 11M, 10L; round 3 => none. |
| + TestPriorityCookieCase(cm.get(), "11HN 10MN 20LN 110MN 20LN 10HN", 20U, |
| + 109U, 21U, 150U, 0U); |
| + // Round 1 => none; round 2 => none; round 3 => 11L, 10M, 10H. |
| + TestPriorityCookieCase(cm.get(), "11LN 10MN 140HN 10MN 10LN", 10U, 10U, |
| + 130U, 150U, 0U); |
| + // Round 1 => none; round 2 => 1M; round 3 => 10L, 10M, 10H. |
| + TestPriorityCookieCase(cm.get(), "11MN 10HN 10LN 60MN 90HN", 0U, 60U, 90U, |
| + 150U, 0U); |
| + // Round 1 => none; round 2 => 10L, 21M; round 3 => none. |
| + TestPriorityCookieCase(cm.get(), "11MN 10HN 10LN 90MN 60HN", 0U, 80U, 70U, |
| + 150U, 0U); |
| + } |
| + |
| + void TestPriorityAwareGarbageCollectHelperSecure() { |
| // Hard-coding limits in the test, but use DCHECK_EQ to enforce constraint. |
| DCHECK_EQ(180U, CookieMonster::kDomainMaxCookies); |
| DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - |
| CookieMonster::kDomainPurgeCookies); |
| - DCHECK_EQ(30U, CookieMonster::kDomainCookiesQuotaLow); |
| - DCHECK_EQ(50U, CookieMonster::kDomainCookiesQuotaMedium); |
| - DCHECK_EQ(70U, CookieMonster::kDomainCookiesQuotaHigh); |
| scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); |
| // Each test case adds 181 cookies, so 31 cookies are evicted. |
| // Cookie same priority, repeated for each priority. |
| - TestPriorityCookieCase(cm.get(), "181L", 150U, 0U, 0U); |
| - TestPriorityCookieCase(cm.get(), "181M", 0U, 150U, 0U); |
| - TestPriorityCookieCase(cm.get(), "181H", 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "181LS", 150U, 0U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "181MS", 0U, 150U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "181HS", 0U, 0U, 150U, 0U, 150U); |
| // Pairwise scenarios. |
| // Round 1 => none; round2 => 31M; round 3 => none. |
| - TestPriorityCookieCase(cm.get(), "10H 171M", 0U, 140U, 10U); |
| + TestPriorityCookieCase(cm.get(), "10HS 171MS", 0U, 140U, 10U, 0U, 150U); |
| // Round 1 => 10L; round2 => 21M; round 3 => none. |
| - TestPriorityCookieCase(cm.get(), "141M 40L", 30U, 120U, 0U); |
| + TestPriorityCookieCase(cm.get(), "141MS 40LS", 30U, 120U, 0U, 0U, 150U); |
| // Round 1 => none; round2 => none; round 3 => 31H. |
| - TestPriorityCookieCase(cm.get(), "101H 80M", 0U, 80U, 70U); |
| + TestPriorityCookieCase(cm.get(), "101HS 80MS", 0U, 80U, 70U, 0U, 150U); |
| // For {low, medium} priorities right on quota, different orders. |
| // Round 1 => 1L; round 2 => none, round3 => 30L. |
| - TestPriorityCookieCase(cm.get(), "31L 50M 100H", 0U, 50U, 100U); |
| + TestPriorityCookieCase(cm.get(), "31LS 50MS 100HS", 0U, 50U, 100U, 0U, |
| + 150U); |
| // Round 1 => none; round 2 => 1M, round3 => 30M. |
| - TestPriorityCookieCase(cm.get(), "51M 100H 30L", 30U, 20U, 100U); |
| + TestPriorityCookieCase(cm.get(), "51MS 100HS 30LS", 30U, 20U, 100U, 0U, |
| + 150U); |
| // Round 1 => none; round 2 => none; round3 => 31H. |
| - TestPriorityCookieCase(cm.get(), "101H 50M 30L", 30U, 50U, 70U); |
| + TestPriorityCookieCase(cm.get(), "101HS 50MS 30LS", 30U, 50U, 70U, 0U, |
| + 150U); |
| // Round 1 => 10L; round 2 => 10M; round3 => 11H. |
| - TestPriorityCookieCase(cm.get(), "81H 60M 40L", 30U, 50U, 70U); |
| + TestPriorityCookieCase(cm.get(), "81HS 60MS 40LS", 30U, 50U, 70U, 0U, 150U); |
| // More complex scenarios. |
| // Round 1 => 10L; round 2 => 10M; round 3 => 11H. |
| - TestPriorityCookieCase(cm.get(), "21H 60M 40L 60H", 30U, 50U, 70U); |
| + TestPriorityCookieCase(cm.get(), "21HS 60MS 40LS 60HS", 30U, 50U, 70U, 0U, |
| + 150U); |
| // Round 1 => 10L; round 2 => 11M, 10L; round 3 => none. |
| - TestPriorityCookieCase(cm.get(), "11H 10M 20L 110M 20L 10H", 20U, 109U, |
| - 21U); |
| + TestPriorityCookieCase(cm.get(), "11HS 10MS 20LS 110MS 20LS 10HS", 20U, |
| + 109U, 21U, 0U, 150U); |
| // Round 1 => none; round 2 => none; round 3 => 11L, 10M, 10H. |
| - TestPriorityCookieCase(cm.get(), "11L 10M 140H 10M 10L", 10U, 10U, 130U); |
| + TestPriorityCookieCase(cm.get(), "11LS 10MS 140HS 10MS 10LS", 10U, 10U, |
| + 130U, 0U, 150U); |
| // Round 1 => none; round 2 => 1M; round 3 => 10L, 10M, 10H. |
| - TestPriorityCookieCase(cm.get(), "11M 10H 10L 60M 90H", 0U, 60U, 90U); |
| + TestPriorityCookieCase(cm.get(), "11MS 10HS 10LS 60MS 90HS", 0U, 60U, 90U, |
| + 0U, 150U); |
| // Round 1 => none; round 2 => 10L, 21M; round 3 => none. |
| - TestPriorityCookieCase(cm.get(), "11M 10H 10L 90M 60H", 0U, 80U, 70U); |
| + TestPriorityCookieCase(cm.get(), "11MS 10HS 10LS 90MS 60HS", 0U, 80U, 70U, |
| + 0U, 150U); |
| + } |
| + |
| + void TestPriorityAwareGarbageCollectHelperMixed() { |
| + // Hard-coding limits in the test, but use DCHECK_EQ to enforce constraint. |
| + DCHECK_EQ(180U, CookieMonster::kDomainMaxCookies); |
| + DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - |
| + CookieMonster::kDomainPurgeCookies); |
| + |
| + scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); |
| + |
| + // Each test case adds 180 secure cookies, and some non-secure cookie. The |
|
jww
2016/02/18 01:05:19
Maybe add a few sanity check cases with > 180 cook
|
| + // secure cookies take priority, so the non-secure cookie is removed, along |
| + // with 30 secure cookies. Repeated for each priority, and with the |
| + // non-secure cookie as older and newer. |
| + TestPriorityCookieCase(cm.get(), "1LN 180LS", 150U, 0U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "1MN 180MS", 0U, 150U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "1HN 180HS", 0U, 0U, 150U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "180LS 1LN", 150U, 0U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "180MS 1MN", 0U, 150U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "180HS 1HN", 0U, 0U, 150U, 0U, 150U); |
| + |
| + // Higher-priority non-secure cookies are removed before any secure cookie. |
| + TestPriorityCookieCase(cm.get(), "180LS 1MN", 150U, 0U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "180LS 1HN", 150U, 0U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "180MS 1HN", 0U, 150U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "1MN 180LS", 150U, 0U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "1HN 180LS", 150U, 0U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "1HN 180MS", 0U, 150U, 0U, 0U, 150U); |
| + |
| + // Pairwise: |
| + TestPriorityCookieCase(cm.get(), "1LS 180LN", 150U, 0U, 0U, 149U, 1U); |
| + TestPriorityCookieCase(cm.get(), "100LS 81LN", 150U, 0U, 0U, 50U, 100U); |
| + TestPriorityCookieCase(cm.get(), "150LS 31LN", 150U, 0U, 0U, 0U, 150U); |
| + TestPriorityCookieCase(cm.get(), "1LS 180HN", 1U, 0U, 149U, 149U, 1U); |
| + TestPriorityCookieCase(cm.get(), "100LS 81HN", 100U, 0U, 50U, 50U, 100U); |
| + TestPriorityCookieCase(cm.get(), "150LS 31HN", 150U, 0U, 0U, 0U, 150U); |
| + |
| + // Quota calculations inside non-secure/secure blocks remain in place: |
| + TestPriorityCookieCase(cm.get(), "50HN 50LS 81HS", 50U, 0U, 100U, 19U, |
| + 131U); |
| } |
| // Function for creating a CM with a number of cookies in it, |
| @@ -1248,8 +1381,16 @@ TEST_F(CookieMonsterTest, TestHostGarbageCollection) { |
| TestHostGarbageCollectHelper(); |
| } |
| -TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollection) { |
| - TestPriorityAwareGarbageCollectHelper(); |
| +TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollectionNonSecure) { |
| + TestPriorityAwareGarbageCollectHelperNonSecure(); |
| +} |
| + |
| +TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollectionSecure) { |
| + TestPriorityAwareGarbageCollectHelperSecure(); |
| +} |
| + |
| +TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollectionMixed) { |
| + TestPriorityAwareGarbageCollectHelperMixed(); |
| } |
| TEST_F(CookieMonsterTest, SetCookieableSchemes) { |