forked from mirrors/gecko-dev
The existing mix of UniquePtr and raw pointers is confusing when trying to figure out the exact lifetime of these objects. MozReview-Commit-ID: Br4S7BXEFKs --HG-- extra : rebase_source : ba35d5c2eeda0741eb4c5491a6caf03f20f3d0ce
282 lines
10 KiB
C++
282 lines
10 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "Common.h"
|
|
|
|
#define EXPIRED_TIME_SEC (PR_Now() / PR_USEC_PER_SEC - 3600)
|
|
#define NOTEXPIRED_TIME_SEC (PR_Now() / PR_USEC_PER_SEC + 3600)
|
|
|
|
static void
|
|
SetupCacheEntry(LookupCacheV2* aLookupCache,
|
|
const nsCString& aCompletion,
|
|
bool aNegExpired = false,
|
|
bool aPosExpired = false)
|
|
{
|
|
AddCompleteArray completes;
|
|
AddCompleteArray emptyCompletes;
|
|
MissPrefixArray misses;
|
|
MissPrefixArray emptyMisses;
|
|
|
|
AddComplete* add = completes.AppendElement(fallible);
|
|
add->complete.FromPlaintext(aCompletion);
|
|
|
|
Prefix* prefix = misses.AppendElement(fallible);
|
|
prefix->FromPlaintext(aCompletion);
|
|
|
|
// Setup positive cache first otherwise negative cache expiry will be
|
|
// overwritten.
|
|
int64_t posExpirySec = aPosExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC;
|
|
aLookupCache->AddGethashResultToCache(completes, emptyMisses, posExpirySec);
|
|
|
|
int64_t negExpirySec = aNegExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC;
|
|
aLookupCache->AddGethashResultToCache(emptyCompletes, misses, negExpirySec);
|
|
}
|
|
|
|
static void
|
|
SetupCacheEntry(LookupCacheV4* aLookupCache,
|
|
const nsCString& aCompletion,
|
|
bool aNegExpired = false,
|
|
bool aPosExpired = false)
|
|
{
|
|
FullHashResponseMap map;
|
|
|
|
Prefix prefix;
|
|
prefix.FromPlaintext(aCompletion);
|
|
|
|
CachedFullHashResponse* response = map.LookupOrAdd(prefix.ToUint32());
|
|
|
|
response->negativeCacheExpirySec =
|
|
aNegExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC;
|
|
response->fullHashes.Put(GeneratePrefix(aCompletion, COMPLETE_SIZE),
|
|
aPosExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC);
|
|
|
|
aLookupCache->AddFullHashResponseToCache(map);
|
|
}
|
|
|
|
template<typename T>
|
|
void
|
|
TestCache(const Completion aCompletion,
|
|
bool aExpectedHas,
|
|
bool aExpectedConfirmed,
|
|
bool aExpectedInCache,
|
|
T* aCache = nullptr)
|
|
{
|
|
bool has, inCache, confirmed;
|
|
uint32_t matchLength;
|
|
|
|
if (aCache) {
|
|
aCache->Has(aCompletion, &has, &matchLength, &confirmed);
|
|
inCache = aCache->IsInCache(aCompletion.ToUint32());
|
|
} else {
|
|
_PrefixArray array = { GeneratePrefix(_Fragment("cache.notexpired.com/"), 10),
|
|
GeneratePrefix(_Fragment("cache.expired.com/"), 8),
|
|
GeneratePrefix(_Fragment("gound.com/"), 5),
|
|
GeneratePrefix(_Fragment("small.com/"), 4)
|
|
};
|
|
|
|
RefPtr<T> cache = SetupLookupCache<T>(array);
|
|
|
|
// Create an expired entry and a non-expired entry
|
|
SetupCacheEntry(cache, _Fragment("cache.notexpired.com/"));
|
|
SetupCacheEntry(cache, _Fragment("cache.expired.com/"), true, true);
|
|
|
|
cache->Has(aCompletion, &has, &matchLength, &confirmed);
|
|
inCache = cache->IsInCache(aCompletion.ToUint32());
|
|
}
|
|
|
|
EXPECT_EQ(has, aExpectedHas);
|
|
EXPECT_EQ(confirmed, aExpectedConfirmed);
|
|
EXPECT_EQ(inCache, aExpectedInCache);
|
|
}
|
|
|
|
template<typename T>
|
|
void
|
|
TestCache(const _Fragment& aFragment,
|
|
bool aExpectedHas,
|
|
bool aExpectedConfirmed,
|
|
bool aExpectedInCache,
|
|
T* aCache = nullptr)
|
|
{
|
|
Completion lookupHash;
|
|
lookupHash.FromPlaintext(aFragment);
|
|
|
|
TestCache<T>(lookupHash, aExpectedHas, aExpectedConfirmed, aExpectedInCache, aCache);
|
|
}
|
|
|
|
// This testcase check the returned result of |Has| API if fullhash cannot match
|
|
// any prefix in the local database.
|
|
TEST(UrlClassifierCaching, NotFound)
|
|
{
|
|
TestCache<LookupCacheV2>(_Fragment("nomatch.com/"), false, false, false);
|
|
TestCache<LookupCacheV4>(_Fragment("nomatch.com/"), false, false, false);
|
|
}
|
|
|
|
// This testcase check the returned result of |Has| API if fullhash find a match
|
|
// in the local database but not in the cache.
|
|
TEST(UrlClassifierCaching, NotInCache)
|
|
{
|
|
TestCache<LookupCacheV2>(_Fragment("gound.com/"), true, false, false);
|
|
TestCache<LookupCacheV4>(_Fragment("gound.com/"), true, false, false);
|
|
}
|
|
|
|
// This testcase check the returned result of |Has| API if fullhash matches
|
|
// a cache entry in positive cache.
|
|
TEST(UrlClassifierCaching, InPositiveCacheNotExpired)
|
|
{
|
|
TestCache<LookupCacheV2>(_Fragment("cache.notexpired.com/"), true, true, true);
|
|
TestCache<LookupCacheV4>(_Fragment("cache.notexpired.com/"), true, true, true);
|
|
}
|
|
|
|
// This testcase check the returned result of |Has| API if fullhash matches
|
|
// a cache entry in positive cache but that it is expired.
|
|
TEST(UrlClassifierCaching, InPositiveCacheExpired)
|
|
{
|
|
TestCache<LookupCacheV2>(_Fragment("cache.expired.com/"), true, false, true);
|
|
TestCache<LookupCacheV4>(_Fragment("cache.expired.com/"), true, false, true);
|
|
}
|
|
|
|
// This testcase check the returned result of |Has| API if fullhash matches
|
|
// a cache entry in negative cache.
|
|
TEST(UrlClassifierCaching, InNegativeCacheNotExpired)
|
|
{
|
|
// Create a fullhash whose prefix matches the prefix in negative cache
|
|
// but completion doesn't match any fullhash in positive cache.
|
|
|
|
Completion prefix;
|
|
prefix.FromPlaintext(_Fragment("cache.notexpired.com/"));
|
|
|
|
Completion fullhash;
|
|
fullhash.FromPlaintext(_Fragment("firefox.com/"));
|
|
|
|
// Overwrite the 4-byte prefix of `fullhash` so that it conflicts with `prefix`.
|
|
// Since "cache.notexpired.com" is added to database in TestCache as a
|
|
// 10-byte prefix, we should copy more than 10 bytes to fullhash to ensure
|
|
// it can match the prefix in database.
|
|
memcpy(fullhash.buf, prefix.buf, 10);
|
|
|
|
TestCache<LookupCacheV2>(fullhash, false, false, true);
|
|
TestCache<LookupCacheV4>(fullhash, false, false, true);
|
|
}
|
|
|
|
// This testcase check the returned result of |Has| API if fullhash matches
|
|
// a cache entry in negative cache but that entry is expired.
|
|
TEST(UrlClassifierCaching, InNegativeCacheExpired)
|
|
{
|
|
// Create a fullhash whose prefix is in the cache.
|
|
|
|
Completion prefix;
|
|
prefix.FromPlaintext(_Fragment("cache.expired.com/"));
|
|
|
|
Completion fullhash;
|
|
fullhash.FromPlaintext(_Fragment("firefox.com/"));
|
|
|
|
memcpy(fullhash.buf, prefix.buf, 10);
|
|
|
|
TestCache<LookupCacheV2>(fullhash, true, false, true);
|
|
TestCache<LookupCacheV4>(fullhash, true, false, true);
|
|
}
|
|
|
|
#define CACHED_URL _Fragment("cache.com/")
|
|
#define NEG_CACHE_EXPIRED_URL _Fragment("cache.negExpired.com/")
|
|
#define POS_CACHE_EXPIRED_URL _Fragment("cache.posExpired.com/")
|
|
#define BOTH_CACHE_EXPIRED_URL _Fragment("cache.negAndposExpired.com/")
|
|
|
|
// This testcase create 4 cache entries.
|
|
// 1. unexpired entry.
|
|
// 2. an entry whose negative cache time is expired but whose positive cache
|
|
// is not expired.
|
|
// 3. an entry whose positive cache time is expired
|
|
// 4. an entry whose negative cache time and positive cache time are expired
|
|
// After calling |InvalidateExpiredCacheEntry| API, entries with expired
|
|
// negative time should be removed from cache(2 & 4)
|
|
template<typename T>
|
|
void TestInvalidateExpiredCacheEntry()
|
|
{
|
|
_PrefixArray array = { GeneratePrefix(CACHED_URL, 10),
|
|
GeneratePrefix(NEG_CACHE_EXPIRED_URL, 8),
|
|
GeneratePrefix(POS_CACHE_EXPIRED_URL, 5),
|
|
GeneratePrefix(BOTH_CACHE_EXPIRED_URL, 4)
|
|
};
|
|
RefPtr<T> cache = SetupLookupCache<T>(array);
|
|
|
|
SetupCacheEntry(cache, CACHED_URL, false, false);
|
|
SetupCacheEntry(cache, NEG_CACHE_EXPIRED_URL, true, false);
|
|
SetupCacheEntry(cache, POS_CACHE_EXPIRED_URL, false, true);
|
|
SetupCacheEntry(cache, BOTH_CACHE_EXPIRED_URL, true, true);
|
|
|
|
// Before invalidate
|
|
TestCache<T>(CACHED_URL, true, true, true, cache.get());
|
|
TestCache<T>(NEG_CACHE_EXPIRED_URL, true, true, true, cache.get());
|
|
TestCache<T>(POS_CACHE_EXPIRED_URL, true, false, true, cache.get());
|
|
TestCache<T>(BOTH_CACHE_EXPIRED_URL, true, false, true, cache.get());
|
|
|
|
// Call InvalidateExpiredCacheEntry to remove cache entries whose negative cache
|
|
// time is expired
|
|
cache->InvalidateExpiredCacheEntries();
|
|
|
|
// After invalidate, NEG_CACHE_EXPIRED_URL & BOTH_CACHE_EXPIRED_URL should
|
|
// not be found in cache.
|
|
TestCache<T>(NEG_CACHE_EXPIRED_URL, true, false, false, cache.get());
|
|
TestCache<T>(BOTH_CACHE_EXPIRED_URL, true, false, false, cache.get());
|
|
|
|
// Other entries should remain the same result.
|
|
TestCache<T>(CACHED_URL, true, true, true, cache.get());
|
|
TestCache<T>(POS_CACHE_EXPIRED_URL, true, false, true, cache.get());
|
|
}
|
|
|
|
TEST(UrlClassifierCaching, InvalidateExpiredCacheEntryV2)
|
|
{
|
|
TestInvalidateExpiredCacheEntry<LookupCacheV2>();
|
|
}
|
|
|
|
TEST(UrlClassifierCaching, InvalidateExpiredCacheEntryV4)
|
|
{
|
|
TestInvalidateExpiredCacheEntry<LookupCacheV4>();
|
|
}
|
|
|
|
// This testcase check if an cache entry whose negative cache time is expired
|
|
// and it doesn't have any postive cache entries in it, it should be removed
|
|
// from cache after calling |Has|.
|
|
TEST(UrlClassifierCaching, NegativeCacheExpireV2)
|
|
{
|
|
_PrefixArray array = { GeneratePrefix(NEG_CACHE_EXPIRED_URL, 8) };
|
|
RefPtr<LookupCacheV2> cache = SetupLookupCache<LookupCacheV2>(array);
|
|
|
|
nsCOMPtr<nsICryptoHash> cryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID);
|
|
|
|
MissPrefixArray misses;
|
|
Prefix* prefix = misses.AppendElement(fallible);
|
|
prefix->FromPlaintext(NEG_CACHE_EXPIRED_URL);
|
|
|
|
AddCompleteArray dummy;
|
|
cache->AddGethashResultToCache(dummy, misses, EXPIRED_TIME_SEC);
|
|
|
|
// Ensure it is in cache in the first place.
|
|
EXPECT_EQ(cache->IsInCache(prefix->ToUint32()), true);
|
|
|
|
// It should be removed after calling Has API.
|
|
TestCache<LookupCacheV2>(NEG_CACHE_EXPIRED_URL, true, false, false, cache.get());
|
|
}
|
|
|
|
TEST(UrlClassifierCaching, NegativeCacheExpireV4)
|
|
{
|
|
_PrefixArray array = { GeneratePrefix(NEG_CACHE_EXPIRED_URL, 8) };
|
|
RefPtr<LookupCacheV4> cache = SetupLookupCache<LookupCacheV4>(array);
|
|
|
|
FullHashResponseMap map;
|
|
Prefix prefix;
|
|
nsCOMPtr<nsICryptoHash> cryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID);
|
|
prefix.FromPlaintext(NEG_CACHE_EXPIRED_URL);
|
|
CachedFullHashResponse* response = map.LookupOrAdd(prefix.ToUint32());
|
|
|
|
response->negativeCacheExpirySec = EXPIRED_TIME_SEC;
|
|
|
|
cache->AddFullHashResponseToCache(map);
|
|
|
|
// Ensure it is in cache in the first place.
|
|
EXPECT_EQ(cache->IsInCache(prefix.ToUint32()), true);
|
|
|
|
// It should be removed after calling Has API.
|
|
TestCache<LookupCacheV4>(NEG_CACHE_EXPIRED_URL, true, false, false, cache.get());
|
|
}
|