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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/test/nacl/OWNERS ('k') | chrome/test/ppapi/ppapi_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "base/command_line.h"
6 #include "base/json/json_reader.h"
7 #include "base/path_service.h"
8 #include "base/timer.h"
9 #include "chrome/browser/ui/browser_tabstrip.h"
10 #include "chrome/common/chrome_paths.h"
11 #include "chrome/common/chrome_switches.h"
12 #include "chrome/test/base/in_process_browser_test.h"
13 #include "chrome/test/base/ui_test_utils.h"
14 #include "content/public/browser/dom_operation_notification_details.h"
15 #include "content/public/browser/notification_observer.h"
16 #include "content/public/browser/notification_registrar.h"
17 #include "content/public/browser/notification_types.h"
18 #include "content/public/browser/plugin_service.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/web_contents.h"
21 #include "net/base/net_util.h"
22 #include "webkit/plugins/webplugininfo.h"
23
24 namespace {
25
26 // Base class for handling a stream of automation messages produced by a
27 // JavascriptTestObserver.
28 class TestMessageHandler {
29 public:
30 enum MessageResponse {
31 // Reset the timeout and keep running.
32 CONTINUE,
33 // Stop runnning.
34 DONE
35 };
36
37 TestMessageHandler() : ok_(true) {}
38 virtual ~TestMessageHandler() {};
39
40 virtual MessageResponse HandleMessage(const std::string& json) = 0;
41
42 void SetError(const std::string& message) {
43 ok_ = false;
44 error_message_ = message;
45 }
46
47 bool ok() const {
48 return ok_;
49 }
50
51 const std::string& error_message() const {
52 return error_message_;
53 }
54
55 private:
56 bool ok_;
57 std::string error_message_;
58 };
59
60 // A helper base class that decodes structured automation messages of the form:
61 // {"type": type_name, ...}
62 class StructuredMessageHandler : public TestMessageHandler {
63 public:
64 virtual MessageResponse HandleMessage(const std::string& json) OVERRIDE {
65 scoped_ptr<Value> value;
66 base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS);
67 // Automation messages are stringified before they are sent because the
68 // automation channel cannot handle arbitrary objects. This means we
69 // need to decode the json twice to get the original message.
70 value.reset(reader.ReadToValue(json));
71 if (!value.get())
72 return InternalError("Could parse automation JSON: " + json +
73 " because " + reader.GetErrorMessage());
74
75 std::string temp;
76 if (!value->GetAsString(&temp))
77 return InternalError("Message was not a string: " + json);
78
79 value.reset(reader.ReadToValue(temp));
80 if (!value.get())
81 return InternalError("Could not parse message JSON: " + temp +
82 " because " + reader.GetErrorMessage());
83
84 DictionaryValue* msg;
85 if (!value->GetAsDictionary(&msg))
86 return InternalError("Message was not an object: " + temp);
87
88 std::string type;
89 if (!msg->GetString("type", &type))
90 return MissingField("unknown", "type");
91
92 return HandleStructuredMessage(type, msg);
93 }
94
95 virtual MessageResponse HandleStructuredMessage(const std::string& type,
96 DictionaryValue* msg) = 0;
97
98 MessageResponse MissingField(const std::string& type,
99 const std::string& field) WARN_UNUSED_RESULT {
100 return InternalError(type + " message did not have field: " + field);
101 }
102
103 MessageResponse InternalError(const std::string& reason) WARN_UNUSED_RESULT {
104 SetError(reason);
105 return DONE;
106 }
107 };
108
109 // A simple structured message handler for tests that load nexes.
110 class LoadTestMessageHandler : public StructuredMessageHandler {
111 public:
112 LoadTestMessageHandler() : test_passed_(false) {}
113
114 void Log(const std::string& type, const std::string& message) {
115 // TODO(ncbray) better logging.
116 LOG(INFO) << type << " " << message;
117 }
118
119 virtual MessageResponse HandleStructuredMessage(
120 const std::string& type,
121 DictionaryValue* msg) OVERRIDE {
122 if (type == "Log") {
123 std::string message;
124 if (!msg->GetString("message", &message))
125 return MissingField(type, "message");
126 Log("LOG", message);
127 return CONTINUE;
128 } else if (type == "Shutdown") {
129 std::string message;
130 if (!msg->GetString("message", &message))
131 return MissingField(type, "message");
132 if (!msg->GetBoolean("passed", &test_passed_))
133 return MissingField(type, "passed");
134 Log("SHUTDOWN", message);
135 return DONE;
136 } else {
137 return InternalError("Unknown message type: " + type);
138 }
139 }
140
141 bool test_passed() const {
142 return test_passed_;
143 }
144
145 private:
146 bool test_passed_;
147
148 DISALLOW_COPY_AND_ASSIGN(LoadTestMessageHandler);
149 };
150
151 // This class captures a stream of automation messages coming from a Javascript
152 // test and dispatches them to a message handler.
153 // TODO(ncbray) factor out and share with PPAPI tests.
154 class JavascriptTestObserver : public content::NotificationObserver {
155 public:
156 JavascriptTestObserver(
157 content::RenderViewHost* render_view_host,
158 TestMessageHandler* handler)
159 : handler_(handler),
160 running_(false) {
161 registrar_.Add(this, content::NOTIFICATION_DOM_OPERATION_RESPONSE,
162 content::Source<content::RenderViewHost>(render_view_host));
163 }
164
165 // Pump the message loop until the message handler indicates the Javascript
166 // test is done running. Return true if the test jig functioned correctly and
167 // nothing timed out.
168 bool Run() {
169 running_ = true;
170 content::RunMessageLoop();
171 running_ = false;
172 return handler_->ok();
173 }
174
175 virtual void Observe(
176 int type,
177 const content::NotificationSource& source,
178 const content::NotificationDetails& details) OVERRIDE {
179 DCHECK(type == content::NOTIFICATION_DOM_OPERATION_RESPONSE);
180 content::Details<content::DomOperationNotificationDetails> dom_op_details(
181 details);
182 // We might receive responses for other script execution, but we only
183 // care about the test finished message.
184 TestMessageHandler::MessageResponse response =
185 handler_->HandleMessage(dom_op_details->json);
186
187 if (response == TestMessageHandler::DONE) {
188 EndTest();
189 } else {
190 Continue();
191 }
192 }
193
194 private:
195 void Continue() {
196 }
197
198 void EndTest() {
199 if (running_) {
200 MessageLoopForUI::current()->Quit();
201 }
202 }
203
204 TestMessageHandler* handler_;
205 bool running_;
206 content::NotificationRegistrar registrar_;
207
208 DISALLOW_COPY_AND_ASSIGN(JavascriptTestObserver);
209 };
210
211 // NaCl browser tests serve files out of the build directory because nexes and
212 // pexes are artifacts of the build. To keep things tidy, all test data is kept
213 // in a subdirectory. Several variants of a test may be run, for example when
214 // linked against newlib and when linked against glibc. These variants are kept
215 // in different subdirectories. For example, the build directory will look
216 // something like this on Linux:
217 // out/
218 // Release/
219 // nacl_test_data/
220 // newlib/
221 // glibc/
222 bool GetNaClVariantRoot(const FilePath::StringType& variant,
223 FilePath* document_root) {
224 if (!ui_test_utils::GetRelativeBuildDirectory(document_root))
225 return false;
226 *document_root = document_root->Append(FILE_PATH_LITERAL("nacl_test_data"));
227 *document_root = document_root->Append(variant);
228 return true;
229 }
230
231 class NaClBrowserTestBase : public InProcessBrowserTest {
232 public:
233 NaClBrowserTestBase() {}
234
235 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
236 command_line->AppendSwitch(switches::kNoFirstRun);
237 command_line->AppendSwitch(switches::kEnableNaCl);
238 }
239
240 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
241 // Sanity check.
242 FilePath plugin_lib;
243 ASSERT_TRUE(PathService::Get(chrome::FILE_NACL_PLUGIN, &plugin_lib));
244 ASSERT_TRUE(file_util::PathExists(plugin_lib)) << plugin_lib.value();
245
246 ASSERT_TRUE(StartTestServer()) << "Cannot start test server.";
247 }
248
249 virtual FilePath::StringType Variant() = 0;
250
251 GURL TestURL(const FilePath::StringType& test_file) {
252 FilePath real_path = test_server_->document_root().Append(test_file);
253 EXPECT_TRUE(file_util::PathExists(real_path)) << real_path.value();
254
255 FilePath url_path = FilePath(FILE_PATH_LITERAL("files"));
256 url_path = url_path.Append(test_file);
257 return test_server_->GetURL(url_path.MaybeAsASCII());
258 }
259
260 bool RunJavascriptTest(const GURL& url, TestMessageHandler* handler) {
261 JavascriptTestObserver observer(
262 chrome::GetActiveWebContents(browser())->GetRenderViewHost(),
263 handler);
264 ui_test_utils::NavigateToURL(browser(), url);
265 return observer.Run();
266 }
267
268 void RunLoadTest(const FilePath::StringType& test_file) {
269 LoadTestMessageHandler handler;
270 bool ok = RunJavascriptTest(TestURL(test_file), &handler);
271 ASSERT_TRUE(ok) << handler.error_message();
272 ASSERT_TRUE(handler.test_passed()) << "Test failed.";
273 }
274
275 private:
276 bool StartTestServer() {
277 // Launch the web server.
278 FilePath document_root;
279 if (!GetNaClVariantRoot(Variant(), &document_root))
280 return false;
281 test_server_.reset(new net::TestServer(net::TestServer::TYPE_HTTP,
282 net::TestServer::kLocalhost,
283 document_root));
284 return test_server_->Start();
285 }
286
287 scoped_ptr<net::TestServer> test_server_;
288 };
289
290 class NaClBrowserTestNewlib : public NaClBrowserTestBase {
291 virtual FilePath::StringType Variant() {
292 return FILE_PATH_LITERAL("newlib");
293 }
294 };
295
296 class NaClBrowserTestGLibc : public NaClBrowserTestBase {
297 virtual FilePath::StringType Variant() {
298 return FILE_PATH_LITERAL("glibc");
299 }
300 };
301
302 // Disable tests under Linux ASAN.
303 // Linux ASAN doesn't work with NaCl. See: http://crbug.com/104832.
304 // TODO(ncbray) enable after http://codereview.chromium.org/10830009/ lands.
305 #if !(defined(ADDRESS_SANITIZER) && defined(OS_LINUX))
306
307 IN_PROC_BROWSER_TEST_F(NaClBrowserTestNewlib, SimpleLoadTest) {
308 RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
309 }
310
311 IN_PROC_BROWSER_TEST_F(NaClBrowserTestGLibc, SimpleLoadTest) {
312 RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
313 }
314
315 #endif // !(defined(ADDRESS_SANITIZER) && defined(OS_LINUX))
316
317 } // namespace anonymous
OLDNEW
« 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