Commit 38d9efa1 authored by mek's avatar mek Committed by Commit bot

Add tests for how LocalStorageContextMojo interacts with file/leveldb services.

Also fixes bugs exposed by those tests:
- when database does not exists it needs to be created.
- when database can't be opened null is passed to LevelDBWrapper.

BUG=586194

Review-Url: https://codereview.chromium.org/2597983003
Cr-Commit-Position: refs/heads/master@{#440886}
parent f9fdc418
......@@ -141,10 +141,13 @@ void LocalStorageContextMojo::OnDirectoryOpened(
// database.
file_service_connection_->GetInterface(&leveldb_service_);
leveldb_service_->Open(std::move(directory_), "leveldb",
MakeRequest(&database_),
base::Bind(&LocalStorageContextMojo::OnDatabaseOpened,
weak_ptr_factory_.GetWeakPtr()));
auto options = leveldb::mojom::OpenOptions::New();
options->create_if_missing = true;
leveldb_service_->OpenWithOptions(
std::move(options), std::move(directory_), "leveldb",
MakeRequest(&database_),
base::Bind(&LocalStorageContextMojo::OnDatabaseOpened,
weak_ptr_factory_.GetWeakPtr()));
}
void LocalStorageContextMojo::OnDatabaseOpened(
......
......@@ -4,11 +4,24 @@
#include "content/browser/dom_storage/local_storage_context_mojo.h"
#include "base/files/file_enumerator.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "components/filesystem/public/interfaces/file_system.mojom.h"
#include "components/leveldb/public/cpp/util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/mock_leveldb_database.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/file/file_service.h"
#include "services/file/public/interfaces/constants.mojom.h"
#include "services/file/user_id_map.h"
#include "services/service_manager/public/cpp/interface_factory.h"
#include "services/service_manager/public/cpp/interface_registry.h"
#include "services/service_manager/public/cpp/service_context.h"
#include "services/service_manager/public/cpp/service_test.h"
#include "services/service_manager/public/interfaces/service_factory.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
using leveldb::StdStringToUint8Vector;
......@@ -59,6 +72,8 @@ class LocalStorageContextMojoTest : public testing::Test {
mojo::Binding<leveldb::mojom::LevelDBDatabase> db_binding_;
std::unique_ptr<LocalStorageContextMojo> context_;
DISALLOW_COPY_AND_ASSIGN(LocalStorageContextMojoTest);
};
TEST_F(LocalStorageContextMojoTest, Basic) {
......@@ -139,7 +154,6 @@ TEST_F(LocalStorageContextMojoTest, VersionOnlyWrittenOnCommit) {
mojom::LevelDBWrapperPtr wrapper;
context()->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
base::RunLoop run_loop;
bool success = false;
std::vector<uint8_t> result;
......@@ -154,4 +168,208 @@ TEST_F(LocalStorageContextMojoTest, VersionOnlyWrittenOnCommit) {
EXPECT_TRUE(mock_data().empty());
}
namespace {
class ServiceTestClient : public service_manager::test::ServiceTestClient,
public service_manager::mojom::ServiceFactory,
public service_manager::InterfaceFactory<
service_manager::mojom::ServiceFactory> {
public:
explicit ServiceTestClient(service_manager::test::ServiceTest* test)
: service_manager::test::ServiceTestClient(test) {}
~ServiceTestClient() override {}
protected:
bool OnConnect(const service_manager::ServiceInfo& remote_info,
service_manager::InterfaceRegistry* registry) override {
registry->AddInterface<service_manager::mojom::ServiceFactory>(this);
return true;
}
void CreateService(service_manager::mojom::ServiceRequest request,
const std::string& name) override {
if (name == file::mojom::kServiceName) {
file_service_context_.reset(new service_manager::ServiceContext(
file::CreateFileService(
BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE),
BrowserThread::GetTaskRunnerForThread(BrowserThread::DB)),
std::move(request)));
}
}
void Create(const service_manager::Identity& remote_identity,
service_manager::mojom::ServiceFactoryRequest request) override {
service_factory_bindings_.AddBinding(this, std::move(request));
}
private:
mojo::BindingSet<service_manager::mojom::ServiceFactory>
service_factory_bindings_;
std::unique_ptr<service_manager::ServiceContext> file_service_context_;
};
} // namespace
class LocalStorageContextMojoTestWithService
: public service_manager::test::ServiceTest {
public:
LocalStorageContextMojoTestWithService()
: ServiceTest("content_unittests", false) {}
~LocalStorageContextMojoTestWithService() override {}
protected:
void SetUp() override {
ServiceTest::SetUp();
ASSERT_TRUE(temp_path_.CreateUniqueTempDir());
file::AssociateServiceUserIdWithUserDir(test_userid(),
temp_path_.GetPath());
}
void TearDown() override {
temp_path_.Take();
ServiceTest::TearDown();
}
std::unique_ptr<service_manager::Service> CreateService() override {
return base::MakeUnique<ServiceTestClient>(this);
}
std::unique_ptr<base::MessageLoop> CreateMessageLoop() override {
return nullptr;
}
const base::FilePath& temp_path() { return temp_path_.GetPath(); }
base::FilePath FirstEntryInDir() {
base::FileEnumerator enumerator(
temp_path(), false /* recursive */,
base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
return enumerator.Next();
}
void DoTestPut(LocalStorageContextMojo* context,
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& value) {
mojom::LevelDBWrapperPtr wrapper;
context->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
wrapper->Put(key, value, "source", base::Bind(&NoOpSuccess));
wrapper.reset();
base::RunLoop().RunUntilIdle();
}
bool DoTestGet(LocalStorageContextMojo* context,
const std::vector<uint8_t>& key,
std::vector<uint8_t>* result) {
mojom::LevelDBWrapperPtr wrapper;
context->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
base::RunLoop run_loop;
bool success = false;
wrapper->Get(key, base::Bind(&GetCallback, run_loop.QuitClosure(), &success,
result));
run_loop.Run();
return success;
}
private:
TestBrowserThreadBundle thread_bundle_;
base::ScopedTempDir temp_path_;
DISALLOW_COPY_AND_ASSIGN(LocalStorageContextMojoTestWithService);
};
// Enable when http://crbug.com/677194 is fixed and ServiceTest works
// correctly on Android.
#if defined(OS_ANDROID)
#define MAYBE_InMemory DISABLED_InMemory
#else
#define MAYBE_InMemory InMemory
#endif
TEST_F(LocalStorageContextMojoTestWithService, MAYBE_InMemory) {
auto context =
base::MakeUnique<LocalStorageContextMojo>(connector(), base::FilePath());
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
mojom::LevelDBWrapperPtr wrapper;
context->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
DoTestPut(context.get(), key, value);
std::vector<uint8_t> result;
EXPECT_TRUE(DoTestGet(context.get(), key, &result));
EXPECT_EQ(value, result);
context.reset();
base::RunLoop().RunUntilIdle();
// Should not have created any files.
EXPECT_TRUE(FirstEntryInDir().empty());
// Re-opening should get fresh data.
context.reset(new LocalStorageContextMojo(connector(), base::FilePath()));
EXPECT_FALSE(DoTestGet(context.get(), key, &result));
}
// Enable when http://crbug.com/677194 is fixed and ServiceTest works
// correctly on Android.
#if defined(OS_ANDROID)
#define MAYBE_InMemoryInvalidPath DISABLED_InMemoryInvalidPath
#else
#define MAYBE_InMemoryInvalidPath InMemoryInvalidPath
#endif
TEST_F(LocalStorageContextMojoTestWithService, MAYBE_InMemoryInvalidPath) {
auto context = base::MakeUnique<LocalStorageContextMojo>(
connector(), base::FilePath(FILE_PATH_LITERAL("../../")));
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
mojom::LevelDBWrapperPtr wrapper;
context->OpenLocalStorage(url::Origin(GURL("http://foobar.com")),
MakeRequest(&wrapper));
DoTestPut(context.get(), key, value);
std::vector<uint8_t> result;
EXPECT_TRUE(DoTestGet(context.get(), key, &result));
EXPECT_EQ(value, result);
context.reset();
base::RunLoop().RunUntilIdle();
// Should not have created any files.
EXPECT_TRUE(FirstEntryInDir().empty());
}
// Enable when http://crbug.com/677194 is fixed and ServiceTest works
// correctly on Android.
#if defined(OS_ANDROID)
#define MAYBE_OnDisk DISABLED_OnDisk
#else
#define MAYBE_OnDisk OnDisk
#endif
TEST_F(LocalStorageContextMojoTestWithService, MAYBE_OnDisk) {
base::FilePath test_path(FILE_PATH_LITERAL("test_path"));
auto context =
base::MakeUnique<LocalStorageContextMojo>(connector(), test_path);
auto key = StdStringToUint8Vector("key");
auto value = StdStringToUint8Vector("value");
DoTestPut(context.get(), key, value);
std::vector<uint8_t> result;
EXPECT_TRUE(DoTestGet(context.get(), key, &result));
EXPECT_EQ(value, result);
context.reset();
base::RunLoop().RunUntilIdle();
// Should have created files.
EXPECT_EQ(test_path, FirstEntryInDir().BaseName());
// Should be able to re-open.
context.reset(new LocalStorageContextMojo(connector(), test_path));
EXPECT_TRUE(DoTestGet(context.get(), key, &result));
EXPECT_EQ(value, result);
}
} // namespace content
......@@ -10,6 +10,7 @@ import("//build/config/ui.gni")
import("//media/media_options.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//ppapi/features/features.gni")
import("//services/service_manager/public/service_manifest.gni")
import("//testing/test.gni")
import("//third_party/WebKit/public/public_features.gni")
import("//v8/gni/v8.gni")
......@@ -1442,6 +1443,9 @@ test("content_unittests") {
"//ppapi/c",
"//ppapi/features",
"//printing",
"//services/file:lib",
"//services/file/public/interfaces",
"//services/service_manager/public/cpp:service_test_support",
"//skia",
"//sql",
"//sql:test_support",
......@@ -1472,6 +1476,8 @@ test("content_unittests") {
]
data_deps = [
":content_unittests_manifest",
"//components/filesystem:filesystem",
"//third_party/mesa:osmesa",
]
......@@ -1710,6 +1716,15 @@ test("content_unittests") {
}
}
service_manifest("content_unittests_manifest") {
name = "content_unittests"
source = "unittests_manifest.json"
packaged_services = [ "file" ]
deps = [
"//services/file:manifest",
]
}
test("content_perftests") {
# See comment at the top of //content/BUILD.gn for why this is disabled in
# component builds.
......
{
"name": "content_unittests",
"display_name": "Content Unittests",
"interface_provider_specs": {
"service_manager:connector": {
"provides": {
"service_manager:service_factory": [
"service_manager::mojom::ServiceFactory"
]
},
"requires": {
"file": [ "file:filesystem", "file:leveldb" ]
}
}
}
}
......@@ -31,8 +31,8 @@ bool ServiceTestClient::OnConnect(const ServiceInfo& remote_info,
ServiceTest::ServiceTest() {}
ServiceTest::ServiceTest(const std::string& test_name)
: test_name_(test_name) {}
ServiceTest::ServiceTest(const std::string& test_name, bool init_edk)
: test_name_(test_name), init_edk_(init_edk) {}
ServiceTest::~ServiceTest() {}
......@@ -62,7 +62,9 @@ void ServiceTest::SetUp() {
message_loop_ = CreateMessageLoop();
background_service_manager_.reset(
new service_manager::BackgroundServiceManager);
background_service_manager_->Init(nullptr);
auto init_params = base::MakeUnique<BackgroundServiceManager::InitParams>();
init_params->init_edk = init_edk_;
background_service_manager_->Init(std::move(init_params));
// Create the service manager connection. We don't proceed until we get our
// Service's OnStart() method is called.
......
......@@ -52,7 +52,7 @@ class ServiceTest : public testing::Test {
// Once set via this constructor, it cannot be changed later by calling
// InitTestName(). The test executable must provide a manifest in the
// appropriate location that specifies this name also.
explicit ServiceTest(const std::string& test_name);
explicit ServiceTest(const std::string& test_name, bool init_edk = true);
~ServiceTest() override;
protected:
......@@ -92,6 +92,7 @@ class ServiceTest : public testing::Test {
// See constructor.
std::string test_name_;
bool init_edk_ = true;
Connector* connector_ = nullptr;
std::string initialize_name_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment