123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- // Copyright 2013 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/nacl/browser/pnacl_translation_cache.h"
- #include <memory>
- #include "base/bind.h"
- #include "base/files/file_path.h"
- #include "base/files/scoped_temp_dir.h"
- #include "base/run_loop.h"
- #include "build/build_config.h"
- #include "components/nacl/common/pnacl_types.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/test/browser_task_environment.h"
- #include "net/base/io_buffer.h"
- #include "net/base/test_completion_callback.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using content::BrowserThread;
- using base::FilePath;
- namespace pnacl {
- const int kTestDiskCacheSize = 16 * 1024 * 1024;
- class PnaclTranslationCacheTest : public testing::Test {
- protected:
- PnaclTranslationCacheTest()
- : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {}
- ~PnaclTranslationCacheTest() override {}
- void SetUp() override { cache_ = std::make_unique<PnaclTranslationCache>(); }
- void TearDown() override {
- // The destructor of PnaclTranslationCacheWriteEntry posts a task to the IO
- // thread to close the backend cache entry. We want to make sure the entries
- // are closed before we delete the backend (and in particular the destructor
- // for the memory backend has a DCHECK to verify this), so we run the loop
- // here to ensure the task gets processed.
- base::RunLoop().RunUntilIdle();
- cache_.reset();
- }
- void InitBackend(bool in_mem);
- void StoreNexe(const std::string& key, const std::string& nexe);
- std::string GetNexe(const std::string& key);
- std::unique_ptr<PnaclTranslationCache> cache_;
- content::BrowserTaskEnvironment task_environment_;
- base::ScopedTempDir temp_dir_;
- };
- void PnaclTranslationCacheTest::InitBackend(bool in_mem) {
- net::TestCompletionCallback init_cb;
- if (!in_mem) {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- }
- // Use the private init method so we can control the size
- int rv = cache_->Init(in_mem ? net::MEMORY_CACHE : net::PNACL_CACHE,
- in_mem ? base::FilePath() : temp_dir_.GetPath(),
- in_mem ? kMaxMemCacheSize : kTestDiskCacheSize,
- init_cb.callback());
- if (in_mem)
- ASSERT_EQ(net::OK, rv);
- ASSERT_EQ(net::OK, init_cb.GetResult(rv));
- ASSERT_EQ(0, cache_->Size());
- }
- void PnaclTranslationCacheTest::StoreNexe(const std::string& key,
- const std::string& nexe) {
- net::TestCompletionCallback store_cb;
- scoped_refptr<net::DrainableIOBuffer> nexe_buf =
- base::MakeRefCounted<net::DrainableIOBuffer>(
- base::MakeRefCounted<net::StringIOBuffer>(nexe), nexe.size());
- cache_->StoreNexe(key, nexe_buf.get(), store_cb.callback());
- // Using ERR_IO_PENDING here causes the callback to wait for the result
- // which should be harmless even if it returns OK immediately. This is because
- // we don't plumb the intermediate writing stages all the way out.
- EXPECT_EQ(net::OK, store_cb.GetResult(net::ERR_IO_PENDING));
- }
- // Inspired by net::TestCompletionCallback. Instantiate a TestNexeCallback and
- // pass the GetNexeCallback returned by the callback() method to GetNexe.
- // Then call GetResult, which will pump the message loop until it gets a result,
- // return the resulting IOBuffer and fill in the return value
- class TestNexeCallback {
- public:
- TestNexeCallback()
- : have_result_(false),
- result_(-1),
- cb_(base::BindOnce(&TestNexeCallback::SetResult,
- base::Unretained(this))) {}
- GetNexeCallback callback() { return std::move(cb_); }
- net::DrainableIOBuffer* GetResult(int* result) {
- while (!have_result_)
- base::RunLoop().RunUntilIdle();
- have_result_ = false;
- *result = result_;
- return buf_.get();
- }
- private:
- void SetResult(int rv, scoped_refptr<net::DrainableIOBuffer> buf) {
- have_result_ = true;
- result_ = rv;
- buf_ = buf;
- }
- bool have_result_;
- int result_;
- scoped_refptr<net::DrainableIOBuffer> buf_;
- GetNexeCallback cb_;
- };
- std::string PnaclTranslationCacheTest::GetNexe(const std::string& key) {
- TestNexeCallback load_cb;
- cache_->GetNexe(key, load_cb.callback());
- int rv;
- scoped_refptr<net::DrainableIOBuffer> buf(load_cb.GetResult(&rv));
- EXPECT_EQ(net::OK, rv);
- if (buf.get() == NULL) // for some reason ASSERT macros don't work here.
- return std::string();
- std::string nexe(buf->data(), buf->size());
- return nexe;
- }
- static const std::string test_key("1");
- static const std::string test_store_val("testnexe");
- static const int kLargeNexeSize = 8 * 1024 * 1024;
- TEST(PnaclTranslationCacheKeyTest, CacheKeyTest) {
- nacl::PnaclCacheInfo info;
- info.pexe_url = GURL("http://www.google.com");
- info.abi_version = 0;
- info.opt_level = 0;
- info.sandbox_isa = "x86-32";
- std::string test_time("Wed, 15 Nov 1995 06:25:24 GMT");
- EXPECT_TRUE(base::Time::FromString(test_time.c_str(), &info.last_modified));
- // Basic check for URL and time components
- EXPECT_EQ("ABI:0;opt:0;URL:http://www.google.com/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- // Check that query portion of URL is not stripped
- info.pexe_url = GURL("http://www.google.com/?foo=bar");
- EXPECT_EQ("ABI:0;opt:0;URL:http://www.google.com/?foo=bar;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- // Check that username, password, and normal port are stripped
- info.pexe_url = GURL("https://user:host@www.google.com:443/");
- EXPECT_EQ("ABI:0;opt:0;URL:https://www.google.com/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- // Check that unusual port is not stripped but ref is stripped
- info.pexe_url = GURL("https://www.google.com:444/#foo");
- EXPECT_EQ("ABI:0;opt:0;URL:https://www.google.com:444/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- // Check chrome-extesnsion scheme
- info.pexe_url = GURL("chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/");
- EXPECT_EQ("ABI:0;opt:0;"
- "URL:chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- // Check that ABI version, opt level, and etag are in the key
- info.pexe_url = GURL("http://www.google.com/");
- info.abi_version = 2;
- EXPECT_EQ("ABI:2;opt:0;URL:http://www.google.com/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- info.opt_level = 2;
- EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- // Check that Subzero gets a different cache key.
- info.use_subzero = true;
- EXPECT_EQ("ABI:2;opt:2subzero;URL:http://www.google.com/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- info.use_subzero = false;
- info.etag = std::string("etag");
- EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:etag;"
- "sandbox:x86-32;extra_flags:;",
- PnaclTranslationCache::GetKey(info));
- info.extra_flags = "-mavx-neon";
- EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
- "modified:1995:11:15:6:25:24:0:UTC;etag:etag;"
- "sandbox:x86-32;extra_flags:-mavx-neon;",
- PnaclTranslationCache::GetKey(info));
- // Check for all the time components, and null time
- info.last_modified = base::Time();
- EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
- "modified:0:0:0:0:0:0:0:UTC;etag:etag;"
- "sandbox:x86-32;extra_flags:-mavx-neon;",
- PnaclTranslationCache::GetKey(info));
- test_time.assign("Fri, 29 Feb 2008 13:04:12 GMT");
- EXPECT_TRUE(base::Time::FromString(test_time.c_str(), &info.last_modified));
- EXPECT_EQ("ABI:2;opt:2;URL:http://www.google.com/;"
- "modified:2008:2:29:13:4:12:0:UTC;etag:etag;"
- "sandbox:x86-32;extra_flags:-mavx-neon;",
- PnaclTranslationCache::GetKey(info));
- }
- TEST_F(PnaclTranslationCacheTest, StoreSmallInMem) {
- // Test that a single store puts something in the mem backend
- InitBackend(true);
- StoreNexe(test_key, test_store_val);
- EXPECT_EQ(1, cache_->Size());
- }
- TEST_F(PnaclTranslationCacheTest, StoreSmallOnDisk) {
- // Test that a single store puts something in the disk backend
- InitBackend(false);
- StoreNexe(test_key, test_store_val);
- EXPECT_EQ(1, cache_->Size());
- }
- TEST_F(PnaclTranslationCacheTest, StoreLargeOnDisk) {
- // Test a value too large(?) for a single I/O operation
- InitBackend(false);
- const std::string large_buffer(kLargeNexeSize, 'a');
- StoreNexe(test_key, large_buffer);
- EXPECT_EQ(1, cache_->Size());
- }
- TEST_F(PnaclTranslationCacheTest, InMemSizeLimit) {
- InitBackend(true);
- scoped_refptr<net::DrainableIOBuffer> large_buffer =
- base::MakeRefCounted<net::DrainableIOBuffer>(
- base::MakeRefCounted<net::StringIOBuffer>(
- std::string(kMaxMemCacheSize + 1, 'a')),
- kMaxMemCacheSize + 1);
- net::TestCompletionCallback store_cb;
- cache_->StoreNexe(test_key, large_buffer.get(), store_cb.callback());
- EXPECT_EQ(net::ERR_FAILED, store_cb.GetResult(net::ERR_IO_PENDING));
- base::RunLoop().RunUntilIdle(); // Ensure the entry is closed.
- EXPECT_EQ(0, cache_->Size());
- }
- TEST_F(PnaclTranslationCacheTest, GetOneInMem) {
- InitBackend(true);
- StoreNexe(test_key, test_store_val);
- EXPECT_EQ(1, cache_->Size());
- EXPECT_EQ(0, GetNexe(test_key).compare(test_store_val));
- }
- TEST_F(PnaclTranslationCacheTest, GetOneOnDisk) {
- InitBackend(false);
- StoreNexe(test_key, test_store_val);
- EXPECT_EQ(1, cache_->Size());
- EXPECT_EQ(0, GetNexe(test_key).compare(test_store_val));
- }
- TEST_F(PnaclTranslationCacheTest, GetLargeOnDisk) {
- InitBackend(false);
- const std::string large_buffer(kLargeNexeSize, 'a');
- StoreNexe(test_key, large_buffer);
- EXPECT_EQ(1, cache_->Size());
- EXPECT_EQ(0, GetNexe(test_key).compare(large_buffer));
- }
- TEST_F(PnaclTranslationCacheTest, StoreTwice) {
- // Test that storing twice with the same key overwrites
- InitBackend(true);
- StoreNexe(test_key, test_store_val);
- StoreNexe(test_key, test_store_val + "aaa");
- EXPECT_EQ(1, cache_->Size());
- EXPECT_EQ(0, GetNexe(test_key).compare(test_store_val + "aaa"));
- }
- TEST_F(PnaclTranslationCacheTest, StoreTwo) {
- InitBackend(true);
- StoreNexe(test_key, test_store_val);
- StoreNexe(test_key + "a", test_store_val + "aaa");
- EXPECT_EQ(2, cache_->Size());
- EXPECT_EQ(0, GetNexe(test_key).compare(test_store_val));
- EXPECT_EQ(0, GetNexe(test_key + "a").compare(test_store_val + "aaa"));
- }
- TEST_F(PnaclTranslationCacheTest, GetMiss) {
- InitBackend(true);
- StoreNexe(test_key, test_store_val);
- TestNexeCallback load_cb;
- std::string nexe;
- cache_->GetNexe(test_key + "a", load_cb.callback());
- int rv;
- scoped_refptr<net::DrainableIOBuffer> buf(load_cb.GetResult(&rv));
- EXPECT_EQ(net::ERR_FAILED, rv);
- }
- } // namespace pnacl
|