blob: fa1114f0a76956a7df130a3541b31398fc6b619d [file] [log] [blame]
Tomasz Wasilczykc9ba6462017-07-07 13:28:00 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
17#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
18
19#include <gmock/gmock.h>
20#include <thread>
21
22/**
23 * Common helper objects for gmock timeout extension.
24 *
25 * INTERNAL IMPLEMENTATION - don't use in user code.
26 */
27#define EGMOCK_TIMEOUT_METHOD_DEF_(Method, ...) \
28 std::atomic<bool> egmock_called_##Method; \
29 std::mutex egmock_mut_##Method; \
30 std::condition_variable egmock_cond_##Method;
31
32/**
33 * Common method body for gmock timeout extension.
34 *
35 * INTERNAL IMPLEMENTATION - don't use in user code.
36 */
37#define EGMOCK_TIMEOUT_METHOD_BODY_(Method, ...) \
38 auto ret = egmock_##Method(__VA_ARGS__); \
39 { \
40 std::lock_guard<std::mutex> lk(egmock_mut_##Method); \
41 egmock_called_##Method = true; \
42 egmock_cond_##Method.notify_all(); \
43 } \
44 return ret;
45
46/**
47 * Gmock MOCK_METHOD1 timeout-capable extension.
48 */
49#define MOCK_TIMEOUT_METHOD1(Method, ...) \
50 MOCK_METHOD1(egmock_##Method, __VA_ARGS__); \
51 EGMOCK_TIMEOUT_METHOD_DEF_(Method); \
52 virtual GMOCK_RESULT_(, __VA_ARGS__) Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \
53 EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1); \
54 }
55
56/**
57 * Gmock MOCK_METHOD2 timeout-capable extension.
58 */
59#define MOCK_TIMEOUT_METHOD2(Method, ...) \
60 MOCK_METHOD2(egmock_##Method, __VA_ARGS__); \
61 EGMOCK_TIMEOUT_METHOD_DEF_(Method); \
62 virtual GMOCK_RESULT_(, __VA_ARGS__) \
63 Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, GMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \
64 EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2); \
65 }
66
67/**
68 * Gmock EXPECT_CALL timeout-capable extension.
69 *
70 * It has slightly different syntax from the original macro, to make method name accessible.
71 * So, instead of typing
72 * EXPECT_CALL(account, charge(100, Currency::USD));
73 * you need to inline arguments
74 * EXPECT_TIMEOUT_CALL(account, charge, 100, Currency::USD);
75 */
76#define EXPECT_TIMEOUT_CALL(obj, Method, ...) \
77 (obj).egmock_called_##Method = false; \
78 EXPECT_CALL(obj, egmock_##Method(__VA_ARGS__))
79
80/**
81 * Waits for an earlier EXPECT_TIMEOUT_CALL to execute.
82 *
83 * It does not fully support special constraints of the EXPECT_CALL clause, just proceeds when the
84 * first call to a given method comes. For example, in the following code:
85 * EXPECT_TIMEOUT_CALL(account, charge, 100, _);
86 * account.charge(50, Currency::USD);
87 * EXPECT_TIMEOUT_CALL_WAIT(account, charge, 500ms);
88 * the wait clause will just continue, as the charge method was called.
89 *
90 * @param obj object for a call
91 * @param Method the method to wait for
92 * @param timeout the maximum time for waiting
93 */
94#define EXPECT_TIMEOUT_CALL_WAIT(obj, Method, timeout) \
95 { \
96 std::unique_lock<std::mutex> lk((obj).egmock_mut_##Method); \
97 if (!(obj).egmock_called_##Method) { \
98 auto status = (obj).egmock_cond_##Method.wait_for(lk, timeout); \
99 EXPECT_EQ(std::cv_status::no_timeout, status); \
100 } \
101 }
102
103#endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT