tor-browser

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

TestStartupCache.cpp (5320B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "gtest/gtest.h"
      7 
      8 #include "mozilla/scache/StartupCache.h"
      9 #include "mozilla/scache/StartupCacheUtils.h"
     10 
     11 #include "nsDirectoryServiceDefs.h"
     12 #include "nsIOutputStream.h"
     13 #include "nsISupports.h"
     14 #include "nsIStorageStream.h"
     15 #include "nsIObjectInputStream.h"
     16 #include "nsIObjectOutputStream.h"
     17 #include "nsIURI.h"
     18 #include "nsThreadUtils.h"
     19 #include "prenv.h"
     20 #include "prio.h"
     21 #include "prprf.h"
     22 #include "mozilla/gtest/MozAssertions.h"
     23 #include "mozilla/Printf.h"
     24 #include "mozilla/UniquePtr.h"
     25 #include "mozilla/UniquePtrExtensions.h"
     26 #include "nsNetCID.h"
     27 #include "nsIURIMutator.h"
     28 
     29 using namespace JS;
     30 
     31 using namespace mozilla::scache;
     32 using mozilla::UniquePtr;
     33 
     34 void WaitForStartupTimer() {
     35  StartupCache* sc = StartupCache::GetSingleton();
     36  PR_Sleep(3 * PR_TicksPerSecond());
     37 
     38  while (true) {
     39    NS_ProcessPendingEvents(nullptr);
     40    if (sc->StartupWriteComplete()) {
     41      return;
     42    }
     43    PR_Sleep(1 * PR_TicksPerSecond());
     44  }
     45 }
     46 
     47 class TestStartupCache : public ::testing::Test {
     48 protected:
     49  TestStartupCache();
     50  ~TestStartupCache();
     51 
     52  nsCOMPtr<nsIFile> mSCFile;
     53 };
     54 
     55 TestStartupCache::TestStartupCache() {
     56  NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mSCFile));
     57  mSCFile->AppendNative("test-startupcache.tmp"_ns);
     58 #ifdef XP_WIN
     59  nsAutoString env(u"MOZ_STARTUP_CACHE="_ns);
     60  env.Append(mSCFile->NativePath());
     61  _wputenv(env.get());
     62 #else
     63  nsAutoCString path;
     64  mSCFile->GetNativePath(path);
     65  char* env = mozilla::Smprintf("MOZ_STARTUP_CACHE=%s", path.get()).release();
     66  PR_SetEnv(env);
     67  // We intentionally leak `env` here because it is required by PR_SetEnv
     68  MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(env);
     69 #endif
     70  StartupCache::GetSingleton()->InvalidateCache();
     71 }
     72 TestStartupCache::~TestStartupCache() {
     73  PR_SetEnv("MOZ_STARTUP_CACHE=");
     74  StartupCache::GetSingleton()->InvalidateCache();
     75 }
     76 
     77 TEST_F(TestStartupCache, StartupWriteRead) {
     78  nsresult rv;
     79  StartupCache* sc = StartupCache::GetSingleton();
     80 
     81  const char* buf = "Market opportunities for BeardBook";
     82  const char* id = "id";
     83  const char* outbuf;
     84  uint32_t len;
     85 
     86  rv = sc->PutBuffer(id, mozilla::UniqueFreePtr<char[]>(strdup(buf)),
     87                     strlen(buf) + 1);
     88  EXPECT_NS_SUCCEEDED(rv);
     89 
     90  rv = sc->GetBuffer(id, &outbuf, &len);
     91  EXPECT_NS_SUCCEEDED(rv);
     92  EXPECT_STREQ(buf, outbuf);
     93 
     94  rv = sc->ResetStartupWriteTimerAndLock();
     95  EXPECT_NS_SUCCEEDED(rv);
     96  WaitForStartupTimer();
     97 
     98  rv = sc->GetBuffer(id, &outbuf, &len);
     99  EXPECT_NS_SUCCEEDED(rv);
    100  EXPECT_STREQ(buf, outbuf);
    101 }
    102 
    103 TEST_F(TestStartupCache, WriteInvalidateRead) {
    104  nsresult rv;
    105  const char* buf = "BeardBook competitive analysis";
    106  const char* id = "id";
    107  const char* outbuf;
    108  uint32_t len;
    109  StartupCache* sc = StartupCache::GetSingleton();
    110  ASSERT_TRUE(sc);
    111 
    112  rv = sc->PutBuffer(id, mozilla::UniqueFreePtr<char[]>(strdup(buf)),
    113                     strlen(buf) + 1);
    114  EXPECT_NS_SUCCEEDED(rv);
    115 
    116  sc->InvalidateCache();
    117 
    118  rv = sc->GetBuffer(id, &outbuf, &len);
    119  EXPECT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
    120 }
    121 
    122 TEST_F(TestStartupCache, WriteObject) {
    123  nsresult rv;
    124 
    125  nsCOMPtr<nsIURI> obj;
    126 
    127  constexpr auto spec = "http://www.mozilla.org"_ns;
    128  rv = NS_MutateURI(NS_SIMPLEURIMUTATOR_CONTRACTID).SetSpec(spec).Finalize(obj);
    129  EXPECT_NS_SUCCEEDED(rv);
    130 
    131  StartupCache* sc = StartupCache::GetSingleton();
    132 
    133  // Create an object stream. Usually this is done with
    134  // NewObjectOutputWrappedStorageStream, but that uses
    135  // StartupCache::GetSingleton in debug builds, and we
    136  // don't have access to that here. Obviously.
    137  const char* id = "id";
    138  nsCOMPtr<nsIStorageStream> storageStream =
    139      do_CreateInstance("@mozilla.org/storagestream;1");
    140  ASSERT_TRUE(storageStream);
    141 
    142  rv = storageStream->Init(256, (uint32_t)-1);
    143  EXPECT_NS_SUCCEEDED(rv);
    144 
    145  nsCOMPtr<nsIObjectOutputStream> objectOutput =
    146      do_CreateInstance("@mozilla.org/binaryoutputstream;1");
    147  ASSERT_TRUE(objectOutput);
    148 
    149  nsCOMPtr<nsIOutputStream> outputStream = do_QueryInterface(storageStream);
    150 
    151  rv = objectOutput->SetOutputStream(outputStream);
    152  EXPECT_NS_SUCCEEDED(rv);
    153 
    154  nsCOMPtr<nsISupports> objQI(do_QueryInterface(obj));
    155  rv = objectOutput->WriteObject(objQI, true);
    156  EXPECT_NS_SUCCEEDED(rv);
    157 
    158  mozilla::UniqueFreePtr<char[]> buf;
    159  uint32_t len;
    160  NewBufferFromStorageStream(storageStream, &buf, &len);
    161 
    162  // Since this is a post-startup write, it should be written and
    163  // available.
    164  rv = sc->PutBuffer(id, std::move(buf), len);
    165  EXPECT_NS_SUCCEEDED(rv);
    166 
    167  const char* buf2;
    168  uint32_t len2;
    169  nsCOMPtr<nsIObjectInputStream> objectInput;
    170  rv = sc->GetBuffer(id, &buf2, &len2);
    171  EXPECT_NS_SUCCEEDED(rv);
    172 
    173  rv = NewObjectInputStreamFromBuffer(buf2, len2, getter_AddRefs(objectInput));
    174  EXPECT_NS_SUCCEEDED(rv);
    175 
    176  nsCOMPtr<nsISupports> deserialized;
    177  rv = objectInput->ReadObject(true, getter_AddRefs(deserialized));
    178  EXPECT_NS_SUCCEEDED(rv);
    179 
    180  nsCOMPtr<nsIURI> uri(do_QueryInterface(deserialized));
    181  ASSERT_TRUE(uri);
    182 
    183  nsCString outSpec;
    184  rv = uri->GetSpec(outSpec);
    185  EXPECT_NS_SUCCEEDED(rv);
    186  ASSERT_TRUE(outSpec.Equals(spec));
    187 }