• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef PPAPI_TESTS_TEST_CASE_H_
6 #define PPAPI_TESTS_TEST_CASE_H_
7 
8 #include <cmath>
9 #include <limits>
10 #include <map>
11 #include <set>
12 #include <string>
13 
14 #include "ppapi/c/pp_resource.h"
15 #include "ppapi/c/pp_time.h"
16 #include "ppapi/c/private/ppb_testing_private.h"
17 #include "ppapi/cpp/dev/scrollbar_dev.h"
18 #include "ppapi/cpp/message_loop.h"
19 #include "ppapi/cpp/view.h"
20 #include "ppapi/tests/test_utils.h"
21 #include "ppapi/tests/testing_instance.h"
22 
23 #if (defined __native_client__)
24 #include "ppapi/cpp/var.h"
25 #else
26 #include "ppapi/cpp/private/var_private.h"
27 #endif
28 
29 class TestingInstance;
30 
31 namespace pp {
32 namespace deprecated {
33 class ScriptableObject;
34 }
35 }
36 
37 // Individual classes of tests derive from this generic test case.
38 class TestCase {
39  public:
40   explicit TestCase(TestingInstance* instance);
41   virtual ~TestCase();
42 
43   // Optionally override to do testcase specific initialization.
44   // Default implementation just returns true.
45   virtual bool Init();
46 
47   // Override to implement the test case. It will be called after the plugin is
48   // first displayed, passing a string. If the string is empty, RunTests should
49   // run all tests for this test case. Otherwise, it must be a comma-delimited
50   // list of test names, possibly prefixed. E.g.:
51   //   "Foo_GoodTest,DISABLED_Foo_BadTest,Foo_OtherGoodTest"
52   // All listed tests which are not prefixed will be run.
53   //
54   // This should generally be implemented in a TestCase subclass using the
55   // RUN_TEST* macros.
56   virtual void RunTests(const std::string& test_filter) = 0;
57 
58   static std::string MakeFailureMessage(const char* file, int line,
59                                         const char* cmd);
60 
61 #if !(defined __native_client__)
62   // Returns the scriptable test object for the current test, if any.
63   // Internally, this uses CreateTestObject which each test overrides.
64   pp::VarPrivate GetTestObject();
65 #endif
66 
67   // A function that is invoked whenever HandleMessage is called on the
68   // associated TestingInstance. Default implementation does nothing.  TestCases
69   // that want to handle incoming postMessage events should override this
70   // method.
71   virtual void HandleMessage(const pp::Var& message_data);
72 
73   // A function that is invoked whenever DidChangeView is called on the
74   // associated TestingInstance. Default implementation does nothing. TestCases
75   // that want to handle view changes should override this method.
76   virtual void DidChangeView(const pp::View& view);
77 
78   // A function that is invoked whenever HandleInputEvent is called on the
79   // associated TestingInstance. Default implementation returns false. TestCases
80   // that want to handle view changes should override this method.
81   virtual bool HandleInputEvent(const pp::InputEvent& event);
82 
83   void IgnoreLeakedVar(int64_t id);
84 
instance()85   TestingInstance* instance() { return instance_; }
86 
testing_interface()87   const PPB_Testing_Private* testing_interface() { return testing_interface_; }
88 
89   static void QuitMainMessageLoop(PP_Instance instance);
90 
remaining_tests()91   const std::map<std::string, bool>& remaining_tests() {
92     return remaining_tests_;
93   }
skipped_tests()94   const std::set<std::string>& skipped_tests() {
95     return skipped_tests_;
96   }
97 
98  protected:
99 #if !(defined __native_client__)
100   // Overridden by each test to supply a ScriptableObject corresponding to the
101   // test. There can only be one object created for all tests in a given class,
102   // so be sure your object is designed to be re-used.
103   //
104   // This object should be created on the heap. Ownership will be passed to the
105   // caller. Return NULL if there is no supported test object (the default).
106   virtual pp::deprecated::ScriptableObject* CreateTestObject();
107 #endif
108 
109   // Checks whether the testing interface is available. Returns true if it is,
110   // false otherwise. If it is not available, adds a descriptive error. This is
111   // for use by tests that require the testing interface.
112   bool CheckTestingInterface();
113 
114   // Makes sure the test is run over HTTP.
115   bool EnsureRunningOverHTTP();
116 
117   // Returns true if |filter| only contains a TestCase name, which normally
118   // means "run all tests". Some TestCases require special setup for individual
119   // tests, and can use this function to decide whether to ignore those tests.
120   bool ShouldRunAllTests(const std::string& filter);
121 
122   // Return true if the given test name matches the filter. This is true if
123   // (a) filter is empty or (b) test_name matches a test name listed in filter
124   // exactly.
125   bool ShouldRunTest(const std::string& test_name, const std::string& filter);
126 
127   // Check for leaked resources and vars at the end of the test. If any exist,
128   // return a string with some information about the error. Otherwise, return
129   // an empty string.
130   //
131   // You should pass the error string from the test so far; if it is non-empty,
132   // CheckResourcesAndVars will do nothing and return the same string.
133   std::string CheckResourcesAndVars(std::string errors);
134 
135   PP_TimeTicks NowInTimeTicks();
136 
137   // Run the given test method on a background thread and return the result.
138   template <class T>
RunOnThread(std::string (T::* test_to_run)())139   std::string RunOnThread(std::string(T::*test_to_run)()) {
140     if (!testing_interface_) {
141       return "Testing blocking callbacks requires the testing interface. In "
142              "Chrome, use the --enable-pepper-testing flag.";
143     }
144     // These tests are only valid if running out-of-process (threading is not
145     // supported in-process). For in-process, just consider it a pass.
146     if (!testing_interface_->IsOutOfProcess())
147       return std::string();
148     pp::MessageLoop background_loop(instance_);
149     ThreadedTestRunner<T> runner(instance_->pp_instance(),
150         static_cast<T*>(this), test_to_run, background_loop);
151     RunOnThreadInternal(&ThreadedTestRunner<T>::ThreadFunction, &runner,
152                         testing_interface_);
153     return runner.result();
154   }
155 
156   // Pointer to the instance that owns us.
157   TestingInstance* instance_;
158 
159   // NULL unless InitTestingInterface is called.
160   const PPB_Testing_Private* testing_interface_;
161 
set_callback_type(CallbackType callback_type)162   void set_callback_type(CallbackType callback_type) {
163     callback_type_ = callback_type;
164   }
callback_type()165   CallbackType callback_type() const {
166     return callback_type_;
167   }
168 
169  private:
170   template <class T>
171   class ThreadedTestRunner {
172    public:
173     typedef std::string(T::*TestMethodType)();
ThreadedTestRunner(PP_Instance instance,T * test_case,TestMethodType test_to_run,pp::MessageLoop loop)174     ThreadedTestRunner(PP_Instance instance,
175                        T* test_case,
176                        TestMethodType test_to_run,
177                        pp::MessageLoop loop)
178         : instance_(instance),
179           test_case_(test_case),
180           test_to_run_(test_to_run),
181           loop_(loop) {
182     }
result()183     const std::string& result() { return result_; }
ThreadFunction(void * runner)184     static void ThreadFunction(void* runner) {
185       static_cast<ThreadedTestRunner<T>*>(runner)->Run();
186     }
187 
188    private:
Run()189     void Run() {
190       int32_t result = loop_.AttachToCurrentThread();
191       static_cast<void>(result); // result is not used in the RELEASE build.
192       PP_DCHECK(PP_OK == result);
193       result_ = (test_case_->*test_to_run_)();
194       // Now give the loop a chance to clean up.
195       loop_.PostQuit(true /* should_destroy */);
196       loop_.Run();
197       // Tell the main thread to quit its nested message loop, now that the test
198       // is complete.
199       TestCase::QuitMainMessageLoop(instance_);
200     }
201 
202     std::string result_;
203     PP_Instance instance_;
204     T* test_case_;
205     TestMethodType test_to_run_;
206     pp::MessageLoop loop_;
207   };
208 
209   // The internals for RunOnThread. This allows us to avoid including
210   // pp_thread.h in this header file, since it includes system headers like
211   // windows.h.
212   // RunOnThreadInternal launches a new thread to run |thread_func|, waits
213   // for it to complete using RunMessageLoop(), then joins.
214   void RunOnThreadInternal(void (*thread_func)(void*),
215                            void* thread_param,
216                            const PPB_Testing_Private* testing_interface);
217 
218   static void DoQuitMainMessageLoop(void* pp_instance, int32_t result);
219 
220   // Passed when creating completion callbacks in some tests. This determines
221   // what kind of callback we use for the test.
222   CallbackType callback_type_;
223 
224   // Var ids that should be ignored when checking for leaks on shutdown.
225   std::set<int64_t> ignored_leaked_vars_;
226 
227   // The tests that were found in test_filter. The bool indicates whether the
228   // test should be run (i.e., it will be false if the test name was prefixed in
229   // the test_filter string).
230   //
231   // This is initialized lazily the first time that ShouldRunTest is called.
232   std::map<std::string, bool> filter_tests_;
233   // Flag indicating whether we have populated filter_tests_ yet.
234   bool have_populated_filter_tests_;
235   // This is initialized with the contents of filter_tests_. As each test is
236   // run, it is removed from remaining_tests_. When RunTests is finished,
237   // remaining_tests_ should be empty. Any remaining tests are tests that were
238   // listed in the test_filter but didn't match any calls to ShouldRunTest,
239   // meaning it was probably a typo. TestingInstance should log this and
240   // consider it a failure.
241   std::map<std::string, bool> remaining_tests_;
242 
243   // If ShouldRunTest is called but the given test name doesn't match anything
244   // in the test_filter, the test name will be added here. This allows
245   // TestingInstance to detect when not all tests were listed.
246   std::set<std::string> skipped_tests_;
247 
248 #if !(defined __native_client__)
249   // Holds the test object, if any was retrieved from CreateTestObject.
250   pp::VarPrivate test_object_;
251 #endif
252 };
253 
254 // This class is an implementation detail.
255 class TestCaseFactory {
256  public:
257   typedef TestCase* (*Method)(TestingInstance* instance);
258 
TestCaseFactory(const char * name,Method method)259   TestCaseFactory(const char* name, Method method)
260       : next_(head_),
261         name_(name),
262         method_(method) {
263     head_ = this;
264   }
265 
266  private:
267   friend class TestingInstance;
268 
269   TestCaseFactory* next_;
270   const char* name_;
271   Method method_;
272 
273   static TestCaseFactory* head_;
274 };
275 
276 // Use the REGISTER_TEST_CASE macro in your TestCase implementation file to
277 // register your TestCase.  If your test is named TestFoo, then add the
278 // following to test_foo.cc:
279 //
280 //   REGISTER_TEST_CASE(Foo);
281 //
282 // This will cause your test to be included in the set of known tests.
283 //
284 #define REGISTER_TEST_CASE(name)                                            \
285   static TestCase* Test##name##_FactoryMethod(TestingInstance* instance) {  \
286     return new Test##name(instance);                                        \
287   }                                                                         \
288   static TestCaseFactory g_Test##name_factory(                              \
289     #name, &Test##name##_FactoryMethod                                      \
290   )
291 
292 // Helper macro for calling functions implementing specific tests in the
293 // RunTest function. This assumes the function name is TestFoo where Foo is the
294 // test |name|.
295 #define RUN_TEST(name, test_filter) \
296   if (ShouldRunTest(#name, test_filter)) { \
297     set_callback_type(PP_OPTIONAL); \
298     PP_TimeTicks start_time(NowInTimeTicks()); \
299     instance_->LogTest(#name, \
300                        CheckResourcesAndVars(Test##name()), \
301                        start_time); \
302   }
303 
304 // Like RUN_TEST above but forces functions taking callbacks to complete
305 // asynchronously on success or error.
306 #define RUN_TEST_FORCEASYNC(name, test_filter) \
307   if (ShouldRunTest(#name, test_filter)) { \
308     set_callback_type(PP_REQUIRED); \
309     PP_TimeTicks start_time(NowInTimeTicks()); \
310     instance_->LogTest(#name"ForceAsync", \
311                        CheckResourcesAndVars(Test##name()), \
312                        start_time); \
313   }
314 
315 #define RUN_TEST_BLOCKING(test_case, name, test_filter) \
316   if (ShouldRunTest(#name, test_filter)) { \
317     set_callback_type(PP_BLOCKING); \
318     PP_TimeTicks start_time(NowInTimeTicks()); \
319     instance_->LogTest( \
320         #name"Blocking", \
321         CheckResourcesAndVars(RunOnThread(&test_case::Test##name)), \
322         start_time); \
323   }
324 
325 #define RUN_TEST_BACKGROUND(test_case, name, test_filter) \
326   if (ShouldRunTest(#name, test_filter)) { \
327     PP_TimeTicks start_time(NowInTimeTicks()); \
328     instance_->LogTest( \
329         #name"Background", \
330         CheckResourcesAndVars(RunOnThread(&test_case::Test##name)), \
331         start_time); \
332   }
333 
334 #define RUN_TEST_FORCEASYNC_AND_NOT(name, test_filter) \
335   do { \
336     RUN_TEST_FORCEASYNC(name, test_filter); \
337     RUN_TEST(name, test_filter); \
338   } while (false)
339 
340 // Run a test with all possible callback types.
341 #define RUN_CALLBACK_TEST(test_case, name, test_filter) \
342   do { \
343     RUN_TEST_FORCEASYNC(name, test_filter); \
344     RUN_TEST(name, test_filter); \
345     RUN_TEST_BLOCKING(test_case, name, test_filter); \
346     RUN_TEST_BACKGROUND(test_case, name, test_filter); \
347   } while (false)
348 
349 #define RUN_TEST_WITH_REFERENCE_CHECK(name, test_filter) \
350   if (ShouldRunTest(#name, test_filter)) { \
351     set_callback_type(PP_OPTIONAL); \
352     uint32_t objects = testing_interface_->GetLiveObjectsForInstance( \
353         instance_->pp_instance()); \
354     std::string error_message = Test##name(); \
355     if (error_message.empty() && \
356         testing_interface_->GetLiveObjectsForInstance( \
357             instance_->pp_instance()) != objects) \
358       error_message = MakeFailureMessage(__FILE__, __LINE__, \
359           "reference leak check"); \
360     PP_TimeTicks start_time(NowInTimeTicks()); \
361     instance_->LogTest(#name, \
362                        CheckResourcesAndVars(error_message), \
363                        start_time); \
364   }
365 // TODO(dmichael): Add CheckResourcesAndVars above when Windows tests pass
366 //                 cleanly. crbug.com/173503
367 
368 // Helper macros for checking values in tests, and returning a location
369 // description of the test fails.
370 #define ASSERT_TRUE(cmd) \
371   do { \
372     if (!(cmd)) \
373       return MakeFailureMessage(__FILE__, __LINE__, #cmd); \
374   } while (false)
375 #define ASSERT_FALSE(cmd) ASSERT_TRUE(!(cmd))
376 #define ASSERT_EQ(a, b) ASSERT_TRUE((a) == (b))
377 #define ASSERT_NE(a, b) ASSERT_TRUE((a) != (b))
378 #define ASSERT_LT(a, b) ASSERT_TRUE((a) < (b))
379 #define ASSERT_LE(a, b) ASSERT_TRUE((a) <= (b))
380 #define ASSERT_GT(a, b) ASSERT_TRUE((a) > (b))
381 #define ASSERT_GE(a, b) ASSERT_TRUE((a) >= (b))
382 
383 #define ASSERT_DOUBLE_EQ(a, b) ASSERT_TRUE( \
384     std::fabs((a)-(b)) <= std::numeric_limits<double>::epsilon())
385 
386 // Runs |function| as a subtest and asserts that it has passed.
387 #define ASSERT_SUBTEST_SUCCESS(function) \
388   do { \
389     std::string result = (function); \
390     if (!result.empty()) \
391       return result; \
392   } while (false)
393 
394 #define PASS() return std::string()
395 
396 #endif  // PPAPI_TESTS_TEST_CASE_H_
397