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