diff options
author | scr@chromium.org <scr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-03 01:25:29 +0000 |
---|---|---|
committer | scr@chromium.org <scr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-03 01:25:29 +0000 |
commit | 369d25ca02211727361c11af0b8e8db2b234d421 (patch) | |
tree | 0d21be7adaca018c56a0728eb5a790f109e2ca1c /chrome/test/base/v8_unit_test.cc | |
parent | 1e29b4e78e03e519bf8e79160d827c22a0c39de0 (diff) | |
download | chromium_src-369d25ca02211727361c11af0b8e8db2b234d421.zip chromium_src-369d25ca02211727361c11af0b8e8db2b234d421.tar.gz chromium_src-369d25ca02211727361c11af0b8e8db2b234d421.tar.bz2 |
Allow javascript unit tests using webui test_api framework.
I moved javascript2webui.js over to chrome/test/base/js2gtest.js and shared it
across webui and unit tests with an extra parameter for test type, which governs
the few differences, such as what to include/subclass from and the flavor of
gtest (TEST_F v. IN_PROC_BROWSER_TEST_F).
v8_unit_test implemented 2 main methods to make it work with the generated C++
- AddLibrary - loads the file in the test context
- RunJavascriptF - launches the runTest with the testFixture and testName,
coordinating with Error and ChromeSend to report results.
Helper functions:
- Error - watches for console.error, noting failure if seen.
- ChromeSend - pulls apart the result from the test_api's call to
chrome.send('testResult', [ok, msg])
R=arv@chromium.org
BUG=87820
TEST=unit_tests --gtest_filter=FrameworkUnitTest.*
Review URL: http://codereview.chromium.org/8418015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108391 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/test/base/v8_unit_test.cc')
-rw-r--r-- | chrome/test/base/v8_unit_test.cc | 191 |
1 files changed, 176 insertions, 15 deletions
diff --git a/chrome/test/base/v8_unit_test.cc b/chrome/test/base/v8_unit_test.cc index 798a03f..92406ed 100644 --- a/chrome/test/base/v8_unit_test.cc +++ b/chrome/test/base/v8_unit_test.cc @@ -4,17 +4,166 @@ #include "chrome/test/base/v8_unit_test.h" +#include "base/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" #include "base/string_piece.h" #include "base/stringprintf.h" +#include "chrome/common/chrome_paths.h" -V8UnitTest::V8UnitTest() {} +namespace { + +// |args| are passed through the various JavaScript logging functions such as +// console.log. Returns a string appropriate for logging with LOG(severity). +std::string LogArgs2String(const v8::Arguments& args) { + std::string message; + bool first = true; + for (int i = 0; i < args.Length(); i++) { + v8::HandleScope handle_scope; + if (first) + first = false; + else + message += " "; + + v8::String::Utf8Value str(args[i]); + message += *str; + } + return message; +} + +// Whether errors were seen. +bool had_errors = false; + +// testDone results. +bool testResult_ok = false; + +// Location of test data (currently test/data/webui). +FilePath test_data_directory; + +// Location of generated test data (<(PROGRAM_DIR)/test_data). +FilePath gen_test_data_directory; + +} // namespace + +V8UnitTest::V8UnitTest() { + InitPathsAndLibraries(); +} V8UnitTest::~V8UnitTest() {} +void V8UnitTest::AddLibrary(const FilePath& library_path) { + user_libraries_.push_back(library_path); +} + +bool V8UnitTest::ExecuteJavascriptLibraries() { + std::string utf8_content; + for (std::vector<FilePath>::iterator user_libraries_iterator = + user_libraries_.begin(); + user_libraries_iterator != user_libraries_.end(); + ++user_libraries_iterator) { + std::string library_content; + FilePath library_file(*user_libraries_iterator); + if (!user_libraries_iterator->IsAbsolute()) { + FilePath gen_file = gen_test_data_directory.Append(library_file); + library_file = file_util::PathExists(gen_file) ? gen_file : + test_data_directory.Append(*user_libraries_iterator); + } + if (!file_util::ReadFileToString(library_file, &library_content)) { + ADD_FAILURE() << library_file.value(); + return false; + } + ExecuteScriptInContext(library_content, library_file.MaybeAsASCII()); + if (::testing::Test::HasFatalFailure()) + return false; + } + return true; +} + +bool V8UnitTest::RunJavascriptTestF( + const std::string& testFixture, const std::string& testName) { + had_errors = false; + testResult_ok = false; + std::string test_js; + if (!ExecuteJavascriptLibraries()) + return false; + + v8::Context::Scope context_scope(context_); + v8::HandleScope handle_scope; + + v8::Handle<v8::Value> functionProperty = + context_->Global()->Get(v8::String::New("runTest")); + EXPECT_FALSE(functionProperty.IsEmpty()); + if (::testing::Test::HasNonfatalFailure()) + return false; + EXPECT_TRUE(functionProperty->IsFunction()); + if (::testing::Test::HasNonfatalFailure()) + return false; + v8::Handle<v8::Function> function = + v8::Handle<v8::Function>::Cast(functionProperty); + + v8::Local<v8::Array> params = v8::Array::New(); + params->Set(0, v8::String::New(testFixture.data(), testFixture.size())); + params->Set(1, v8::String::New(testName.data(), testName.size())); + v8::Handle<v8::Value> args[] = { + v8::Boolean::New(false), + v8::String::New("RUN_TEST_F"), + params + }; + + v8::TryCatch try_catch; + v8::Handle<v8::Value> result = function->Call(context_->Global(), 3, args); + // The test fails if an exception was thrown. + EXPECT_FALSE(result.IsEmpty()); + if (::testing::Test::HasNonfatalFailure()) + return false; + + // Ok if ran successfully, passed tests, and didn't have console errors. + return result->BooleanValue() && testResult_ok && !had_errors; +} + +void V8UnitTest::InitPathsAndLibraries() { + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory)); + test_data_directory = test_data_directory.AppendASCII("webui"); + ASSERT_TRUE(PathService::Get(chrome::DIR_GEN_TEST_DATA, + &gen_test_data_directory)); + + FilePath mockPath; + ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &mockPath)); + mockPath = mockPath.AppendASCII("chrome"); + mockPath = mockPath.AppendASCII("third_party"); + mockPath = mockPath.AppendASCII("mock4js"); + mockPath = mockPath.AppendASCII("mock4js.js"); + AddLibrary(mockPath); + + FilePath testApiPath; + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &testApiPath)); + testApiPath = testApiPath.AppendASCII("webui"); + testApiPath = testApiPath.AppendASCII("test_api.js"); + AddLibrary(testApiPath); +} + void V8UnitTest::SetUp() { v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); - global->Set(v8::String::New("log"), - v8::FunctionTemplate::New(&V8UnitTest::Log)); + v8::Handle<v8::String> logString = v8::String::New("log"); + v8::Handle<v8::FunctionTemplate> logFunction = + v8::FunctionTemplate::New(&V8UnitTest::Log); + global->Set(logString, logFunction); + + // Set up chrome object for chrome.send(). + v8::Handle<v8::ObjectTemplate> chrome = v8::ObjectTemplate::New(); + global->Set(v8::String::New("chrome"), chrome); + chrome->Set(v8::String::New("send"), + v8::FunctionTemplate::New(&V8UnitTest::ChromeSend)); + + // Set up console object for console.log(), etc. + v8::Handle<v8::ObjectTemplate> console = v8::ObjectTemplate::New(); + global->Set(v8::String::New("console"), console); + console->Set(logString, logFunction); + console->Set(v8::String::New("info"), logFunction); + console->Set(v8::String::New("warn"), logFunction); + console->Set(v8::String::New("error"), + v8::FunctionTemplate::New(&V8UnitTest::Error)); + context_ = v8::Context::New(NULL, global); } @@ -85,18 +234,30 @@ void V8UnitTest::TestFunction(const std::string& function_name) { // static v8::Handle<v8::Value> V8UnitTest::Log(const v8::Arguments& args) { - std::string message; - bool first = true; - for (int i = 0; i < args.Length(); i++) { - v8::HandleScope handle_scope; - if (first) { - first = false; - } else { - message += " "; - } - v8::String::Utf8Value str(args[i]); - message += *str; + LOG(INFO) << LogArgs2String(args); + return v8::Undefined(); +} + +v8::Handle<v8::Value> V8UnitTest::Error(const v8::Arguments& args) { + had_errors = true; + LOG(ERROR) << LogArgs2String(args); + return v8::Undefined(); +} + +v8::Handle<v8::Value> V8UnitTest::ChromeSend(const v8::Arguments& args) { + v8::HandleScope handle_scope; + EXPECT_EQ(2, args.Length()); + if (::testing::Test::HasNonfatalFailure()) + return v8::Undefined(); + v8::String::Utf8Value message(args[0]); + v8::Handle<v8::Array> testResult(args[1].As<v8::Array>()); + EXPECT_EQ(2U, testResult->Length()); + if (::testing::Test::HasNonfatalFailure()) + return v8::Undefined(); + testResult_ok = testResult->Get(0)->BooleanValue(); + if (!testResult_ok) { + v8::String::Utf8Value message(testResult->Get(1)); + LOG(ERROR) << *message; } - std::cout << message << "\n"; return v8::Undefined(); } |