test_case.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 <set>
11#include <string>
12
13#include "ppapi/c/pp_resource.h"
14#include "ppapi/c/dev/ppb_testing_dev.h"
15#include "ppapi/cpp/dev/message_loop_dev.h"
16#include "ppapi/cpp/dev/scrollbar_dev.h"
17#include "ppapi/cpp/view.h"
18#include "ppapi/tests/test_utils.h"
19#include "ppapi/tests/testing_instance.h"
20
21#if (defined __native_client__)
22#include "ppapi/cpp/var.h"
23#else
24#include "ppapi/cpp/private/var_private.h"
25#endif
26
27class TestingInstance;
28
29namespace pp {
30namespace deprecated {
31class ScriptableObject;
32}
33}
34
35// Individual classes of tests derive from this generic test case.
36class TestCase {
37 public:
38  explicit TestCase(TestingInstance* instance);
39  virtual ~TestCase();
40
41  // Optionally override to do testcase specific initialization.
42  // Default implementation just returns true.
43  virtual bool Init();
44
45  // Override to implement the test case. It will be called after the plugin is
46  // first displayed, passing a string. If the string is empty, the
47  // should run all tests for this test case. Otherwise, it should run the test
48  // whose name matches test_filter exactly (if there is one). This should
49  // generally be implemented using the RUN_TEST* macros.
50  virtual void RunTests(const std::string& test_filter) = 0;
51
52  static std::string MakeFailureMessage(const char* file, int line,
53                                        const char* cmd);
54
55#if !(defined __native_client__)
56  // Returns the scriptable test object for the current test, if any.
57  // Internally, this uses CreateTestObject which each test overrides.
58  pp::VarPrivate GetTestObject();
59#endif
60
61  // A function that is invoked whenever HandleMessage is called on the
62  // associated TestingInstance. Default implementation does nothing.  TestCases
63  // that want to handle incoming postMessage events should override this
64  // method.
65  virtual void HandleMessage(const pp::Var& message_data);
66
67  // A function that is invoked whenever DidChangeView is called on the
68  // associated TestingInstance. Default implementation does nothing. TestCases
69  // that want to handle view changes should override this method.
70  virtual void DidChangeView(const pp::View& view);
71
72  // A function that is invoked whenever HandleInputEvent is called on the
73  // associated TestingInstance. Default implementation returns false. TestCases
74  // that want to handle view changes should override this method.
75  virtual bool HandleInputEvent(const pp::InputEvent& event);
76
77  void IgnoreLeakedVar(int64_t id);
78
79  TestingInstance* instance() { return instance_; }
80
81  const PPB_Testing_Dev* testing_interface() { return testing_interface_; }
82
83  static void QuitMainMessageLoop(PP_Instance instance);
84
85 protected:
86#if !(defined __native_client__)
87  // Overridden by each test to supply a ScriptableObject corresponding to the
88  // test. There can only be one object created for all tests in a given class,
89  // so be sure your object is designed to be re-used.
90  //
91  // This object should be created on the heap. Ownership will be passed to the
92  // caller. Return NULL if there is no supported test object (the default).
93  virtual pp::deprecated::ScriptableObject* CreateTestObject();
94#endif
95
96  // Checks whether the testing interface is available. Returns true if it is,
97  // false otherwise. If it is not available, adds a descriptive error. This is
98  // for use by tests that require the testing interface.
99  bool CheckTestingInterface();
100
101  // Makes sure the test is run over HTTP.
102  bool EnsureRunningOverHTTP();
103
104  // Return true if the given test name matches the filter. This is true if
105  // (a) filter is empty or (b) test_name and filter match exactly.
106  bool MatchesFilter(const std::string& test_name, const std::string& filter);
107
108  // Check for leaked resources and vars at the end of the test. If any exist,
109  // return a string with some information about the error. Otherwise, return
110  // an empty string.
111  //
112  // You should pass the error string from the test so far; if it is non-empty,
113  // CheckResourcesAndVars will do nothing and return the same string.
114  std::string CheckResourcesAndVars(std::string errors);
115
116  // Run the given test method on a background thread and return the result.
117  template <class T>
118  std::string RunOnThread(std::string(T::*test_to_run)()) {
119#ifdef ENABLE_PEPPER_THREADING
120    if (!testing_interface_) {
121      return "Testing blocking callbacks requires the testing interface. In "
122             "Chrome, use the --enable-pepper-testing flag.";
123    }
124    // These tests are only valid if running out-of-process (threading is not
125    // supported in-process). For in-process, just consider it a pass.
126    if (!testing_interface_->IsOutOfProcess())
127      return std::string();
128    pp::MessageLoop_Dev background_loop(instance_);
129    ThreadedTestRunner<T> runner(instance_->pp_instance(),
130        static_cast<T*>(this), test_to_run, background_loop);
131    RunOnThreadInternal(&ThreadedTestRunner<T>::ThreadFunction, &runner,
132                        testing_interface_);
133    return runner.result();
134#else
135    // If threading's not enabled, just treat it as success.
136    return std::string();
137#endif
138  }
139
140  // Pointer to the instance that owns us.
141  TestingInstance* instance_;
142
143  // NULL unless InitTestingInterface is called.
144  const PPB_Testing_Dev* testing_interface_;
145
146  // TODO(dmichael): Remove this, it's for temporary backwards compatibility so
147  // I don't have to change all the tests at once.
148  bool force_async_;
149
150  void set_callback_type(CallbackType callback_type) {
151    callback_type_ = callback_type;
152    // TODO(dmichael): Remove this; see comment on force_async_.
153    force_async_ = (callback_type_ == PP_REQUIRED);
154  }
155  CallbackType callback_type() const {
156    return callback_type_;
157  }
158
159 private:
160  template <class T>
161  class ThreadedTestRunner {
162   public:
163    typedef std::string(T::*TestMethodType)();
164    ThreadedTestRunner(PP_Instance instance,
165                       T* test_case,
166                       TestMethodType test_to_run,
167                       pp::MessageLoop_Dev loop)
168        : instance_(instance),
169          test_case_(test_case),
170          test_to_run_(test_to_run),
171          loop_(loop) {
172    }
173    const std::string& result() { return result_; }
174    static void ThreadFunction(void* runner) {
175      static_cast<ThreadedTestRunner<T>*>(runner)->Run();
176    }
177
178   private:
179    void Run() {
180      PP_DCHECK(PP_OK == loop_.AttachToCurrentThread());
181      result_ = (test_case_->*test_to_run_)();
182      // Now give the loop a chance to clean up.
183      loop_.PostQuit(true /* should_destroy */);
184      loop_.Run();
185      // Tell the main thread to quit its nested message loop, now that the test
186      // is complete.
187      TestCase::QuitMainMessageLoop(instance_);
188    }
189
190    std::string result_;
191    PP_Instance instance_;
192    T* test_case_;
193    TestMethodType test_to_run_;
194    pp::MessageLoop_Dev loop_;
195  };
196
197  // The internals for RunOnThread. This allows us to avoid including
198  // pp_thread.h in this header file, since it includes system headers like
199  // windows.h.
200  // RunOnThreadInternal launches a new thread to run |thread_func|, waits
201  // for it to complete using RunMessageLoop(), then joins.
202  void RunOnThreadInternal(void (*thread_func)(void*),
203                           void* thread_param,
204                           const PPB_Testing_Dev* testing_interface);
205
206  static void DoQuitMainMessageLoop(void* pp_instance, int32_t result);
207
208  // Passed when creating completion callbacks in some tests. This determines
209  // what kind of callback we use for the test.
210  CallbackType callback_type_;
211
212  // Var ids that should be ignored when checking for leaks on shutdown.
213  std::set<int64_t> ignored_leaked_vars_;
214
215#if !(defined __native_client__)
216  // Holds the test object, if any was retrieved from CreateTestObject.
217  pp::VarPrivate test_object_;
218#endif
219};
220
221// This class is an implementation detail.
222class TestCaseFactory {
223 public:
224  typedef TestCase* (*Method)(TestingInstance* instance);
225
226  TestCaseFactory(const char* name, Method method)
227      : next_(head_),
228        name_(name),
229        method_(method) {
230    head_ = this;
231  }
232
233 private:
234  friend class TestingInstance;
235
236  TestCaseFactory* next_;
237  const char* name_;
238  Method method_;
239
240  static TestCaseFactory* head_;
241};
242
243// Use the REGISTER_TEST_CASE macro in your TestCase implementation file to
244// register your TestCase.  If your test is named TestFoo, then add the
245// following to test_foo.cc:
246//
247//   REGISTER_TEST_CASE(Foo);
248//
249// This will cause your test to be included in the set of known tests.
250//
251#define REGISTER_TEST_CASE(name)                                            \
252  static TestCase* Test##name##_FactoryMethod(TestingInstance* instance) {  \
253    return new Test##name(instance);                                        \
254  }                                                                         \
255  static TestCaseFactory g_Test##name_factory(                              \
256    #name, &Test##name##_FactoryMethod                                      \
257  )
258
259// Helper macro for calling functions implementing specific tests in the
260// RunTest function. This assumes the function name is TestFoo where Foo is the
261// test |name|.
262#define RUN_TEST(name, test_filter) \
263  if (MatchesFilter(#name, test_filter)) { \
264    set_callback_type(PP_OPTIONAL); \
265    instance_->LogTest(#name, CheckResourcesAndVars(Test##name())); \
266  }
267
268// Like RUN_TEST above but forces functions taking callbacks to complete
269// asynchronously on success or error.
270#define RUN_TEST_FORCEASYNC(name, test_filter) \
271  if (MatchesFilter(#name, test_filter)) { \
272    set_callback_type(PP_REQUIRED); \
273    instance_->LogTest(#name"ForceAsync", \
274                       CheckResourcesAndVars(Test##name())); \
275  }
276
277#define RUN_TEST_BLOCKING(test_case, name, test_filter) \
278  if (MatchesFilter(#name, test_filter)) { \
279    set_callback_type(PP_BLOCKING); \
280    instance_->LogTest(#name"Blocking", \
281        CheckResourcesAndVars(RunOnThread(&test_case::Test##name))); \
282  }
283
284#define RUN_TEST_BACKGROUND(test_case, name, test_filter) \
285  if (MatchesFilter(#name, test_filter)) { \
286    instance_->LogTest(#name"Background", \
287        CheckResourcesAndVars(RunOnThread(&test_case::Test##name))); \
288  }
289
290#define RUN_TEST_FORCEASYNC_AND_NOT(name, test_filter) \
291  do { \
292    RUN_TEST_FORCEASYNC(name, test_filter); \
293    RUN_TEST(name, test_filter); \
294  } while (false)
295
296// Run a test with all possible callback types.
297#define RUN_CALLBACK_TEST(test_case, name, test_filter) \
298  do { \
299    RUN_TEST_FORCEASYNC(name, test_filter); \
300    RUN_TEST(name, test_filter); \
301    RUN_TEST_BLOCKING(test_case, name, test_filter); \
302    RUN_TEST_BACKGROUND(test_case, name, test_filter); \
303  } while (false)
304
305#define RUN_TEST_WITH_REFERENCE_CHECK(name, test_filter) \
306  if (MatchesFilter(#name, test_filter)) { \
307    set_callback_type(PP_OPTIONAL); \
308    uint32_t objects = testing_interface_->GetLiveObjectsForInstance( \
309        instance_->pp_instance()); \
310    std::string error_message = Test##name(); \
311    if (error_message.empty() && \
312        testing_interface_->GetLiveObjectsForInstance( \
313            instance_->pp_instance()) != objects) \
314      error_message = MakeFailureMessage(__FILE__, __LINE__, \
315          "reference leak check"); \
316    instance_->LogTest(#name, error_message); \
317  }
318
319// Helper macros for checking values in tests, and returning a location
320// description of the test fails.
321#define ASSERT_TRUE(cmd) \
322  if (!(cmd)) { \
323    return MakeFailureMessage(__FILE__, __LINE__, #cmd); \
324  }
325#define ASSERT_FALSE(cmd) ASSERT_TRUE(!(cmd))
326#define ASSERT_EQ(a, b) ASSERT_TRUE((a) == (b))
327#define ASSERT_NE(a, b) ASSERT_TRUE((a) != (b))
328
329#define ASSERT_DOUBLE_EQ(a, b) ASSERT_TRUE( \
330    std::fabs((a)-(b)) <= std::numeric_limits<double>::epsilon())
331
332// Runs |function| as a subtest and asserts that it has passed.
333#define ASSERT_SUBTEST_SUCCESS(function) \
334  do { \
335    std::string result = (function); \
336    if (!result.empty()) \
337      return result; \
338  } while (false)
339
340#define PASS() return std::string()
341
342#endif  // PPAPI_TESTS_TEST_CASE_H_
343