Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/url-classifier/tests/gtest/TestUrlClassifierTableUpdateV4.cpp
Line
Count
Source (jump to first uncovered line)
1
/* Any copyright is dedicated to the Public Domain.
2
 * http://creativecommons.org/publicdomain/zero/1.0/ */
3
4
#include "Common.h"
5
#include "Classifier.h"
6
#include "HashStore.h"
7
#include "nsAppDirectoryServiceDefs.h"
8
#include "nsIFile.h"
9
#include "nsIThread.h"
10
#include "string.h"
11
#include "gtest/gtest.h"
12
#include "nsThreadUtils.h"
13
14
using namespace mozilla;
15
using namespace mozilla::safebrowsing;
16
17
typedef nsCString _Prefix;
18
typedef nsTArray<_Prefix> _PrefixArray;
19
20
0
#define GTEST_SAFEBROWSING_DIR NS_LITERAL_CSTRING("safebrowsing")
21
0
#define GTEST_TABLE NS_LITERAL_CSTRING("gtest-malware-proto")
22
0
#define GTEST_PREFIXFILE NS_LITERAL_CSTRING("gtest-malware-proto.pset")
23
24
// This function removes common elements of inArray and outArray from
25
// outArray. This is used by partial update testcase to ensure partial update
26
// data won't contain prefixes we already have.
27
static void
28
RemoveIntersection(const _PrefixArray& inArray, _PrefixArray& outArray)
29
0
{
30
0
  for (uint32_t i = 0; i < inArray.Length(); i++) {
31
0
    int32_t idx = outArray.BinaryIndexOf(inArray[i]);
32
0
    if (idx >= 0) {
33
0
      outArray.RemoveElementAt(idx);
34
0
    }
35
0
  }
36
0
}
37
38
// This fucntion removes elements from outArray by index specified in
39
// removal array.
40
static void
41
RemoveElements(const nsTArray<uint32_t>& removal, _PrefixArray& outArray)
42
0
{
43
0
  for (int32_t i = removal.Length() - 1; i >= 0; i--) {
44
0
    outArray.RemoveElementAt(removal[i]);
45
0
  }
46
0
}
47
48
static void
49
MergeAndSortArray(const _PrefixArray& array1,
50
                  const _PrefixArray& array2,
51
                  _PrefixArray& output)
52
0
{
53
0
  output.Clear();
54
0
  output.AppendElements(array1);
55
0
  output.AppendElements(array2);
56
0
  output.Sort();
57
0
}
58
59
static void
60
CalculateCheckSum(_PrefixArray& prefixArray, nsCString& checksum)
61
0
{
62
0
  prefixArray.Sort();
63
0
64
0
  nsresult rv;
65
0
  nsCOMPtr<nsICryptoHash> cryptoHash =
66
0
    do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
67
0
68
0
  cryptoHash->Init(nsICryptoHash::SHA256);
69
0
  for (uint32_t i = 0; i < prefixArray.Length(); i++) {
70
0
    const _Prefix& prefix = prefixArray[i];
71
0
    cryptoHash->Update(reinterpret_cast<uint8_t*>(
72
0
                       const_cast<char*>(prefix.get())), prefix.Length());
73
0
  }
74
0
  cryptoHash->Finish(false, checksum);
75
0
}
76
77
// N: Number of prefixes, MIN/MAX: minimum/maximum prefix size
78
// This function will append generated prefixes to outArray.
79
static void
80
CreateRandomSortedPrefixArray(uint32_t N,
81
                              uint32_t MIN,
82
                              uint32_t MAX,
83
                              _PrefixArray& outArray)
84
0
{
85
0
  outArray.SetCapacity(outArray.Length() + N);
86
0
87
0
  const uint32_t range = (MAX - MIN + 1);
88
0
89
0
  for (uint32_t i = 0; i < N; i++) {
90
0
    uint32_t prefixSize = (rand() % range) + MIN;
91
0
    _Prefix prefix;
92
0
    prefix.SetLength(prefixSize);
93
0
94
0
    while (true) {
95
0
      char* dst = prefix.BeginWriting();
96
0
      for (uint32_t j = 0; j < prefixSize; j++) {
97
0
        dst[j] = rand() % 256;
98
0
      }
99
0
100
0
      if (!outArray.Contains(prefix)) {
101
0
        outArray.AppendElement(prefix);
102
0
        break;
103
0
      }
104
0
    }
105
0
  }
106
0
107
0
  outArray.Sort();
108
0
}
109
110
// N: Number of removal indices, MAX: maximum index
111
static void
112
CreateRandomRemovalIndices(uint32_t N,
113
                           uint32_t MAX,
114
                           nsTArray<uint32_t>& outArray)
