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/fake_clock.h"
15 #include "rtc_base/logging.h"
16 #include "rtc_base/thread.h"
17 #include "test/gtest.h"
18 
19 // Wait until "ex" is true, or "timeout" expires.
20 #define WAIT(ex, timeout)                                       \
21   for (int64_t start = rtc::SystemTimeMillis();                 \
22        !(ex) && rtc::SystemTimeMillis() < start + (timeout);) { \
23     rtc::Thread::Current()->ProcessMessages(0);                 \
24     rtc::Thread::Current()->SleepMs(1);                         \
25   }
26 
27 // This returns the result of the test in res, so that we don't re-evaluate
28 // the expression in the XXXX_WAIT macros below, since that causes problems
29 // when the expression is only true the first time you check it.
30 #define WAIT_(ex, timeout, res)                                   \
31   do {                                                            \
32     int64_t start = rtc::SystemTimeMillis();                      \
33     res = (ex);                                                   \
34     while (!res && rtc::SystemTimeMillis() < start + (timeout)) { \
35       rtc::Thread::Current()->ProcessMessages(0);                 \
36       rtc::Thread::Current()->SleepMs(1);                         \
37       res = (ex);                                                 \
38     }                                                             \
39   } while (0)
40 
41 // The typical EXPECT_XXXX and ASSERT_XXXXs, but done until true or a timeout.
42 // One can add failure message by appending "<< msg".
43 #define EXPECT_TRUE_WAIT(ex, timeout)                   \
44   GTEST_AMBIGUOUS_ELSE_BLOCKER_                         \
45   if (bool res = true) {                                \
46     WAIT_(ex, timeout, res);                            \
47     if (!res)                                           \
48       goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \
49   } else                                                \
50     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : EXPECT_TRUE(ex)
51 
52 #define EXPECT_EQ_WAIT(v1, v2, timeout)                 \
53   GTEST_AMBIGUOUS_ELSE_BLOCKER_                         \
54   if (bool res = true) {                                \
55     WAIT_(v1 == v2, timeout, res);                      \
56     if (!res)                                           \
57       goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \
58   } else                                                \
59     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : EXPECT_EQ(v1, v2)
60 
61 #define ASSERT_TRUE_WAIT(ex, timeout)                   \
62   GTEST_AMBIGUOUS_ELSE_BLOCKER_                         \
63   if (bool res = true) {                                \
64     WAIT_(ex, timeout, res);                            \
65     if (!res)                                           \
66       goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \
67   } else                                                \
68     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_TRUE(ex)
69 
70 #define ASSERT_EQ_WAIT(v1, v2, timeout)                 \
71   GTEST_AMBIGUOUS_ELSE_BLOCKER_                         \
72   if (bool res = true) {                                \
73     WAIT_(v1 == v2, timeout, res);                      \
74     if (!res)                                           \
75       goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \
76   } else                                                \
77     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_EQ(v1, v2)
78 
79 // Version with a "soft" timeout and a margin. This logs if the timeout is
80 // exceeded, but it only fails if the expression still isn't true after the
81 // margin time passes.
82 #define EXPECT_TRUE_WAIT_MARGIN(ex, timeout, margin)                           \
83   GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                \
84   if (bool res = true) {                                                       \
85     WAIT_(ex, timeout, res);                                                   \
86     if (res)                                                                   \
87       break;                                                                   \
88     RTC_LOG(LS_WARNING) << "Expression " << #ex << " still not true after "    \
89                         << (timeout) << "ms; waiting an additional " << margin \
90                         << "ms";                                               \
91     WAIT_(ex, margin, res);                                                    \
92     if (!res)                                                                  \
93       goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__);                        \
94   } else                                                                       \
95     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : EXPECT_TRUE(ex)
96 
97 // Wait until "ex" is true, or "timeout" expires, using fake clock where
98 // messages are processed every millisecond.
99 // TODO(pthatcher): Allow tests to control how many milliseconds to advance.
100 #define SIMULATED_WAIT(ex, timeout, clock)                \
101   for (int64_t start = rtc::TimeMillis();                 \
102        !(ex) && rtc::TimeMillis() < start + (timeout);) { \
103     (clock).AdvanceTime(webrtc::TimeDelta::Millis(1));    \
104   }
105 
106 // This returns the result of the test in res, so that we don't re-evaluate
107 // the expression in the XXXX_WAIT macros below, since that causes problems
108 // when the expression is only true the first time you check it.
109 #define SIMULATED_WAIT_(ex, timeout, res, clock)            \
110   do {                                                      \
111     int64_t start = rtc::TimeMillis();                      \
112     res = (ex);                                             \
113     while (!res && rtc::TimeMillis() < start + (timeout)) { \
114       (clock).AdvanceTime(webrtc::TimeDelta::Millis(1));    \
115       res = (ex);                                           \
116     }                                                       \
117   } while (0)
118 
119 // The typical EXPECT_XXXX, but done until true or a timeout with a fake clock.
120 #define EXPECT_TRUE_SIMULATED_WAIT(ex, timeout, clock) \
121   do {                                                 \
122     bool res;                                          \
123     SIMULATED_WAIT_(ex, timeout, res, clock);          \
124     if (!res) {                                        \
125       EXPECT_TRUE(ex);                                 \
126     }                                                  \
127   } while (0)
128 
129 #define EXPECT_EQ_SIMULATED_WAIT(v1, v2, timeout, clock) \
130   GTEST_AMBIGUOUS_ELSE_BLOCKER_                          \
131   if (bool res = true) {                                 \
132     SIMULATED_WAIT_(v1 == v2, timeout, res, clock);      \
133     if (!res)                                            \
134       goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__);  \
135   } else                                                 \
136     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : EXPECT_EQ(v1, v2)
137 
138 #define ASSERT_TRUE_SIMULATED_WAIT(ex, timeout, clock)  \
139   GTEST_AMBIGUOUS_ELSE_BLOCKER_                         \
140   if (bool res = true) {                                \
141     SIMULATED_WAIT_(ex, timeout, res, clock);           \
142     if (!res)                                           \
143       goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__); \
144   } else                                                \
145     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_TRUE(ex)
146 
147 #define ASSERT_EQ_SIMULATED_WAIT(v1, v2, timeout, clock) \
148   GTEST_AMBIGUOUS_ELSE_BLOCKER_                          \
149   if (bool res = true) {                                 \
150     SIMULATED_WAIT_(v1 == v2, timeout, res, clock);      \
151     if (!res)                                            \
152       goto GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__);  \
153   } else                                                 \
154     GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_EQ(v1, v2)
155 
156 // Usage: EXPECT_PRED_FORMAT2(AssertStartsWith, text, "prefix");
157 testing::AssertionResult AssertStartsWith(const char* text_expr,
158                                           const char* prefix_expr,
159                                           absl::string_view text,
160                                           absl::string_view prefix);
161 
162 // Usage: EXPECT_PRED_FORMAT2(AssertStringContains, str, "substring");
163 testing::AssertionResult AssertStringContains(const char* str_expr,
164                                               const char* substr_expr,
165                                               const std::string& str,
166                                               const std::string& substr);
167 
168 #endif  // RTC_BASE_GUNIT_H_
169