diff options
Diffstat (limited to 'startupcache/test/TestStartupCache.cpp')
-rw-r--r-- | startupcache/test/TestStartupCache.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/startupcache/test/TestStartupCache.cpp b/startupcache/test/TestStartupCache.cpp new file mode 100644 index 0000000000..28e758c6a5 --- /dev/null +++ b/startupcache/test/TestStartupCache.cpp @@ -0,0 +1,184 @@ +/* -*- 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/Maybe.h" +#include "mozilla/Printf.h" +#include "mozilla/UniquePtr.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, UniquePtr<char[]>(strdup(buf)), strlen(buf) + 1); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + + rv = sc->GetBuffer(id, &outbuf, &len); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + EXPECT_STREQ(buf, outbuf); + + rv = sc->ResetStartupWriteTimer(); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + WaitForStartupTimer(); + + rv = sc->GetBuffer(id, &outbuf, &len); + EXPECT_TRUE(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, UniquePtr<char[]>(strdup(buf)), strlen(buf) + 1); + EXPECT_TRUE(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_TRUE(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_TRUE(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_TRUE(NS_SUCCEEDED(rv)); + + nsCOMPtr<nsISupports> objQI(do_QueryInterface(obj)); + rv = objectOutput->WriteObject(objQI, true); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + + UniquePtr<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_TRUE(NS_SUCCEEDED(rv)); + + const char* buf2; + uint32_t len2; + nsCOMPtr<nsIObjectInputStream> objectInput; + rv = sc->GetBuffer(id, &buf2, &len2); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + + rv = NewObjectInputStreamFromBuffer(buf2, len2, getter_AddRefs(objectInput)); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + + nsCOMPtr<nsISupports> deserialized; + rv = objectInput->ReadObject(true, getter_AddRefs(deserialized)); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + + nsCOMPtr<nsIURI> uri(do_QueryInterface(deserialized)); + ASSERT_TRUE(uri); + + nsCString outSpec; + rv = uri->GetSpec(outSpec); + EXPECT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_TRUE(outSpec.Equals(spec)); +} |