15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/testing_instance.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstring>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <iomanip>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sstream>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ppapi/cpp/core.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/module.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/var.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/cpp/view.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/tests/test_case.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestCaseFactory* TestCaseFactory::head_ = NULL;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cookie value we use to signal "we're still working." See the comment above
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the class declaration for how this works.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kProgressSignal[] = "...";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns a new heap-allocated test case for the given test, or NULL on
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// failure.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestingInstance::TestingInstance(PP_Instance instance)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (defined __native_client__)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : pp::Instance(instance),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : pp::InstancePrivate(instance),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_case_(NULL),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      executed_tests_(false),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_tests_executed_(0),
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nacl_mode_(false),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_server_port_(-1),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket_port_(-1),
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remove_plugin_(true) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_factory_.Initialize(this);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestingInstance::~TestingInstance() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_case_)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete current_case_;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestingInstance::Init(uint32_t argc,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const char* argn[],
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const char* argv[]) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 0; i < argc; i++) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (std::strcmp(argn[i], "mode") == 0) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (std::strcmp(argv[i], "nacl") == 0)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nacl_mode_ = true;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (std::strcmp(argn[i], "protocol") == 0) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      protocol_ = argv[i];
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (std::strcmp(argn[i], "websocket_host") == 0) {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      websocket_host_ = argv[i];
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (std::strcmp(argn[i], "websocket_port") == 0) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket_port_ = atoi(argv[i]);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (std::strcmp(argn[i], "ssl_server_port") == 0) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_server_port_ = atoi(argv[i]);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the proper test case from the argument.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (uint32_t i = 0; i < argc; i++) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (std::strcmp(argn[i], "testcase") == 0) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (argv[i][0] == '\0')
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_case_ = CaseForTestName(argv[i]);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_filter_ = argv[i];
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!current_case_)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        errors_.append(std::string("Unknown test case ") + argv[i]);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (!current_case_->Init())
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        errors_.append(" Test case could not initialize.");
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In DidChangeView, we'll dump out a list of all available tests.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !(defined __native_client__)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pp::Var TestingInstance::GetInstanceObject() {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_case_)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return current_case_->GetTestObject();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pp::VarPrivate();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::HandleMessage(const pp::Var& message_data) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_case_)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_case_->HandleMessage(message_data);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::DidChangeView(const pp::View& view) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!executed_tests_) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    executed_tests_ = true;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pp::Module::Get()->core()->CallOnMainThread(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_factory_.NewCallback(&TestingInstance::ExecuteTests));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_case_)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_case_->DidChangeView(view);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TestingInstance::HandleInputEvent(const pp::InputEvent& event) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_case_)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return current_case_->HandleInputEvent(event);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::EvalScript(const std::string& script) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendTestCommand("EvalScript", script);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::SetCookie(const std::string& name,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const std::string& value) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendTestCommand("SetCookie", name + "=" + value);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::LogTest(const std::string& test_name,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const std::string& error_message,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              PP_TimeTicks start_time) {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Compute the time to run the test and save it in a string for logging:
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_TimeTicks end_time(pp::Module::Get()->core()->GetTimeTicks());
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::ostringstream number_stream;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PP_TimeTicks elapsed_time(end_time - start_time);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  number_stream << std::fixed << std::setprecision(3) << elapsed_time;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string time_string(number_stream.str());
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell the browser we're still working.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportProgress(kProgressSignal);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  number_tests_executed_++;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string html;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append("<div class=\"test_line\"><span class=\"test_name\">");
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append(test_name);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append("</span> ");
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error_message.empty()) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append("<span class=\"pass\">PASS</span>");
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append("<span class=\"fail\">FAIL</span>: <span class=\"err_msg\">");
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append(error_message);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append("</span>");
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!errors_.empty())
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errors_.append(", ");  // Separator for different error messages.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errors_.append(test_name + " FAIL: " + error_message);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  html.append(" <span class=\"time\">(");
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  html.append(time_string);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  html.append("s)</span>");
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append("</div>");
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHTML(html);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::AppendError(const std::string& message) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!errors_.empty())
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errors_.append(", ");
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errors_.append(message);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::ExecuteTests(int32_t unused) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportProgress(kProgressSignal);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear the console.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendTestCommand("ClearConsole");
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!errors_.empty()) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Catch initialization errors and output the current error string to
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the console.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogError("Plugin initialization failed: " + errors_);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!current_case_) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogAvailableTests();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errors_.append("FAIL: Only listed tests");
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_case_->RunTests(test_filter_);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (number_tests_executed_ == 0) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      errors_.append("No tests executed. The test filter might be too "
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "restrictive: '" + test_filter_ + "'.");
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogError(errors_);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (current_case_->skipped_tests().size()) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // TODO(dmichael): Convert all TestCases to run all tests in one fixture,
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      //                 and enable this check. Currently, a lot of our tests
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      //                 run 1 test per fixture, which is slow.
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      /*
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      errors_.append("Some tests were not listed and thus were not run. Make "
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     "sure all tests are passed in the test_case URL (even if "
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     "they are marked DISABLED_). Forgotten tests: ");
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::set<std::string>::const_iterator iter =
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          current_case_->skipped_tests().begin();
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (; iter != current_case_->skipped_tests().end(); ++iter) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors_.append(*iter);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors_.append(" ");
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LogError(errors_);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      */
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (current_case_->remaining_tests().size()) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      errors_.append("Some listed tests were not found in the TestCase. Check "
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     "the test names that were passed to make sure they match "
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     "tests in the TestCase. Unknown tests: ");
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::map<std::string, bool>::const_iterator iter =
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          current_case_->remaining_tests().begin();
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (; iter != current_case_->remaining_tests().end(); ++iter) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors_.append(iter->first);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        errors_.append(" ");
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LogError(errors_);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remove_plugin_)
2219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    SendTestCommand("RemovePluginWhenFinished");
2229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  std::string result(errors_);
2239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  if (result.empty())
2249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    result = "PASS";
2259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  SendTestCommand("DidExecuteTests", result);
2269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  // Note, DidExecuteTests may unload the plugin. We can't really do anything
2279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  // after this point.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TestCase* TestingInstance::CaseForTestName(const std::string& name) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string case_name = name.substr(0, name.find_first_of('_'));
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCaseFactory* iter = TestCaseFactory::head_;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (iter != NULL) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (case_name == iter->name_)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return iter->method_(this);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter = iter->next_;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::SendTestCommand(const std::string& command) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string msg("TESTING_MESSAGE:");
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  msg += command;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostMessage(pp::Var(msg));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::SendTestCommand(const std::string& command,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& params) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendTestCommand(command + ":" + params);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::LogAvailableTests() {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Print out a listing of all tests.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> test_cases;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCaseFactory* iter = TestCaseFactory::head_;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (iter != NULL) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_cases.push_back(iter->name_);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter = iter->next_;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(test_cases.begin(), test_cases.end());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string html;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append("Available test cases: <dl>");
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < test_cases.size(); ++i) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append("<dd><a href='?testcase=");
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append(test_cases[i]);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (nacl_mode_)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       html.append("&mode=nacl");
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append("'>");
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append(test_cases[i]);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    html.append("</a></dd>");
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append("</dl>");
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append("<button onclick='RunAll()'>Run All Tests</button>");
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHTML(html);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::LogError(const std::string& text) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string html;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append("<span class=\"fail\">FAIL</span>: <span class=\"err_msg\">");
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append(text);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  html.append("</span>");
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHTML(html);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::LogHTML(const std::string& html) {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendTestCommand("LogHTML", html);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::ReportProgress(const std::string& progress_value) {
2939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  SendTestCommand("ReportProgress", progress_value);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TestingInstance::AddPostCondition(const std::string& script) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendTestCommand("AddPostCondition", script);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Module : public pp::Module {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Module() : pp::Module() {}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Module() {}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual pp::Instance* CreateInstance(PP_Instance instance) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new TestingInstance(instance);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace pp {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Module* CreateModule() {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ::Module();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace pp
317