/src/mozilla-central/startupcache/test/TestStartupCache.cpp
Line | Count | Source (jump to first uncovered line) |
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 "nsIClassInfo.h" |
13 | | #include "nsIOutputStream.h" |
14 | | #include "nsIObserver.h" |
15 | | #include "nsISerializable.h" |
16 | | #include "nsISupports.h" |
17 | | #include "nsIStringStream.h" |
18 | | #include "nsIStorageStream.h" |
19 | | #include "nsIObjectInputStream.h" |
20 | | #include "nsIObjectOutputStream.h" |
21 | | #include "nsIURI.h" |
22 | | #include "nsIPrefBranch.h" |
23 | | #include "nsIPrefService.h" |
24 | | #include "nsIXPConnect.h" |
25 | | #include "nsThreadUtils.h" |
26 | | #include "prenv.h" |
27 | | #include "prio.h" |
28 | | #include "prprf.h" |
29 | | #include "mozilla/Maybe.h" |
30 | | #include "mozilla/Printf.h" |
31 | | #include "mozilla/UniquePtr.h" |
32 | | #include "nsNetCID.h" |
33 | | #include "nsIURIMutator.h" |
34 | | |
35 | | using namespace JS; |
36 | | |
37 | | using namespace mozilla::scache; |
38 | | using mozilla::UniquePtr; |
39 | | |
40 | | void |
41 | | WaitForStartupTimer() |
42 | 0 | { |
43 | 0 | StartupCache* sc = StartupCache::GetSingleton(); |
44 | 0 | PR_Sleep(10 * PR_TicksPerSecond()); |
45 | 0 |
|
46 | 0 | while (true) { |
47 | 0 | NS_ProcessPendingEvents(nullptr); |
48 | 0 | if (sc->StartupWriteComplete()) { |
49 | 0 | return; |
50 | 0 | } |
51 | 0 | PR_Sleep(1 * PR_TicksPerSecond()); |
52 | 0 | } |
53 | 0 | } |
54 | | |
55 | | class TestStartupCache : public ::testing::Test |
56 | | { |
57 | | protected: |
58 | | TestStartupCache(); |
59 | | ~TestStartupCache(); |
60 | | |
61 | | nsCOMPtr<nsIFile> mSCFile; |
62 | | }; |
63 | | |
64 | | TestStartupCache::TestStartupCache() |
65 | 0 | { |
66 | 0 | NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mSCFile)); |
67 | 0 | mSCFile->AppendNative(NS_LITERAL_CSTRING("test-startupcache.tmp")); |
68 | | #ifdef XP_WIN |
69 | | nsAutoString env(NS_LITERAL_STRING("MOZ_STARTUP_CACHE=")); |
70 | | env.Append(mSCFile->NativePath()); |
71 | | _wputenv(env.get()); |
72 | | #else |
73 | | nsAutoCString path; |
74 | 0 | mSCFile->GetNativePath(path); |
75 | 0 | char* env = mozilla::Smprintf("MOZ_STARTUP_CACHE=%s", path.get()).release(); |
76 | 0 | PR_SetEnv(env); |
77 | 0 | // We intentionally leak `env` here because it is required by PR_SetEnv |
78 | 0 | MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(env); |
79 | 0 | #endif |
80 | 0 | StartupCache::GetSingleton()->InvalidateCache(); |
81 | 0 | } |
82 | | TestStartupCache::~TestStartupCache() |
83 | 0 | { |
84 | 0 | PR_SetEnv("MOZ_STARTUP_CACHE="); |
85 | 0 | StartupCache::GetSingleton()->InvalidateCache(); |
86 | 0 | } |
87 | | |
88 | | |
89 | | TEST_F(TestStartupCache, StartupWriteRead) |
90 | 0 | { |
91 | 0 | nsresult rv; |
92 | 0 | StartupCache* sc = StartupCache::GetSingleton(); |
93 | 0 |
|
94 | 0 | const char* buf = "Market opportunities for BeardBook"; |
95 | 0 | const char* id = "id"; |
96 | 0 | UniquePtr<char[]> outbuf; |
97 | 0 | uint32_t len; |
98 | 0 |
|
99 | 0 | rv = sc->PutBuffer(id, UniquePtr<char[]>(strdup(buf)), strlen(buf) + 1); |
100 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
101 | 0 |
|
102 | 0 | rv = sc->GetBuffer(id, &outbuf, &len); |
103 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
104 | 0 | EXPECT_STREQ(buf, outbuf.get()); |
105 | 0 |
|
106 | 0 | rv = sc->ResetStartupWriteTimer(); |
107 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
108 | 0 | WaitForStartupTimer(); |
109 | 0 |
|
110 | 0 | rv = sc->GetBuffer(id, &outbuf, &len); |
111 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
112 | 0 | EXPECT_STREQ(buf, outbuf.get()); |
113 | 0 | } |
114 | | |
115 | | TEST_F(TestStartupCache, WriteInvalidateRead) |
116 | 0 | { |
117 | 0 | nsresult rv; |
118 | 0 | const char* buf = "BeardBook competitive analysis"; |
119 | 0 | const char* id = "id"; |
120 | 0 | UniquePtr<char[]> outbuf; |
121 | 0 | uint32_t len; |
122 | 0 | StartupCache* sc = StartupCache::GetSingleton(); |
123 | 0 | ASSERT_TRUE(sc); |
124 | 0 |
|
125 | 0 | rv = sc->PutBuffer(id, UniquePtr<char[]>(strdup(buf)), strlen(buf) + 1); |
126 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
127 | 0 |
|
128 | 0 | sc->InvalidateCache(); |
129 | 0 |
|
130 | 0 | rv = sc->GetBuffer(id, &outbuf, &len); |
131 | 0 | EXPECT_EQ(rv, NS_ERROR_NOT_AVAILABLE); |
132 | 0 | } |
133 | | |
134 | | TEST_F(TestStartupCache, WriteObject) |
135 | 0 | { |
136 | 0 | nsresult rv; |
137 | 0 |
|
138 | 0 | nsCOMPtr<nsIURI> obj; |
139 | 0 |
|
140 | 0 | NS_NAMED_LITERAL_CSTRING(spec, "http://www.mozilla.org"); |
141 | 0 | rv = NS_MutateURI(NS_SIMPLEURIMUTATOR_CONTRACTID) |
142 | 0 | .SetSpec(spec) |
143 | 0 | .Finalize(obj); |
144 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
145 | 0 |
|
146 | 0 | StartupCache* sc = StartupCache::GetSingleton(); |
147 | 0 |
|
148 | 0 | // Create an object stream. Usually this is done with |
149 | 0 | // NewObjectOutputWrappedStorageStream, but that uses |
150 | 0 | // StartupCache::GetSingleton in debug builds, and we |
151 | 0 | // don't have access to that here. Obviously. |
152 | 0 | const char* id = "id"; |
153 | 0 | nsCOMPtr<nsIStorageStream> storageStream |
154 | 0 | = do_CreateInstance("@mozilla.org/storagestream;1"); |
155 | 0 | ASSERT_TRUE(storageStream); |
156 | 0 |
|
157 | 0 | rv = storageStream->Init(256, (uint32_t) -1); |
158 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
159 | 0 |
|
160 | 0 | nsCOMPtr<nsIObjectOutputStream> objectOutput |
161 | 0 | = do_CreateInstance("@mozilla.org/binaryoutputstream;1"); |
162 | 0 | ASSERT_TRUE(objectOutput); |
163 | 0 |
|
164 | 0 | nsCOMPtr<nsIOutputStream> outputStream |
165 | 0 | = do_QueryInterface(storageStream); |
166 | 0 |
|
167 | 0 | rv = objectOutput->SetOutputStream(outputStream); |
168 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
169 | 0 |
|
170 | 0 | nsCOMPtr<nsISupports> objQI(do_QueryInterface(obj)); |
171 | 0 | rv = objectOutput->WriteObject(objQI, true); |
172 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
173 | 0 |
|
174 | 0 | UniquePtr<char[]> buf; |
175 | 0 | uint32_t len; |
176 | 0 | NewBufferFromStorageStream(storageStream, &buf, &len); |
177 | 0 |
|
178 | 0 | // Since this is a post-startup write, it should be written and |
179 | 0 | // available. |
180 | 0 | rv = sc->PutBuffer(id, std::move(buf), len); |
181 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
182 | 0 |
|
183 | 0 | UniquePtr<char[]> buf2; |
184 | 0 | uint32_t len2; |
185 | 0 | nsCOMPtr<nsIObjectInputStream> objectInput; |
186 | 0 | rv = sc->GetBuffer(id, &buf2, &len2); |
187 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
188 | 0 |
|
189 | 0 | rv = NewObjectInputStreamFromBuffer(std::move(buf2), len2, |
190 | 0 | getter_AddRefs(objectInput)); |
191 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
192 | 0 |
|
193 | 0 | nsCOMPtr<nsISupports> deserialized; |
194 | 0 | rv = objectInput->ReadObject(true, getter_AddRefs(deserialized)); |
195 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
196 | 0 |
|
197 | 0 | nsCOMPtr<nsIURI> uri(do_QueryInterface(deserialized)); |
198 | 0 | ASSERT_TRUE(uri); |
199 | 0 |
|
200 | 0 | nsCString outSpec; |
201 | 0 | rv = uri->GetSpec(outSpec); |
202 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
203 | 0 | ASSERT_TRUE(outSpec.Equals(spec)); |
204 | 0 | } |