xpcom/tests/gtest/TestMruCache.cpp
author Chris Peterson <cpeterson@mozilla.com>
Sun, 24 Feb 2019 17:35:59 -0800
changeset 464363 5ff84e853d700af894616574f581551a88a93dc7
parent 450554 09c71a7cf75aeaf2963050e315276fb9a866fd62
child 468049 389b6bbd76dbdf3357453f0989bbe9595751b7ae
permissions -rw-r--r--
Bug 1534878 - xpcom: Make some global functions static. r=erahm clang's -Wmissing-prototypes option identifies global functions that can be made static (because they're only called from one compilation unit) or removed (if they're never called). xpcom/base/Logging.cpp:85:13 [-Wmissing-prototypes] no previous prototype for function 'ToLogStr' xpcom/base/Logging.cpp:132:13 [-Wmissing-prototypes] no previous prototype for function 'ExpandPIDMarker' xpcom/base/LogModulePrefWatcher.cpp:37:6 [-Wmissing-prototypes] no previous prototype for function 'ResetExistingPrefs' xpcom/base/LogModulePrefWatcher.cpp:109:6 [-Wmissing-prototypes] no previous prototype for function 'LoadExistingPrefs' xpcom/base/nsCycleCollector.cpp:212:6 [-Wmissing-prototypes] no previous prototype for function 'SuspectUsingNurseryPurpleBuffer' xpcom/components/nsComponentManager.cpp:421:31 [-Wmissing-prototypes] no previous prototype for function 'begin' xpcom/components/nsComponentManager.cpp:427:31 [-Wmissing-prototypes] no previous prototype for function 'end' xpcom/ds/Dafsa.cpp:23:6 [-Wmissing-prototypes] no previous prototype for function 'GetNextOffset' xpcom/ds/Dafsa.cpp:55:6 [-Wmissing-prototypes] no previous prototype for function 'IsEOL' xpcom/ds/Dafsa.cpp:62:6 [-Wmissing-prototypes] no previous prototype for function 'IsMatch' xpcom/ds/Dafsa.cpp:70:6 [-Wmissing-prototypes] no previous prototype for function 'IsEndCharMatch' xpcom/ds/Dafsa.cpp:78:6 [-Wmissing-prototypes] no previous prototype for function 'GetReturnValue' xpcom/ds/Dafsa.cpp:91:5 [-Wmissing-prototypes] no previous prototype for function 'LookupString' xpcom/io/CocoaFileUtils.mm:195:13 [-Wmissing-prototypes] no previous prototype for function 'GetQuarantinePropKey' xpcom/io/CocoaFileUtils.mm:203:24 [-Wmissing-prototypes] no previous prototype for function 'CreateQuarantineDictionary' xpcom/rust/gtest/bench-collections/Bench.cpp:65:11 [-Wmissing-prototypes] no previous prototype for function 'MyRand' xpcom/rust/gtest/bench-collections/Bench.cpp:85:6 [-Wmissing-prototypes] no previous prototype for function 'Bench_Cpp_unordered_set' xpcom/rust/gtest/bench-collections/Bench.cpp:125:6 [-Wmissing-prototypes] no previous prototype for function 'Bench_Cpp_PLDHashTable' xpcom/rust/gtest/bench-collections/Bench.cpp:166:6 [-Wmissing-prototypes] no previous prototype for function 'Bench_Cpp_MozHashSet' xpcom/tests/gtest/TestAtoms.cpp:114:6 [-Wmissing-prototypes] no previous prototype for function 'isStaticAtom' xpcom/tests/gtest/TestCallTemplates.cpp:72:6 [-Wmissing-prototypes] no previous prototype for function 'JustTestingCompilation' xpcom/tests/gtest/TestCOMPtr.cpp:87:10 [-Wmissing-prototypes] no previous prototype for function 'CreateIFoo' xpcom/tests/gtest/TestCOMPtr.cpp:98:6 [-Wmissing-prototypes] no previous prototype for function 'set_a_IFoo' xpcom/tests/gtest/TestCOMPtr.cpp:105:16 [-Wmissing-prototypes] no previous prototype for function 'return_a_IFoo' xpcom/tests/gtest/TestCOMPtr.cpp:164:10 [-Wmissing-prototypes] no previous prototype for function 'CreateIBar' xpcom/tests/gtest/TestCOMPtr.cpp:175:6 [-Wmissing-prototypes] no previous prototype for function 'AnIFooPtrPtrContext' xpcom/tests/gtest/TestCOMPtr.cpp:177:6 [-Wmissing-prototypes] no previous prototype for function 'AVoidPtrPtrContext' xpcom/tests/gtest/TestCOMPtr.cpp:179:6 [-Wmissing-prototypes] no previous prototype for function 'AnISupportsPtrPtrContext' xpcom/tests/gtest/TestCOMPtr.cpp:263:6 [-Wmissing-prototypes] no previous prototype for function 'Comparison' xpcom/tests/gtest/TestCOMPtr.cpp:298:6 [-Wmissing-prototypes] no previous prototype for function 'DontAddRef' xpcom/tests/gtest/TestCRT.cpp:17:5 [-Wmissing-prototypes] no previous prototype for function 'sign' xpcom/tests/gtest/TestDeadlockDetector.cpp:62:6 [-Wmissing-prototypes] no previous prototype for function 'DisableCrashReporter' xpcom/tests/gtest/TestDeadlockDetector.cpp:74:5 [-Wmissing-prototypes] no previous prototype for function 'Sanity_Child' xpcom/tests/gtest/TestDeadlockDetector.cpp:95:5 [-Wmissing-prototypes] no previous prototype for function 'Sanity2_Child' xpcom/tests/gtest/TestDeadlockDetector.cpp:159:5 [-Wmissing-prototypes] no previous prototype for function 'Sanity4_Child' xpcom/tests/gtest/TestDeadlockDetector.cpp:182:5 [-Wmissing-prototypes] no previous prototype for function 'Sanity5_Child' xpcom/tests/gtest/TestDeadlockDetector.cpp:303:5 [-Wmissing-prototypes] no previous prototype for function 'ContentionNoDeadlock_Child' xpcom/tests/gtest/TestHashtables.cpp:88:6 [-Wmissing-prototypes] no previous prototype for function 'testTHashtable' xpcom/tests/gtest/TestHashtables.cpp:205:10 [-Wmissing-prototypes] no previous prototype for function 'CreateIFoo' xpcom/tests/gtest/TestMoveString.cpp:25:6 [-Wmissing-prototypes] no previous prototype for function 'SetAsOwned' xpcom/tests/gtest/TestMoveString.cpp:34:6 [-Wmissing-prototypes] no previous prototype for function 'ExpectTruncated' xpcom/tests/gtest/TestMoveString.cpp:40:6 [-Wmissing-prototypes] no previous prototype for function 'ExpectNew' xpcom/tests/gtest/TestMruCache.cpp:52:11 [-Wmissing-prototypes] no previous prototype for function 'MakeStringKey' xpcom/tests/gtest/TestMultiplexInputStream.cpp:106:34 [-Wmissing-prototypes] no previous prototype for function 'CreateStreamHelper' xpcom/tests/gtest/TestNonBlockingAsyncInputStream.cpp:62:10 [-Wmissing-prototypes] no previous prototype for function 'ReadSegmentsFunction' xpcom/tests/gtest/TestNsDeque.cpp:240:6 [-Wmissing-prototypes] no previous prototype for function 'CheckIfQueueEmpty' xpcom/tests/gtest/TestNsRefPtr.cpp:105:10 [-Wmissing-prototypes] no previous prototype for function 'CreateFoo' xpcom/tests/gtest/TestNsRefPtr.cpp:116:6 [-Wmissing-prototypes] no previous prototype for function 'set_a_Foo' xpcom/tests/gtest/TestNsRefPtr.cpp:123:13 [-Wmissing-prototypes] no previous prototype for function 'return_a_Foo' xpcom/tests/gtest/TestNsRefPtr.cpp:391:6 [-Wmissing-prototypes] no previous prototype for function 'AnFooPtrPtrContext' xpcom/tests/gtest/TestNsRefPtr.cpp:392:6 [-Wmissing-prototypes] no previous prototype for function 'AVoidPtrPtrContext' xpcom/tests/gtest/TestPLDHash.cpp:33:6 [-Wmissing-prototypes] no previous prototype for function 'TestCrashyOperation' xpcom/tests/gtest/TestPipes.cpp:98:10 [-Wmissing-prototypes] no previous prototype for function 'TestPipe' xpcom/tests/gtest/TestPipes.cpp:212:10 [-Wmissing-prototypes] no previous prototype for function 'TestShortWrites' xpcom/tests/gtest/TestPipes.cpp:354:6 [-Wmissing-prototypes] no previous prototype for function 'RunTests' xpcom/tests/gtest/TestPLDHash.cpp:90:6 [-Wmissing-prototypes] no previous prototype for function 'InitCapacityOk_InitialLengthTooBig' xpcom/tests/gtest/TestPLDHash.cpp:95:6 [-Wmissing-prototypes] no previous prototype for function 'InitCapacityOk_InitialEntryStoreTooBig' xpcom/tests/gtest/TestPLDHash.cpp:102:6 [-Wmissing-prototypes] no previous prototype for function 'InitCapacityOk_EntrySizeTooBig' xpcom/tests/gtest/TestSlicedInputStream.cpp:111:20 [-Wmissing-prototypes] no previous prototype for function 'CreateSeekableStreams' xpcom/tests/gtest/TestSlicedInputStream.cpp:125:20 [-Wmissing-prototypes] no previous prototype for function 'CreateNonSeekableStreams' xpcom/tests/gtest/TestStrings.cpp:471:6 [-Wmissing-prototypes] no previous prototype for function 'test_assign_helper' xpcom/tests/gtest/TestTArray.cpp:60:22 [-Wmissing-prototypes] no previous prototype for function 'DummyArray' xpcom/tests/gtest/TestTArray.cpp:72:22 [-Wmissing-prototypes] no previous prototype for function 'FakeHugeArray' xpcom/tests/gtest/TestThrottledEventQueue.cpp:96:6 [-Wmissing-prototypes] no previous prototype for function 'Enqueue' xpcom/threads/BlockingResourceBase.cpp:86:6 [-Wmissing-prototypes] no previous prototype for function 'PrintCycle' xpcom/threads/CPUUsageWatcher.cpp:41:10 [-Wmissing-prototypes] no previous prototype for function 'GetMicroseconds' xpcom/threads/CPUUsageWatcher.cpp:46:10 [-Wmissing-prototypes] no previous prototype for function 'GetMicroseconds' xpcom/threads/CPUUsageWatcher.cpp:51:40 [-Wmissing-prototypes] no previous prototype for function 'GetProcessCPUStats' xpcom/threads/CPUUsageWatcher.cpp:80:40 [-Wmissing-prototypes] no previous prototype for function 'GetGlobalCPUStats' xpcom/threads/nsTimerImpl.cpp:196:21 [-Wmissing-prototypes] no previous prototype for function 'GetTimerFiringsLog' Differential Revision: https://phabricator.services.mozilla.com/D23264

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "gtest/gtest.h"

#include "mozilla/MruCache.h"
#include "nsString.h"

using namespace mozilla;

// A few MruCache implementations to use during testing.
struct IntMap : public MruCache<int, int, IntMap> {
  static HashNumber Hash(const KeyType& aKey) { return aKey - 1; }
  static bool Match(const KeyType& aKey, const ValueType& aVal) {
    return aKey == aVal;
  }
};

struct UintPtrMap : public MruCache<uintptr_t, int*, UintPtrMap> {
  static HashNumber Hash(const KeyType& aKey) { return aKey - 1; }
  static bool Match(const KeyType& aKey, const ValueType& aVal) {
    return aKey == (KeyType)aVal;
  }
};

struct StringStruct {
  nsCString mKey;
  nsCString mOther;
};

struct StringStructMap
    : public MruCache<nsCString, StringStruct, StringStructMap> {
  static HashNumber Hash(const KeyType& aKey) {
    return *aKey.BeginReading() - 1;
  }
  static bool Match(const KeyType& aKey, const ValueType& aVal) {
    return aKey == aVal.mKey;
  }
};

// Helper for emulating convertable holders such as RefPtr.
template <typename T>
struct Convertable {
  T mItem;
  operator T() const { return mItem; }
};

// Helper to create a StringStructMap key.
static nsCString MakeStringKey(char aKey) {
  nsCString key;
  key.Append(aKey);
  return key;
}

TEST(MruCache, TestNullChecker) {
  using mozilla::detail::EmptyChecker;

  {
    int test = 0;
    EXPECT_TRUE(EmptyChecker<decltype(test)>::IsNotEmpty(test));

    test = 42;
    EXPECT_TRUE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
  }

  {
    const char* test = "abc";
    EXPECT_TRUE(EmptyChecker<decltype(test)>::IsNotEmpty(test));

    test = nullptr;
    EXPECT_FALSE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
  }

  {
    int foo = 42;
    int* test = &foo;
    EXPECT_TRUE(EmptyChecker<decltype(test)>::IsNotEmpty(test));

    test = nullptr;
    EXPECT_FALSE(EmptyChecker<decltype(test)>::IsNotEmpty(test));
  }
}

TEST(MruCache, TestEmptyCache) {
  {
    // Test a basic empty cache.
    IntMap mru;

    // Make sure the default values are set.
    for (int i = 1; i < 32; i++) {
      auto p = mru.Lookup(i);

      // Shouldn't be found.
      EXPECT_FALSE(p);
    }
  }

  {
    // Test an empty cache with pointer values.
    UintPtrMap mru;

    // Make sure the default values are set.
    for (uintptr_t i = 1; i < 32; i++) {
      auto p = mru.Lookup(i);

      // Shouldn't be found.
      EXPECT_FALSE(p);
    }
  }

  {
    // Test an empty cache with more complex structure.
    StringStructMap mru;

    // Make sure the default values are set.
    for (char i = 1; i < 32; i++) {
      const nsCString key = MakeStringKey(i);
      auto p = mru.Lookup(key);

      // Shouldn't be found.
      EXPECT_FALSE(p);
    }
  }
}

TEST(MruCache, TestPut) {
  IntMap mru;

  // Fill it up.
  for (int i = 1; i < 32; i++) {
    mru.Put(i, i);
  }

  // Now check each value.
  for (int i = 1; i < 32; i++) {
    auto p = mru.Lookup(i);

    // Should be found.
    EXPECT_TRUE(p);
    EXPECT_EQ(p.Data(), i);
  }
}

TEST(MruCache, TestPutConvertable) {
  UintPtrMap mru;

  // Fill it up.
  for (uintptr_t i = 1; i < 32; i++) {
    Convertable<int*> val{(int*)i};
    mru.Put(i, val);
  }

  // Now check each value.
  for (uintptr_t i = 1; i < 32; i++) {
    auto p = mru.Lookup(i);

    // Should be found.
    EXPECT_TRUE(p);
    EXPECT_EQ(p.Data(), (int*)i);
  }
}

TEST(MruCache, TestOverwriting) {
  // Test overwrting
  IntMap mru;

  // 1-31 should be overwritten by 32-63
  for (int i = 1; i < 63; i++) {
    mru.Put(i, i);
  }

  // Look them up.
  for (int i = 32; i < 63; i++) {
    auto p = mru.Lookup(i);

    // Should be found.
    EXPECT_TRUE(p);
    EXPECT_EQ(p.Data(), i);
  }
}

TEST(MruCache, TestRemove) {
  {
    IntMap mru;

    // Fill it up.
    for (int i = 1; i < 32; i++) {
      mru.Put(i, i);
    }

    // Now remove each value.
    for (int i = 1; i < 32; i++) {
      // Should be present.
      auto p = mru.Lookup(i);
      EXPECT_TRUE(p);

      mru.Remove(i);

      // Should no longer match.
      p = mru.Lookup(i);
      EXPECT_FALSE(p);
    }
  }

  {
    UintPtrMap mru;

    // Fill it up.
    for (uintptr_t i = 1; i < 32; i++) {
      mru.Put(i, (int*)i);
    }

    // Now remove each value.
    for (uintptr_t i = 1; i < 32; i++) {
      // Should be present.
      auto p = mru.Lookup(i);
      EXPECT_TRUE(p);

      mru.Remove(i);

      // Should no longer match.
      p = mru.Lookup(i);
      EXPECT_FALSE(p);
    }
  }

  {
    StringStructMap mru;

    // Fill it up.
    for (char i = 1; i < 32; i++) {
      const nsCString key = MakeStringKey(i);
      mru.Put(key, StringStruct{key, NS_LITERAL_CSTRING("foo")});
    }

    // Now remove each value.
    for (char i = 1; i < 32; i++) {
      const nsCString key = MakeStringKey(i);

      // Should be present.
      auto p = mru.Lookup(key);
      EXPECT_TRUE(p);

      mru.Remove(key);

      // Should no longer match.
      p = mru.Lookup(key);
      EXPECT_FALSE(p);
    }
  }
}

TEST(MruCache, TestClear) {
  IntMap mru;

  // Fill it up.
  for (int i = 1; i < 32; i++) {
    mru.Put(i, i);
  }

  // Empty it.
  mru.Clear();

  // Now check each value.
  for (int i = 1; i < 32; i++) {
    auto p = mru.Lookup(i);

    // Should not be found.
    EXPECT_FALSE(p);
  }
}

TEST(MruCache, TestLookupMissingAndSet) {
  IntMap mru;

  // Value not found.
  auto p = mru.Lookup(1);
  EXPECT_FALSE(p);

  // Set it.
  p.Set(1);
  EXPECT_TRUE(p);
  EXPECT_EQ(p.Data(), 1);

  // Look it up again.
  p = mru.Lookup(1);
  EXPECT_TRUE(p);
  EXPECT_EQ(p.Data(), 1);

  // Test w/ a convertable value.
  p = mru.Lookup(2);
  EXPECT_FALSE(p);

  // Set it.
  Convertable<int> val{2};
  p.Set(val);
  EXPECT_TRUE(p);
  EXPECT_EQ(p.Data(), 2);

  // Look it up again.
  p = mru.Lookup(2);
  EXPECT_TRUE(p);
  EXPECT_EQ(p.Data(), 2);
}

TEST(MruCache, TestLookupAndOverwrite) {
  IntMap mru;

  // Set 1.
  mru.Put(1, 1);

  // Lookup a key that maps the 1's entry.
  auto p = mru.Lookup(32);
  EXPECT_FALSE(p);  // not a match

  // Now overwrite the entry.
  p.Set(32);
  EXPECT_TRUE(p);
  EXPECT_EQ(p.Data(), 32);

  // 1 should be gone now.
  p = mru.Lookup(1);
  EXPECT_FALSE(p);

  // 32 should be found.
  p = mru.Lookup(32);
  EXPECT_TRUE(p);
  EXPECT_EQ(p.Data(), 32);
}

TEST(MruCache, TestLookupAndRemove) {
  IntMap mru;

  // Set 1.
  mru.Put(1, 1);

  auto p = mru.Lookup(1);
  EXPECT_TRUE(p);
  EXPECT_EQ(p.Data(), 1);

  // Now remove it.
  p.Remove();
  EXPECT_FALSE(p);

  p = mru.Lookup(1);
  EXPECT_FALSE(p);
}

TEST(MruCache, TestLookupNotMatchedAndRemove) {
  IntMap mru;

  // Set 1.
  mru.Put(1, 1);

  // Lookup a key that matches 1's entry.
  auto p = mru.Lookup(32);
  EXPECT_FALSE(p);

  // Now attempt to remove it.
  p.Remove();

  // Make sure 1 is still there.
  p = mru.Lookup(1);
  EXPECT_TRUE(p);
  EXPECT_EQ(p.Data(), 1);
}

TEST(MruCache, TestLookupAndSetWithMove) {
  StringStructMap mru;

  const nsCString key = MakeStringKey((char)1);
  StringStruct val{key, NS_LITERAL_CSTRING("foo")};

  auto p = mru.Lookup(key);
  EXPECT_FALSE(p);
  p.Set(std::move(val));

  EXPECT_TRUE(p.Data().mKey == key);
  EXPECT_TRUE(p.Data().mOther == NS_LITERAL_CSTRING("foo"));
}