Merge mozilla-central to autoland. CLOSED TREE
[gecko.git] / startupcache / test / TestStartupCache.cpp
blob9c817ff7256640e049a6a5c10775954b1bea9b8b
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/. */
6 #include "gtest/gtest.h"
8 #include "mozilla/scache/StartupCache.h"
9 #include "mozilla/scache/StartupCacheUtils.h"
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/Maybe.h"
24 #include "mozilla/Printf.h"
25 #include "mozilla/UniquePtr.h"
26 #include "mozilla/UniquePtrExtensions.h"
27 #include "nsNetCID.h"
28 #include "nsIURIMutator.h"
30 using namespace JS;
32 using namespace mozilla::scache;
33 using mozilla::UniquePtr;
35 void WaitForStartupTimer() {
36 StartupCache* sc = StartupCache::GetSingleton();
37 PR_Sleep(3 * PR_TicksPerSecond());
39 while (true) {
40 NS_ProcessPendingEvents(nullptr);
41 if (sc->StartupWriteComplete()) {
42 return;
44 PR_Sleep(1 * PR_TicksPerSecond());
48 class TestStartupCache : public ::testing::Test {
49 protected:
50 TestStartupCache();
51 ~TestStartupCache();
53 nsCOMPtr<nsIFile> mSCFile;
56 TestStartupCache::TestStartupCache() {
57 NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mSCFile));
58 mSCFile->AppendNative("test-startupcache.tmp"_ns);
59 #ifdef XP_WIN
60 nsAutoString env(u"MOZ_STARTUP_CACHE="_ns);
61 env.Append(mSCFile->NativePath());
62 _wputenv(env.get());
63 #else
64 nsAutoCString path;
65 mSCFile->GetNativePath(path);
66 char* env = mozilla::Smprintf("MOZ_STARTUP_CACHE=%s", path.get()).release();
67 PR_SetEnv(env);
68 // We intentionally leak `env` here because it is required by PR_SetEnv
69 MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(env);
70 #endif
71 StartupCache::GetSingleton()->InvalidateCache();
73 TestStartupCache::~TestStartupCache() {
74 PR_SetEnv("MOZ_STARTUP_CACHE=");
75 StartupCache::GetSingleton()->InvalidateCache();
78 TEST_F(TestStartupCache, StartupWriteRead) {
79 nsresult rv;
80 StartupCache* sc = StartupCache::GetSingleton();
82 const char* buf = "Market opportunities for BeardBook";
83 const char* id = "id";
84 const char* outbuf;
85 uint32_t len;
87 rv = sc->PutBuffer(id, mozilla::UniqueFreePtr<char[]>(strdup(buf)),
88 strlen(buf) + 1);
89 EXPECT_NS_SUCCEEDED(rv);
91 rv = sc->GetBuffer(id, &outbuf, &len);
92 EXPECT_NS_SUCCEEDED(rv);
93 EXPECT_STREQ(buf, outbuf);
95 rv = sc->ResetStartupWriteTimerAndLock();
96 EXPECT_NS_SUCCEEDED(rv);
97 WaitForStartupTimer();
99 rv = sc->GetBuffer(id, &outbuf, &len);
100 EXPECT_NS_SUCCEEDED(rv);
101 EXPECT_STREQ(buf, outbuf);
104 TEST_F(TestStartupCache, WriteInvalidateRead) {
105 nsresult rv;
106 const char* buf = "BeardBook competitive analysis";
107 const char* id = "id";
108 const char* outbuf;
109 uint32_t len;
110 StartupCache* sc = StartupCache::GetSingleton();
111 ASSERT_TRUE(sc);
113 rv = sc->PutBuffer(id, mozilla::UniqueFreePtr<char[]>(strdup(buf)),
114 strlen(buf) + 1);
115 EXPECT_NS_SUCCEEDED(rv);
117 sc->InvalidateCache();
119 rv = sc->GetBuffer(id, &outbuf, &len);
120 EXPECT_EQ(rv, NS_ERROR_NOT_AVAILABLE);
123 TEST_F(TestStartupCache, WriteObject) {
124 nsresult rv;
126 nsCOMPtr<nsIURI> obj;
128 constexpr auto spec = "http://www.mozilla.org"_ns;
129 rv = NS_MutateURI(NS_SIMPLEURIMUTATOR_CONTRACTID).SetSpec(spec).Finalize(obj);
130 EXPECT_NS_SUCCEEDED(rv);
132 StartupCache* sc = StartupCache::GetSingleton();
134 // Create an object stream. Usually this is done with
135 // NewObjectOutputWrappedStorageStream, but that uses
136 // StartupCache::GetSingleton in debug builds, and we
137 // don't have access to that here. Obviously.
138 const char* id = "id";
139 nsCOMPtr<nsIStorageStream> storageStream =
140 do_CreateInstance("@mozilla.org/storagestream;1");
141 ASSERT_TRUE(storageStream);
143 rv = storageStream->Init(256, (uint32_t)-1);
144 EXPECT_NS_SUCCEEDED(rv);
146 nsCOMPtr<nsIObjectOutputStream> objectOutput =
147 do_CreateInstance("@mozilla.org/binaryoutputstream;1");
148 ASSERT_TRUE(objectOutput);
150 nsCOMPtr<nsIOutputStream> outputStream = do_QueryInterface(storageStream);
152 rv = objectOutput->SetOutputStream(outputStream);
153 EXPECT_NS_SUCCEEDED(rv);
155 nsCOMPtr<nsISupports> objQI(do_QueryInterface(obj));
156 rv = objectOutput->WriteObject(objQI, true);
157 EXPECT_NS_SUCCEEDED(rv);
159 mozilla::UniqueFreePtr<char[]> buf;
160 uint32_t len;
161 NewBufferFromStorageStream(storageStream, &buf, &len);
163 // Since this is a post-startup write, it should be written and
164 // available.
165 rv = sc->PutBuffer(id, std::move(buf), len);
166 EXPECT_NS_SUCCEEDED(rv);
168 const char* buf2;
169 uint32_t len2;
170 nsCOMPtr<nsIObjectInputStream> objectInput;
171 rv = sc->GetBuffer(id, &buf2, &len2);
172 EXPECT_NS_SUCCEEDED(rv);
174 rv = NewObjectInputStreamFromBuffer(buf2, len2, getter_AddRefs(objectInput));
175 EXPECT_NS_SUCCEEDED(rv);
177 nsCOMPtr<nsISupports> deserialized;
178 rv = objectInput->ReadObject(true, getter_AddRefs(deserialized));
179 EXPECT_NS_SUCCEEDED(rv);
181 nsCOMPtr<nsIURI> uri(do_QueryInterface(deserialized));
182 ASSERT_TRUE(uri);
184 nsCString outSpec;
185 rv = uri->GetSpec(outSpec);
186 EXPECT_NS_SUCCEEDED(rv);
187 ASSERT_TRUE(outSpec.Equals(spec));