115
0
{
116
0
  for (uint32_t i = 0; i < N; i++) {
117
0
    uint32_t idx = rand() % MAX;
118
0
    if (!outArray.Contains(idx)) {
119
0
      outArray.InsertElementSorted(idx);
120
0
    }
121
0
  }
122
0
}
123
124
// Function to generate TableUpdateV4.
125
static void
126
GenerateUpdateData(bool fullUpdate,
127
                   PrefixStringMap& add,
128
                   nsTArray<uint32_t>* removal,
129
                   nsCString* checksum,
130
                   TableUpdateArray& tableUpdates)
131
0
{
132
0
  RefPtr<TableUpdateV4> tableUpdate = new TableUpdateV4(GTEST_TABLE);
133
0
  tableUpdate->SetFullUpdate(fullUpdate);
134
0
135
0
  for (auto iter = add.ConstIter(); !iter.Done(); iter.Next()) {
136
0
    nsCString* pstring = iter.Data();
137
0
    tableUpdate->NewPrefixes(iter.Key(), *pstring);
138
0
  }
139
0
140
0
  if (removal) {
141
0
    tableUpdate->NewRemovalIndices(removal->Elements(), removal->Length());
142
0
  }
143
0
144
0
  if (checksum) {
145
0
    std::string stdChecksum;
146
0
    stdChecksum.assign(const_cast<char*>(checksum->BeginReading()), checksum->Length());
147
0
148
0
    tableUpdate->NewChecksum(stdChecksum);
149
0
  }
150
0
151
0
  tableUpdates.AppendElement(tableUpdate);
152
0
}
153
154
static void
155
VerifyPrefixSet(PrefixStringMap& expected)
156
0
{
157
0
  // Verify the prefix set is written to disk.
158
0
  nsCOMPtr<nsIFile> file;
159
0
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
160
0
161
0
  file->AppendNative(GTEST_SAFEBROWSING_DIR);
162
0
  file->AppendNative(GTEST_PREFIXFILE);
163
0
164
0
  RefPtr<VariableLengthPrefixSet> load = new VariableLengthPrefixSet;
165
0
  load->Init(GTEST_TABLE);
166
0
167
0
  PrefixStringMap prefixesInFile;
168
0
  load->LoadFromFile(file);
169
0
  load->GetPrefixes(prefixesInFile);
170
0
171
0
  for (auto iter = expected.ConstIter(); !iter.Done(); iter.Next()) {
172
0
    nsCString* expectedPrefix = iter.Data();
173
0
    nsCString* resultPrefix = prefixesInFile.Get(iter.Key());
174
0
175
0
    ASSERT_TRUE(*resultPrefix == *expectedPrefix);
176
0
  }
177
0
}
178
179
static void
180
Clear()
181
0
{
182
0
  nsCOMPtr<nsIFile> file;
183
0
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
184
0
185
0
  RefPtr<Classifier> classifier = new Classifier();
186
0
  classifier->Open(*file);
187
0
  classifier->Reset();
188
0
}
189
190
static void
191
testUpdateFail(TableUpdateArray& tableUpdates)
192
0
{
193
0
  nsCOMPtr<nsIFile> file;
194
0
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
195
0
196
0
  RefPtr<Classifier> classifier = new Classifier();
197
0
  classifier->Open(*file);
198
0
199
0
  nsresult rv = SyncApplyUpdates(classifier, tableUpdates);
200
0
  ASSERT_TRUE(NS_FAILED(rv));
201
0
}
202
203
static void
204
testUpdate(TableUpdateArray& tableUpdates,
205
           PrefixStringMap& expected)
