Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Unified Diff: chrome/test/nacl/nacl_browsertest.cc

Issue 10827357: Add NaCl smoke test to browser_tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: VS2010 fix? Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/test/nacl/OWNERS ('k') | chrome/test/ppapi/ppapi_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/nacl/nacl_browsertest.cc
diff --git a/chrome/test/nacl/nacl_browsertest.cc b/chrome/test/nacl/nacl_browsertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8e5cf3f20f19dfb024e448ce1d0dbaf2786daf43
--- /dev/null
+++ b/chrome/test/nacl/nacl_browsertest.cc
@@ -0,0 +1,317 @@
+// Copyright (c) 2012 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 "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "base/path_service.h"
+#include "base/timer.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/dom_operation_notification_details.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/plugin_service.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "net/base/net_util.h"
+#include "webkit/plugins/webplugininfo.h"
+
+namespace {
+
+// Base class for handling a stream of automation messages produced by a
+// JavascriptTestObserver.
+class TestMessageHandler {
+ public:
+ enum MessageResponse {
+ // Reset the timeout and keep running.
+ CONTINUE,
+ // Stop runnning.
+ DONE
+ };
+
+ TestMessageHandler() : ok_(true) {}
+ virtual ~TestMessageHandler() {};
+
+ virtual MessageResponse HandleMessage(const std::string& json) = 0;
+
+ void SetError(const std::string& message) {
+ ok_ = false;
+ error_message_ = message;
+ }
+
+ bool ok() const {
+ return ok_;
+ }
+
+ const std::string& error_message() const {
+ return error_message_;
+ }
+
+ private:
+ bool ok_;
+ std::string error_message_;
+};
+
+// A helper base class that decodes structured automation messages of the form:
+// {"type": type_name, ...}
+class StructuredMessageHandler : public TestMessageHandler {
+ public:
+ virtual MessageResponse HandleMessage(const std::string& json) OVERRIDE {
+ scoped_ptr<Value> value;
+ base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS);
+ // Automation messages are stringified before they are sent because the
+ // automation channel cannot handle arbitrary objects. This means we
+ // need to decode the json twice to get the original message.
+ value.reset(reader.ReadToValue(json));
+ if (!value.get())
+ return InternalError("Could parse automation JSON: " + json +
+ " because " + reader.GetErrorMessage());
+
+ std::string temp;
+ if (!value->GetAsString(&temp))
+ return InternalError("Message was not a string: " + json);
+
+ value.reset(reader.ReadToValue(temp));
+ if (!value.get())
+ return InternalError("Could not parse message JSON: " + temp +
+ " because " + reader.GetErrorMessage());
+
+ DictionaryValue* msg;
+ if (!value->GetAsDictionary(&msg))
+ return InternalError("Message was not an object: " + temp);
+
+ std::string type;
+ if (!msg->GetString("type", &type))
+ return MissingField("unknown", "type");
+
+ return HandleStructuredMessage(type, msg);
+ }
+
+ virtual MessageResponse HandleStructuredMessage(const std::string& type,
+ DictionaryValue* msg) = 0;
+
+ MessageResponse MissingField(const std::string& type,
+ const std::string& field) WARN_UNUSED_RESULT {
+ return InternalError(type + " message did not have field: " + field);
+ }
+
+ MessageResponse InternalError(const std::string& reason) WARN_UNUSED_RESULT {
+ SetError(reason);
+ return DONE;
+ }
+};
+
+// A simple structured message handler for tests that load nexes.
+class LoadTestMessageHandler : public StructuredMessageHandler {
+ public:
+ LoadTestMessageHandler() : test_passed_(false) {}
+
+ void Log(const std::string& type, const std::string& message) {
+ // TODO(ncbray) better logging.
+ LOG(INFO) << type << " " << message;
+ }
+
+ virtual MessageResponse HandleStructuredMessage(
+ const std::string& type,
+ DictionaryValue* msg) OVERRIDE {
+ if (type == "Log") {
+ std::string message;
+ if (!msg->GetString("message", &message))
+ return MissingField(type, "message");
+ Log("LOG", message);
+ return CONTINUE;
+ } else if (type == "Shutdown") {
+ std::string message;
+ if (!msg->GetString("message", &message))
+ return MissingField(type, "message");
+ if (!msg->GetBoolean("passed", &test_passed_))
+ return MissingField(type, "passed");
+ Log("SHUTDOWN", message);
+ return DONE;
+ } else {
+ return InternalError("Unknown message type: " + type);
+ }
+ }
+
+ bool test_passed() const {
+ return test_passed_;
+ }
+
+ private:
+ bool test_passed_;
+
+ DISALLOW_COPY_AND_ASSIGN(LoadTestMessageHandler);
+};
+
+// This class captures a stream of automation messages coming from a Javascript
+// test and dispatches them to a message handler.
+// TODO(ncbray) factor out and share with PPAPI tests.
+class JavascriptTestObserver : public content::NotificationObserver {
+ public:
+ JavascriptTestObserver(
+ content::RenderViewHost* render_view_host,
+ TestMessageHandler* handler)
+ : handler_(handler),
+ running_(false) {
+ registrar_.Add(this, content::NOTIFICATION_DOM_OPERATION_RESPONSE,
+ content::Source<content::RenderViewHost>(render_view_host));
+ }
+
+ // Pump the message loop until the message handler indicates the Javascript
+ // test is done running. Return true if the test jig functioned correctly and
+ // nothing timed out.
+ bool Run() {
+ running_ = true;
+ content::RunMessageLoop();
+ running_ = false;
+ return handler_->ok();
+ }
+
+ virtual void Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE {
+ DCHECK(type == content::NOTIFICATION_DOM_OPERATION_RESPONSE);
+ content::Details<content::DomOperationNotificationDetails> dom_op_details(
+ details);
+ // We might receive responses for other script execution, but we only
+ // care about the test finished message.
+ TestMessageHandler::MessageResponse response =
+ handler_->HandleMessage(dom_op_details->json);
+
+ if (response == TestMessageHandler::DONE) {
+ EndTest();
+ } else {
+ Continue();
+ }
+ }
+
+ private:
+ void Continue() {
+ }
+
+ void EndTest() {
+ if (running_) {
+ MessageLoopForUI::current()->Quit();
+ }
+ }
+
+ TestMessageHandler* handler_;
+ bool running_;
+ content::NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(JavascriptTestObserver);
+};
+
+// NaCl browser tests serve files out of the build directory because nexes and
+// pexes are artifacts of the build. To keep things tidy, all test data is kept
+// in a subdirectory. Several variants of a test may be run, for example when
+// linked against newlib and when linked against glibc. These variants are kept
+// in different subdirectories. For example, the build directory will look
+// something like this on Linux:
+// out/
+// Release/
+// nacl_test_data/
+// newlib/
+// glibc/
+bool GetNaClVariantRoot(const FilePath::StringType& variant,
+ FilePath* document_root) {
+ if (!ui_test_utils::GetRelativeBuildDirectory(document_root))
+ return false;
+ *document_root = document_root->Append(FILE_PATH_LITERAL("nacl_test_data"));
+ *document_root = document_root->Append(variant);
+ return true;
+}
+
+class NaClBrowserTestBase : public InProcessBrowserTest {
+ public:
+ NaClBrowserTestBase() {}
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ command_line->AppendSwitch(switches::kNoFirstRun);
+ command_line->AppendSwitch(switches::kEnableNaCl);
+ }
+
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ // Sanity check.
+ FilePath plugin_lib;
+ ASSERT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib));
+ ASSERT_TRUE(file_util::PathExists(plugin_lib)) << plugin_lib.value();
+
+ ASSERT_TRUE(StartTestServer()) << "Cannot start test server.";
+ }
+
+ virtual FilePath::StringType Variant() = 0;
+
+ GURL TestURL(const FilePath::StringType& test_file) {
+ FilePath real_path = test_server_->document_root().Append(test_file);
+ EXPECT_TRUE(file_util::PathExists(real_path)) << real_path.value();
+
+ FilePath url_path = FilePath(FILE_PATH_LITERAL("files"));
+ url_path = url_path.Append(test_file);
+ return test_server_->GetURL(url_path.MaybeAsASCII());
+ }
+
+ bool RunJavascriptTest(const GURL& url, TestMessageHandler* handler) {
+ JavascriptTestObserver observer(
+ chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
+ handler);
+ ui_test_utils::NavigateToURL(browser(), url);
+ return observer.Run();
+ }
+
+ void RunLoadTest(const FilePath::StringType& test_file) {
+ LoadTestMessageHandler handler;
+ bool ok = RunJavascriptTest(TestURL(test_file), &handler);
+ ASSERT_TRUE(ok) << handler.error_message();
+ ASSERT_TRUE(handler.test_passed()) << "Test failed.";
+ }
+
+ private:
+ bool StartTestServer() {
+ // Launch the web server.
+ FilePath document_root;
+ if (!GetNaClVariantRoot(Variant(), &document_root))
+ return false;
+ test_server_.reset(new net::TestServer(net::TestServer::TYPE_HTTP,
+ net::TestServer::kLocalhost,
+ document_root));
+ return test_server_->Start();
+ }
+
+ scoped_ptr<net::TestServer> test_server_;
+};
+
+class NaClBrowserTestNewlib : public NaClBrowserTestBase {
+ virtual FilePath::StringType Variant() {
+ return FILE_PATH_LITERAL("newlib");
+ }
+};
+
+class NaClBrowserTestGLibc : public NaClBrowserTestBase {
+ virtual FilePath::StringType Variant() {
+ return FILE_PATH_LITERAL("glibc");
+ }
+};
+
+// Disable tests under Linux ASAN.
+// Linux ASAN doesn't work with NaCl. See: http://crbug.com/104832.
+// TODO(ncbray) enable after http://codereview.chromium.org/10830009/ lands.
+#if !(defined(ADDRESS_SANITIZER) && defined(OS_LINUX))
+
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestNewlib, SimpleLoadTest) {
+ RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestGLibc, SimpleLoadTest) {
+ RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
+}
+
+#endif // !(defined(ADDRESS_SANITIZER) && defined(OS_LINUX))
+
+} // namespace anonymous
« no previous file with comments | « chrome/test/nacl/OWNERS ('k') | chrome/test/ppapi/ppapi_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698