tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestCacheIndex.cpp (5298B)


      1 #include "gtest/gtest.h"
      2 #include "mozilla/StaticMutex.h"
      3 #include "mozilla/TimeStamp.h"
      4 #include "nsTArray.h"
      5 #include "../cache2/CacheIndex.h"
      6 
      7 namespace mozilla {
      8 namespace net {
      9 
     10 using namespace mozilla::net;
     11 
     12 class FrecencyStorageTest : public ::testing::Test {
     13 protected:
     14  RefPtr<CacheIndexRecordWrapper> MakeRecord(uint32_t frecency) {
     15    auto* rec = new CacheIndexRecordWrapper();
     16    rec->Get()->mFrecency = frecency;
     17    return RefPtr<CacheIndexRecordWrapper>(rec);
     18  }
     19 };
     20 
     21 // Test to ensure that AppendRecord and RemoveRecord work correctly. Also
     22 // implicitly tests RecordExistedUnlocked
     23 TEST_F(FrecencyStorageTest, AppendRemoveRecordTest) {
     24  CacheIndex::FrecencyStorage storage;
     25  RefPtr<CacheIndexRecordWrapper> rec1 = MakeRecord(10);
     26  RefPtr<CacheIndexRecordWrapper> rec2 = MakeRecord(20);
     27 
     28  mozilla::StaticMutexAutoLock lock(CacheIndex::sLock);
     29 
     30  // sanity check
     31  EXPECT_FALSE(storage.RecordExistedUnlocked(rec1));
     32  EXPECT_FALSE(storage.RecordExistedUnlocked(rec2));
     33  EXPECT_EQ(storage.Length(), 0u);
     34 
     35  // Append test
     36  storage.AppendRecord(rec1, lock);
     37  EXPECT_EQ(storage.Length(), 1u);
     38  EXPECT_TRUE(storage.RecordExistedUnlocked(rec1));
     39 
     40  storage.AppendRecord(rec2, lock);
     41  EXPECT_EQ(storage.Length(), 2u);
     42  EXPECT_TRUE(storage.RecordExistedUnlocked(rec1));
     43  EXPECT_TRUE(storage.RecordExistedUnlocked(rec2));
     44 
     45  // Remove test
     46  storage.RemoveRecord(rec1, lock);
     47  EXPECT_EQ(storage.Length(), 1u);
     48 
     49  storage.RemoveRecord(rec2, lock);
     50  EXPECT_EQ(storage.Length(), 0u);
     51 
     52  EXPECT_FALSE(storage.RecordExistedUnlocked(rec1));
     53  EXPECT_FALSE(storage.RecordExistedUnlocked(rec2));
     54 }
     55 
     56 // Test to ensure that ReplaceRecord updates the record correctly.
     57 TEST_F(FrecencyStorageTest, ReplaceRecordTest) {
     58  RefPtr<CacheIndexRecordWrapper> oldRec = MakeRecord(10);
     59  RefPtr<CacheIndexRecordWrapper> newRec = MakeRecord(20);
     60 
     61  CacheIndex::FrecencyStorage storage;
     62  mozilla::StaticMutexAutoLock lock(CacheIndex::sLock);
     63  storage.AppendRecord(oldRec, lock);
     64  EXPECT_TRUE(storage.RecordExistedUnlocked(oldRec));
     65  EXPECT_FALSE(storage.RecordExistedUnlocked(newRec));
     66 
     67  storage.ReplaceRecord(oldRec, newRec, lock);
     68  EXPECT_FALSE(storage.RecordExistedUnlocked(oldRec));
     69  EXPECT_TRUE(storage.RecordExistedUnlocked(newRec));
     70 }
     71 
     72 // Test to ensure that Clear() method empties the storage.
     73 TEST_F(FrecencyStorageTest, ClearTest) {
     74  RefPtr<CacheIndexRecordWrapper> rec1 = MakeRecord(10);
     75  RefPtr<CacheIndexRecordWrapper> rec2 = MakeRecord(20);
     76 
     77  CacheIndex::FrecencyStorage storage;
     78  mozilla::StaticMutexAutoLock lock(CacheIndex::sLock);
     79  storage.AppendRecord(rec1, lock);
     80  storage.AppendRecord(rec2, lock);
     81  EXPECT_EQ(storage.Length(), 2u);
     82 
     83  storage.Clear(lock);
     84  EXPECT_EQ(storage.Length(), 0u);
     85 }
     86 
     87 // Test to ensure that GetSortedSnapshotForEviction returns records in sorted
     88 // order based on frecency.
     89 TEST_F(FrecencyStorageTest, GetSortedSnapshotForEvictionTest) {
     90  auto r1 = MakeRecord(30);
     91  auto r2 = MakeRecord(10);
     92  auto r3 = MakeRecord(20);
     93 
     94  CacheIndex::FrecencyStorage storage;
     95  mozilla::StaticMutexAutoLock lock(CacheIndex::sLock);
     96  storage.AppendRecord(r1, lock);
     97  storage.AppendRecord(r2, lock);
     98  storage.AppendRecord(r3, lock);
     99 
    100  auto snapshot = storage.GetSortedSnapshotForEviction();
    101  ASSERT_EQ(snapshot.Length(), 3u);
    102  EXPECT_EQ(snapshot[0]->Get()->mFrecency, 10u);
    103  EXPECT_EQ(snapshot[1]->Get()->mFrecency, 20u);
    104  EXPECT_EQ(snapshot[2]->Get()->mFrecency, 30u);
    105 }
    106 
    107 // Performance test to ensure that AppendRecord and RemoveRecord do not degrade
    108 // with large numbers of records.
    109 TEST_F(FrecencyStorageTest, PerformanceTest) {
    110  constexpr int N = 100'000;
    111  CacheIndex::FrecencyStorage storage;
    112 
    113  std::vector<RefPtr<CacheIndexRecordWrapper>> records;
    114  records.reserve(N);
    115  for (int i = 0; i < N; ++i) {
    116    records.push_back(MakeRecord(i));
    117  }
    118  mozilla::StaticMutexAutoLock lock(CacheIndex::sLock);
    119 
    120  // Utility function to measure the time taken
    121  auto measure = [](const std::function<void()>& func) {
    122    auto start = std::chrono::high_resolution_clock::now();
    123    func();
    124    auto end = std::chrono::high_resolution_clock::now();
    125    return std::chrono::duration<double, std::milli>(end - start).count();
    126  };
    127 
    128  // Measure AppendRecord performance
    129  auto append_duration = measure([&] {
    130    for (const auto& rec : records) {
    131      storage.AppendRecord(rec.get(), lock);
    132    }
    133  });
    134  EXPECT_LE(append_duration, 200)
    135      << "AppendRecord is too slow" << " (" << append_duration << " ms) for "
    136      << N << " records";
    137 
    138  // Measure ContainsRecord
    139  auto contains_duration = measure([&] {
    140    for (const auto& rec : records) {
    141      auto res = storage.RecordExistedUnlocked(rec.get());
    142      EXPECT_TRUE(res);
    143      // Avoid any loop optimizations by adding this check
    144      if (!res) {
    145        break;
    146      }
    147    }
    148  });
    149  EXPECT_LE(contains_duration, 100)
    150      << "ContainsRecord is too slow" << " (" << contains_duration
    151      << " ms) for " << N << " records";
    152 
    153  // Measure RemoveRecord performance
    154  auto remove_duration = measure([&] {
    155    for (const auto& rec : records) {
    156      storage.RemoveRecord(rec.get(), lock);
    157    }
    158  });
    159  EXPECT_LE(remove_duration, 200)
    160      << "RemoveRecord is too slow" << " (" << remove_duration << " ms) for "
    161      << N << " records";
    162 }
    163 
    164 }  // namespace net
    165 }  // namespace mozilla