206
0
{
207
0
  nsCOMPtr<nsIFile> file;
208
0
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
209
0
210
0
  {
211
0
    // Force nsIUrlClassifierUtils loading on main thread
212
0
    // because nsIUrlClassifierDBService will not run in advance
213
0
    // in gtest.
214
0
    nsresult rv;
215
0
    nsCOMPtr<nsIUrlClassifierUtils> dummy =
216
0
      do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID, &rv);
217
0
      ASSERT_TRUE(NS_SUCCEEDED(rv));
218
0
  }
219
0
220
0
  RefPtr<Classifier> classifier = new Classifier();
221
0
  classifier->Open(*file);
222
0
223
0
  nsresult rv = SyncApplyUpdates(classifier, tableUpdates);
224
0
  ASSERT_TRUE(rv == NS_OK);
225
0
  VerifyPrefixSet(expected);
226
0
}
227
228
static void
229
testFullUpdate(PrefixStringMap& add, nsCString* checksum)
230
0
{
231
0
  TableUpdateArray tableUpdates;
232
0
233
0
  GenerateUpdateData(true, add, nullptr, checksum, tableUpdates);
234
0
235
0
  testUpdate(tableUpdates, add);
236
0
}
237
238
static void
239
testPartialUpdate(PrefixStringMap& add,
240
                  nsTArray<uint32_t>* removal,
241
                  nsCString* checksum,
242
                  PrefixStringMap& expected)
