Index: ppapi/tests/test_case.h |
diff --git a/ppapi/tests/test_case.h b/ppapi/tests/test_case.h |
index c7699963b64f112e50a9e08f6e1cbb2cbdb3a051..47324b6f6c93667f5e4060436e084738c627b501 100644 |
--- a/ppapi/tests/test_case.h |
+++ b/ppapi/tests/test_case.h |
@@ -7,11 +7,13 @@ |
#include <cmath> |
#include <limits> |
+#include <map> |
#include <set> |
#include <string> |
-#include "ppapi/c/pp_resource.h" |
#include "ppapi/c/dev/ppb_testing_dev.h" |
+#include "ppapi/c/pp_resource.h" |
+#include "ppapi/c/pp_time.h" |
#include "ppapi/cpp/dev/scrollbar_dev.h" |
#include "ppapi/cpp/message_loop.h" |
#include "ppapi/cpp/view.h" |
@@ -43,10 +45,14 @@ class TestCase { |
virtual bool Init(); |
// Override to implement the test case. It will be called after the plugin is |
- // first displayed, passing a string. If the string is empty, the |
- // should run all tests for this test case. Otherwise, it should run the test |
- // whose name matches test_filter exactly (if there is one). This should |
- // generally be implemented using the RUN_TEST* macros. |
+ // first displayed, passing a string. If the string is empty, RunTests should |
+ // run all tests for this test case. Otherwise, it must be a comma-delimited |
+ // list of test names, possibly prefixed. E.g.: |
+ // "Foo_GoodTest,DISABLED_Foo_BadTest,Foo_OtherGoodTest" |
+ // All listed tests which are not prefixed will be run. |
+ // |
+ // This should generally be implemented in a TestCase subclass using the |
+ // RUN_TEST* macros. |
virtual void RunTests(const std::string& test_filter) = 0; |
static std::string MakeFailureMessage(const char* file, int line, |
@@ -82,6 +88,13 @@ class TestCase { |
static void QuitMainMessageLoop(PP_Instance instance); |
+ const std::map<std::string, bool>& remaining_tests() { |
+ return remaining_tests_; |
+ } |
+ const std::set<std::string>& skipped_tests() { |
+ return skipped_tests_; |
+ } |
+ |
protected: |
#if !(defined __native_client__) |
// Overridden by each test to supply a ScriptableObject corresponding to the |
@@ -101,9 +114,15 @@ class TestCase { |
// Makes sure the test is run over HTTP. |
bool EnsureRunningOverHTTP(); |
+ // Returns true if |filter| only contains a TestCase name, which normally |
+ // means "run all tests". Some TestCases require special setup for individual |
+ // tests, and can use this function to decide whether to ignore those tests. |
+ bool ShouldRunAllTests(const std::string& filter); |
+ |
// Return true if the given test name matches the filter. This is true if |
- // (a) filter is empty or (b) test_name and filter match exactly. |
- bool MatchesFilter(const std::string& test_name, const std::string& filter); |
+ // (a) filter is empty or (b) test_name matches a test name listed in filter |
+ // exactly. |
+ bool ShouldRunTest(const std::string& test_name, const std::string& filter); |
// Check for leaked resources and vars at the end of the test. If any exist, |
// return a string with some information about the error. Otherwise, return |
@@ -113,6 +132,8 @@ class TestCase { |
// CheckResourcesAndVars will do nothing and return the same string. |
std::string CheckResourcesAndVars(std::string errors); |
+ PP_TimeTicks NowInTimeTicks(); |
+ |
// Run the given test method on a background thread and return the result. |
template <class T> |
std::string RunOnThread(std::string(T::*test_to_run)()) { |
@@ -212,6 +233,24 @@ class TestCase { |
// Var ids that should be ignored when checking for leaks on shutdown. |
std::set<int64_t> ignored_leaked_vars_; |
+ // The tests that were found in test_filter but have not yet been run. The |
+ // bool indicates whether the test should be run (i.e., it will be false if |
+ // the test name was prefixed in the test_filter string). |
+ // |
+ // This is initialized lazily the first time that ShouldRunTest is called by |
+ // RunTests. When RunTests is finished, this should be empty. Any remaining |
+ // tests are tests that were listed in the test_filter but didn't match |
+ // any calls to ShouldRunTest, meaning it was probably a typo. TestingInstance |
+ // should log this and consider it a failure. |
+ std::map<std::string, bool> remaining_tests_; |
+ // Flag indicating whether we have populated remaining_tests_ yet. |
+ bool have_populated_remaining_tests_; |
+ |
+ // If ShouldRunTest is called but the given test name doesn't match anything |
+ // in the test_filter, the test name will be added here. This allows |
+ // TestingInstance to detect when not all tests were listed. |
+ std::set<std::string> skipped_tests_; |
+ |
#if !(defined __native_client__) |
// Holds the test object, if any was retrieved from CreateTestObject. |
pp::VarPrivate test_object_; |
@@ -260,31 +299,42 @@ class TestCaseFactory { |
// RunTest function. This assumes the function name is TestFoo where Foo is the |
// test |name|. |
#define RUN_TEST(name, test_filter) \ |
- if (MatchesFilter(#name, test_filter)) { \ |
+ if (ShouldRunTest(#name, test_filter)) { \ |
set_callback_type(PP_OPTIONAL); \ |
- instance_->LogTest(#name, CheckResourcesAndVars(Test##name())); \ |
+ PP_TimeTicks start_time(NowInTimeTicks()); \ |
+ instance_->LogTest(#name, \ |
+ CheckResourcesAndVars(Test##name()), \ |
+ start_time); \ |
} |
// Like RUN_TEST above but forces functions taking callbacks to complete |
// asynchronously on success or error. |
#define RUN_TEST_FORCEASYNC(name, test_filter) \ |
- if (MatchesFilter(#name, test_filter)) { \ |
+ if (ShouldRunTest(#name, test_filter)) { \ |
set_callback_type(PP_REQUIRED); \ |
+ PP_TimeTicks start_time(NowInTimeTicks()); \ |
instance_->LogTest(#name"ForceAsync", \ |
- CheckResourcesAndVars(Test##name())); \ |
+ CheckResourcesAndVars(Test##name()), \ |
+ start_time); \ |
} |
#define RUN_TEST_BLOCKING(test_case, name, test_filter) \ |
- if (MatchesFilter(#name, test_filter)) { \ |
+ if (ShouldRunTest(#name, test_filter)) { \ |
set_callback_type(PP_BLOCKING); \ |
- instance_->LogTest(#name"Blocking", \ |
- CheckResourcesAndVars(RunOnThread(&test_case::Test##name))); \ |
+ PP_TimeTicks start_time(NowInTimeTicks()); \ |
+ instance_->LogTest( \ |
+ #name"Blocking", \ |
+ CheckResourcesAndVars(RunOnThread(&test_case::Test##name)), \ |
+ start_time); \ |
} |
#define RUN_TEST_BACKGROUND(test_case, name, test_filter) \ |
- if (MatchesFilter(#name, test_filter)) { \ |
- instance_->LogTest(#name"Background", \ |
- CheckResourcesAndVars(RunOnThread(&test_case::Test##name))); \ |
+ if (ShouldRunTest(#name, test_filter)) { \ |
+ PP_TimeTicks start_time(NowInTimeTicks()); \ |
+ instance_->LogTest( \ |
+ #name"Background", \ |
+ CheckResourcesAndVars(RunOnThread(&test_case::Test##name)), \ |
+ start_time); \ |
} |
#define RUN_TEST_FORCEASYNC_AND_NOT(name, test_filter) \ |
@@ -303,7 +353,7 @@ class TestCaseFactory { |
} while (false) |
#define RUN_TEST_WITH_REFERENCE_CHECK(name, test_filter) \ |
- if (MatchesFilter(#name, test_filter)) { \ |
+ if (ShouldRunTest(#name, test_filter)) { \ |
set_callback_type(PP_OPTIONAL); \ |
uint32_t objects = testing_interface_->GetLiveObjectsForInstance( \ |
instance_->pp_instance()); \ |
@@ -313,7 +363,10 @@ class TestCaseFactory { |
instance_->pp_instance()) != objects) \ |
error_message = MakeFailureMessage(__FILE__, __LINE__, \ |
"reference leak check"); \ |
- instance_->LogTest(#name, error_message); \ |
+ PP_TimeTicks start_time(NowInTimeTicks()); \ |
+ instance_->LogTest(#name, \ |
+ error_message, \ |
+ start_time); \ |
} |
// TODO(dmichael): Add CheckResourcesAndVars above when Windows tests pass |
// cleanly. crbug.com/173503 |