summaryrefslogtreecommitdiffstats
path: root/ppapi/tests/testing_instance.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/tests/testing_instance.cc')
-rw-r--r--ppapi/tests/testing_instance.cc182
1 files changed, 182 insertions, 0 deletions
diff --git a/ppapi/tests/testing_instance.cc b/ppapi/tests/testing_instance.cc
new file mode 100644
index 0000000..9cdd942
--- /dev/null
+++ b/ppapi/tests/testing_instance.cc
@@ -0,0 +1,182 @@
+// Copyright (c) 2010 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 "ppapi/tests/testing_instance.h"
+
+#include <algorithm>
+#include <string.h>
+
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/tests/test_case.h"
+
+TestCaseFactory* TestCaseFactory::head_ = NULL;
+
+// Returns a new heap-allocated test case for the given test, or NULL on
+// failure.
+TestingInstance::TestingInstance(PP_Instance instance)
+ : pp::Instance(instance),
+ current_case_(NULL),
+ executed_tests_(false) {
+ callback_factory_.Initialize(this);
+}
+
+bool TestingInstance::Init(uint32_t argc, const char* argn[], const char* argv[]) {
+ // Create the proper test case from the argument.
+ for (uint32_t i = 0; i < argc; i++) {
+ if (strcmp(argn[i], "testcase") == 0) {
+ if (argv[i][0] == '\0')
+ break;
+ current_case_ = CaseForTestName(argv[i]);
+ if (!current_case_)
+ errors_.append(std::string("Unknown test case ") + argv[i]);
+ else if (!current_case_->Init())
+ errors_.append(" Test case could not initialize.");
+ return true;
+ }
+ }
+
+ // In DidChangeView, we'll dump out a list of all available tests.
+ return true;
+}
+
+pp::Var TestingInstance::GetInstanceObject() {
+ return current_case_->GetTestObject();
+}
+
+void TestingInstance::DidChangeView(const pp::Rect& position,
+ const pp::Rect& clip) {
+ if (!executed_tests_) {
+ executed_tests_ = true;
+ pp::Module::Get()->core()->CallOnMainThread(
+ 0,
+ callback_factory_.NewCallback(&TestingInstance::ExecuteTests));
+ }
+}
+
+void TestingInstance::LogTest(const std::string& test_name,
+ const std::string& error_message) {
+ std::string html;
+ html.append("<div class=\"test_line\"><span class=\"test_name\">");
+ html.append(test_name);
+ html.append("</span> ");
+ if (error_message.empty()) {
+ html.append("<span class=\"pass\">PASS</span>");
+ } else {
+ html.append("<span class=\"fail\">FAIL</span>: <span class=\"err_msg\">");
+ html.append(error_message);
+ html.append("</span>");
+
+ if (!errors_.empty())
+ errors_.append(", "); // Separator for different error messages.
+ errors_.append(test_name + " FAIL: " + error_message);
+ }
+ html.append("</div>");
+ LogHTML(html);
+}
+
+void TestingInstance::AppendError(const std::string& message) {
+ if (!errors_.empty())
+ errors_.append(", ");
+ errors_.append(message);
+}
+
+void TestingInstance::ExecuteTests(int32_t unused) {
+ // Clear the console.
+ // This does: window.document.getElementById("console").innerHTML = "";
+ pp::Var window = GetWindowObject();
+ window.GetProperty("document").
+ Call("getElementById", "console").SetProperty("innerHTML", "");
+
+ if (!errors_.empty()) {
+ // Catch initialization errors and output the current error string to
+ // the console.
+ LogError("Plugin initialization failed: " + errors_);
+ } else if (!current_case_) {
+ LogAvailableTests();
+ } else {
+ current_case_->RunTest();
+ }
+
+ // Declare we're done by setting a cookie to either "PASS" or the errors.
+ SetCookie("COMPLETION_COOKIE", errors_.empty() ? "PASS" : errors_);
+
+ window.Call("DidExecuteTests");
+}
+
+TestCase* TestingInstance::CaseForTestName(const char* name) {
+ TestCaseFactory* iter = TestCaseFactory::head_;
+ while (iter != NULL) {
+ if (strcmp(name, iter->name_) == 0)
+ return iter->method_(this);
+ iter = iter->next_;
+ }
+ return NULL;
+}
+
+void TestingInstance::LogAvailableTests() {
+ // Print out a listing of all tests.
+ std::vector<std::string> test_cases;
+ TestCaseFactory* iter = TestCaseFactory::head_;
+ while (iter != NULL) {
+ test_cases.push_back(iter->name_);
+ iter = iter->next_;
+ }
+ std::sort(test_cases.begin(), test_cases.end());
+
+ std::string html;
+ html.append("Available test cases: <dl>");
+ for (size_t i = 0; i < test_cases.size(); ++i) {
+ html.append("<dd><a href='?");
+ html.append(test_cases[i]);
+ html.append("'>");
+ html.append(test_cases[i]);
+ html.append("</a></dd>");
+ }
+ html.append("</dl>");
+ html.append("<button onclick='RunAll()'>Run All Tests</button>");
+ LogHTML(html);
+}
+
+void TestingInstance::LogError(const std::string& text) {
+ std::string html;
+ html.append("<span class=\"fail\">FAIL</span>: <span class=\"err_msg\">");
+ html.append(text);
+ html.append("</span>");
+ LogHTML(html);
+}
+
+void TestingInstance::LogHTML(const std::string& html) {
+ // This does: window.document.getElementById("console").innerHTML += html
+ pp::Var console = GetWindowObject().GetProperty("document").
+ Call("getElementById", "console");
+ pp::Var inner_html = console.GetProperty("innerHTML");
+ console.SetProperty("innerHTML", inner_html.AsString() + html);
+}
+
+void TestingInstance::SetCookie(const std::string& name,
+ const std::string& value) {
+ // window.document.cookie = "<name>=<value>; path=/"
+ std::string cookie_string = name + "=" + value + "; path=/";
+ pp::Var document = GetWindowObject().GetProperty("document");
+ document.SetProperty("cookie", cookie_string);
+}
+
+class Module : public pp::Module {
+ public:
+ Module() : pp::Module() {}
+ virtual ~Module() {}
+
+ virtual pp::Instance* CreateInstance(PP_Instance instance) {
+ return new TestingInstance(instance);
+ }
+};
+
+namespace pp {
+
+Module* CreateModule() {
+ return new ::Module();
+}
+
+} // namespace pp