Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / test / nacl / nacl_browsertest_util.cc
blob3ecb690e555626d684c5911f53e78a9037b94595
1 // Copyright (c) 2012 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 "chrome/test/nacl/nacl_browsertest_util.h"
7 #include <stdlib.h>
8 #include "base/command_line.h"
9 #include "base/json/json_reader.h"
10 #include "base/path_service.h"
11 #include "base/values.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/common/chrome_paths.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "components/nacl/common/nacl_switches.h"
18 #include "content/public/browser/plugin_service.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/webplugininfo.h"
21 #include "net/base/net_util.h"
23 typedef content::TestMessageHandler::MessageResponse MessageResponse;
25 MessageResponse StructuredMessageHandler::HandleMessage(
26 const std::string& json) {
27 base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS);
28 // Automation messages are stringified before they are sent because the
29 // automation channel cannot handle arbitrary objects. This means we
30 // need to decode the json twice to get the original message.
31 scoped_ptr<base::Value> value = reader.ReadToValue(json);
32 if (!value.get())
33 return InternalError("Could parse automation JSON: " + json +
34 " because " + reader.GetErrorMessage());
36 std::string temp;
37 if (!value->GetAsString(&temp))
38 return InternalError("Message was not a string: " + json);
40 value = reader.ReadToValue(temp);
41 if (!value.get())
42 return InternalError("Could not parse message JSON: " + temp +
43 " because " + reader.GetErrorMessage());
45 base::DictionaryValue* msg;
46 if (!value->GetAsDictionary(&msg))
47 return InternalError("Message was not an object: " + temp);
49 std::string type;
50 if (!msg->GetString("type", &type))
51 return MissingField("unknown", "type");
53 return HandleStructuredMessage(type, msg);
56 MessageResponse StructuredMessageHandler::MissingField(
57 const std::string& type,
58 const std::string& field) {
59 return InternalError(type + " message did not have field: " + field);
62 MessageResponse StructuredMessageHandler::InternalError(
63 const std::string& reason) {
64 SetError(reason);
65 return DONE;
68 LoadTestMessageHandler::LoadTestMessageHandler()
69 : test_passed_(false) {
72 void LoadTestMessageHandler::Log(const std::string& type,
73 const std::string& message) {
74 // TODO(ncbray) better logging.
75 LOG(INFO) << type << " " << message;
78 MessageResponse LoadTestMessageHandler::HandleStructuredMessage(
79 const std::string& type,
80 base::DictionaryValue* msg) {
81 if (type == "Log") {
82 std::string message;
83 if (!msg->GetString("message", &message))
84 return MissingField(type, "message");
85 Log("LOG", message);
86 return CONTINUE;
87 } else if (type == "Shutdown") {
88 std::string message;
89 if (!msg->GetString("message", &message))
90 return MissingField(type, "message");
91 if (!msg->GetBoolean("passed", &test_passed_))
92 return MissingField(type, "passed");
93 Log("SHUTDOWN", message);
94 return DONE;
95 } else {
96 return InternalError("Unknown message type: " + type);
100 // A message handler for nacl_integration tests ported to be browser_tests.
101 // nacl_integration tests report to their test jig using a series of RPC calls
102 // that are encoded as URL requests. When these tests run as browser_tests,
103 // they make the same RPC requests, but use the automation channel instead of
104 // URL requests. This message handler decodes and responds to these requests.
105 class NaClIntegrationMessageHandler : public StructuredMessageHandler {
106 public:
107 NaClIntegrationMessageHandler();
109 void Log(const std::string& message);
111 MessageResponse HandleStructuredMessage(const std::string& type,
112 base::DictionaryValue* msg) override;
114 bool test_passed() const {
115 return test_passed_;
118 private:
119 bool test_passed_;
121 DISALLOW_COPY_AND_ASSIGN(NaClIntegrationMessageHandler);
124 NaClIntegrationMessageHandler::NaClIntegrationMessageHandler()
125 : test_passed_(false) {
128 void NaClIntegrationMessageHandler::Log(const std::string& message) {
129 // TODO(ncbray) better logging.
130 LOG(INFO) << "|||| " << message;
133 MessageResponse NaClIntegrationMessageHandler::HandleStructuredMessage(
134 const std::string& type,
135 base::DictionaryValue* msg) {
136 if (type == "TestLog") {
137 std::string message;
138 if (!msg->GetString("message", &message))
139 return MissingField(type, "message");
140 Log(message);
141 return CONTINUE;
142 } else if (type == "Shutdown") {
143 std::string message;
144 if (!msg->GetString("message", &message))
145 return MissingField(type, "message");
146 if (!msg->GetBoolean("passed", &test_passed_))
147 return MissingField(type, "passed");
148 Log(message);
149 return DONE;
150 } else if (type == "Ping") {
151 return CONTINUE;
152 } else if (type == "JavaScriptIsAlive") {
153 return CONTINUE;
154 } else {
155 return InternalError("Unknown message type: " + type);
159 // NaCl browser tests serve files out of the build directory because nexes and
160 // pexes are artifacts of the build. To keep things tidy, all test data is kept
161 // in a subdirectory. Several variants of a test may be run, for example when
162 // linked against newlib and when linked against glibc. These variants are kept
163 // in different subdirectories. For example, the build directory will look
164 // something like this on Linux:
165 // out/
166 // Release/
167 // nacl_test_data/
168 // newlib/
169 // glibc/
170 // pnacl/
171 static bool GetNaClVariantRoot(const base::FilePath::StringType& variant,
172 base::FilePath* document_root) {
173 if (!ui_test_utils::GetRelativeBuildDirectory(document_root))
174 return false;
175 *document_root = document_root->Append(FILE_PATH_LITERAL("nacl_test_data"));
176 *document_root = document_root->Append(variant);
177 return true;
180 static void AddPnaclParm(const base::FilePath::StringType& url,
181 base::FilePath::StringType* url_with_parm) {
182 if (url.find(FILE_PATH_LITERAL("?")) == base::FilePath::StringType::npos) {
183 *url_with_parm = url + FILE_PATH_LITERAL("?pnacl=1");
184 } else {
185 *url_with_parm = url + FILE_PATH_LITERAL("&pnacl=1");
189 NaClBrowserTestBase::NaClBrowserTestBase() {
192 NaClBrowserTestBase::~NaClBrowserTestBase() {
195 void NaClBrowserTestBase::SetUpCommandLine(base::CommandLine* command_line) {
196 command_line->AppendSwitch(switches::kEnableNaCl);
199 void NaClBrowserTestBase::SetUpOnMainThread() {
200 ASSERT_TRUE(StartTestServer()) << "Cannot start test server.";
203 bool NaClBrowserTestBase::GetDocumentRoot(base::FilePath* document_root) {
204 return GetNaClVariantRoot(Variant(), document_root);
207 bool NaClBrowserTestBase::IsAPnaclTest() {
208 return false;
211 GURL NaClBrowserTestBase::TestURL(
212 const base::FilePath::StringType& url_fragment) {
213 base::FilePath expanded_url = base::FilePath(FILE_PATH_LITERAL("files"));
214 expanded_url = expanded_url.Append(url_fragment);
215 return test_server_->GetURL(expanded_url.MaybeAsASCII());
218 bool NaClBrowserTestBase::RunJavascriptTest(
219 const GURL& url,
220 content::TestMessageHandler* handler) {
221 content::JavascriptTestObserver observer(
222 browser()->tab_strip_model()->GetActiveWebContents(),
223 handler);
224 ui_test_utils::NavigateToURL(browser(), url);
225 return observer.Run();
228 void NaClBrowserTestBase::RunLoadTest(
229 const base::FilePath::StringType& test_file) {
230 LoadTestMessageHandler handler;
231 base::FilePath::StringType test_file_with_pnacl = test_file;
232 if (IsAPnaclTest()) {
233 AddPnaclParm(test_file, &test_file_with_pnacl);
235 base::FilePath::StringType test_file_with_both = test_file_with_pnacl;
236 bool ok = RunJavascriptTest(TestURL(test_file_with_both), &handler);
237 ASSERT_TRUE(ok) << handler.error_message();
238 ASSERT_TRUE(handler.test_passed()) << "Test failed.";
241 void NaClBrowserTestBase::RunNaClIntegrationTest(
242 const base::FilePath::StringType& url_fragment, bool full_url) {
243 NaClIntegrationMessageHandler handler;
244 base::FilePath::StringType url_fragment_with_pnacl = url_fragment;
245 if (IsAPnaclTest()) {
246 AddPnaclParm(url_fragment, &url_fragment_with_pnacl);
248 base::FilePath::StringType url_fragment_with_both = url_fragment_with_pnacl;
249 bool ok = RunJavascriptTest(full_url
250 ? GURL(url_fragment_with_both)
251 : TestURL(url_fragment_with_both),
252 &handler);
253 ASSERT_TRUE(ok) << handler.error_message();
254 ASSERT_TRUE(handler.test_passed()) << "Test failed.";
257 bool NaClBrowserTestBase::StartTestServer() {
258 // Launch the web server.
259 base::FilePath document_root;
260 if (!GetDocumentRoot(&document_root))
261 return false;
262 test_server_.reset(new net::SpawnedTestServer(
263 net::SpawnedTestServer::TYPE_HTTP,
264 net::SpawnedTestServer::kLocalhost,
265 document_root));
266 return test_server_->Start();
269 base::FilePath::StringType NaClBrowserTestNewlib::Variant() {
270 return FILE_PATH_LITERAL("newlib");
273 base::FilePath::StringType NaClBrowserTestGLibc::Variant() {
274 return FILE_PATH_LITERAL("glibc");
277 base::FilePath::StringType NaClBrowserTestPnacl::Variant() {
278 return FILE_PATH_LITERAL("pnacl");
281 bool NaClBrowserTestPnacl::IsAPnaclTest() {
282 return true;
285 void NaClBrowserTestPnaclSubzero::SetUpCommandLine(
286 base::CommandLine* command_line) {
287 NaClBrowserTestPnacl::SetUpCommandLine(command_line);
288 command_line->AppendSwitch(switches::kEnablePNaClSubzero);
291 base::FilePath::StringType NaClBrowserTestNonSfiMode::Variant() {
292 return FILE_PATH_LITERAL("libc-free");
295 void NaClBrowserTestNonSfiMode::SetUpCommandLine(
296 base::CommandLine* command_line) {
297 NaClBrowserTestBase::SetUpCommandLine(command_line);
298 command_line->AppendSwitch(switches::kEnableNaClNonSfiMode);
301 void NaClBrowserTestTransitionalNonSfi::SetUpCommandLine(
302 base::CommandLine* command_line) {
303 NaClBrowserTestNonSfiMode::SetUpCommandLine(command_line);
304 command_line->AppendSwitchASCII(switches::kUseNaClHelperNonSfi, "false");
307 base::FilePath::StringType NaClBrowserTestStatic::Variant() {
308 return FILE_PATH_LITERAL("static");
311 bool NaClBrowserTestStatic::GetDocumentRoot(base::FilePath* document_root) {
312 *document_root = base::FilePath(FILE_PATH_LITERAL("chrome/test/data/nacl"));
313 return true;
316 base::FilePath::StringType NaClBrowserTestPnaclNonSfi::Variant() {
317 return FILE_PATH_LITERAL("nonsfi");
320 void NaClBrowserTestPnaclNonSfi::SetUpCommandLine(
321 base::CommandLine* command_line) {
322 NaClBrowserTestBase::SetUpCommandLine(command_line);
323 command_line->AppendSwitch(switches::kEnableNaClNonSfiMode);
326 void NaClBrowserTestPnaclTransitionalNonSfi::SetUpCommandLine(
327 base::CommandLine* command_line) {
328 NaClBrowserTestPnaclNonSfi::SetUpCommandLine(command_line);
329 command_line->AppendSwitch(switches::kUseNaClHelperNonSfi);
332 void NaClBrowserTestNewlibExtension::SetUpCommandLine(
333 base::CommandLine* command_line) {
334 NaClBrowserTestBase::SetUpCommandLine(command_line);
335 base::FilePath src_root;
336 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &src_root));
338 // Extension-based tests should specialize the GetDocumentRoot() / Variant()
339 // to point at the isolated the test extension directory.
340 // Otherwise, multiple NaCl extensions tests will end up sharing the
341 // same directory when loading the extension files.
342 base::FilePath document_root;
343 ASSERT_TRUE(GetDocumentRoot(&document_root));
345 // Document root is relative to source root, and source root may not be CWD.
346 command_line->AppendSwitchPath(switches::kLoadExtension,
347 src_root.Append(document_root));
350 void NaClBrowserTestGLibcExtension::SetUpCommandLine(
351 base::CommandLine* command_line) {
352 NaClBrowserTestBase::SetUpCommandLine(command_line);
353 base::FilePath src_root;
354 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &src_root));
356 // Extension-based tests should specialize the GetDocumentRoot() / Variant()
357 // to point at the isolated the test extension directory.
358 // Otherwise, multiple NaCl extensions tests will end up sharing the
359 // same directory when loading the extension files.
360 base::FilePath document_root;
361 ASSERT_TRUE(GetDocumentRoot(&document_root));
363 // Document root is relative to source root, and source root may not be CWD.
364 command_line->AppendSwitchPath(switches::kLoadExtension,
365 src_root.Append(document_root));