Roll src/third_party/WebKit 9f7fb92:f103b33 (svn 202621:202622)
[chromium-blink-merge.git] / components / nacl / browser / pnacl_translation_cache_unittest.cc
bloba8c8093a7a7f90d36a0544517b150b2159a084b5
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/nacl/browser/pnacl_translation_cache.h"
7 #include "base/files/file_path.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "components/nacl/common/pnacl_types.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/test/test_browser_thread_bundle.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/test_completion_callback.h"
16 #include "testing/gtest/include/gtest/gtest.h"
18 // For fine-grained suppression on flaky tests.
19 #if defined(OS_WIN)
20 #include "base/win/windows_version.h"
21 #endif
23 using content::BrowserThread;
24 using base::FilePath;
26 namespace pnacl {
28 const int kTestDiskCacheSize = 16 * 1024 * 1024;
30 class PnaclTranslationCacheTest : public testing::Test {
31 protected:
32 PnaclTranslationCacheTest()
33 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
34 ~PnaclTranslationCacheTest() override {}
35 void SetUp() override { cache_.reset(new PnaclTranslationCache()); }
36 void TearDown() override {
37 // The destructor of PnaclTranslationCacheWriteEntry posts a task to the IO
38 // thread to close the backend cache entry. We want to make sure the entries
39 // are closed before we delete the backend (and in particular the destructor
40 // for the memory backend has a DCHECK to verify this), so we run the loop
41 // here to ensure the task gets processed.
42 base::RunLoop().RunUntilIdle();
43 cache_.reset();
46 void InitBackend(bool in_mem);
47 void StoreNexe(const std::string& key, const std::string& nexe);
48 std::string GetNexe(const std::string& key);
50 scoped_ptr<PnaclTranslationCache> cache_;
51 content::TestBrowserThreadBundle thread_bundle_;
52 base::ScopedTempDir temp_dir_;
55 void PnaclTranslationCacheTest::InitBackend(bool in_mem) {
56 net::TestCompletionCallback init_cb;
57 if (!in_mem) {
58 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
60 // Use the private init method so we can control the size
61 int rv = cache_->Init(in_mem ? net::MEMORY_CACHE : net::PNACL_CACHE,
62 temp_dir_.path(),
63 in_mem ? kMaxMemCacheSize : kTestDiskCacheSize,
64 init_cb.callback());
65 if (in_mem)
66 ASSERT_EQ(net::OK, rv);
67 ASSERT_EQ(net::OK, init_cb.GetResult(rv));
68 ASSERT_EQ(0, cache_->Size());
71 void PnaclTranslationCacheTest::StoreNexe(const std::string& key,
72 const std::string& nexe) {
73 net::TestCompletionCallback store_cb;
74 scoped_refptr<net::DrainableIOBuffer> nexe_buf(
75 new net::DrainableIOBuffer(new net::StringIOBuffer(nexe), nexe.size()));
76 cache_->StoreNexe(key, nexe_buf.get(), store_cb.callback());
77 // Using ERR_IO_PENDING here causes the callback to wait for the result
78 // which should be harmless even if it returns OK immediately. This is because
79 // we don't plumb the intermediate writing stages all the way out.
80 EXPECT_EQ(net::OK, store_cb.GetResult(net::ERR_IO_PENDING));
83 // Inspired by net::TestCompletionCallback. Instantiate a TestNexeCallback and
84 // pass the GetNexeCallback returned by the callback() method to GetNexe.
85 // Then call GetResult, which will pump the message loop until it gets a result,
86 // return the resulting IOBuffer and fill in the return value
87 class TestNexeCallback {
88 public:
89 TestNexeCallback()
90 : have_result_(false),
91 result_(-1),
92 cb_(base::Bind(&TestNexeCallback::SetResult, base::Unretained(this))) {}
93 GetNexeCallback callback() { return cb_; }
94 net::DrainableIOBuffer* GetResult(int* result) {
95 while (!have_result_)
96 base::RunLoop().RunUntilIdle();
97 have_result_ = false;
98 *result = result_;
99 return buf_.get();
102 private:
103 void SetResult(int rv, scoped_refptr<net::DrainableIOBuffer> buf) {
104 have_result_ = true;
105 result_ = rv;
106 buf_ = buf;
108 bool have_result_;
109 int result_;
110 scoped_refptr<net::DrainableIOBuffer> buf_;
111 const GetNexeCallback cb_;
114 std::string PnaclTranslationCacheTest::GetNexe(const std::string& key) {
115 TestNexeCallback load_cb;
116 cache_->GetNexe(key, load_cb.callback());
117 int rv;
118 scoped_refptr<net::DrainableIOBuffer> buf(load_cb.GetResult(&rv));
119 EXPECT_EQ(net::OK, rv);
120 if (buf.get() == NULL) // for some reason ASSERT macros don't work here.
121 return std::string();
122 std::string nexe(buf->data(), buf->size());
123 return nexe;
126 static const std::string test_key("1");
127 static const std::string test_store_val("testnexe");
128 static const int kLargeNexeSize = 8 * 1024 * 1024;
130 TEST(PnaclTranslationCacheKeyTest, CacheKeyTest) {
131 nacl::PnaclCacheInfo info;
132 info.pexe_url = GURL("http://www.google.com");
133 info.abi_version = 0;
134 info.opt_level = 0;
135 info.sandbox_isa = "x86-32";
136 std::string test_time("Wed, 15 Nov 1995 06:25:24 GMT");
137 base::Time::FromString(test_time.c_str(), &info.last_modified);
138 // Basic check for URL and time components
139 EXPECT_EQ("ABI:0;opt:0;URL:http://www.google.com/;"
140 "modified:1995:11:15:6:25:24:0:UTC;etag:;"
141 "sandbox:x86-32;extra_flags:;",
142 PnaclTranslationCache::GetKey(info));
143 // Check that query portion of URL is not stripped
144 info.pexe_url = GURL("http://www.google.com/?foo=bar");
145 EXPECT_EQ("ABI:0;opt:0;URL:http://www.google.com/?foo=bar;"
146 "modified:1995:11:15:6:25:24:0:UTC;etag:;"
147 "sandbox:x86-32;extra_flags:;",
148 PnaclTranslationCache::GetKey(info));
149 // Check that username, password, and normal port are stripped
150 info.pexe_url = GURL("https://user:host@www.google.com:443/");
151 EXPECT_EQ("ABI:0;opt:0;URL:https://www.google.com/;"
152 "modified:1995:11:15:6:25:24:0:UTC;etag:;"
153 "sandbox:x86-32;extra_flags:;",
154 PnaclTranslationCache::GetKey(info));
155 // Check that unusual port is not stripped but ref is stripped
156 info.pexe_url = GURL("https://www.google.com:444/#foo");
157 EXPECT_EQ("ABI:0;opt:0;URL:https://www.google.com:444/;"
158 "modified:1995:11:15:6:25:24:0:UTC;etag:;"
159 "sandbox:x86-32;extra_flags:;",
160 PnaclTranslationCache::GetKey(info));
161 // Check chrome-extesnsion scheme
162 info.pexe_url = GURL("chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/");
163 EXPECT_EQ("ABI:0;opt:0;"
164 "URL:chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/;"
165 "modified:1995:11:15:6:25:24:0:UTC;etag:;"
166 "sandbox:x86-32;extra_flags:;",
167 PnaclTranslationCache::GetKey(info));
168 // Check that ABI version, opt level, and etag are in the key
169 info.pexe_url = GURL("http://www.google.com/");
170 info.abi_version = 2;
171 EXPECT_EQ("ABI:2;opt:0;URL:http://www.google.com/;"
172 "modified:1995:11:15:6:25:24:0:UTC;etag:;"
173 "sandbox:x86-32;extra_flags:;",
174 PnaclTranslationCache::GetKey(info));
175 info.opt_level = 2;
176 EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
177 "modified:1995:11:15:6:25:24:0:UTC;etag:;"
178 "sandbox:x86-32;extra_flags:;",
179 PnaclTranslationCache::GetKey(info));
180 // Check that Subzero gets a different cache key.
181 info.use_subzero = true;
182 EXPECT_EQ("ABI:2;opt:2subzero;URL:http://www.google.com/;"
183 "modified:1995:11:15:6:25:24:0:UTC;etag:;"
184 "sandbox:x86-32;extra_flags:;",
185 PnaclTranslationCache::GetKey(info));
186 info.use_subzero = false;
187 info.etag = std::string("etag");
188 EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
189 "modified:1995:11:15:6:25:24:0:UTC;etag:etag;"
190 "sandbox:x86-32;extra_flags:;",
191 PnaclTranslationCache::GetKey(info));
193 info.extra_flags = "-mavx-neon";
194 EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
195 "modified:1995:11:15:6:25:24:0:UTC;etag:etag;"
196 "sandbox:x86-32;extra_flags:-mavx-neon;",
197 PnaclTranslationCache::GetKey(info));
199 // Check for all the time components, and null time
200 info.last_modified = base::Time();
201 EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
202 "modified:0:0:0:0:0:0:0:UTC;etag:etag;"
203 "sandbox:x86-32;extra_flags:-mavx-neon;",
204 PnaclTranslationCache::GetKey(info));
205 test_time.assign("Fri, 29 Feb 2008 13:04:12 GMT");
206 base::Time::FromString(test_time.c_str(), &info.last_modified);
207 EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
208 "modified:2008:2:29:13:4:12:0:UTC;etag:etag;"
209 "sandbox:x86-32;extra_flags:-mavx-neon;",
210 PnaclTranslationCache::GetKey(info));
213 TEST_F(PnaclTranslationCacheTest, StoreSmallInMem) {
214 // Test that a single store puts something in the mem backend
215 InitBackend(true);
216 StoreNexe(test_key, test_store_val);
217 EXPECT_EQ(1, cache_->Size());
220 TEST_F(PnaclTranslationCacheTest, StoreSmallOnDisk) {
221 // Test that a single store puts something in the disk backend
222 InitBackend(false);
223 StoreNexe(test_key, test_store_val);
224 EXPECT_EQ(1, cache_->Size());
227 TEST_F(PnaclTranslationCacheTest, StoreLargeOnDisk) {
228 #if defined(OS_WIN)
229 // Flaky on XP bot http://crbug.com/468741
230 if (base::win::GetVersion() <= base::win::VERSION_XP)
231 return;
232 #endif
233 // Test a value too large(?) for a single I/O operation
234 InitBackend(false);
235 const std::string large_buffer(kLargeNexeSize, 'a');
236 StoreNexe(test_key, large_buffer);
237 EXPECT_EQ(1, cache_->Size());
240 TEST_F(PnaclTranslationCacheTest, InMemSizeLimit) {
241 InitBackend(true);
242 scoped_refptr<net::DrainableIOBuffer> large_buffer(new net::DrainableIOBuffer(
243 new net::StringIOBuffer(std::string(kMaxMemCacheSize + 1, 'a')),
244 kMaxMemCacheSize + 1));
245 net::TestCompletionCallback store_cb;
246 cache_->StoreNexe(test_key, large_buffer.get(), store_cb.callback());
247 EXPECT_EQ(net::ERR_FAILED, store_cb.GetResult(net::ERR_IO_PENDING));
248 base::RunLoop().RunUntilIdle(); // Ensure the entry is closed.
249 EXPECT_EQ(0, cache_->Size());
252 TEST_F(PnaclTranslationCacheTest, GetOneInMem) {
253 InitBackend(true);
254 StoreNexe(test_key, test_store_val);
255 EXPECT_EQ(1, cache_->Size());
256 EXPECT_EQ(0, GetNexe(test_key).compare(test_store_val));
259 TEST_F(PnaclTranslationCacheTest, GetOneOnDisk) {
260 InitBackend(false);
261 StoreNexe(test_key, test_store_val);
262 EXPECT_EQ(1, cache_->Size());
263 EXPECT_EQ(0, GetNexe(test_key).compare(test_store_val));
266 TEST_F(PnaclTranslationCacheTest, GetLargeOnDisk) {
267 #if defined(OS_WIN)
268 // Flaky on XP bot http://crbug.com/468741
269 if (base::win::GetVersion() <= base::win::VERSION_XP)
270 return;
271 #endif
272 InitBackend(false);
273 const std::string large_buffer(kLargeNexeSize, 'a');
274 StoreNexe(test_key, large_buffer);
275 EXPECT_EQ(1, cache_->Size());
276 EXPECT_EQ(0, GetNexe(test_key).compare(large_buffer));
279 TEST_F(PnaclTranslationCacheTest, StoreTwice) {
280 // Test that storing twice with the same key overwrites
281 InitBackend(true);
282 StoreNexe(test_key, test_store_val);
283 StoreNexe(test_key, test_store_val + "aaa");
284 EXPECT_EQ(1, cache_->Size());
285 EXPECT_EQ(0, GetNexe(test_key).compare(test_store_val + "aaa"));
288 TEST_F(PnaclTranslationCacheTest, StoreTwo) {
289 InitBackend(true);
290 StoreNexe(test_key, test_store_val);
291 StoreNexe(test_key + "a", test_store_val + "aaa");
292 EXPECT_EQ(2, cache_->Size());
293 EXPECT_EQ(0, GetNexe(test_key).compare(test_store_val));
294 EXPECT_EQ(0, GetNexe(test_key + "a").compare(test_store_val + "aaa"));
297 TEST_F(PnaclTranslationCacheTest, GetMiss) {
298 InitBackend(true);
299 StoreNexe(test_key, test_store_val);
300 TestNexeCallback load_cb;
301 std::string nexe;
302 cache_->GetNexe(test_key + "a", load_cb.callback());
303 int rv;
304 scoped_refptr<net::DrainableIOBuffer> buf(load_cb.GetResult(&rv));
305 EXPECT_EQ(net::ERR_FAILED, rv);
308 } // namespace pnacl