243
0
{
244
0
  TableUpdateArray tableUpdates;
245
0
  GenerateUpdateData(false, add, removal, checksum, tableUpdates);
246
0
247
0
  testUpdate(tableUpdates, expected);
248
0
}
249
250
static void
251
testOpenLookupCache()
252
0
{
253
0
  nsCOMPtr<nsIFile> file;
254
0
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
255
0
  file->AppendNative(GTEST_SAFEBROWSING_DIR);
256
0
257
0
  RunTestInNewThread([&] () -> void {
258
0
    RefPtr<LookupCacheV4> cache = new LookupCacheV4(nsCString(GTEST_TABLE),
259
0
                                                    EmptyCString(), file);
260
0
    nsresult rv = cache->Init();
261
0
    ASSERT_EQ(rv, NS_OK);
262
0
263
0
    rv = cache->Open();
264
0
    ASSERT_EQ(rv, NS_OK);
265
0
  });
266
0
}
267
268
// Tests start from here.
269
TEST(UrlClassifierTableUpdateV4, FixLenghtPSetFullUpdate)
270
0
{
271
0
  srand(time(NULL));
272
0
273
0
   _PrefixArray array;
274
0
  PrefixStringMap map;
275
0
  nsCString checksum;
276
0
277
0
  CreateRandomSortedPrefixArray(5000, 4, 4, array);
278
0
  PrefixArrayToPrefixStringMap(array, map);
279
0
  CalculateCheckSum(array, checksum);
280
0
281
0
  testFullUpdate(map, &checksum);
282
0
283
0
  Clear();
284
0
}
285
286
TEST(UrlClassifierTableUpdateV4, VariableLenghtPSetFullUpdate)
287
0
{
288
0
   _PrefixArray array;
289
0
  PrefixStringMap map;
290
0
  nsCString checksum;
291
0
292
0
  CreateRandomSortedPrefixArray(5000, 5, 32, array);
293
0
  PrefixArrayToPrefixStringMap(array, map);
294
0
  CalculateCheckSum(array, checksum);
295
0
296
0
  testFullUpdate(map, &checksum);
297
0
298
0
  Clear();
299
0
}
300
301
// This test contain both variable length prefix set and fixed-length prefix set
302
TEST(UrlClassifierTableUpdateV4, MixedPSetFullUpdate)
303
0
{
304
0
  _PrefixArray array;
305
0
  PrefixStringMap map;
306
0
  nsCString checksum;
307
0
308
0
  CreateRandomSortedPrefixArray(5000, 4, 4, array);
309
0
  CreateRandomSortedPrefixArray(1000, 5, 32, array);
310
0
  PrefixArrayToPrefixStringMap(array, map);
311
0
  CalculateCheckSum(array, checksum);
312
0
313
0
  testFullUpdate(map, &checksum);
314
0
315
0
  Clear();
316
0
}
317
318
TEST(UrlClassifierTableUpdateV4, PartialUpdateWithRemoval)
319
0
{
320
0
  _PrefixArray fArray;
321
0
322
0
  // Apply a full update first.
323
0
  {
324
0
    PrefixStringMap fMap;
325
0
    nsCString checksum;
326
0
327
0
    CreateRandomSortedPrefixArray(10000, 4, 4, fArray);
328
0
    CreateRandomSortedPrefixArray(2000, 5, 32, fArray);
329
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
330
0
    CalculateCheckSum(fArray, checksum);
331
0
332
0
    testFullUpdate(fMap, &checksum);
333
0
  }
334
0
335
0
  // Apply a partial update with removal.
336
0
  {
337
0
    _PrefixArray pArray, mergedArray;
338
0
    PrefixStringMap pMap, mergedMap;
339
0
    nsCString checksum;
340
0
341
0
    CreateRandomSortedPrefixArray(5000, 4, 4, pArray);
342
0
    CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
343
0
    RemoveIntersection(fArray, pArray);
344
0
    PrefixArrayToPrefixStringMap(pArray, pMap);
345
0
346
0
    // Remove 1/5 of elements of original prefix set.
347
0
    nsTArray<uint32_t> removal;
348
0
    CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
349
0
    RemoveElements(removal, fArray);
350
0
351
0
    // Calculate the expected prefix map.
352
0
    MergeAndSortArray(fArray, pArray, mergedArray);
353
0
    PrefixArrayToPrefixStringMap(mergedArray, mergedMap);
354
0
    CalculateCheckSum(mergedArray, checksum);
355
0
356
0
    testPartialUpdate(pMap, &removal, &checksum, mergedMap);
357
0
  }
358
0
359
0
  Clear();
360
0
}
361
362
TEST(UrlClassifierTableUpdateV4, PartialUpdateWithoutRemoval)
363
0
{
364
0
  _PrefixArray fArray;
365
0
366
0
  // Apply a full update first.
367
0
  {
368
0
    PrefixStringMap fMap;
369
0
    nsCString checksum;
370
0
371
0
    CreateRandomSortedPrefixArray(10000, 4, 4, fArray);
372
0
    CreateRandomSortedPrefixArray(2000, 5, 32, fArray);
373
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
374
0
    CalculateCheckSum(fArray, checksum);
375
0
376
0
    testFullUpdate(fMap, &checksum);
377
0
  }
378
0
379
0
  // Apply a partial update without removal
380
0
  {
381
0
    _PrefixArray pArray, mergedArray;
382
0
    PrefixStringMap pMap, mergedMap;
383
0
    nsCString checksum;
384
0
385
0
    CreateRandomSortedPrefixArray(5000, 4, 4, pArray);
386
0
    CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
387
0
    RemoveIntersection(fArray, pArray);
388
0
    PrefixArrayToPrefixStringMap(pArray, pMap);
389
0
390
0
    // Calculate the expected prefix map.
391
0
    MergeAndSortArray(fArray, pArray, mergedArray);
392
0
    PrefixArrayToPrefixStringMap(mergedArray, mergedMap);
393
0
    CalculateCheckSum(mergedArray, checksum);
394
0
395
0
    testPartialUpdate(pMap, nullptr, &checksum, mergedMap);
396
0
  }
397
0
398
0
  Clear();
399
0
}
400
401
// Expect failure because partial update contains prefix already
402
// in old prefix set.
403
TEST(UrlClassifierTableUpdateV4, PartialUpdatePrefixAlreadyExist)
404
0
{
405
0
  _PrefixArray fArray;
406
0
407
0
  // Apply a full update fist.
408
0
  {
409
0
    PrefixStringMap fMap;
410
0
    nsCString checksum;
411
0
412
0
    CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
413
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
414
0
    CalculateCheckSum(fArray, checksum);
415
0
416
0
    testFullUpdate(fMap, &checksum);
417
0
  }
418
0
419
0
  // Apply a partial update which contains a prefix in previous full update.
420
0
  // This should cause an update error.
421
0
  {
422
0
    _PrefixArray pArray;
423
0
    PrefixStringMap pMap;
424
0
    TableUpdateArray tableUpdates;
425
0
426
0
    // Pick one prefix from full update prefix and add it to partial update.
427
0
    // This should result a failure when call ApplyUpdates.
428
0
    pArray.AppendElement(fArray[rand() % fArray.Length()]);
429
0
    CreateRandomSortedPrefixArray(200, 4, 32, pArray);
430
0
    PrefixArrayToPrefixStringMap(pArray, pMap);
431
0
432
0
    GenerateUpdateData(false, pMap, nullptr, nullptr, tableUpdates);
433
0
    testUpdateFail(tableUpdates);
434
0
  }
435
0
436
0
  Clear();
437
0
}
438
439
// Test apply partial update directly without applying an full update first.
440
TEST(UrlClassifierTableUpdateV4, OnlyPartialUpdate)
441
0
{
442
0
  _PrefixArray pArray;
443
0
  PrefixStringMap pMap;
444
0
  nsCString checksum;
445
0
446
0
  CreateRandomSortedPrefixArray(5000, 4, 4, pArray);
447
0
  CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
448
0
  PrefixArrayToPrefixStringMap(pArray, pMap);
449
0
  CalculateCheckSum(pArray, checksum);
450
0
451
0
  testPartialUpdate(pMap, nullptr, &checksum, pMap);
452
0
453
0
  Clear();
454
0
}
455
456
// Test partial update without any ADD prefixes, only removalIndices.
457
TEST(UrlClassifierTableUpdateV4, PartialUpdateOnlyRemoval)
458
0
{
459
0
  _PrefixArray fArray;
460
0
461
0
  // Apply a full update first.
462
0
  {
463
0
    PrefixStringMap fMap;
464
0
    nsCString checksum;
465
0
466
0
    CreateRandomSortedPrefixArray(5000, 4, 4, fArray);
467
0
    CreateRandomSortedPrefixArray(1000, 5, 32, fArray);
468
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
469
0
    CalculateCheckSum(fArray, checksum);
470
0
471
0
    testFullUpdate(fMap, &checksum);
472
0
  }
473
0
474
0
  // Apply a partial update without add prefix, only contain removal indices.
475
0
  {
476
0
    _PrefixArray pArray;
477
0
    PrefixStringMap pMap, mergedMap;
478
0
    nsCString checksum;
479
0
480
0
    // Remove 1/5 of elements of original prefix set.
481
0
    nsTArray<uint32_t> removal;
482
0
    CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
483
0
    RemoveElements(removal, fArray);
484
0
485
0
    PrefixArrayToPrefixStringMap(fArray, mergedMap);
486
0
    CalculateCheckSum(fArray, checksum);
487
0
488
0
    testPartialUpdate(pMap, &removal, &checksum, mergedMap);
489
0
  }
490
0
491
0
  Clear();
492
0
}
493
494
// Test one tableupdate array contains full update and multiple partial updates.
495
TEST(UrlClassifierTableUpdateV4, MultipleTableUpdates)
496
0
{
497
0
  _PrefixArray fArray, pArray, mergedArray;
498
0
  PrefixStringMap fMap, pMap, mergedMap;
499
0
  nsCString checksum;
500
0
501
0
  TableUpdateArray tableUpdates;
502
0
503
0
  // Generate first full udpate
504
0
  CreateRandomSortedPrefixArray(10000, 4, 4, fArray);
505
0
  CreateRandomSortedPrefixArray(2000, 5, 32, fArray);
506
0
  PrefixArrayToPrefixStringMap(fArray, fMap);
507
0
  CalculateCheckSum(fArray, checksum);
508
0
509
0
  GenerateUpdateData(true, fMap, nullptr, &checksum, tableUpdates);
510
0
511
0
  // Generate second partial update
512
0
  CreateRandomSortedPrefixArray(3000, 4, 4, pArray);
513
0
  CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
514
0
  RemoveIntersection(fArray, pArray);
515
0
  PrefixArrayToPrefixStringMap(pArray, pMap);
516
0
517
0
  MergeAndSortArray(fArray, pArray, mergedArray);
518
0
  CalculateCheckSum(mergedArray, checksum);
519
0
520
0
  GenerateUpdateData(false, pMap, nullptr, &checksum, tableUpdates);
521
0
522
0
  // Generate thrid partial update
523
0
  fArray.AppendElements(pArray);
524
0
  fArray.Sort();
525
0
  pArray.Clear();
526
0
  CreateRandomSortedPrefixArray(3000, 4, 4, pArray);
527
0
  CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
528
0
  RemoveIntersection(fArray, pArray);
529
0
  PrefixArrayToPrefixStringMap(pArray, pMap);
530
0
531
0
  // Remove 1/5 of elements of original prefix set.
532
0
  nsTArray<uint32_t> removal;
533
0
  CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
534
0
  RemoveElements(removal, fArray);
535
0
536
0
  MergeAndSortArray(fArray, pArray, mergedArray);
537
0
  PrefixArrayToPrefixStringMap(mergedArray, mergedMap);
538
0
  CalculateCheckSum(mergedArray, checksum);
539
0
540
0
  GenerateUpdateData(false, pMap, &removal, &checksum, tableUpdates);
541
0
542
0
  testUpdate(tableUpdates, mergedMap);
543
0
544
0
  Clear();
545
0
}
546
547
// Test apply full update first, and then apply multiple partial updates
548
// in one tableupdate array.
549
TEST(UrlClassifierTableUpdateV4, MultiplePartialUpdateTableUpdates)
550
0
{
551
0
  _PrefixArray fArray;
552
0
553
0
  // Apply a full update first
554
0
  {
555
0
    PrefixStringMap fMap;
556
0
    nsCString checksum;
557
0
558
0
    // Generate first full udpate
559
0
    CreateRandomSortedPrefixArray(10000, 4, 4, fArray);
560
0
    CreateRandomSortedPrefixArray(3000, 5, 32, fArray);
561
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
562
0
    CalculateCheckSum(fArray, checksum);
563
0
564
0
    testFullUpdate(fMap, &checksum);
565
0
  }
566
0
567
0
  // Apply multiple partial updates in one table update
568
0
  {
569
0
    _PrefixArray pArray, mergedArray;
570
0
    PrefixStringMap pMap, mergedMap;
571
0
    nsCString checksum;
572
0
    nsTArray<uint32_t> removal;
573
0
    TableUpdateArray tableUpdates;
574
0
575
0
    // Generate first partial update
576
0
    CreateRandomSortedPrefixArray(3000, 4, 4, pArray);
577
0
    CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
578
0
    RemoveIntersection(fArray, pArray);
579
0
    PrefixArrayToPrefixStringMap(pArray, pMap);
580
0
581
0
    // Remove 1/5 of elements of original prefix set.
582
0
    CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
583
0
    RemoveElements(removal, fArray);
584
0
585
0
    MergeAndSortArray(fArray, pArray, mergedArray);
586
0
    CalculateCheckSum(mergedArray, checksum);
587
0
588
0
    GenerateUpdateData(false, pMap, &removal, &checksum, tableUpdates);
589
0
590
0
    fArray.AppendElements(pArray);
591
0
    fArray.Sort();
592
0
    pArray.Clear();
593
0
    removal.Clear();
594
0
595
0
    // Generate second partial update.
596
0
    CreateRandomSortedPrefixArray(2000, 4, 4, pArray);
597
0
    CreateRandomSortedPrefixArray(1000, 5, 32, pArray);
598
0
    RemoveIntersection(fArray, pArray);
599
0
    PrefixArrayToPrefixStringMap(pArray, pMap);
600
0
601
0
    // Remove 1/5 of elements of original prefix set.
602
0
    CreateRandomRemovalIndices(fArray.Length() / 5, fArray.Length(), removal);
603
0
    RemoveElements(removal, fArray);
604
0
605
0
    MergeAndSortArray(fArray, pArray, mergedArray);
606
0
    PrefixArrayToPrefixStringMap(mergedArray, mergedMap);
607
0
    CalculateCheckSum(mergedArray, checksum);
608
0
609
0
    GenerateUpdateData(false, pMap, &removal, &checksum, tableUpdates);
610
0
611
0
    testUpdate(tableUpdates, mergedMap);
612
0
  }
613
0
614
0
  Clear();
615
0
}
616
617
// Test removal indices are larger than the original prefix set.
618
TEST(UrlClassifierTableUpdateV4, RemovalIndexTooLarge)
619
0
{
620
0
  _PrefixArray fArray;
621
0
622
0
  // Apply a full update first
623
0
  {
624
0
    PrefixStringMap fMap;
625
0
    nsCString checksum;
626
0
627
0
    CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
628
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
629
0
    CalculateCheckSum(fArray, checksum);
630
0
631
0
    testFullUpdate(fMap, &checksum);
632
0
  }
633
0
634
0
  // Apply a partial update with removal indice array larger than
635
0
  // old prefix set(fArray). This should cause an error.
636
0
  {
637
0
    _PrefixArray pArray;
638
0
    PrefixStringMap pMap;
639
0
    nsTArray<uint32_t> removal;
640
0
    TableUpdateArray tableUpdates;
641
0
642
0
    CreateRandomSortedPrefixArray(200, 4, 32, pArray);
643
0
    RemoveIntersection(fArray, pArray);
644
0
    PrefixArrayToPrefixStringMap(pArray, pMap);
645
0
646
0
    for (uint32_t i = 0; i < fArray.Length() + 1 ;i++) {
647
0
      removal.AppendElement(i);
648
0
    }
649
0
650
0
    GenerateUpdateData(false, pMap, &removal, nullptr, tableUpdates);
651
0
    testUpdateFail(tableUpdates);
652
0
  }
653
0
654
0
  Clear();
655
0
}
656
657
TEST(UrlClassifierTableUpdateV4, ChecksumMismatch)
658
0
{
659
0
  // Apply a full update first
660
0
  {
661
0
    _PrefixArray fArray;
662
0
    PrefixStringMap fMap;
663
0
    nsCString checksum;
664
0
665
0
    CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
666
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
667
0
    CalculateCheckSum(fArray, checksum);
668
0
669
0
    testFullUpdate(fMap, &checksum);
670
0
  }
671
0
672
0
  // Apply a partial update with incorrect checksum
673
0
  {
674
0
    _PrefixArray pArray;
675
0
    PrefixStringMap pMap;
676
0
    nsCString checksum;
677
0
    TableUpdateArray tableUpdates;
678
0
679
0
    CreateRandomSortedPrefixArray(200, 4, 32, pArray);
680
0
    PrefixArrayToPrefixStringMap(pArray, pMap);
681
0
682
0
    // Checksum should be calculated with both old prefix set and add prefix set,
683
0
    // here we only calculate checksum with add prefix set to check if applyUpdate
684
0
    // will return failure.
685
0
    CalculateCheckSum(pArray, checksum);
686
0
687
0
    GenerateUpdateData(false, pMap, nullptr, &checksum, tableUpdates);
688
0
    testUpdateFail(tableUpdates);
689
0
  }
690
0
691
0
  Clear();
692
0
}
693
694
TEST(UrlClassifierTableUpdateV4, ApplyUpdateThenLoad)
695
0
{
696
0
  // Apply update with checksum
697
0
  {
698
0
    _PrefixArray fArray;
699
0
    PrefixStringMap fMap;
700
0
    nsCString checksum;
701
0
702
0
    CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
703
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
704
0
    CalculateCheckSum(fArray, checksum);
705
0
706
0
    testFullUpdate(fMap, &checksum);
707
0
708
0
    // Open lookup cache will load prefix set and verify the checksum
709
0
    testOpenLookupCache();
710
0
  }
711
0
712
0
  Clear();
713
0
714
0
  // Apply update without checksum
715
0
  {
716
0
    _PrefixArray fArray;
717
0
    PrefixStringMap fMap;
718
0
719
0
    CreateRandomSortedPrefixArray(1000, 4, 32, fArray);
720
0
    PrefixArrayToPrefixStringMap(fArray, fMap);
721
0
722
0
    testFullUpdate(fMap, nullptr);
723
0
724
0
    testOpenLookupCache();
725
0
  }
726
0
727
0
  Clear();
728
0
}
729
730
// This test is used to avoid an eror from nsICryptoHash
731
TEST(UrlClassifierTableUpdateV4, ApplyUpdateWithFixedChecksum)
732
0
{
733
0
  _PrefixArray fArray = { _Prefix("enus"), _Prefix("apollo"), _Prefix("mars"),
734
0
                          _Prefix("Hecatonchires cyclopes"),
735
0
                          _Prefix("vesta"), _Prefix("neptunus"), _Prefix("jupiter"),
736
0
                          _Prefix("diana"), _Prefix("minerva"), _Prefix("ceres"),
737
0
                          _Prefix("Aidos,Adephagia,Adikia,Aletheia"),
738
0
                          _Prefix("hecatonchires"), _Prefix("alcyoneus"), _Prefix("hades"),
739
0
                          _Prefix("vulcanus"), _Prefix("juno"), _Prefix("mercury"),
740
0
                          _Prefix("Stheno, Euryale and Medusa")
741
0
                        };
742
0
  fArray.Sort();
743
0
744
0
  PrefixStringMap fMap;
745
0
  PrefixArrayToPrefixStringMap(fArray, fMap);
746
0
747
0
  nsCString checksum("\xae\x18\x94\xd7\xd0\x83\x5f\xc1"
748
0
                     "\x58\x59\x5c\x2c\x72\xb9\x6e\x5e"
749
0
                     "\xf4\xe8\x0a\x6b\xff\x5e\x6b\x81"
750
0
                     "\x65\x34\x06\x16\x06\x59\xa0\x67");
751
0
752
0
  testFullUpdate(fMap, &checksum);
753
0
754
0
  // Open lookup cache will load prefix set and verify the checksum
755
0
  testOpenLookupCache();
756
0
757
0
  Clear();
758
0
}
759
760
// This test ensure that an empty update works correctly. Empty update
761
// should be skipped by CheckValidUpdate in Classifier::UpdateTableV4.
762
TEST(UrlClassifierTableUpdateV4, EmptyUpdate)
763
0
{
764
0
  PrefixStringMap emptyAddition;
765
0
  nsTArray<uint32_t> emptyRemoval;
766
0
767
0
   _PrefixArray array;
768
0
  PrefixStringMap map;
769
0
  nsCString checksum;
770
0
771
0
  CalculateCheckSum(array, checksum);
772
0
773
0
  // Test apply empty full/partial update before we already
774
0
  // have data in DB.
775
0
  testFullUpdate(emptyAddition, &checksum);
776
0
  testPartialUpdate(emptyAddition, &emptyRemoval, &checksum, map);
777
0
778
0
  // Apply an full update.
779
0
  CreateRandomSortedPrefixArray(100, 4, 4, array);
780
0
  CreateRandomSortedPrefixArray(10, 5, 32, array);
781
0
  PrefixArrayToPrefixStringMap(array, map);
782
0
  CalculateCheckSum(array, checksum);
783
0
784
0
  testFullUpdate(map, &checksum);
785
0
786
0
  // Test apply empty full/partial update when we already
787
0
  // have data in DB
788
0
  testPartialUpdate(emptyAddition, &emptyRemoval, &checksum, map);
789
0
  testFullUpdate(emptyAddition, &checksum);
790
0
791
0
  Clear();
792
0
}
793
794
// This test ensure applying an empty update directly through update algorithm
795
// should be correct.
796
TEST(UrlClassifierTableUpdateV4, EmptyUpdate2)
797
0
{
798
0
  // Setup LookupCache with initial data
799
0
  _PrefixArray array;
800
0
  CreateRandomSortedPrefixArray(100, 4, 4, array);
801
0
  CreateRandomSortedPrefixArray(10, 5, 32, array);
802
0
  RefPtr<LookupCacheV4> cache = SetupLookupCache<LookupCacheV4>(array);
803
0
804
0
  // Setup TableUpdate object with only checksum from previous update(initial data).
805
0
  nsCString checksum;
806
0
  CalculateCheckSum(array, checksum);
807
0
  std::string stdChecksum;
808
0
  stdChecksum.assign(const_cast<char*>(checksum.BeginReading()), checksum.Length());
809
0
810
0
  RefPtr<TableUpdateV4> tableUpdate = new TableUpdateV4(GTEST_TABLE);
811
0
  tableUpdate->NewChecksum(stdChecksum);
812
0
813
0
  // Apply update directly through LookupCache interface
814
0
  PrefixStringMap input, output;
815
0
  PrefixArrayToPrefixStringMap(array, input);
816
0
  nsresult rv = cache->ApplyUpdate(tableUpdate.get(), input, output);
817
0
818
0
  ASSERT_TRUE(rv == NS_OK);
819
0
820
0
  Clear();
821
0
}