Make it possible to run a test in sky_shell

This CL makes it possible to run sky/tests/raw/bogus_import.dart in sky_shell
on Linux. We'd eventually like to scale this up to running all the tests.

R=eseidel@chromium.org

Review URL: https://codereview.chromium.org/1218633003.
This commit is contained in:
Adam Barth 2015-06-29 10:39:44 -07:00
parent 53e64fc92f
commit f442a035b8
6 changed files with 232 additions and 29 deletions

View File

@ -181,9 +181,14 @@ if (is_android) {
"linux/main.cc",
"linux/platform_service_provider_linux.cc",
"linux/platform_view_linux.cc",
"testing/test_runner.cc",
"testing/test_runner.h",
]
deps = common_deps + [ ":common" ]
deps = common_deps + [
":common",
"//sky/services/testing",
]
}
} else {
assert(false, "Unsupported platform")

View File

@ -16,6 +16,7 @@
#include "sky/shell/shell.h"
#include "sky/shell/shell_view.h"
#include "sky/shell/switches.h"
#include "sky/shell/testing/test_runner.h"
namespace sky {
namespace shell {
@ -23,39 +24,26 @@ namespace {
void Usage() {
std::cerr << "Usage: sky_shell"
<< " [MAIN_DART --" << switches::kPackageRoot << "=PACKAGE_ROOT]"
<< " [--" << switches::kSnapshot << "=SNAPSHOT]" << std::endl;
<< " --" << switches::kPackageRoot << "=PACKAGE_ROOT"
<< " [ MAIN_DART ]" << std::endl;
}
void Init() {
Shell::Init(make_scoped_ptr(new ServiceProviderContext(
base::MessageLoop::current()->task_runner())));
// TODO(abarth): Currently we leak the ShellView.
ShellView* shell_view = new ShellView(Shell::Shared());
ViewportObserverPtr viewport_observer;
shell_view->view()->ConnectToViewportObserver(GetProxy(&viewport_observer));
base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kSnapshot)) {
std::string snapshot =
command_line.GetSwitchValueASCII(switches::kSnapshot);
viewport_observer->RunFromSnapshot(snapshot);
return;
}
std::string package_root =
command_line.GetSwitchValueASCII(switches::kPackageRoot);
if (command_line.HasSwitch(switches::kPackageRoot)) {
std::string main = command_line.GetArgs()[0];
std::string package_root =
command_line.GetSwitchValueASCII(switches::kPackageRoot);
viewport_observer->RunFromFile(main, package_root);
return;
}
std::string main;
auto args = command_line.GetArgs();
if (!args.empty())
main = args[0];
std::cerr << "One of --" << switches::kPackageRoot << " or --"
<< switches::kSnapshot << " is required." << std::endl;
TestRunner::Shared().set_package_root(package_root);
TestRunner::Shared().Start(main);
}
} // namespace
@ -68,7 +56,8 @@ int main(int argc, const char* argv[]) {
base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(sky::shell::switches::kHelp)) {
if (command_line.HasSwitch(sky::shell::switches::kHelp) ||
!command_line.HasSwitch(sky::shell::switches::kPackageRoot)) {
sky::shell::Usage();
return 0;
}

View File

@ -3,17 +3,36 @@
// found in the LICENSE file.
#include "base/bind.h"
#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "mojo/public/cpp/application/service_provider_impl.h"
#include "sky/shell/service_provider.h"
#include "sky/shell/testing/test_runner.h"
namespace sky {
namespace shell {
namespace {
base::LazyInstance<scoped_ptr<mojo::ServiceProviderImpl>> g_service_provider =
LAZY_INSTANCE_INITIALIZER;
static void CreateServiceProviderImpl(
mojo::InterfaceRequest<mojo::ServiceProvider> request) {
g_service_provider.Get().reset(new mojo::ServiceProviderImpl(request.Pass()));
g_service_provider.Get()->AddService(&TestRunner::Shared());
}
} // namespace
mojo::ServiceProviderPtr CreateServiceProvider(
ServiceProviderContext* context) {
DCHECK(context);
mojo::MessagePipe pipe;
// TODO(abarth): Wire pipe.handle1 up to something.
auto request = mojo::MakeRequest<mojo::ServiceProvider>(pipe.handle1.Pass());
context->platform_task_runner->PostTask(
FROM_HERE, base::Bind(CreateServiceProviderImpl, base::Passed(&request)));
return mojo::MakeProxy(
mojo::InterfacePtrInfo<mojo::ServiceProvider>(pipe.handle0.Pass(), 0u));
}

View File

@ -0,0 +1,128 @@
// Copyright 2014 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 "sky/shell/testing/test_runner.h"
#include <iostream>
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "sky/shell/platform_view.h"
#include "sky/shell/shell.h"
#include "sky/shell/shell_view.h"
namespace sky {
namespace shell {
namespace {
struct UrlData {
std::string url;
std::string expected_pixel_hash;
bool enable_pixel_dumping = false;
};
void WaitForURL(UrlData& data) {
// A test name is formated like file:///path/to/test'--pixel-test'pixelhash
std::cin >> data.url;
std::string pixel_switch;
std::string::size_type separator_position = data.url.find('\'');
if (separator_position != std::string::npos) {
pixel_switch = data.url.substr(separator_position + 1);
data.url.erase(separator_position);
}
std::string pixel_hash;
separator_position = pixel_switch.find('\'');
if (separator_position != std::string::npos) {
pixel_hash = pixel_switch.substr(separator_position + 1);
pixel_switch.erase(separator_position);
}
data.enable_pixel_dumping = pixel_switch == "--pixel-test";
data.expected_pixel_hash = pixel_hash;
}
void PrintAndFlush(const std::string& value) {
std::cout << value;
std::cout.flush();
}
const char kFileUrlPrefix[] = "file://";
static TestRunner* g_test_runner = nullptr;
} // namespace
TestRunner::TestRunner()
: shell_view_(new ShellView(Shell::Shared())),
weak_ptr_factory_(this) {
CHECK(!g_test_runner) << "Only create one TestRunner.";
shell_view_->view()->ConnectToViewportObserver(GetProxy(&viewport_observer_));
viewport_observer_->OnViewportMetricsChanged(320, 640, 1.0);
}
TestRunner::~TestRunner() {
}
TestRunner& TestRunner::Shared() {
if (!g_test_runner)
g_test_runner = new TestRunner();
return *g_test_runner;
}
void TestRunner::Start(const std::string& single_test_url) {
single_test_url_ = single_test_url;
PrintAndFlush("#READY\n");
ScheduleRun();
}
void TestRunner::OnTestComplete(const mojo::String& test_result,
const mojo::Array<uint8_t> pixels) {
std::cout << "Content-Type: text/plain\n";
std::cout << test_result << "\n";
PrintAndFlush("#EOF\n"); // Text result complete
PrintAndFlush("#EOF\n"); // Pixel result complete
std::cerr << "#EOF\n";
std::cerr.flush();
bindings_.CloseAllBindings();
if (single_test_url_.length())
exit(0);
ScheduleRun();
}
void TestRunner::DispatchInputEvent(mojo::EventPtr event) {
// TODO(abarth): Not implemented.
}
void TestRunner::Create(mojo::ApplicationConnection* app,
mojo::InterfaceRequest<TestHarness> request) {
bindings_.AddBinding(this, request.Pass());
}
void TestRunner::ScheduleRun() {
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(&TestRunner::Run, weak_ptr_factory_.GetWeakPtr()));
}
void TestRunner::Run() {
UrlData data;
if (single_test_url_.length()) {
data.url = single_test_url_;
} else {
WaitForURL(data);
}
std::cout << "#BEGIN\n";
std::cout.flush();
if (StartsWithASCII(data.url, kFileUrlPrefix, true))
ReplaceFirstSubstringAfterOffset(&data.url, 0, kFileUrlPrefix, "");
viewport_observer_->RunFromFile(data.url, package_root_);
}
} // namespace shell
} // namespace sky

View File

@ -0,0 +1,62 @@
// Copyright 2015 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.
#ifndef SKY_SHELL_TESTING_TEST_RUNNER_H_
#define SKY_SHELL_TESTING_TEST_RUNNER_H_
#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/common/weak_binding_set.h"
#include "mojo/public/cpp/application/interface_factory_impl.h"
#include "sky/services/testing/test_harness.mojom.h"
#include "sky/services/viewport/viewport_observer.mojom.h"
namespace sky {
namespace shell {
class ShellView;
class TestRunner : public mojo::InterfaceFactory<TestHarness>,
public TestHarness {
public:
static TestRunner& Shared();
void set_package_root(const std::string& package_root) {
package_root_ = package_root;
}
void Start(const std::string& single_test_url);
private:
// mojo::InterfaceFactory<TestHarness> implementation:
void Create(mojo::ApplicationConnection* app,
mojo::InterfaceRequest<TestHarness> request) override;
// TestHarness implementation:
void OnTestComplete(const mojo::String& test_result,
const mojo::Array<uint8_t> pixels) override;
void DispatchInputEvent(mojo::EventPtr event) override;
TestRunner();
~TestRunner() override;
void ScheduleRun();
void Run();
std::string package_root_;
scoped_ptr<ShellView> shell_view_;
ViewportObserverPtr viewport_observer_;
std::string single_test_url_;
mojo::WeakBindingSet<TestHarness> bindings_;
base::WeakPtrFactory<TestRunner> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(TestRunner);
};
} // namespace shell
} // namespace sky
#endif // SKY_SHELL_TESTING_TEST_RUNNER_H_

View File

@ -26,6 +26,6 @@ mojo_native_application("tester") {
"//mojo/services/input_events/public/interfaces",
"//mojo/services/view_manager/public/cpp",
"//services/window_manager:lib",
"//sky/services/testing:bindings",
"//sky/services/testing",
]
}