A new function Classifier::AsyncApplyUpdates() is implemented for async update. Besides, all public Classifier interfaces become "worker thread only" and we remove DBServiceWorker::ApplyUpdatesBackground/Foreground. In DBServiceWorker::FinishUpdate, instead of calling Classifier::ApplyUpdates, we call Classifier::AsyncApplyUpdates and install a callback for notifying the update observer when update is finished. The callback will occur on the caller thread (i.e. worker thread.) As for the shutdown issue, when the main thread is notified to shut down, we at first *synchronously* dispatch an event to the worker thread to shut down the update thread. After getting synchronized with all other threads, we send last two events "CancelUpdate" and "CloseDb" to notify dangling update (i.e. BeginUpdate is called but FinishUpdate isn't) and do cleanup work. MozReview-Commit-ID: DXZvA2eFKlc
761 lines
21 KiB
C++
761 lines
21 KiB
C++
/* Any copyright is dedicated to the Public Domain.
|
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
#include "Common.h"
|
|
#include "Classifier.h"
|
|
#include "HashStore.h"
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
#include "nsIFile.h"
|
|
#include "nsIThread.h"
|
|
#include "string.h"
|
|
#include "gtest/gtest.h"
|
|
#include "nsThreadUtils.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::safebrowsing;
|
|
|
|
typedef nsCString _Prefix;
|
|
typedef nsTArray<_Prefix> _PrefixArray;
|
|
|
|
#define GTEST_SAFEBROWSING_DIR NS_LITERAL_CSTRING("safebrowsing")
|
|
#define GTEST_TABLE NS_LITERAL_CSTRING("gtest-malware-proto")
|
|
#define GTEST_PREFIXFILE NS_LITERAL_CSTRING("gtest-malware-proto.pset")
|
|
|
|
// This function removes common elements of inArray and outArray from
|
|
// outArray. This is used by partial update testcase to ensure partial update
|
|
// data won't contain prefixes we already have.
|
|
static void
|
|
RemoveIntersection(const _PrefixArray& inArray, _PrefixArray& outArray)
|
|
{
|
|
for (uint32_t i = 0; i < inArray.Length(); i++) {
|
|
int32_t idx = outArray.BinaryIndexOf(inArray[i]);
|
|
if (idx >= 0) {
|
|
outArray.RemoveElementAt(idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
// This fucntion removes elements from outArray by index specified in
|
|
// removal array.
|
|
static void
|
|
RemoveElements(const nsTArray<uint32_t>& removal, _PrefixArray& outArray)
|
|
{
|
|
for (int32_t i = removal.Length() - 1; i >= 0; i--) {
|
|
outArray.RemoveElementAt(removal[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
MergeAndSortArray(const _PrefixArray& array1,
|
|
const _PrefixArray& array2,
|
|
_PrefixArray& output)
|
|
{
|
|
output.Clear();
|
|
output.AppendElements(array1);
|
|
output.AppendElements(array2);
|
|
output.Sort();
|
|
}
|
|
|
|
static void
|
|
CalculateCheckSum(_PrefixArray& prefixArray, nsCString& checksum)
|
|
{
|
|
prefixArray.Sort();
|
|
|
|
nsresult rv;
|
|
nsCOMPtr<nsICryptoHash> cryptoHash =
|
|
do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
|
|
|
|
cryptoHash->Init(nsICryptoHash::SHA256);
|
|
for (uint32_t i = 0; i < prefixArray.Length(); i++) {
|
|
const _Prefix& prefix = prefixArray[i];
|
|
cryptoHash->Update(reinterpret_cast<uint8_t*>(
|
|
const_cast<char*>(prefix.get())), prefix.Length());
|
|
}
|
|
cryptoHash->Finish(false, checksum);
|
|
}
|
|
|
|
// N: Number of prefixes, MIN/MAX: minimum/maximum prefix size
|
|
// This function will append generated prefixes to outArray.
|
|
static void
|
|
CreateRandomSortedPrefixArray(uint32_t N,
|
|
uint32_t MIN,
|
|
uint32_t MAX,
|
|
_PrefixArray& outArray)
|
|
{
|
|
outArray.SetCapacity(outArray.Length() + N);
|
|
|
|
const uint32_t range = (MAX - MIN + 1);
|
|
|
|
for (uint32_t i = 0; i < N; i++) {
|
|
uint32_t prefixSize = (rand() % range) + MIN;
|
|
_Prefix prefix;
|
|
prefix.SetLength(prefixSize);
|
|
|
|
while (true) {
|
|
char* dst = prefix.BeginWriting();
|
|
for (uint32_t j = 0; j < prefixSize; j++) {
|
|
dst[j] = rand() % 256;
|
|
}
|
|
|
|
if (!outArray.Contains(prefix)) {
|
|
outArray.AppendElement(prefix);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
outArray.Sort();
|
|
}
|
|
|
|
// N: Number of removal indices, MAX: maximum index
|
|
static void
|
|
CreateRandomRemovalIndices(uint32_t N,
|
|
uint32_t MAX,
|
|
nsTArray<uint32_t>& outArray)
|
|
{
|
|
for (uint32_t i = 0; i < N; i++) {
|
|
uint32_t idx = rand() % MAX;
|
|
if (!outArray.Contains(idx)) {
|
|
outArray.InsertElementSorted(idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Function to generate TableUpdateV4.
|
|
static void
|
|
GenerateUpdateData(bool fullUpdate,
|
|
PrefixStringMap& add,
|
|
nsTArray<uint32_t>* removal,
|
|
nsCString* checksum,
|
|
nsTArray<TableUpdate*>& tableUpdates)
|
|
{
|
|
TableUpdateV4* tableUpdate = new TableUpdateV4(GTEST_TABLE);
|
|
tableUpdate->SetFullUpdate(fullUpdate);
|
|
|
|
for (auto iter = add.ConstIter(); !iter.Done(); iter.Next()) {
|
|
nsCString* pstring = iter.Data();
|
|
std::string str(pstring->BeginReading(), pstring->Length());
|
|
|
|
tableUpdate->NewPrefixes(iter.Key(), str);
|
|
}
|
|
|
|
if (removal) {
|
|
tableUpdate->NewRemovalIndices(removal->Elements(), removal->Length());
|
|
}
|
|
|
|
if (checksum) {
|
|
std::string stdChecksum;
|
|
stdChecksum.assign(const_cast<char*>(checksum->BeginReading()), checksum->Length());
|
|
|
|
tableUpdate->NewChecksum(stdChecksum);
|
|
}
|
|
|
|
tableUpdates.AppendElement(tableUpdate);
|
|
}
|
|
|
|
static void
|
|
VerifyPrefixSet(PrefixStringMap& expected)
|
|
{
|
|
// Verify the prefix set is written to disk.
|
|
nsCOMPtr<nsIFile> file;
|
|
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
|
|
|
|
file->AppendNative(GTEST_SAFEBROWSING_DIR);
|
|
file->AppendNative(GTEST_PREFIXFILE);
|
|
|
|
RefPtr<VariableLengthPrefixSet> load = new VariableLengthPrefixSet;
|
|
load->Init(GTEST_TABLE);
|
|
|
|
PrefixStringMap prefixesInFile;
|
|
load->LoadFromFile(file);
|
|
load->GetPrefixes(prefixesInFile);
|
|
|
|
for (auto iter = expected.ConstIter(); !iter.Done(); iter.Next()) {
|
|
nsCString* expectedPrefix = iter.Data();
|
|
nsCString* resultPrefix = prefixesInFile.Get(iter.Key());
|
|
|
|
ASSERT_TRUE(*resultPrefix == *expectedPrefix);
|
|
}
|
|
}
|
|
|
|
static void
|
|
Clear()
|
|
{
|
|
nsCOMPtr<nsIFile> file;
|
|
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
|
|
|
|
UniquePtr<Classifier> classifier(new Classifier());
|
|
classifier->Open(*file);
|
|
classifier->Reset();
|
|
}
|
|
|
|
static void
|
|
testUpdateFail(nsTArray<TableUpdate*>& tableUpdates)
|
|
{
|
|
nsCOMPtr<nsIFile> file;
|
|
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
|
|
|
|
UniquePtr<Classifier> classifier(new Classifier());
|
|
classifier->Open(*file);
|
|
|
|
nsresult rv = SyncApplyUpdates(classifier.get(), &tableUpdates);
|
|
ASSERT_TRUE(NS_FAILED(rv));
|
|
}
|
|
|
|
static void
|
|
testUpdate(nsTArray<TableUpdate*>& tableUpdates,
|
|
PrefixStringMap& expected)
|
|
{
|
|
nsCOMPtr<nsIFile> file;
|
|
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
|
|
|
|
{
|
|
// Force nsIUrlClassifierUtils loading on main thread
|
|
// because nsIUrlClassifierDBService will not run in advance
|
|
// in gtest.
|
|
nsresult rv;
|
|
nsCOMPtr<nsIUrlClassifierUtils> dummy =
|
|
do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID, &rv);
|
|
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
|
}
|
|
|
|
UniquePtr<Classifier> classifier(new Classifier());
|
|
classifier->Open(*file);
|
|
|
|
nsresult rv = SyncApplyUpdates(classifier.get(), &tableUpdates);
|
|
ASSERT_TRUE(rv == NS_OK);
|
|
VerifyPrefixSet(expected);
|
|
}
|
|
|
|
static void
|
|
testFullUpdate(PrefixStringMap& add, nsCString* checksum)
|
|
{
|
|
nsTArray<TableUpdate*> tableUpdates;
|
|
|
|
GenerateUpdateData(true, add, nullptr, checksum, tableUpdates);
|
|
|
|
testUpdate(tableUpdates, add);
|
|
}
|
|
|
|
static void
|
|
testPartialUpdate(PrefixStringMap& add,
|
|
nsTArray<uint32_t>* removal,
|
|
nsCString* checksum,
|
|
PrefixStringMap& expected)
|
|
{
|
|
nsTArray<TableUpdate*> tableUpdates;
|
|
GenerateUpdateData(false, add, removal, checksum, tableUpdates);
|
|
|
|
testUpdate(tableUpdates, expected);
|
|
}
|
|
|
|
static void
|
|
testOpenLookupCache()
|
|
{
|
|
nsCOMPtr<nsIFile> file;
|
|
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
|
|
file->AppendNative(GTEST_SAFEBROWSING_DIR);
|
|
|
|
RunTestInNewThread([&] () -> void {
|
|
LookupCacheV4 cache(nsCString(GTEST_TABLE), EmptyCString(), file);
|
|
nsresult rv = cache.Init();
|
|
ASSERT_EQ(rv, NS_OK);
|
|
|
|
rv = cache.Open();
|
|
ASSERT_EQ(rv, NS_OK);
|
|
});
|
|
}
|
|
|
|
// Tests start from here.
|
|
TEST(UrlClassifierTableUpdateV4, FixLenghtPSetFullUpdate)
|
|
{
|
|
srand(time(NULL));
|
|
|
|
_PrefixArray array;
|
|
PrefixStringMap map;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(5000, 4, 4, array);
|
|
PrefixArrayToPrefixStringMap(array, map);
|
|
CalculateCheckSum(array, checksum);
|
|
|
|
testFullUpdate(map, &checksum);
|
|
|
|
Clear();
|
|
}
|
|
|
|
TEST(UrlClassifierTableUpdateV4, VariableLenghtPSetFullUpdate)
|
|
{
|
|
_PrefixArray array;
|
|
PrefixStringMap map;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(5000, 5, 32, array);
|
|
PrefixArrayToPrefixStringMap(array, map);
|
|
CalculateCheckSum(array, checksum);
|
|
|
|
testFullUpdate(map, &checksum);
|
|
|
|
Clear();
|
|
}
|
|
|
|
// This test contain both variable length prefix set and fixed-length prefix set
|
|
TEST(UrlClassifierTableUpdateV4, MixedPSetFullUpdate)
|
|
{
|
|
_PrefixArray array;
|
|
PrefixStringMap map;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(5000, 4, 4, array);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, array);
|
|
PrefixArrayToPrefixStringMap(array, map);
|
|
CalculateCheckSum(array, checksum);
|
|
|
|
testFullUpdate(map, &checksum);
|
|
|
|
Clear();
|
|
}
|
|
|
|
TEST(UrlClassifierTableUpdateV4, PartialUpdateWithRemoval)
|
|
{
|
|
_PrefixArray fArray;
|
|
|
|
// Apply a full update first.
|
|
{
|
|
PrefixStringMap fMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(10000, 4, 4, fArray);
|
|
CreateRandomSortedPrefixArray(2000, 5, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
}
|
|
|
|
// Apply a partial update with removal.
|
|
{
|
|
_PrefixArray pArray, mergedArray;
|
|
PrefixStringMap pMap, mergedMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(5000, 4, 4, pArray);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
|
|
RemoveIntersection(fArray, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
// Remove 1/5 of elements of original prefix set.
|
|
nsTArray<uint32_t> removal;
|
|
CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
|
|
RemoveElements(removal, fArray);
|
|
|
|
// Calculate the expected prefix map.
|
|
MergeAndSortArray(fArray, pArray, mergedArray);
|
|
PrefixArrayToPrefixStringMap(mergedArray, mergedMap);
|
|
CalculateCheckSum(mergedArray, checksum);
|
|
|
|
testPartialUpdate(pMap, &removal, &checksum, mergedMap);
|
|
}
|
|
|
|
Clear();
|
|
}
|
|
|
|
TEST(UrlClassifierTableUpdateV4, PartialUpdateWithoutRemoval)
|
|
{
|
|
_PrefixArray fArray;
|
|
|
|
// Apply a full update first.
|
|
{
|
|
PrefixStringMap fMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(10000, 4, 4, fArray);
|
|
CreateRandomSortedPrefixArray(2000, 5, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
}
|
|
|
|
// Apply a partial update without removal
|
|
{
|
|
_PrefixArray pArray, mergedArray;
|
|
PrefixStringMap pMap, mergedMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(5000, 4, 4, pArray);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
|
|
RemoveIntersection(fArray, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
// Calculate the expected prefix map.
|
|
MergeAndSortArray(fArray, pArray, mergedArray);
|
|
PrefixArrayToPrefixStringMap(mergedArray, mergedMap);
|
|
CalculateCheckSum(mergedArray, checksum);
|
|
|
|
testPartialUpdate(pMap, nullptr, &checksum, mergedMap);
|
|
}
|
|
|
|
Clear();
|
|
}
|
|
|
|
// Expect failure because partial update contains prefix already
|
|
// in old prefix set.
|
|
TEST(UrlClassifierTableUpdateV4, PartialUpdatePrefixAlreadyExist)
|
|
{
|
|
_PrefixArray fArray;
|
|
|
|
// Apply a full update fist.
|
|
{
|
|
PrefixStringMap fMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
}
|
|
|
|
// Apply a partial update which contains a prefix in previous full update.
|
|
// This should cause an update error.
|
|
{
|
|
_PrefixArray pArray;
|
|
PrefixStringMap pMap;
|
|
nsTArray<TableUpdate*> tableUpdates;
|
|
|
|
// Pick one prefix from full update prefix and add it to partial update.
|
|
// This should result a failure when call ApplyUpdates.
|
|
pArray.AppendElement(fArray[rand() % fArray.Length()]);
|
|
CreateRandomSortedPrefixArray(200, 4, 32, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
GenerateUpdateData(false, pMap, nullptr, nullptr, tableUpdates);
|
|
testUpdateFail(tableUpdates);
|
|
}
|
|
|
|
Clear();
|
|
}
|
|
|
|
// Test apply partial update directly without applying an full update first.
|
|
TEST(UrlClassifierTableUpdateV4, OnlyPartialUpdate)
|
|
{
|
|
_PrefixArray pArray;
|
|
PrefixStringMap pMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(5000, 4, 4, pArray);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
CalculateCheckSum(pArray, checksum);
|
|
|
|
testPartialUpdate(pMap, nullptr, &checksum, pMap);
|
|
|
|
Clear();
|
|
}
|
|
|
|
// Test partial update without any ADD prefixes, only removalIndices.
|
|
TEST(UrlClassifierTableUpdateV4, PartialUpdateOnlyRemoval)
|
|
{
|
|
_PrefixArray fArray;
|
|
|
|
// Apply a full update first.
|
|
{
|
|
PrefixStringMap fMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(5000, 4, 4, fArray);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
}
|
|
|
|
// Apply a partial update without add prefix, only contain removal indices.
|
|
{
|
|
_PrefixArray pArray;
|
|
PrefixStringMap pMap, mergedMap;
|
|
nsCString checksum;
|
|
|
|
// Remove 1/5 of elements of original prefix set.
|
|
nsTArray<uint32_t> removal;
|
|
CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
|
|
RemoveElements(removal, fArray);
|
|
|
|
PrefixArrayToPrefixStringMap(fArray, mergedMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testPartialUpdate(pMap, &removal, &checksum, mergedMap);
|
|
}
|
|
|
|
Clear();
|
|
}
|
|
|
|
// Test one tableupdate array contains full update and multiple partial updates.
|
|
TEST(UrlClassifierTableUpdateV4, MultipleTableUpdates)
|
|
{
|
|
_PrefixArray fArray, pArray, mergedArray;
|
|
PrefixStringMap fMap, pMap, mergedMap;
|
|
nsCString checksum;
|
|
|
|
nsTArray<TableUpdate*> tableUpdates;
|
|
|
|
// Generate first full udpate
|
|
CreateRandomSortedPrefixArray(10000, 4, 4, fArray);
|
|
CreateRandomSortedPrefixArray(2000, 5, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
GenerateUpdateData(true, fMap, nullptr, &checksum, tableUpdates);
|
|
|
|
// Generate second partial update
|
|
CreateRandomSortedPrefixArray(3000, 4, 4, pArray);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
|
|
RemoveIntersection(fArray, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
MergeAndSortArray(fArray, pArray, mergedArray);
|
|
CalculateCheckSum(mergedArray, checksum);
|
|
|
|
GenerateUpdateData(false, pMap, nullptr, &checksum, tableUpdates);
|
|
|
|
// Generate thrid partial update
|
|
fArray.AppendElements(pArray);
|
|
fArray.Sort();
|
|
pArray.Clear();
|
|
CreateRandomSortedPrefixArray(3000, 4, 4, pArray);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
|
|
RemoveIntersection(fArray, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
// Remove 1/5 of elements of original prefix set.
|
|
nsTArray<uint32_t> removal;
|
|
CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
|
|
RemoveElements(removal, fArray);
|
|
|
|
MergeAndSortArray(fArray, pArray, mergedArray);
|
|
PrefixArrayToPrefixStringMap(mergedArray, mergedMap);
|
|
CalculateCheckSum(mergedArray, checksum);
|
|
|
|
GenerateUpdateData(false, pMap, &removal, &checksum, tableUpdates);
|
|
|
|
testUpdate(tableUpdates, mergedMap);
|
|
|
|
Clear();
|
|
}
|
|
|
|
// Test apply full update first, and then apply multiple partial updates
|
|
// in one tableupdate array.
|
|
TEST(UrlClassifierTableUpdateV4, MultiplePartialUpdateTableUpdates)
|
|
{
|
|
_PrefixArray fArray;
|
|
|
|
// Apply a full update first
|
|
{
|
|
PrefixStringMap fMap;
|
|
nsCString checksum;
|
|
|
|
// Generate first full udpate
|
|
CreateRandomSortedPrefixArray(10000, 4, 4, fArray);
|
|
CreateRandomSortedPrefixArray(3000, 5, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
}
|
|
|
|
// Apply multiple partial updates in one table update
|
|
{
|
|
_PrefixArray pArray, mergedArray;
|
|
PrefixStringMap pMap, mergedMap;
|
|
nsCString checksum;
|
|
nsTArray<uint32_t> removal;
|
|
nsTArray<TableUpdate*> tableUpdates;
|
|
|
|
// Generate first partial update
|
|
CreateRandomSortedPrefixArray(3000, 4, 4, pArray);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
|
|
RemoveIntersection(fArray, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
// Remove 1/5 of elements of original prefix set.
|
|
CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
|
|
RemoveElements(removal, fArray);
|
|
|
|
MergeAndSortArray(fArray, pArray, mergedArray);
|
|
CalculateCheckSum(mergedArray, checksum);
|
|
|
|
GenerateUpdateData(false, pMap, &removal, &checksum, tableUpdates);
|
|
|
|
fArray.AppendElements(pArray);
|
|
fArray.Sort();
|
|
pArray.Clear();
|
|
removal.Clear();
|
|
|
|
// Generate second partial update.
|
|
CreateRandomSortedPrefixArray(2000, 4, 4, pArray);
|
|
CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
|
|
RemoveIntersection(fArray, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
// Remove 1/5 of elements of original prefix set.
|
|
CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
|
|
RemoveElements(removal, fArray);
|
|
|
|
MergeAndSortArray(fArray, pArray, mergedArray);
|
|
PrefixArrayToPrefixStringMap(mergedArray, mergedMap);
|
|
CalculateCheckSum(mergedArray, checksum);
|
|
|
|
GenerateUpdateData(false, pMap, &removal, &checksum, tableUpdates);
|
|
|
|
testUpdate(tableUpdates, mergedMap);
|
|
}
|
|
|
|
Clear();
|
|
}
|
|
|
|
// Test removal indices are larger than the original prefix set.
|
|
TEST(UrlClassifierTableUpdateV4, RemovalIndexTooLarge)
|
|
{
|
|
_PrefixArray fArray;
|
|
|
|
// Apply a full update first
|
|
{
|
|
PrefixStringMap fMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
}
|
|
|
|
// Apply a partial update with removal indice array larger than
|
|
// old prefix set(fArray). This should cause an error.
|
|
{
|
|
_PrefixArray pArray;
|
|
PrefixStringMap pMap;
|
|
nsTArray<uint32_t> removal;
|
|
nsTArray<TableUpdate*> tableUpdates;
|
|
|
|
CreateRandomSortedPrefixArray(200, 4, 32, pArray);
|
|
RemoveIntersection(fArray, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
for (uint32_t i = 0; i < fArray.Length() + 1 ;i++) {
|
|
removal.AppendElement(i);
|
|
}
|
|
|
|
GenerateUpdateData(false, pMap, &removal, nullptr, tableUpdates);
|
|
testUpdateFail(tableUpdates);
|
|
}
|
|
|
|
Clear();
|
|
}
|
|
|
|
TEST(UrlClassifierTableUpdateV4, ChecksumMismatch)
|
|
{
|
|
// Apply a full update first
|
|
{
|
|
_PrefixArray fArray;
|
|
PrefixStringMap fMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
}
|
|
|
|
// Apply a partial update with incorrect checksum
|
|
{
|
|
_PrefixArray pArray;
|
|
PrefixStringMap pMap;
|
|
nsCString checksum;
|
|
nsTArray<TableUpdate*> tableUpdates;
|
|
|
|
CreateRandomSortedPrefixArray(200, 4, 32, pArray);
|
|
PrefixArrayToPrefixStringMap(pArray, pMap);
|
|
|
|
// Checksum should be calculated with both old prefix set and add prefix set,
|
|
// here we only calculate checksum with add prefix set to check if applyUpdate
|
|
// will return failure.
|
|
CalculateCheckSum(pArray, checksum);
|
|
|
|
GenerateUpdateData(false, pMap, nullptr, &checksum, tableUpdates);
|
|
testUpdateFail(tableUpdates);
|
|
}
|
|
|
|
Clear();
|
|
}
|
|
|
|
TEST(UrlClassifierTableUpdateV4, ApplyUpdateThenLoad)
|
|
{
|
|
// Apply update with checksum
|
|
{
|
|
_PrefixArray fArray;
|
|
PrefixStringMap fMap;
|
|
nsCString checksum;
|
|
|
|
CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
CalculateCheckSum(fArray, checksum);
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
|
|
// Open lookup cache will load prefix set and verify the checksum
|
|
testOpenLookupCache();
|
|
}
|
|
|
|
Clear();
|
|
|
|
// Apply update without checksum
|
|
{
|
|
_PrefixArray fArray;
|
|
PrefixStringMap fMap;
|
|
|
|
CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
|
|
testFullUpdate(fMap, nullptr);
|
|
|
|
testOpenLookupCache();
|
|
}
|
|
|
|
Clear();
|
|
}
|
|
|
|
// This test is used to avoid an eror from nsICryptoHash
|
|
TEST(UrlClassifierTableUpdateV4, ApplyUpdateWithFixedChecksum)
|
|
{
|
|
_PrefixArray fArray = { _Prefix("enus"), _Prefix("apollo"), _Prefix("mars"),
|
|
_Prefix("Hecatonchires cyclopes"),
|
|
_Prefix("vesta"), _Prefix("neptunus"), _Prefix("jupiter"),
|
|
_Prefix("diana"), _Prefix("minerva"), _Prefix("ceres"),
|
|
_Prefix("Aidos,Adephagia,Adikia,Aletheia"),
|
|
_Prefix("hecatonchires"), _Prefix("alcyoneus"), _Prefix("hades"),
|
|
_Prefix("vulcanus"), _Prefix("juno"), _Prefix("mercury"),
|
|
_Prefix("Stheno, Euryale and Medusa")
|
|
};
|
|
fArray.Sort();
|
|
|
|
PrefixStringMap fMap;
|
|
PrefixArrayToPrefixStringMap(fArray, fMap);
|
|
|
|
nsCString checksum("\xae\x18\x94\xd7\xd0\x83\x5f\xc1"
|
|
"\x58\x59\x5c\x2c\x72\xb9\x6e\x5e"
|
|
"\xf4\xe8\x0a\x6b\xff\x5e\x6b\x81"
|
|
"\x65\x34\x06\x16\x06\x59\xa0\x67");
|
|
|
|
testFullUpdate(fMap, &checksum);
|
|
|
|
// Open lookup cache will load prefix set and verify the checksum
|
|
testOpenLookupCache();
|
|
|
|
Clear();
|
|
}
|
|
|