summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorerikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-17 20:57:14 +0000
committererikkay@chromium.org <erikkay@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-17 20:57:14 +0000
commit25fd1b2ecec6dbbdf281e954b991644f155e9a35 (patch)
treed5d368234e4fbf7494512f70478c162c4de9c987 /chrome
parent4154786bb3f8655d0a9cb6dee37df90ff735c8e7 (diff)
downloadchromium_src-25fd1b2ecec6dbbdf281e954b991644f155e9a35.zip
chromium_src-25fd1b2ecec6dbbdf281e954b991644f155e9a35.tar.gz
chromium_src-25fd1b2ecec6dbbdf281e954b991644f155e9a35.tar.bz2
An initial pass at structure to do end-to-end extension API tests. I'll work on actually fleshing out some tests in the next CL.
Review URL: http://codereview.chromium.org/171032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23577 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/extension_apitest.cc74
-rw-r--r--chrome/browser/extensions/extension_apitest.h47
-rw-r--r--chrome/browser/extensions/extension_bookmarks_apitest.cc10
-rw-r--r--chrome/browser/extensions/extension_browsertest.h8
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc15
-rw-r--r--chrome/browser/extensions/extension_test_api.cc29
-rw-r--r--chrome/browser/extensions/extension_test_api.h24
-rw-r--r--chrome/chrome.gyp9
-rw-r--r--chrome/common/common_resources.grd2
-rwxr-xr-xchrome/common/extensions/api/extension_api.json21
-rw-r--r--chrome/common/notification_type.h5
-rw-r--r--chrome/test/data/extensions/api_test/bookmarks/manifest.json7
-rw-r--r--chrome/test/data/extensions/api_test/bookmarks/test.html1
-rwxr-xr-xchrome/test/data/extensions/api_test/bookmarks/test.js76
14 files changed, 319 insertions, 9 deletions
diff --git a/chrome/browser/extensions/extension_apitest.cc b/chrome/browser/extensions/extension_apitest.cc
new file mode 100644
index 0000000..3c45524
--- /dev/null
+++ b/chrome/browser/extensions/extension_apitest.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2009 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 "chrome/browser/extensions/extension_apitest.h"
+
+#include "chrome/browser/browser.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/test/ui_test_utils.h"
+
+namespace {
+static const int kTimeoutMs = 60 * 1000; // 1 minute
+};
+
+// Load an extension and wait for it to notify of PASSED or FAILED.
+bool ExtensionApiTest::RunExtensionTest(const char* extension_name) {
+ bool result;
+ completed_ = false;
+ {
+ NotificationRegistrar registrar;
+ registrar.Add(this, NotificationType::EXTENSION_TEST_PASSED,
+ NotificationService::AllSources());
+ registrar.Add(this, NotificationType::EXTENSION_TEST_FAILED,
+ NotificationService::AllSources());
+ result = LoadExtension(test_data_dir_.AppendASCII(extension_name));
+
+ // If the test runs quickly, we may get the notification while waiting
+ // for the Load to finish.
+ if (completed_) {
+ result = passed_;
+ } else {
+ result = WaitForPassFail();
+ }
+ }
+ return result;
+}
+
+bool ExtensionApiTest::WaitForPassFail() {
+ completed_ = false;
+ passed_ = false;
+ MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, new MessageLoop::QuitTask, kTimeoutMs);
+ ui_test_utils::RunMessageLoop();
+ return passed_;
+}
+
+void ExtensionApiTest::SetUpCommandLine(CommandLine* command_line) {
+ ExtensionBrowserTest::SetUpCommandLine(command_line);
+ test_data_dir_ = test_data_dir_.AppendASCII("api_test");
+}
+
+void ExtensionApiTest::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::EXTENSION_TEST_PASSED:
+ std::cout << "Got EXTENSION_TEST_PASSED notification.\n";
+ completed_ = true;
+ passed_ = true;
+ MessageLoopForUI::current()->Quit();
+ break;
+
+ case NotificationType::EXTENSION_TEST_FAILED:
+ std::cout << "Got EXTENSION_TEST_FAILED notification.\n";
+ completed_ = true;
+ passed_ = false;
+ message_ = *(Details<std::string>(details).ptr());
+ MessageLoopForUI::current()->Quit();
+ break;
+
+ default:
+ ExtensionBrowserTest::Observe(type, source, details);
+ }
+}
diff --git a/chrome/browser/extensions/extension_apitest.h b/chrome/browser/extensions/extension_apitest.h
new file mode 100644
index 0000000..9e1885b
--- /dev/null
+++ b/chrome/browser/extensions/extension_apitest.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2009 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 CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_
+
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/common/notification_service.h"
+
+// The general flow of these API tests should work like this:
+// (1) Setup initial browser state (e.g. create some bookmarks for the
+// bookmark test)
+// (2) Call ASSERT_TRUE(RunExtensionTest(name));
+// (3) In your extension code, run your test and call chrome.test.pass or
+// chrome.test.fail
+// (4) Verify expected browser state.
+// TODO(erikkay): There should also be a way to drive events in these tests.
+
+class ExtensionApiTest : public ExtensionBrowserTest {
+ protected:
+ // Load |extension_name| and wait for pass / fail notification.
+ // |extension_name| is a directory in "test/data/extensions/api_test".
+ bool RunExtensionTest(const char* extension_name);
+
+ // Reset |completed_| and wait for a new pass / fail notification.
+ bool WaitForPassFail();
+
+ // All extensions tested by ExtensionApiTest are in the "api_test" dir.
+ virtual void SetUpCommandLine(CommandLine* command_line);
+
+ // NotificationObserver
+ void ExtensionApiTest::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Did the extension side of the unit test complete?
+ bool completed_;
+
+ // Did the extension side of the unit test pass?
+ bool passed_;
+
+ // If it failed, what was the error message?
+ std::string message_;
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_APITEST_H_
diff --git a/chrome/browser/extensions/extension_bookmarks_apitest.cc b/chrome/browser/extensions/extension_bookmarks_apitest.cc
new file mode 100644
index 0000000..ba24900
--- /dev/null
+++ b/chrome/browser/extensions/extension_bookmarks_apitest.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2009 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 "chrome/browser/extensions/extension_apitest.h"
+
+IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Bookmarks) {
+ // TODO(erikkay) no initial state for this test.
+ ASSERT_TRUE(RunExtensionTest("bookmarks")) << message_;
+}
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index 7ef797c..98fb948 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -32,14 +32,16 @@ class ExtensionBrowserTest
// Wait for the number of visible page actions to change to |count|.
bool WaitForPageActionVisibilityChangeTo(int count);
+ // NotificationObserver
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
bool loaded_;
bool installed_;
FilePath test_data_dir_;
private:
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
bool WaitForExtensionHostsToLoad();
};
diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc
index e2fa753..5a3bb34 100644
--- a/chrome/browser/extensions/extension_function_dispatcher.cc
+++ b/chrome/browser/extensions/extension_function_dispatcher.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/extensions/extension_process_manager.h"
#include "chrome/browser/extensions/extension_tabs_module.h"
#include "chrome/browser/extensions/extension_tabs_module_constants.h"
+#include "chrome/browser/extensions/extension_test_api.h"
#include "chrome/browser/extensions/extension_toolstrip_api.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
@@ -67,9 +68,10 @@ FactoryRegistry* FactoryRegistry::instance() {
void FactoryRegistry::ResetFunctions() {
// Register all functions here.
- namespace tabs = extension_tabs_module_constants;
- namespace page_actions = extension_page_actions_module_constants;
namespace bookmarks = extension_bookmarks_module_constants;
+ namespace page_actions = extension_page_actions_module_constants;
+ namespace tabs = extension_tabs_module_constants;
+ namespace test = extension_test_api_functions;
namespace toolstrip = extension_toolstrip_api_functions;
// Windows
@@ -139,6 +141,12 @@ void FactoryRegistry::ResetFunctions() {
&NewExtensionFunction<ToolstripExpandFunction>;
factories_[toolstrip::kCollapseFunction] =
&NewExtensionFunction<ToolstripCollapseFunction>;
+
+ // Test.
+ factories_[test::kPassFunction] =
+ &NewExtensionFunction<ExtensionTestPassFunction>;
+ factories_[test::kFailFunction] =
+ &NewExtensionFunction<ExtensionTestFailFunction>;
}
void FactoryRegistry::GetAllNames(std::vector<std::string>* names) {
@@ -253,7 +261,8 @@ void ExtensionFunctionDispatcher::SendResponse(ExtensionFunction* function,
}
void ExtensionFunctionDispatcher::HandleBadMessage(ExtensionFunction* api) {
- LOG(ERROR) << "bad extension message " << // TODO(erikkay) name?
+ LOG(ERROR) << "bad extension message " <<
+ api->name() <<
" : terminating renderer.";
if (RenderProcessHost::run_renderer_in_process()) {
// In single process mode it is better if we don't suicide but just crash.
diff --git a/chrome/browser/extensions/extension_test_api.cc b/chrome/browser/extensions/extension_test_api.cc
new file mode 100644
index 0000000..a381286
--- /dev/null
+++ b/chrome/browser/extensions/extension_test_api.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2009 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 "chrome/browser/extensions/extension_test_api.h"
+#include "chrome/common/notification_service.h"
+
+namespace extension_test_api_functions {
+const char kPassFunction[] = "test.pass";
+const char kFailFunction[] = "test.fail";
+}; // namespace extension_test_api_functions
+
+bool ExtensionTestPassFunction::RunImpl() {
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_TEST_PASSED,
+ Source<Profile>(dispatcher()->profile()),
+ NotificationService::NoDetails());
+ return true;
+}
+
+bool ExtensionTestFailFunction::RunImpl() {
+ std::string message;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetAsString(&message));
+ NotificationService::current()->Notify(
+ NotificationType::EXTENSION_TEST_FAILED,
+ Source<Profile>(dispatcher()->profile()),
+ Details<std::string>(&message));
+ return true;
+}
diff --git a/chrome/browser/extensions/extension_test_api.h b/chrome/browser/extensions/extension_test_api.h
new file mode 100644
index 0000000..ce7cb9e
--- /dev/null
+++ b/chrome/browser/extensions/extension_test_api.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2009 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 CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_API_H_
+#define CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_API_H_
+
+#include "chrome/browser/extensions/extension_function.h"
+
+// Function names.
+namespace extension_test_api_functions {
+ extern const char kPassFunction[];
+ extern const char kFailFunction[];
+}; // namespace extension_test_api_functions
+
+class ExtensionTestPassFunction : public SyncExtensionFunction {
+ virtual bool RunImpl();
+};
+
+class ExtensionTestFailFunction : public SyncExtensionFunction {
+ virtual bool RunImpl();
+};
+
+#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_API_H_
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 34d2c93..5ebd804 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -47,11 +47,14 @@
'browser/ssl/ssl_browser_tests.cc',
],
'browser_tests_sources_win_specific': [
- 'browser/extensions/extension_shelf_model_unittest.cc',
- 'browser/extensions/extension_startup_unittest.cc',
+ 'browser/extensions/extension_apitest.cc',
+ 'browser/extensions/extension_apitest.h',
+ 'browser/extensions/extension_bookmarks_apitest.cc',
'browser/extensions/extension_browsertest.cc',
'browser/extensions/extension_browsertest.h',
'browser/extensions/extension_browsertests_misc.cc',
+ 'browser/extensions/extension_shelf_model_unittest.cc',
+ 'browser/extensions/extension_startup_unittest.cc',
'browser/views/browser_views_accessibility_browsertest.cc',
'browser/views/find_bar_win_browsertest.cc',
# TODO(jam): http://crbug.com/15101 These tests fail on Linux and Mac.
@@ -1054,6 +1057,8 @@
'browser/extensions/extension_tabs_module.h',
'browser/extensions/extension_tabs_module_constants.cc',
'browser/extensions/extension_tabs_module_constants.h',
+ 'browser/extensions/extension_test_api.cc',
+ 'browser/extensions/extension_test_api.h',
'browser/extensions/extension_toolstrip_api.cc',
'browser/extensions/extension_toolstrip_api.h',
'browser/extensions/extension_updater.cc',
diff --git a/chrome/common/common_resources.grd b/chrome/common/common_resources.grd
index e8510c5..457cd27 100644
--- a/chrome/common/common_resources.grd
+++ b/chrome/common/common_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. aa1 -->
+without changes to the corresponding grd file. -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/common_resources.h" type="rc_header">
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 2225236..e5989bc 100755
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -849,5 +849,26 @@
}
],
"events": []
+ },
+ {
+ "namespace": "test",
+ "types": [],
+ "functions": [
+ {
+ "name": "fail",
+ "type": "function",
+ "description": "Notify the browser process that test code running in the extension failed. This is only used for internal unit testing.",
+ "parameters": [
+ {"type": "string", "name": "message"}
+ ]
+ },
+ {
+ "name": "pass",
+ "type": "function",
+ "description": "Notify the browser process that test code running in the extension passed. This is only used for internal unit testing.",
+ "parameters": []
+ }
+ ],
+ "events": []
}
]
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 8ba2d84..ed37cc6 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -642,6 +642,11 @@ class NotificationType {
// Sent when a background page is ready so other components can load.
EXTENSION_BACKGROUND_PAGE_READY,
+ // Sent by an extension to notify the browser about the results of a unit
+ // test.
+ EXTENSION_TEST_PASSED,
+ EXTENSION_TEST_FAILED,
+
// Debugging ---------------------------------------------------------------
// Count (must be last) ----------------------------------------------------
diff --git a/chrome/test/data/extensions/api_test/bookmarks/manifest.json b/chrome/test/data/extensions/api_test/bookmarks/manifest.json
new file mode 100644
index 0000000..0ed2a60
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bookmarks/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "chrome.bookmarks",
+ "version": "0.1",
+ "description": "end-to-end browser test for chrome.bookmarks API",
+ "background_page": "test.html",
+ "permissions": ["bookmarks"]
+}
diff --git a/chrome/test/data/extensions/api_test/bookmarks/test.html b/chrome/test/data/extensions/api_test/bookmarks/test.html
new file mode 100644
index 0000000..3e7b4a4
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bookmarks/test.html
@@ -0,0 +1 @@
+<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/bookmarks/test.js b/chrome/test/data/extensions/api_test/bookmarks/test.js
new file mode 100755
index 0000000..13de9b5
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/bookmarks/test.js
@@ -0,0 +1,76 @@
+var completed = false;
+
+function complete() {
+ completed = true;
+ // a bit of a hack just to try to get the script to stop running at this point
+ throw "completed";
+}
+
+function fail(message) {
+ if (completed) throw "completed";
+
+ console.log("FAIL: " + message);
+ chrome.test.fail(message);
+ complete();
+}
+
+function succeed() {
+ if (completed) throw "completed";
+
+ chrome.test.pass();
+ complete();
+}
+
+window.onerror = function(message, url, code) {
+ if (completed) return;
+
+ fail(message);
+};
+
+function expectTrue(test, message) {
+ if (!test) {
+ fail(message);
+ }
+}
+
+var expected = [
+ {"children": [
+ {"children": [], "id": "1", "parentId": "0", "title":"Bookmarks bar"},
+ {"children": [], "id": "2", "parentId": "0", "title":"Other bookmarks"}
+ ],
+ "id": "0", "title": ""
+ }
+];
+
+function compareTrees(left, right) {
+ console.log("compare");
+ console.log(JSON.stringify(right));
+ console.log(JSON.stringify(left));
+ // TODO(erikkay): do some comparison of dateAdded
+ if (left == null && right == null) {
+ console.log("both left and right are NULL");
+ return true;
+ }
+ if (left == null || right == null)
+ return false;
+ if (left.length < right.length)
+ return false;
+ for (var i = 0; i < left.length; i++) {
+ if (left[i].id != right[i].id)
+ return false;
+ console.log(left[i].title + " ? " + right[i].title);
+ if (left[i].title != right[i].title)
+ return false;
+ if (!compareTrees(left[i].children, right[i].children))
+ return false;
+ }
+ return true;
+}
+
+chrome.bookmarks.getTree(function(results) {
+ expectTrue(compareTrees(results, expected),
+ "getTree() result doesn't match expected");
+ expected = results;
+ console.log("done");
+ succeed();
+});