Add support for V8 startup tests and a new V8Test.Extension test (issue #712).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@818 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2012-09-28 17:11:10 +00:00
parent 149ae3df88
commit 410bbcfea4
5 changed files with 178 additions and 47 deletions

View File

@ -176,6 +176,7 @@ class ClientAppExtensionHandler : public CefV8Handler {
ClientApp::ClientApp()
: proxy_type_(CEF_PROXY_TYPE_DIRECT) {
CreateBrowserDelegates(browser_delegates_);
CreateRenderDelegates(render_delegates_);
// Default schemes that support cookies.
@ -213,6 +214,19 @@ void ClientApp::OnContextInitialized() {
CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager();
ASSERT(manager.get());
manager->SetSupportedSchemes(cookieable_schemes_);
// Execute delegate callbacks.
BrowserDelegateSet::iterator it = browser_delegates_.begin();
for (; it != browser_delegates_.end(); ++it)
(*it)->OnContextInitialized(this);
}
void ClientApp::OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) {
// Execute delegate callbacks.
BrowserDelegateSet::iterator it = browser_delegates_.begin();
for (; it != browser_delegates_.end(); ++it)
(*it)->OnBeforeChildProcessLaunch(this, command_line);
}
void ClientApp::GetProxyForUrl(const CefString& url,

View File

@ -18,6 +18,26 @@ class ClientApp : public CefApp,
public CefProxyHandler,
public CefRenderProcessHandler {
public:
// Interface for browser delegates. All BrowserDelegates must be returned via
// CreateBrowserDelegates. Do not perform work in the BrowserDelegate
// constructor.
class BrowserDelegate : public virtual CefBase {
public:
// Called on the browser process UI thread immediately after the CEF context
// has been initialized.
virtual void OnContextInitialized(CefRefPtr<ClientApp> app) {
}
// Called on the browser process IO thread before a child process is launched.
// Provides an opportunity to modify the child process command line.
virtual void OnBeforeChildProcessLaunch(
CefRefPtr<ClientApp> app,
CefRefPtr<CefCommandLine> command_line) {
}
};
typedef std::set<CefRefPtr<BrowserDelegate> > BrowserDelegateSet;
// Interface for renderer delegates. All RenderDelegates must be returned via
// CreateRenderDelegates. Do not perform work in the RenderDelegate
// constructor.
@ -97,6 +117,10 @@ class ClientApp : public CefApp,
int browser_id);
private:
// Creates all of the BrowserDelegate objects. Implemented in
// client_app_delegates.
static void CreateBrowserDelegates(BrowserDelegateSet& delegates);
// Creates all of the RenderDelegate objects. Implemented in
// client_app_delegates.
static void CreateRenderDelegates(RenderDelegateSet& delegates);
@ -117,7 +141,9 @@ class ClientApp : public CefApp,
// CefBrowserProcessHandler methods.
virtual CefRefPtr<CefProxyHandler> GetProxyHandler() OVERRIDE { return this; }
virtual void OnContextInitialized();
virtual void OnContextInitialized() OVERRIDE;
virtual void OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) OVERRIDE;
// CefProxyHandler methods.
virtual void GetProxyForUrl(const CefString& url,
@ -150,6 +176,9 @@ class ClientApp : public CefApp,
CallbackMap;
CallbackMap callback_map_;
// Set of supported BrowserDelegates.
BrowserDelegateSet browser_delegates_;
// Set of supported RenderDelegates.
RenderDelegateSet render_delegates_;

View File

@ -7,6 +7,10 @@
#include "cefclient/dom_test.h"
#include "cefclient/scheme_test.h"
// static
void ClientApp::CreateBrowserDelegates(BrowserDelegateSet& delegates) {
}
// static
void ClientApp::CreateRenderDelegates(RenderDelegateSet& delegates) {
client_renderer::CreateRenderDelegates(delegates);

View File

@ -4,6 +4,13 @@
#include "tests/cefclient/client_app.h"
// static
void ClientApp::CreateBrowserDelegates(BrowserDelegateSet& delegates) {
// Bring in the V8 tests.
extern void CreateV8BrowserTests(BrowserDelegateSet& delegates);
CreateV8BrowserTests(delegates);
}
// static
void ClientApp::CreateRenderDelegates(RenderDelegateSet& delegates) {
// Bring in the process message tests.

View File

@ -3,6 +3,7 @@
// can be found in the LICENSE file.
#include <sstream>
#include "include/cef_runnable.h"
#include "include/cef_task.h"
#include "include/cef_v8.h"
#include "tests/cefclient/client_app.h"
@ -24,9 +25,11 @@ const char* kV8BindingTestUrl = "http://tests/V8Test.BindingTest";
const char* kV8ContextParentTestUrl = "http://tests/V8Test.ContextParentTest";
const char* kV8ContextChildTestUrl = "http://tests/V8Test.ContextChildTest";
const char* kV8TestMsg = "V8Test.Test";
const char* kV8TestCmdArg = "v8-test";
enum V8TestMode {
V8TEST_NULL_CREATE = 0,
V8TEST_NONE = 0,
V8TEST_NULL_CREATE,
V8TEST_BOOL_CREATE,
V8TEST_INT_CREATE,
V8TEST_UINT_CREATE,
@ -59,16 +62,45 @@ enum V8TestMode {
V8TEST_CONTEXT_ENTERED,
V8TEST_BINDING,
V8TEST_STACK_TRACE,
V8TEST_EXTENSION,
};
// Set to the current test being run in the browser process. Will always be
// V8TEST_NONE in the render process.
V8TestMode g_current_test_mode = V8TEST_NONE;
// Browser side.
class V8BrowserTest : public ClientApp::BrowserDelegate {
public:
V8BrowserTest() {}
virtual void OnBeforeChildProcessLaunch(
CefRefPtr<ClientApp> app,
CefRefPtr<CefCommandLine> command_line) OVERRIDE {
CefString process_type = command_line->GetSwitchValue("type");
if (process_type == "renderer") {
// Add the current test mode to the render process command line arguments.
char buff[33];
sprintf(buff, "%d", g_current_test_mode);
command_line->AppendSwitchWithValue(kV8TestCmdArg, buff);
}
}
private:
IMPLEMENT_REFCOUNTING(V8BrowserTest);
};
// Renderer side.
class V8RendererTest : public ClientApp::RenderDelegate {
public:
V8RendererTest() {}
V8RendererTest()
: test_mode_(V8TEST_NONE) {
}
// Run the specified test.
void RunTest(V8TestMode test_mode) {
switch (test_mode) {
// Run a test when the process message is received from the browser.
void RunTest() {
switch (test_mode_) {
case V8TEST_NULL_CREATE:
RunNullCreateTest();
break;
@ -169,12 +201,24 @@ class V8RendererTest : public ClientApp::RenderDelegate {
RunStackTraceTest();
break;
default:
ADD_FAILURE();
// Was a startup test.
EXPECT_TRUE(startup_test_success_);
DestroyTest();
break;
}
}
// Run a test on render process startup.
void RunStartupTest() {
switch (test_mode_) {
case V8TEST_EXTENSION:
RunExtensionTest();
break;
default:
break;
}
}
void RunNullCreateTest() {
CefRefPtr<CefV8Value> value = CefV8Value::CreateNull();
EXPECT_TRUE(value.get());
@ -1508,10 +1552,57 @@ class V8RendererTest : public ClientApp::RenderDelegate {
DestroyTest();
}
// Test execution of a native function when the extension is loaded.
void RunExtensionTest() {
std::string code = "native function v8_extension_test();"
"v8_extension_test();";
class Handler : public CefV8Handler {
public:
Handler(TrackCallback* callback)
: callback_(callback) {
}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
EXPECT_STREQ("v8_extension_test", name.ToString().c_str());
callback_->yes();
return true;
}
TrackCallback* callback_;
IMPLEMENT_REFCOUNTING(Handler);
};
CefRegisterExtension("v8/test-extension", code,
new Handler(&startup_test_success_));
}
virtual void OnWebKitInitialized(CefRefPtr<ClientApp> app) {
test_mode_ = g_current_test_mode;
if (test_mode_ == V8TEST_NONE) {
// Retrieve the test mode from the command line.
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
CefString value = command_line->GetSwitchValue(kV8TestCmdArg);
if (!value.empty())
test_mode_ = static_cast<V8TestMode>(atoi(value.ToString().c_str()));
}
EXPECT_GT(test_mode_, V8TEST_NONE);
RunStartupTest();
}
virtual void OnContextCreated(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) OVERRIDE {
app_ = app;
browser_ = browser;
std::string url = frame->GetURL();
if (url == kV8ContextChildTestUrl) {
// For V8TEST_CONTEXT_ENTERED
@ -1556,6 +1647,9 @@ class V8RendererTest : public ClientApp::RenderDelegate {
EXPECT_TRUE(object.get());
EXPECT_TRUE(object->SetValue("v8_context_entered_test", func,
V8_PROPERTY_ATTRIBUTE_NONE));
} else if (url == kV8ContextParentTestUrl) {
// For V8TEST_CONTEXT_ENTERED. Do nothing.
return;
} else if (url == kV8BindingTestUrl) {
// For V8TEST_BINDING
CefRefPtr<CefV8Value> object = context->GetGlobal();
@ -1564,27 +1658,10 @@ class V8RendererTest : public ClientApp::RenderDelegate {
CefV8Value::CreateInt(12),
V8_PROPERTY_ATTRIBUTE_NONE));
}
}
virtual bool OnProcessMessageReceived(
CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) OVERRIDE {
if (message->GetName() == kV8TestMsg) {
app_ = app;
browser_ = browser;
V8TestMode test_mode =
static_cast<V8TestMode>(message->GetArgumentList()->GetInt(0));
// Run the test.
RunTest(test_mode);
return true;
}
// Message not handled.
return false;
// Run the test asynchronously.
CefPostTask(TID_RENDERER,
NewCefRunnableMethod(this, &V8RendererTest::RunTest));
}
protected:
@ -1612,8 +1689,12 @@ class V8RendererTest : public ClientApp::RenderDelegate {
CefRefPtr<ClientApp> app_;
CefRefPtr<CefBrowser> browser_;
V8TestMode test_mode_;
IMPLEMENT_REFCOUNTING(SendRecvRendererTest);
// Used by startup tests to indicate success.
TrackCallback startup_test_success_;
IMPLEMENT_REFCOUNTING(V8RendererTest);
};
// Browser side.
@ -1625,36 +1706,24 @@ class V8TestHandler : public TestHandler {
}
virtual void RunTest() OVERRIDE {
// Nested script tag forces creation of the V8 context.
if (test_mode_ == V8TEST_CONTEXT_ENTERED) {
AddResource(kV8ContextParentTestUrl, "<html><body><iframe src=\"" +
AddResource(kV8ContextParentTestUrl, "<html><body>"
"<script>var i = 0;</script><iframe src=\"" +
std::string(kV8ContextChildTestUrl) + "\" id=\"f\"></iframe></body>"
"</html>", "text/html");
AddResource(kV8ContextChildTestUrl, "<html><body>CHILD</body></html>",
AddResource(kV8ContextChildTestUrl, "<html><body>"
"<script>var i = 0;</script>CHILD</body></html>",
"text/html");
CreateBrowser(kV8ContextParentTestUrl);
} else {
EXPECT_TRUE(test_url_ != NULL);
AddResource(test_url_, "<html><body>TEST</body></html>", "text/html");
AddResource(test_url_, "<html><body>"
"<script>var i = 0;</script>TEST</body></html>", "text/html");
CreateBrowser(test_url_);
}
}
CefRefPtr<CefProcessMessage> CreateTestMessage() {
CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create(kV8TestMsg);
EXPECT_TRUE(msg->GetArgumentList()->SetInt(0, test_mode_));
return msg;
}
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE {
if (frame->IsMain()) {
// Send the message to the renderer process to run the test.
EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER,
CreateTestMessage()));
}
}
virtual bool OnProcessMessageReceived(
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
@ -1684,6 +1753,12 @@ class V8TestHandler : public TestHandler {
} // namespace
// Entry point for creating V8 browser test objects.
// Called from client_app_delegates.cc.
void CreateV8BrowserTests(ClientApp::BrowserDelegateSet& delegates) {
delegates.insert(new V8BrowserTest);
}
// Entry point for creating V8 renderer test objects.
// Called from client_app_delegates.cc.
void CreateV8RendererTests(ClientApp::RenderDelegateSet& delegates) {
@ -1694,6 +1769,7 @@ void CreateV8RendererTests(ClientApp::RenderDelegateSet& delegates) {
// Helpers for defining V8 tests.
#define V8_TEST_EX(name, test_mode, test_url) \
TEST(V8Test, name) { \
g_current_test_mode = test_mode; \
CefRefPtr<V8TestHandler> handler = \
new V8TestHandler(test_mode, test_url); \
handler->ExecuteTest(); \
@ -1739,3 +1815,4 @@ V8_TEST(ContextEvalException, V8TEST_CONTEXT_EVAL_EXCEPTION);
V8_TEST_EX(ContextEntered, V8TEST_CONTEXT_ENTERED, NULL);
V8_TEST_EX(Binding, V8TEST_BINDING, kV8BindingTestUrl);
V8_TEST(StackTrace, V8TEST_STACK_TRACE);
V8_TEST(Extension, V8TEST_EXTENSION);