15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/expiring_cache.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <functional>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Pointee;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::StrEq;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxCacheEntries = 10;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ExpiringCache<std::string, std::string, base::TimeTicks,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::less<base::TimeTicks> > Cache;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct TestFunctor {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const std::string& now,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const std::string& expiration) const {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return now != expiration;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ExpiringCacheTest, Basic) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cache cache(kMaxCacheEntries);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start at t=0.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks now;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, cache.size());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add an entry at t=0
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("entry1", now));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("entry1", "test1", now, now + kTTL);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("entry1", now), Pointee(StrEq("test1")));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, cache.size());
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advance to t=5.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  now += base::TimeDelta::FromSeconds(5);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add an entry at t=5.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("entry2", now));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("entry2", "test2", now, now + kTTL);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("entry2", now), Pointee(StrEq("test2")));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, cache.size());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advance to t=9.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  now += base::TimeDelta::FromSeconds(4);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the entries added are still retrievable and usable.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("entry1", now), Pointee(StrEq("test1")));
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("entry2", now), Pointee(StrEq("test2")));
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advance to t=10; entry1 is now expired.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  now += base::TimeDelta::FromSeconds(1);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("entry1", now));
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("entry2", now), Pointee(StrEq("test2")));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The expired element should no longer be in the cache.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, cache.size());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update entry1 so it is no longer expired.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("entry1", "test1", now, now + kTTL);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Both entries should be retrievable and usable.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, cache.size());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("entry1", now), Pointee(StrEq("test1")));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("entry2", now), Pointee(StrEq("test2")));
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advance to t=20; both entries are now expired.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  now += base::TimeDelta::FromSeconds(10);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("entry1", now));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("entry2", now));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ExpiringCacheTest, Compact) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cache cache(kMaxCacheEntries);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start at t=0.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks now;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, cache.size());
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add five valid entries at t=10 that expire at t=20.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks t10 = now + kTTL;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 5; ++i) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name = base::StringPrintf("valid%d", i);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache.Put(name, "I'm valid!", t10, t10 + kTTL);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, cache.size());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add three entries at t=0 that expire at t=10.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 3; ++i) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name = base::StringPrintf("expired%d", i);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache.Put(name, "I'm expired.", now, t10);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(8U, cache.size());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add two negative (instantly expired) entries at t=0 that expire at t=0.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name = base::StringPrintf("negative%d", i);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache.Put(name, "I was never valid.", now, now);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(10U, cache.size());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid0"));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid1"));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid2"));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid3"));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid4"));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "expired0"));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "expired1"));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "expired2"));
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "negative0"));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "negative1"));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shrink the new max constraints bound and compact. The "negative" and
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "expired" entries should be dropped.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.max_entries_ = 6;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Compact(now);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, cache.size());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid0"));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid1"));
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid2"));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid3"));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(ContainsKey(cache.entries_, "valid4"));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(ContainsKey(cache.entries_, "expired0"));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(ContainsKey(cache.entries_, "expired1"));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(ContainsKey(cache.entries_, "expired2"));
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(ContainsKey(cache.entries_, "negative0"));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(ContainsKey(cache.entries_, "negative1"));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shrink further -- this time the compact will start dropping valid entries
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to make space.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.max_entries_ = 4;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Compact(now);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Add entries while the cache is at capacity, causing evictions.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ExpiringCacheTest, SetWithCompact) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cache cache(3);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // t=10
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks() + kTTL;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test1", "test1", now, now + kTTL);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test2", "test2", now, now + kTTL);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("expired", "expired", now, now);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should all be retrievable except "expired".
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test1", now), Pointee(StrEq("test1")));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test2", now), Pointee(StrEq("test2")));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("expired", now));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adding the fourth entry will cause "expired" to be evicted.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test3", "test3", now, now + kTTL);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("expired", now));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test1", now), Pointee(StrEq("test1")));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test2", now), Pointee(StrEq("test2")));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test3", now), Pointee(StrEq("test3")));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add two more entries. Something should be evicted, however "test5"
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should definitely be in there (since it was last inserted).
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test4", "test4", now, now + kTTL);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test5", "test5", now, now + kTTL);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test5", now), Pointee(StrEq("test5")));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ExpiringCacheTest, Clear) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cache cache(kMaxCacheEntries);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start at t=0.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks now;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, cache.size());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add three entries.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test1", "foo", now, now + kTTL);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test2", "foo", now, now + kTTL);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test3", "foo", now, now + kTTL);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Clear();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, cache.size());
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ExpiringCacheTest, GetTruncatesExpiredEntries) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Cache cache(kMaxCacheEntries);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start at t=0.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks now;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0U, cache.size());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add three entries at t=0.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test1", "foo1", now, now + kTTL);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test2", "foo2", now, now + kTTL);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test3", "foo3", now, now + kTTL);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure the entries were added.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test1", now), Pointee(StrEq("foo1")));
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test2", now), Pointee(StrEq("foo2")));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test3", now), Pointee(StrEq("foo3")));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add five entries at t=10.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  now += kTTL;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 5; ++i) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name = base::StringPrintf("valid%d", i);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache.Put(name, name, now, now + kTTL);  // Expire at t=20.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(8U, cache.size());
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now access two expired entries and ensure the cache size goes down.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("test1", now));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("test2", now));
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, cache.size());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Accessing non-expired entries should return entries and not adjust the
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cache size.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 5; ++i) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name = base::StringPrintf("valid%d", i);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_THAT(cache.Get(name, now), Pointee(StrEq(name)));
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(6U, cache.size());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ExpiringCacheTest, CustomFunctor) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpiringCache<std::string, std::string, std::string, TestFunctor> cache(5);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kNow("Now");
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kLater("A little bit later");
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kMuchLater("Much later");
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kHeatDeath("The heat death of the universe");
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0u, cache.size());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add three entries at t=kNow that expire at kLater.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test1", "foo1", kNow, kLater);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test2", "foo2", kNow, kLater);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test3", "foo3", kNow, kLater);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add two entries at t=kNow that expire at kMuchLater
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test4", "foo4", kNow, kMuchLater);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test5", "foo5", kNow, kMuchLater);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5U, cache.size());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure the entries were added.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test1", kNow), Pointee(StrEq("foo1")));
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test2", kNow), Pointee(StrEq("foo2")));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test3", kNow), Pointee(StrEq("foo3")));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test4", kNow), Pointee(StrEq("foo4")));
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test5", kNow), Pointee(StrEq("foo5")));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add one entry at t=kLater that expires at kHeatDeath, which will expire
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one of test1-3.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test6", "foo6", kLater, kHeatDeath);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test6", kLater), Pointee(StrEq("foo6")));
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cache.size());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now compact at kMuchLater, which should remove all but "test6".
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.max_entries_ = 2;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Compact(kMuchLater);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, cache.size());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test6", kMuchLater), Pointee(StrEq("foo6")));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finally, "test6" should not be valid at the end of the universe.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("test6", kHeatDeath));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Because comparison is based on equality, not strict weak ordering, we
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be able to add something at kHeatDeath that expires at kMuchLater.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache.Put("test7", "foo7", kHeatDeath, kMuchLater);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1U, cache.size());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test7", kNow), Pointee(StrEq("foo7")));
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test7", kLater), Pointee(StrEq("foo7")));
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cache.Get("test7", kHeatDeath), Pointee(StrEq("foo7")));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(cache.Get("test7", kMuchLater));
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
312