diff options
Diffstat (limited to 'startupcache/test')
-rw-r--r-- | startupcache/test/TestStartupCache.cpp | 188 | ||||
-rw-r--r-- | startupcache/test/browser/browser.toml | 3 | ||||
-rw-r--r-- | startupcache/test/browser/browser_startupcache_telemetry.js | 50 | ||||
-rw-r--r-- | startupcache/test/moz.build | 10 |
4 files changed, 251 insertions, 0 deletions
diff --git a/startupcache/test/TestStartupCache.cpp b/startupcache/test/TestStartupCache.cpp new file mode 100644 index 0000000000..9c817ff725 --- /dev/null +++ b/startupcache/test/TestStartupCache.cpp @@ -0,0 +1,188 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ +/* 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/scache/StartupCache.h" +#include "mozilla/scache/StartupCacheUtils.h" + +#include "nsDirectoryServiceDefs.h" +#include "nsIOutputStream.h" +#include "nsISupports.h" +#include "nsIStorageStream.h" +#include "nsIObjectInputStream.h" +#include "nsIObjectOutputStream.h" +#include "nsIURI.h" +#include "nsThreadUtils.h" +#include "prenv.h" +#include "prio.h" +#include "prprf.h" +#include "mozilla/gtest/MozAssertions.h" +#include "mozilla/Maybe.h" +#include "mozilla/Printf.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/UniquePtrExtensions.h" +#include "nsNetCID.h" +#include "nsIURIMutator.h" + +using namespace JS; + +using namespace mozilla::scache; +using mozilla::UniquePtr; + +void WaitForStartupTimer() { + StartupCache* sc = StartupCache::GetSingleton(); + PR_Sleep(3 * PR_TicksPerSecond()); + + while (true) { + NS_ProcessPendingEvents(nullptr); + if (sc->StartupWriteComplete()) { + return; + } + PR_Sleep(1 * PR_TicksPerSecond()); + } +} + +class TestStartupCache : public ::testing::Test { + protected: + TestStartupCache(); + ~TestStartupCache(); + + nsCOMPtr<nsIFile> mSCFile; +}; + +TestStartupCache::TestStartupCache() { + NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mSCFile)); + mSCFile->AppendNative("test-startupcache.tmp"_ns); +#ifdef XP_WIN + nsAutoString env(u"MOZ_STARTUP_CACHE="_ns); + env.Append(mSCFile->NativePath()); + _wputenv(env.get()); +#else + nsAutoCString path; + mSCFile->GetNativePath(path); + char* env = mozilla::Smprintf("MOZ_STARTUP_CACHE=%s", path.get()).release(); + PR_SetEnv(env); + // We intentionally leak `env` here because it is required by PR_SetEnv + MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(env); +#endif + StartupCache::GetSingleton()->InvalidateCache(); +} +TestStartupCache::~TestStartupCache() { + PR_SetEnv("MOZ_STARTUP_CACHE="); + StartupCache::GetSingleton()->InvalidateCache(); +} + +TEST_F(TestStartupCache, StartupWriteRead) { + nsresult rv; + StartupCache* sc = StartupCache::GetSingleton(); + + const char* buf = "Market opportunities for BeardBook"; + const char* id = "id"; + const char* outbuf; + uint32_t len; + + rv = sc->PutBuffer(id, mozilla::UniqueFreePtr<char[]>(strdup(buf)), + strlen(buf) + 1); + EXPECT_NS_SUCCEEDED(rv); + + rv = sc->GetBuffer(id, &outbuf, &len); + EXPECT_NS_SUCCEEDED(rv); + EXPECT_STREQ(buf, outbuf); + + rv = sc->ResetStartupWriteTimerAndLock(); + EXPECT_NS_SUCCEEDED(rv); + WaitForStartupTimer(); + + rv = sc->GetBuffer(id, &outbuf, &len); + EXPECT_NS_SUCCEEDED(rv); + EXPECT_STREQ(buf, outbuf); +} + +TEST_F(TestStartupCache, WriteInvalidateRead) { + nsresult rv; + const char* buf = "BeardBook competitive analysis"; + const char* id = "id"; + const char* outbuf; + uint32_t len; + StartupCache* sc = StartupCache::GetSingleton(); + ASSERT_TRUE(sc); + + rv = sc->PutBuffer(id, mozilla::UniqueFreePtr<char[]>(strdup(buf)), + strlen(buf) + 1); + EXPECT_NS_SUCCEEDED(rv); + + sc->InvalidateCache(); + + rv = sc->GetBuffer(id, &outbuf, &len); + EXPECT_EQ(rv, NS_ERROR_NOT_AVAILABLE); +} + +TEST_F(TestStartupCache, WriteObject) { + nsresult rv; + + nsCOMPtr<nsIURI> obj; + + constexpr auto spec = "http://www.mozilla.org"_ns; + rv = NS_MutateURI(NS_SIMPLEURIMUTATOR_CONTRACTID).SetSpec(spec).Finalize(obj); + EXPECT_NS_SUCCEEDED(rv); + + StartupCache* sc = StartupCache::GetSingleton(); + + // Create an object stream. Usually this is done with + // NewObjectOutputWrappedStorageStream, but that uses + // StartupCache::GetSingleton in debug builds, and we + // don't have access to that here. Obviously. + const char* id = "id"; + nsCOMPtr<nsIStorageStream> storageStream = + do_CreateInstance("@mozilla.org/storagestream;1"); + ASSERT_TRUE(storageStream); + + rv = storageStream->Init(256, (uint32_t)-1); + EXPECT_NS_SUCCEEDED(rv); + + nsCOMPtr<nsIObjectOutputStream> objectOutput = + do_CreateInstance("@mozilla.org/binaryoutputstream;1"); + ASSERT_TRUE(objectOutput); + + nsCOMPtr<nsIOutputStream> outputStream = do_QueryInterface(storageStream); + + rv = objectOutput->SetOutputStream(outputStream); + EXPECT_NS_SUCCEEDED(rv); + + nsCOMPtr<nsISupports> objQI(do_QueryInterface(obj)); + rv = objectOutput->WriteObject(objQI, true); + EXPECT_NS_SUCCEEDED(rv); + + mozilla::UniqueFreePtr<char[]> buf; + uint32_t len; + NewBufferFromStorageStream(storageStream, &buf, &len); + + // Since this is a post-startup write, it should be written and + // available. + rv = sc->PutBuffer(id, std::move(buf), len); + EXPECT_NS_SUCCEEDED(rv); + + const char* buf2; + uint32_t len2; + nsCOMPtr<nsIObjectInputStream> objectInput; + rv = sc->GetBuffer(id, &buf2, &len2); + EXPECT_NS_SUCCEEDED(rv); + + rv = NewObjectInputStreamFromBuffer(buf2, len2, getter_AddRefs(objectInput)); + EXPECT_NS_SUCCEEDED(rv); + + nsCOMPtr<nsISupports> deserialized; + rv = objectInput->ReadObject(true, getter_AddRefs(deserialized)); + EXPECT_NS_SUCCEEDED(rv); + + nsCOMPtr<nsIURI> uri(do_QueryInterface(deserialized)); + ASSERT_TRUE(uri); + + nsCString outSpec; + rv = uri->GetSpec(outSpec); + EXPECT_NS_SUCCEEDED(rv); + ASSERT_TRUE(outSpec.Equals(spec)); +} diff --git a/startupcache/test/browser/browser.toml b/startupcache/test/browser/browser.toml new file mode 100644 index 0000000000..3de76f21ed --- /dev/null +++ b/startupcache/test/browser/browser.toml @@ -0,0 +1,3 @@ +[DEFAULT] + +["browser_startupcache_telemetry.js"] diff --git a/startupcache/test/browser/browser_startupcache_telemetry.js b/startupcache/test/browser/browser_startupcache_telemetry.js new file mode 100644 index 0000000000..e4c8085bed --- /dev/null +++ b/startupcache/test/browser/browser_startupcache_telemetry.js @@ -0,0 +1,50 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const LABELS_STARTUP_CACHE_REQUESTS = { + HitMemory: 0, + HitDisk: 1, + Miss: 2, +}; + +add_task(async function () { + // Turn off tab preloading to avoid issues with RemoteController.js + await SpecialPowers.pushPrefEnv({ + set: [["browser.newtab.preload", false]], + }); + + Services.obs.notifyObservers(null, "startupcache-invalidate"); + Services.telemetry.getSnapshotForHistograms("main", true); + let newWin = await BrowserTestUtils.openNewBrowserWindow(); + let snapshot = Services.telemetry.getSnapshotForHistograms("main", true); + function histValue(label) { + return snapshot.parent.STARTUP_CACHE_REQUESTS.values[label] || 0; + } + Assert.equal(histValue(LABELS_STARTUP_CACHE_REQUESTS.HitMemory), 0); + Assert.equal(histValue(LABELS_STARTUP_CACHE_REQUESTS.HitDisk), 0); + Assert.notEqual(histValue(LABELS_STARTUP_CACHE_REQUESTS.Miss), 0); + await BrowserTestUtils.closeWindow(newWin); + + newWin = await BrowserTestUtils.openNewBrowserWindow(); + snapshot = Services.telemetry.getSnapshotForHistograms("main", true); + Assert.notEqual(histValue(LABELS_STARTUP_CACHE_REQUESTS.HitMemory), 0); + Assert.equal(histValue(LABELS_STARTUP_CACHE_REQUESTS.HitDisk), 0); + + // Here and below, 50 is just a nice round number that should be well over + // what we should observe under normal circumstances, and well under what + // we should see if something is seriously wrong. It won't catch everything, + // but it's better than nothing, and better than a test that cries wolf. + Assert.less(histValue(LABELS_STARTUP_CACHE_REQUESTS.Miss), 50); + await BrowserTestUtils.closeWindow(newWin); + + Services.obs.notifyObservers(null, "startupcache-invalidate", "memoryOnly"); + newWin = await BrowserTestUtils.openNewBrowserWindow(); + snapshot = Services.telemetry.getSnapshotForHistograms("main", true); + Assert.less(histValue(LABELS_STARTUP_CACHE_REQUESTS.HitMemory), 50); + Assert.notEqual(histValue(LABELS_STARTUP_CACHE_REQUESTS.HitDisk), 0); + // Some misses can come through - just ensure it's a small number + Assert.less(histValue(LABELS_STARTUP_CACHE_REQUESTS.Miss), 50); + await BrowserTestUtils.closeWindow(newWin); +}); diff --git a/startupcache/test/moz.build b/startupcache/test/moz.build new file mode 100644 index 0000000000..0197659309 --- /dev/null +++ b/startupcache/test/moz.build @@ -0,0 +1,10 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +UNIFIED_SOURCES += [ + "TestStartupCache.cpp", +] +FINAL_LIBRARY = "xul-gtest" |