1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef RTC_BASE_GUNIT_H_ 12 #define RTC_BASE_GUNIT_H_ 13 14 #include "rtc_base/fakeclock.h" 15 #include "rtc_base/logging.h" 16 #include "rtc_base/thread.h" 17 #if defined(GTEST_RELATIVE_PATH) 18 #include "test/gtest.h" 19 #else 20 #include "testing/base/public/gunit.h" 21 #endif 22 23 // Wait until "ex" is true, or "timeout" expires. 24 #define WAIT(ex, timeout) \ 25 for (int64_t start = rtc::SystemTimeMillis(); \ 26 !(ex) && rtc::SystemTimeMillis() < start + (timeout);) { \ 27 rtc::Thread::Current()->ProcessMessages(0); \ 28 rtc::Thread::Current()->SleepMs(1); \ 29 } 30 31 // This returns the result of the test in res, so that we don't re-evaluate 32 // the expression in the XXXX_WAIT macros below, since that causes problems 33 // when the expression is only true the first time you check it. 34 #define WAIT_(ex, timeout, res) \ 35 do { \ 36 int64_t start = rtc::SystemTimeMillis(); \ 37 res = (ex); \ 38 while (!res && rtc::SystemTimeMillis() < start + (timeout)) { \ 39 rtc::Thread::Current()->ProcessMessages(0); \ 40 rtc::Thread::Current()->SleepMs(1); \ 41 res = (ex); \ 42 } \ 43 } while (0) 44 45 // The typical EXPECT_XXXX and ASSERT_XXXXs, but done until true or a timeout. 46 // One can add failure message by appending "<< msg". 47 #define EXPECT_TRUE_WAIT(ex, timeout) \ 48 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 49 if (bool res = true) { \ 50 WAIT_(ex, timeout, res); \ 51 if (!res) \ 52 goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \ 53 } else \ 54 GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : EXPECT_TRUE(ex) 55 56 #define EXPECT_EQ_WAIT(v1, v2, timeout) \ 57 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 58 if (bool res = true) { \ 59 WAIT_(v1 == v2, timeout, res); \ 60 if (!res) \ 61 goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \ 62 } else \ 63 GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : EXPECT_EQ(v1, v2) 64 65 #define ASSERT_TRUE_WAIT(ex, timeout) \ 66 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 67 if (bool res = true) { \ 68 WAIT_(ex, timeout, res); \ 69 if (!res) \ 70 goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \ 71 } else \ 72 GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_TRUE(ex) 73 74 #define ASSERT_EQ_WAIT(v1, v2, timeout) \ 75 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 76 if (bool res = true) { \ 77 WAIT_(v1 == v2, timeout, res); \ 78 if (!res) \ 79 goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \ 80 } else \ 81 GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_EQ(v1, v2) 82 83 // Version with a "soft" timeout and a margin. This logs if the timeout is 84 // exceeded, but it only fails if the expression still isn't true after the 85 // margin time passes. 86 #define EXPECT_TRUE_WAIT_MARGIN(ex, timeout, margin) \ 87 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 88 if (bool res = true) { \ 89 WAIT_(ex, timeout, res); \ 90 if (res) \ 91 break; \ 92 RTC_LOG(LS_WARNING) << "Expression " << #ex << " still not true after " \ 93 << (timeout) << "ms; waiting an additional " << margin \ 94 << "ms"; \ 95 WAIT_(ex, margin, res); \ 96 if (!res) \ 97 goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \ 98 } else \ 99 GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : EXPECT_TRUE(ex) 100 101 // Wait until "ex" is true, or "timeout" expires, using fake clock where 102 // messages are processed every millisecond. 103 // TODO(pthatcher): Allow tests to control how many milliseconds to advance. 104 #define SIMULATED_WAIT(ex, timeout, clock) \ 105 for (int64_t start = rtc::TimeMillis(); \ 106 !(ex) && rtc::TimeMillis() < start + (timeout);) { \ 107 (clock).AdvanceTime(rtc::TimeDelta::FromMilliseconds(1)); \ 108 } 109 110 // This returns the result of the test in res, so that we don't re-evaluate 111 // the expression in the XXXX_WAIT macros below, since that causes problems 112 // when the expression is only true the first time you check it. 113 #define SIMULATED_WAIT_(ex, timeout, res, clock) \ 114 do { \ 115 int64_t start = rtc::TimeMillis(); \ 116 res = (ex); \ 117 while (!res && rtc::TimeMillis() < start + (timeout)) { \ 118 (clock).AdvanceTime(rtc::TimeDelta::FromMilliseconds(1)); \ 119 res = (ex); \ 120 } \ 121 } while (0) 122 123 // The typical EXPECT_XXXX, but done until true or a timeout with a fake clock. 124 #define EXPECT_TRUE_SIMULATED_WAIT(ex, timeout, clock) \ 125 do { \ 126 bool res; \ 127 SIMULATED_WAIT_(ex, timeout, res, clock); \ 128 if (!res) { \ 129 EXPECT_TRUE(ex); \ 130 } \ 131 } while (0) 132 133 #define EXPECT_EQ_SIMULATED_WAIT(v1, v2, timeout, clock) \ 134 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 135 if (bool res = true) { \ 136 SIMULATED_WAIT_(v1 == v2, timeout, res, clock); \ 137 if (!res) \ 138 goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \ 139 } else \ 140 GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : EXPECT_EQ(v1, v2) 141 142 #define ASSERT_TRUE_SIMULATED_WAIT(ex, timeout, clock) \ 143 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 144 if (bool res = true) { \ 145 SIMULATED_WAIT_(ex, timeout, res, clock); \ 146 if (!res) \ 147 goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \ 148 } else \ 149 GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_TRUE(ex) 150 151 #define ASSERT_EQ_SIMULATED_WAIT(v1, v2, timeout, clock) \ 152 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ 153 if (bool res = true) { \ 154 SIMULATED_WAIT_(v1 == v2, timeout, res, clock); \ 155 if (!res) \ 156 goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \ 157 } else \ 158 GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_EQ(v1, v2) 159 160 #endif // RTC_BASE_GUNIT_H_ 161