| /****************************************************************************** |
| * |
| * Copyright 2014 Google, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ******************************************************************************/ |
| |
| #pragma once |
| |
| // Helper macros for stubbing out functions and modules for testing. |
| |
| // Stub out a function, with call counting and mode awareness |
| #define STUB_FUNCTION(ret, name, params) \ |
| UNUSED_ATTR static int name##_callcount; \ |
| static ret name params { \ |
| UNUSED_ATTR int _local_callcount = name##_callcount; \ |
| name##_callcount++; |
| |
| // Expect a certain number of calls to the specified stub function |
| #define EXPECT_CALL_COUNT(name, count) \ |
| EXPECT_EQ((count), (name##_callcount)) \ |
| << "expected " #name " to be called " #count " times" |
| |
| // Reset the call count for the specificed stub function |
| #define RESET_CALL_COUNT(name) ((name##_callcount) = 0) |
| |
| // Use this in a stub function to catch unexpected calls. |
| // Prints out a nice message including the call count, the |
| // stub function name, and the mode index (sadly no mode name) |
| #define UNEXPECTED_CALL \ |
| EXPECT_TRUE(false) << "unexpected call " << _local_callcount << " to " \ |
| << __func__ << " during mode " << (int)_current_mode |
| |
| #define MODE_IS(mode) (_current_mode == (mode)) |
| |
| // Macro selection helpers |
| #define OVERLOAD_CAT(A, B) A##B |
| #define OVERLOAD_SELECT(NAME, NUM) OVERLOAD_CAT(NAME##_, NUM) |
| #define OVERLOAD_GET_COUNT(_1, _2, _3, _4, _5, _6, COUNT, ...) COUNT |
| #define OVERLOAD_VA_SIZE(...) OVERLOAD_GET_COUNT(__VA_ARGS__, 6, 5, 4, 3, 2, 1) |
| #define OVERLOAD_OF(NAME, ...) \ |
| OVERLOAD_SELECT(NAME, OVERLOAD_VA_SIZE(__VA_ARGS__))(__VA_ARGS__) |
| |
| // Use this to branch stub function execution to a specific mode or modes. |
| // Treat it like an if statement. For example: |
| // |
| // DURING(dinner) EXPECT_EQ(bread_pudding, food); |
| // DURING(midday_snack, midnight_snack) EXPECT_EQ(chocolate, food); |
| #define DURING(...) OVERLOAD_OF(DURING, __VA_ARGS__) |
| |
| #define DURING_1(mode0) if (MODE_IS(mode0)) |
| #define DURING_2(mode0, mode1) if (MODE_IS(mode0) || MODE_IS(mode1)) |
| #define DURING_3(mode0, mode1, mode2) \ |
| if (MODE_IS(mode0) || MODE_IS(mode1) || MODE_IS(mode2)) |
| #define DURING_4(mode0, mode1, mode2, mode3) \ |
| if (MODE_IS(mode0) || MODE_IS(mode1) || MODE_IS(mode2) || MODE_IS(mode3)) |
| #define DURING_5(mode0, mode1, mode2, mode3, mode4) \ |
| if (MODE_IS(mode0) || MODE_IS(mode1) || MODE_IS(mode2) || MODE_IS(mode3) || \ |
| MODE_IS(mode4)) |
| #define DURING_6(mode0, mode1, mode2, mode3, mode4, mode5) \ |
| if (MODE_IS(mode0) || MODE_IS(mode1) || MODE_IS(mode2) || MODE_IS(mode3) || \ |
| MODE_IS(mode4) || MODE_IS(mode5)) |
| |
| // Use this to branch stub function exeuction to a specific call |
| // count index (zero based). Treat it like an if statement. |
| // Usually most helpful following a DURING clause. For example: |
| // |
| // DURING (breakfast) AT_CALL(0) EXPECT_EQ(bacon, food); |
| // |
| // or |
| // |
| // DURING (three_course_meal) { |
| // AT_CALL(0) EXPECT_EQ(shrimp_cocktail, food); |
| // AT_CALL(1) EXPECT_EQ(bacon_wrapped_bacon, food); |
| // AT_CALL(1) EXPECT_EQ(chocolate_covered_fake_blueberries, food); |
| // } |
| #define AT_CALL(index) if (_local_callcount == (index)) |
| |
| // Declare all the available test modes for the DURING clauses |
| // For example: |
| // |
| // DECLARE_TEST_MODES(breakfast, lunch, dinner); |
| #define DECLARE_TEST_MODES(...) \ |
| typedef enum { __VA_ARGS__ } _test_modes_t; \ |
| static _test_modes_t _current_mode; |
| |
| // Get the current test mode |
| #define CURRENT_TEST_MODE _current_mode |
| |
| #define TEST_MODES_T _test_modes_t |