1 /* 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_METHOD0 timeout-capable extension. 48 */ 49 #define MOCK_TIMEOUT_METHOD0(Method, ...) \ 50 MOCK_METHOD0(egmock_##Method, __VA_ARGS__); \ 51 EGMOCK_TIMEOUT_METHOD_DEF_(Method); \ 52 virtual GMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); } 53 54 /** 55 * Gmock MOCK_METHOD1 timeout-capable extension. 56 */ 57 #define MOCK_TIMEOUT_METHOD1(Method, ...) \ 58 MOCK_METHOD1(egmock_##Method, __VA_ARGS__); \ 59 EGMOCK_TIMEOUT_METHOD_DEF_(Method); \ 60 virtual GMOCK_RESULT_(, __VA_ARGS__) Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \ 61 EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1); \ 62 } 63 64 /** 65 * Gmock MOCK_METHOD2 timeout-capable extension. 66 */ 67 #define MOCK_TIMEOUT_METHOD2(Method, ...) \ 68 MOCK_METHOD2(egmock_##Method, __VA_ARGS__); \ 69 EGMOCK_TIMEOUT_METHOD_DEF_(Method); \ 70 virtual GMOCK_RESULT_(, __VA_ARGS__) \ 71 Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, GMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \ 72 EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2); \ 73 } 74 75 /** 76 * Gmock EXPECT_CALL timeout-capable extension. 77 * 78 * It has slightly different syntax from the original macro, to make method name accessible. 79 * So, instead of typing 80 * EXPECT_CALL(account, charge(100, Currency::USD)); 81 * you need to inline arguments 82 * EXPECT_TIMEOUT_CALL(account, charge, 100, Currency::USD); 83 */ 84 #define EXPECT_TIMEOUT_CALL(obj, Method, ...) \ 85 (obj).egmock_called_##Method = false; \ 86 EXPECT_CALL(obj, egmock_##Method(__VA_ARGS__)) 87 88 /** 89 * Waits for an earlier EXPECT_TIMEOUT_CALL to execute. 90 * 91 * It does not fully support special constraints of the EXPECT_CALL clause, just proceeds when the 92 * first call to a given method comes. For example, in the following code: 93 * EXPECT_TIMEOUT_CALL(account, charge, 100, _); 94 * account.charge(50, Currency::USD); 95 * EXPECT_TIMEOUT_CALL_WAIT(account, charge, 500ms); 96 * the wait clause will just continue, as the charge method was called. 97 * 98 * @param obj object for a call 99 * @param Method the method to wait for 100 * @param timeout the maximum time for waiting 101 */ 102 #define EXPECT_TIMEOUT_CALL_WAIT(obj, Method, timeout) \ 103 { \ 104 std::unique_lock<std::mutex> lk((obj).egmock_mut_##Method); \ 105 if (!(obj).egmock_called_##Method) { \ 106 auto status = (obj).egmock_cond_##Method.wait_for(lk, timeout); \ 107 EXPECT_EQ(std::cv_status::no_timeout, status); \ 108 } \ 109 } 110 111 #endif // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT 112