blob: 41e0fd08f45a6566b287d80e0725377815aa3c8b [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: jmarantz@google.com (Joshua Marantz)
// Unit-test PurgeSet
#include "pagespeed/kernel/cache/purge_set.h"
#include <cstddef>
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/string_util.h"
namespace net_instaweb {
namespace {
const size_t kMaxSize = 100;
}
class PurgeSetTest : public testing::Test {
protected:
PurgeSetTest() : purge_set_(kMaxSize) {
}
PurgeSet purge_set_;
private:
DISALLOW_COPY_AND_ASSIGN(PurgeSetTest);
};
TEST_F(PurgeSetTest, Empty) {
EXPECT_TRUE(purge_set_.empty());
}
TEST_F(PurgeSetTest, SimpleInvaldations) {
EXPECT_TRUE(purge_set_.IsValid("a", 1));
ASSERT_TRUE(purge_set_.Put("a", 2));
EXPECT_FALSE(purge_set_.IsValid("a", 1));
EXPECT_TRUE(purge_set_.IsValid("a", 3));
EXPECT_TRUE(purge_set_.IsValid("b", 1));
}
TEST_F(PurgeSetTest, NoEvictionsOnUpdateSameEntry) {
int64 last_eviction_time_ms = 1;
for (int i = 0; i < kMaxSize * 10; ++i) {
++last_eviction_time_ms;
ASSERT_TRUE(purge_set_.Put("a", last_eviction_time_ms));
}
EXPECT_FALSE(purge_set_.has_global_invalidation_timestamp_ms());
EXPECT_FALSE(purge_set_.IsValid("a", 1));
EXPECT_FALSE(purge_set_.IsValid("a", last_eviction_time_ms));
EXPECT_TRUE(purge_set_.IsValid("a", last_eviction_time_ms + 1));
EXPECT_TRUE(purge_set_.IsValid("b", 1));
}
TEST_F(PurgeSetTest, EvictionsOnUpdateNewEntries) {
for (int i = 0; i < kMaxSize * 10; ++i) {
ASSERT_TRUE(purge_set_.Put(StrCat("a", IntegerToString(i)), i + 1));
}
EXPECT_LT(0, purge_set_.global_invalidation_timestamp_ms());
EXPECT_FALSE(purge_set_.IsValid("a", 1));
EXPECT_FALSE(purge_set_.IsValid("b", 1));
// Check that all explicitly disallowed entries are still disallowed
// whether they are before or after the global invalidation
// timestamp.
for (int i = 0; i < kMaxSize * 10; ++i) {
EXPECT_FALSE(purge_set_.IsValid(StrCat("a", IntegerToString(i)), i));
}
}
TEST_F(PurgeSetTest, Merge) {
ASSERT_TRUE(purge_set_.UpdateGlobalInvalidationTimestampMs(10));
ASSERT_TRUE(purge_set_.Put("b", 50));
EXPECT_FALSE(purge_set_.IsValid("c", 5));
EXPECT_TRUE(purge_set_.IsValid("c", 20));
EXPECT_FALSE(purge_set_.IsValid("b", 40));
PurgeSet src(kMaxSize);
ASSERT_TRUE(src.UpdateGlobalInvalidationTimestampMs(20));
ASSERT_TRUE(src.Put("a", 50));
purge_set_.Merge(src);
EXPECT_FALSE(purge_set_.IsValid("a", 40));
EXPECT_FALSE(purge_set_.IsValid("b", 40));
EXPECT_FALSE(purge_set_.IsValid("c", 19));
EXPECT_TRUE(purge_set_.IsValid("c", 40));
}
TEST_F(PurgeSetTest, MergeMaxWins) {
ASSERT_TRUE(purge_set_.UpdateGlobalInvalidationTimestampMs(10));
ASSERT_TRUE(purge_set_.Put("a", 40));
ASSERT_TRUE(purge_set_.Put("b", 70));
PurgeSet src(kMaxSize);
ASSERT_TRUE(src.UpdateGlobalInvalidationTimestampMs(5)); // ignored on merge
ASSERT_TRUE(src.Put("a", 50));
ASSERT_TRUE(src.Put("b", 60));
purge_set_.Merge(src);
EXPECT_FALSE(purge_set_.IsValid("a", 45));
EXPECT_TRUE(purge_set_.IsValid("a", 55));
EXPECT_FALSE(purge_set_.IsValid("b", 65)); // implement combining policy
EXPECT_TRUE(purge_set_.IsValid("b", 75));
EXPECT_FALSE(purge_set_.IsValid("c", 9));
EXPECT_TRUE(purge_set_.IsValid("c", 11));
}
TEST_F(PurgeSetTest, SlightSkew) {
ASSERT_TRUE(purge_set_.Put("a", 10));
ASSERT_TRUE(purge_set_.UpdateGlobalInvalidationTimestampMs(8)); // clamped
EXPECT_FALSE(purge_set_.IsValid("b", 9));
EXPECT_FALSE(purge_set_.IsValid("b", 10));
EXPECT_TRUE(purge_set_.IsValid("b", 11));
}
TEST_F(PurgeSetTest, TooMuchSkew) {
ASSERT_TRUE(purge_set_.Put("a", PurgeSet::kClockSkewAllowanceMs + 100));
EXPECT_FALSE(purge_set_.UpdateGlobalInvalidationTimestampMs(10)); // ignored
EXPECT_TRUE(purge_set_.IsValid("b", 9));
EXPECT_TRUE(purge_set_.IsValid("b", 10));
EXPECT_TRUE(purge_set_.IsValid("b", 11));
}
TEST_F(PurgeSetTest, Equals) {
ASSERT_TRUE(purge_set_.Put("a", 100));
EXPECT_TRUE(purge_set_.Equals(purge_set_));
EXPECT_FALSE(purge_set_.IsValid("a", 99));
EXPECT_TRUE(purge_set_.IsValid("a", 101));
PurgeSet other(kMaxSize);
EXPECT_FALSE(purge_set_.Equals(other));
EXPECT_TRUE(other.Put("a", 99));
EXPECT_FALSE(purge_set_.Equals(other));
EXPECT_TRUE(other.Put("a", 100));
EXPECT_TRUE(purge_set_.Equals(other));
ASSERT_TRUE(purge_set_.UpdateGlobalInvalidationTimestampMs(101));
EXPECT_FALSE(purge_set_.Equals(other));
}
TEST_F(PurgeSetTest, CopyConstruct) {
ASSERT_TRUE(purge_set_.UpdateGlobalInvalidationTimestampMs(8));
ASSERT_TRUE(purge_set_.Put("a", 100));
PurgeSet other(purge_set_);
EXPECT_TRUE(purge_set_.Equals(other));
}
TEST_F(PurgeSetTest, Assign) {
ASSERT_TRUE(purge_set_.UpdateGlobalInvalidationTimestampMs(8));
ASSERT_TRUE(purge_set_.Put("a", 100));
PurgeSet other(kMaxSize);
other = purge_set_;
EXPECT_TRUE(purge_set_.Equals(other));
}
TEST_F(PurgeSetTest, ToString) {
ASSERT_TRUE(purge_set_.UpdateGlobalInvalidationTimestampMs(
MockTimer::kApr_5_2010_ms));
ASSERT_TRUE(purge_set_.Put("a",
MockTimer::kApr_5_2010_ms + Timer::kSecondMs));
EXPECT_STREQ("Global@Mon, 05 Apr 2010 18:51:26 GMT\n"
"a@Mon, 05 Apr 2010 18:51:27 GMT", purge_set_.ToString());
}
} // namespace net_instaweb