summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscr@chromium.org <scr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-19 17:45:32 +0000
committerscr@chromium.org <scr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-19 17:45:32 +0000
commitab280dcaa18c71368cd6c24797f3e85c1748449c (patch)
tree7236554713b9d26524d8da6d4a4c87b7f72a67bb
parent7fd5a4682071fc1406b8609dafa6473d5a16bebf (diff)
downloadchromium_src-ab280dcaa18c71368cd6c24797f3e85c1748449c.zip
chromium_src-ab280dcaa18c71368cd6c24797f3e85c1748449c.tar.gz
chromium_src-ab280dcaa18c71368cd6c24797f3e85c1748449c.tar.bz2
Support automatic javascript test registry in gtest when creating WebUI tests.
The goal was to support something as simple as the following, where the tests in the javascript files would be 1st class GTESTs, supporting FLAKY_, DISABLED_, etc, and registered at linker_initialization time. WEB_UI_BROWSER_TEST_JS(WebUIBrowserTest, TestJSPass, FILE_PATH_LITERAL("sample_passing.js")) { ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDownloadsURL)); } This solution ended up being fairly fragile, and I ended up with a script to parse javascript (with the help of v8_shell) and generate an includable ...-inl.h file with the following for every test in the .js file specified in the |rules| section of tools/js2webui.py IN_PROC_BROWSER_TEST_F(WebUIBrowserTestPass, testHelper) { AddLibrary(FilePath(FILE_PATH_LITERAL("sample_pass.js"))); ASSERT_TRUE(RunJavascriptTest("testHelper")); } http://www.chromium.org/Home/domui-testing BUG=82437 R=estade@chromium.org,jhawkins@chromium.org TEST=browser_tests --gtest_filter=WebUIBrowserTest* Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=89453 Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=89605 Review URL: http://codereview.chromium.org/7087014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@89626 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--.gitignore1
-rw-r--r--chrome/browser/ui/webui/javascript2webui.js30
-rw-r--r--chrome/browser/ui/webui/web_ui_browsertest.cc48
-rw-r--r--chrome/browser/ui/webui/web_ui_browsertest.h6
-rw-r--r--chrome/chrome_tests.gypi19
-rw-r--r--chrome/test/data/webui/sample_pass.js27
-rw-r--r--tools/js2webui.py90
7 files changed, 185 insertions, 36 deletions
diff --git a/.gitignore b/.gitignore
index 1091306..1175f5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,7 @@ v8.log
/chrome/app/theme/google_chrome
/chrome/browser/autofill/internal
/chrome/browser/extensions/default_extensions/chromeos
+/chrome/browser/ui/webui/web_ui_browsertest-inl.h
/chrome/installer/linux
/chrome/installer/mac/internal
/chrome/installer/mac/third_party/xz/xz
diff --git a/chrome/browser/ui/webui/javascript2webui.js b/chrome/browser/ui/webui/javascript2webui.js
deleted file mode 100644
index b4ad607..0000000
--- a/chrome/browser/ui/webui/javascript2webui.js
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2011 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.
-if (arguments.length < 4) {
- print('usage: ' +
- arguments[0] + ' test_fixture path-to-testfile.js testfile.js');
- quit();
-}
-var test_fixture = arguments[1];
-var js_file = arguments[2];
-var js_file_base = arguments[3];
-var prevfuncs = {};
-for (var func in this) {
- if (this[func] instanceof Function)
- prevfuncs[func] = func;
-}
-var js = load(js_file);
-print('// GENERATED FILE');
-print('// ' + arguments.join(' '));
-print('// PLEASE DO NOT HAND EDIT!');
-print();
-for (var func in this) {
- if (!prevfuncs[func] && this[func] instanceof Function) {
- print('IN_PROC_BROWSER_TEST_F(' + test_fixture + ', ' + func + ') {');
- print(' AddLibrary(FilePath(FILE_PATH_LITERAL("' + js_file_base + '")));');
- print(' ASSERT_TRUE(RunJavascriptTest("' + func + '"));');
- print('}');
- print();
- }
-}
diff --git a/chrome/browser/ui/webui/web_ui_browsertest.cc b/chrome/browser/ui/webui/web_ui_browsertest.cc
index 66815d0..4e8e959 100644
--- a/chrome/browser/ui/webui/web_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/web_ui_browsertest.cc
@@ -11,6 +11,7 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/webui/test_chrome_web_ui_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/ui_test_utils.h"
@@ -21,9 +22,8 @@
namespace {
-const FilePath::StringType kWebUILibraryJS =
- FILE_PATH_LITERAL("test_api.js");
-const FilePath::StringType kWebUITestFolder = FILE_PATH_LITERAL("webui");
+const FilePath::CharType kWebUILibraryJS[] = FILE_PATH_LITERAL("test_api.js");
+const FilePath::CharType kWebUITestFolder[] = FILE_PATH_LITERAL("webui");
base::LazyInstance<std::vector<std::string> > error_messages_(
base::LINKER_INITIALIZED);
@@ -244,3 +244,45 @@ IN_PROC_BROWSER_TEST_F(WebUIBrowserExpectFailTest, TestFailsFast) {
EXPECT_FATAL_FAILURE(RunJavascriptTestNoReturn("FAILS_BogusFunctionName"),
"WebUITestHandler::Observe");
}
+
+
+// This test framework is used in the generated tests, which are included
+// below. WebUIBrowserTest requires being on a page which is a WebUI page. Using
+// the TestChromeWebUIFactory, we use a dummy URL |kChromeTestBrowserTestPass|,
+// which we force to be a WebUI page.
+class WebUIBrowserTestPass
+ : public WebUIBrowserTest,
+ public TestChromeWebUIFactory::WebUIProvider {
+ private:
+ // TestChromeWebUIFactory::WebUIProvider:
+ virtual WebUI* NewWebUI(TabContents* tab_contents,
+ const GURL& url) OVERRIDE {
+ return new WebUI(tab_contents);
+ }
+
+ // InProcessBrowserTest:
+ virtual void SetUpOnMainThread() OVERRIDE {
+ WebUIBrowserTest::SetUpOnMainThread();
+ ui_test_utils::NavigateToURL(browser(),
+ GURL(kChromeTestBrowserTestPass));
+ }
+
+ virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+ WebUIBrowserTest::SetUpInProcessBrowserTestFixture();
+ TestChromeWebUIFactory::AddFactoryOverride(
+ GURL(kChromeTestBrowserTestPass).host(), this);
+ }
+
+ virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
+ WebUIBrowserTest::TearDownInProcessBrowserTestFixture();
+ TestChromeWebUIFactory::RemoveFactoryOverride(
+ GURL(kChromeTestBrowserTestPass).host());
+ }
+
+ static const char kChromeTestBrowserTestPass[];
+};
+
+const char WebUIBrowserTestPass::kChromeTestBrowserTestPass[] =
+ "chrome://WebUIBrowserTestPass";
+
+#include "chrome/browser/ui/webui/web_ui_browsertest-inl.h"
diff --git a/chrome/browser/ui/webui/web_ui_browsertest.h b/chrome/browser/ui/webui/web_ui_browsertest.h
index 001ae7a..a8e9f96 100644
--- a/chrome/browser/ui/webui/web_ui_browsertest.h
+++ b/chrome/browser/ui/webui/web_ui_browsertest.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_H_
-#define CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_H_
+#ifndef CHROME_BROWSER_UI_WEBUI_WEB_UI_BROWSERTEST_H_
+#define CHROME_BROWSER_UI_WEBUI_WEB_UI_BROWSERTEST_H_
#pragma once
#include <string>
@@ -98,4 +98,4 @@ class WebUIBrowserTest : public InProcessBrowserTest {
std::vector<FilePath> user_libraries;
};
-#endif // CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_H_
+#endif // CHROME_BROWSER_UI_WEBUI_WEB_UI_BROWSERTEST_H_
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index cf87f75..bdb5271 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -2292,6 +2292,7 @@
'../third_party/icu/icu.gyp:icui18n',
'../third_party/icu/icu.gyp:icuuc',
'../v8/tools/gyp/v8.gyp:v8',
+ '../v8/tools/gyp/v8.gyp:v8_shell',
'../webkit/webkit.gyp:test_shell_test_support',
# Runtime dependencies
'../third_party/mesa/mesa.gyp:osmesa',
@@ -2556,6 +2557,24 @@
'../content/renderer/render_widget_browsertest.h',
'../content/renderer/v8_value_converter_browsertest.cc',
],
+ 'actions': [
+ {
+ 'action_name': 'js2webui',
+ 'variables': {
+ 'js2webui': '../tools/js2webui.py',
+ },
+ 'inputs': [
+ '<(js2webui)',
+ '<!@(python <(js2webui) -i)',
+ ],
+ 'outputs': [
+ '<!@(python <(js2webui) -o)',
+ ],
+ 'action': [
+ 'python', '<(js2webui)', '-p', '<(PRODUCT_DIR)',
+ ],
+ },
+ ],
'conditions': [
['chromeos==0', {
'sources/': [
diff --git a/chrome/test/data/webui/sample_pass.js b/chrome/test/data/webui/sample_pass.js
new file mode 100644
index 0000000..1b2b22da
--- /dev/null
+++ b/chrome/test/data/webui/sample_pass.js
@@ -0,0 +1,27 @@
+// Copyright (c) 2011 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.
+
+// Sample tests that exercise the test JS library and show how this framework
+// could be used to test the downloads page.
+var helper = {
+ helpFunc: function helpFunc() {
+ assertTrue(true);
+ }
+};
+
+function testAssertFalse() {
+ assertFalse(false);
+}
+
+function testHelper() {
+ helper.helpFunc(false);
+}
+
+function testAssertTrue() {
+ assertTrue(true);
+}
+
+function testAssertEquals() {
+ assertEquals(5, 5, "fives");
+}
diff --git a/tools/js2webui.py b/tools/js2webui.py
new file mode 100644
index 0000000..b076f94
--- /dev/null
+++ b/tools/js2webui.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 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.
+
+"""This script is used by chrome_tests.gypi's js2webui action to maintain the
+argument lists and to generate inlinable tests for webui testing.
+
+Usage:
+ python tools/js2webui.py -p product_dir path/to/javascript2webui.js
+ python tools/js2webui.py -t # print test_harnesses
+ python tools/js2webui.py -i # print inputs
+ python tools/js2webui.py -o # print outputs
+"""
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
+import optparse
+import os
+import subprocess
+import sys
+
+# Please adjust the following to edit or add new javascript webui tests.
+rules = [
+ [
+ 'WebUIBrowserTestPass',
+ 'test/data/webui/sample_pass.js',
+ 'browser/ui/webui/web_ui_browsertest-inl.h',
+ ],
+]
+
+def main ():
+ """Run the program"""
+ # For options -t, -i, & -o, we print the "column" of the |rules|. We keep a
+ # set of indices to print in |print_rule_indices| and print them in sorted
+ # order if non-empty.
+ parser = optparse.OptionParser()
+ parser.set_usage(
+ "%prog [-v][-n] --product_dir PRODUCT_DIR -or- "
+ "%prog [-v][-n] (-i|-t|-o)")
+ parser.add_option('-v', '--verbose', action='store_true')
+ parser.add_option('-n', '--impotent', action='store_true',
+ help="don't execute; just print (as if verbose)")
+ parser.add_option(
+ '-p', '--product_dir',
+ help='for gyp to set the <(PRODUCT_DIR) for running v8_shell')
+ parser.add_option('-t', '--test_fixture', action='store_const', const=0,
+ dest='print_rule_index', help='print test_fixtures')
+ parser.add_option('-i', '--in', action='store_const', const=1,
+ dest='print_rule_index', help='print inputs')
+ parser.add_option('-o', '--out', action='store_const', const=2,
+ dest='print_rule_index', help='print outputs')
+ (opts, args) = parser.parse_args()
+
+ if (opts.print_rule_index != None):
+ for rule in rules:
+ print rule[opts.print_rule_index]
+ else:
+ if not opts.product_dir:
+ parser.error("--product_dir option is required")
+ v8_shell = os.path.join(opts.product_dir, 'v8_shell')
+ for (test_fixture, input_js, output_cc) in rules:
+ cmd = [v8_shell, '--print_json_ast', input_js]
+ if opts.verbose or opts.impotent:
+ print cmd
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+ ast = json.load(proc.stdout)
+ if not opts.impotent:
+ sys.stdout = open(output_cc, 'w')
+ print '// GENERATED FILE'
+ print '// ', ' '.join(sys.argv)
+ print '// PLEASE DO NOT HAND EDIT!\n'
+ for declaration in ast[2:]:
+ try:
+ function_literal = declaration[3]
+ function_name = function_literal[1]['name']
+ print 'IN_PROC_BROWSER_TEST_F(%s, %s) {' % (
+ test_fixture, function_name)
+ print ' AddLibrary(FilePath(FILE_PATH_LITERAL("%s")));' % (
+ os.path.basename(input_js))
+ print ' ASSERT_TRUE(RunJavascriptTest("%s"));' % (function_name)
+ print '}\n'
+ except IndexError:
+ if opts.verbose or opts.impotent:
+ print "skipping declaration ", declaration
+
+if __name__ == '__main__':
+ sys.exit(main())