summaryrefslogtreecommitdiffstats
path: root/ceee/testing/utils/mock_static.h
diff options
context:
space:
mode:
Diffstat (limited to 'ceee/testing/utils/mock_static.h')
-rw-r--r--ceee/testing/utils/mock_static.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/ceee/testing/utils/mock_static.h b/ceee/testing/utils/mock_static.h
new file mode 100644
index 0000000..07b4cda
--- /dev/null
+++ b/ceee/testing/utils/mock_static.h
@@ -0,0 +1,161 @@
+// 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.
+//
+// Framework for mocking sets of static functions using SideStep, so that
+// no code change is needed in the static functions themselves.
+//
+// Note that tiny functions may get inlined by the compiler in debug builds,
+// so this approach is not suitable for tiny functions you need to unit test in
+// release mode. Mock classes based on this framework are further limited to
+// use from a single thread at a time, they are non-nestable, and only intended
+// for testing code.
+//
+// To define a new static mock class, the structure is as follows:
+//
+// === cut here ===
+// MOCK_STATIC_CLASS_BEGIN(MockClassName)
+// MOCK_STATIC_INIT_BEGIN(MockClassName)
+// MOCK_STATIC_INIT(IsWindow);
+// MOCK_STATIC_INIT2(SomeClass::SomeStatic, SomeStatic);
+// ... more MOCK_STATIC_INIT(2) macros ...
+// MOCK_STATIC_INIT_END()
+//
+// MOCK_STATIC1(BOOL, CALLBACK, IsWindow, HWND);
+// MOCK_STATIC3(BOOL,, SomeStatic, SomeClass*, int, int);
+// ... more MOCK_STATICX macros ...
+// MOCK_STATIC_CLASS_END(MockClassName)
+// === cut here ===
+//
+// Note that each function being mocked appears twice, once in the
+// initialization map (between MOCK_STATIC_INIT_BEGIN and _END) and again
+// in the method map (the MOCK_STATICX macros). For further details see
+// documentation of the macros.
+
+#ifndef CEEE_TESTING_UTILS_MOCK_STATIC_H_
+#define CEEE_TESTING_UTILS_MOCK_STATIC_H_
+
+#include "base/scoped_vector.h"
+#include "ceee/testing/sidestep/auto_testing_hook.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace testing {
+
+// A base class for mock objects that mock sets of static functions. Used via
+// MOCK_STATIC_XYZ macros below.
+class MockStatic {
+ public:
+ virtual ~MockStatic() {}
+
+ protected:
+ ScopedVector<sidestep::AutoTestingHookBase> hooks_;
+};
+
+} // namespace testing
+
+// Begins definition of a static mock class named ClassName.
+#define MOCK_STATIC_CLASS_BEGIN(ClassName) \
+ class ClassName : public testing::MockStatic { \
+ public: \
+ virtual ~ClassName() { \
+ current_ = NULL; \
+ } \
+ static ClassName* GetCurrent() { return current_; } \
+ private: \
+ static ClassName* current_; // NOLINT
+
+// Begins the initialization map of a static mock class named ClassName.
+#define MOCK_STATIC_INIT_BEGIN(ClassName) \
+ public: \
+ ClassName() { \
+ current_ = this;
+
+// Add this to the initialization map of a static mock class to mock a
+// global function named function_name.
+#define MOCK_STATIC_INIT(function_name) \
+ hooks_.push_back(sidestep::MakeTestingHookHolder(::##function_name, \
+ &function_name##Hook));
+
+// Add this to the initialization map of a static mock class to mock a
+// static function that is not global (e.g. in a namespace or a class function)
+// @param function The function to mock
+// @param method_name The name of the mock method you are defining for this
+// function using one of the MOCK_STATICX macros below.
+#define MOCK_STATIC_INIT2(function, method_name) \
+ hooks_.push_back(sidestep::MakeTestingHookHolder(function, \
+ &method_name##Hook));
+
+// Ends the initialization map of a static mock class.
+#define MOCK_STATIC_INIT_END() \
+ }
+
+// Each of the following MOCK_STATICX macros defines a mock method taking X
+// arguments and a corresponding static function, used as a hook on the
+// production function, that redirects calls to your mock method for the
+// lifetime of the static mock object.
+//
+// @param return_type Return type of the function you are mocking.
+// @param cconv The calling convention of the function you are mocking.
+// @param name The name of the mock method. For global functions, this must
+// match the name of the global function. For non-global static functions,
+// it must match the method_name you provided in the MOCK_STATIC_INIT2
+// macro.
+// @param t1 The type of the 1st parameter of the function.
+// @param t2 The type of the 2nd parameter of the function.
+// @param t3 The type of the 3rd parameter of the function.
+// @param t4 The type of the 4th parameter of the function.
+// @param t5 The type of the 5th parameter of the function.
+// @param t6 The type of the 6th parameter of the function.
+// @param t7 The type of the 7th parameter of the function.
+#define MOCK_STATIC0(return_type, cconv, name) \
+ MOCK_METHOD0(name, return_type()); \
+ static return_type cconv name##Hook () { \
+ return GetCurrent()->name(); \
+ } // NOLINT
+#define MOCK_STATIC1(return_type, cconv, name, t1) \
+ MOCK_METHOD1(name, return_type(t1)); \
+ static return_type cconv name##Hook (t1 p1) { \
+ return GetCurrent()->name(p1); \
+ } // NOLINT
+#define MOCK_STATIC2(return_type, cconv, name, t1, t2) \
+ MOCK_METHOD2(name, return_type(t1, t2)); \
+ static return_type cconv name##Hook (t1 p1, t2 p2) { \
+ return GetCurrent()->name(p1, p2); \
+ } // NOLINT
+#define MOCK_STATIC3(return_type, cconv, name, t1, t2, t3) \
+ MOCK_METHOD3(name, return_type(t1, t2, t3)); \
+ static return_type cconv name##Hook (t1 p1, t2 p2, t3 p3) { \
+ return GetCurrent()->name(p1, p2, p3); \
+ } // NOLINT
+#define MOCK_STATIC4(return_type, cconv, name, t1, t2, t3, t4) \
+ MOCK_METHOD4(name, return_type(t1, t2, t3, t4)); \
+ static return_type cconv name##Hook (t1 p1, t2 p2, t3 p3, t4 p4) { \
+ return GetCurrent()->name(p1, p2, p3, p4); \
+ } // NOLINT
+#define MOCK_STATIC5(return_type, cconv, name, \
+ t1, t2, t3, t4, t5) \
+ MOCK_METHOD5(name, return_type(t1, t2, t3, t4, t5)); \
+ static return_type cconv name##Hook (t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) { \
+ return GetCurrent()->name(p1, p2, p3, p4, p5); \
+ } // NOLINT
+#define MOCK_STATIC6(return_type, cconv, name, \
+ t1, t2, t3, t4, t5, t6) \
+ MOCK_METHOD6(name, return_type(t1, t2, t3, t4, t5, t6)); \
+ static return_type cconv name##Hook ( \
+ t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) { \
+ return GetCurrent()->name(p1, p2, p3, p4, p5, p6); \
+ } // NOLINT
+#define MOCK_STATIC7(return_type, cconv, name, \
+ t1, t2, t3, t4, t5, t6, t7) \
+ MOCK_METHOD7(name, return_type(t1, t2, t3, t4, t5, t6, t7)); \
+ static return_type cconv name##Hook ( \
+ t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) { \
+ return GetCurrent()->name(p1, p2, p3, p4, p5, p6, p7); \
+ } // NOLINT
+
+// Ends definition of a static mock class named ClassName.
+#define MOCK_STATIC_CLASS_END(ClassName) \
+ }; \
+ __declspec(selectany) ClassName* ClassName::current_ = NULL;
+
+#endif // CEEE_TESTING_UTILS_MOCK_STATIC_H_