]>
Commit | Line | Data |
---|---|---|
31f18b77 FG |
1 | // Copyright 2008, Google Inc. |
2 | // All rights reserved. | |
3 | // | |
4 | // Redistribution and use in source and binary forms, with or without | |
5 | // modification, are permitted provided that the following conditions are | |
6 | // met: | |
7 | // | |
8 | // * Redistributions of source code must retain the above copyright | |
9 | // notice, this list of conditions and the following disclaimer. | |
10 | // * Redistributions in binary form must reproduce the above | |
11 | // copyright notice, this list of conditions and the following disclaimer | |
12 | // in the documentation and/or other materials provided with the | |
13 | // distribution. | |
14 | // * Neither the name of Google Inc. nor the names of its | |
15 | // contributors may be used to endorse or promote products derived from | |
16 | // this software without specific prior written permission. | |
17 | // | |
18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 | // | |
31f18b77 | 30 | // This file tests the internal cross-platform support utilities. |
1e59de90 | 31 | #include <stdio.h> |
31f18b77 FG |
32 | |
33 | #include "gtest/internal/gtest-port.h" | |
34 | ||
31f18b77 FG |
35 | #if GTEST_OS_MAC |
36 | # include <time.h> | |
37 | #endif // GTEST_OS_MAC | |
38 | ||
39 | #include <list> | |
1e59de90 | 40 | #include <memory> |
31f18b77 FG |
41 | #include <utility> // For std::pair and std::make_pair. |
42 | #include <vector> | |
43 | ||
44 | #include "gtest/gtest.h" | |
45 | #include "gtest/gtest-spi.h" | |
31f18b77 | 46 | #include "src/gtest-internal-inl.h" |
31f18b77 FG |
47 | |
48 | using std::make_pair; | |
49 | using std::pair; | |
50 | ||
51 | namespace testing { | |
52 | namespace internal { | |
53 | ||
54 | TEST(IsXDigitTest, WorksForNarrowAscii) { | |
55 | EXPECT_TRUE(IsXDigit('0')); | |
56 | EXPECT_TRUE(IsXDigit('9')); | |
57 | EXPECT_TRUE(IsXDigit('A')); | |
58 | EXPECT_TRUE(IsXDigit('F')); | |
59 | EXPECT_TRUE(IsXDigit('a')); | |
60 | EXPECT_TRUE(IsXDigit('f')); | |
61 | ||
62 | EXPECT_FALSE(IsXDigit('-')); | |
63 | EXPECT_FALSE(IsXDigit('g')); | |
64 | EXPECT_FALSE(IsXDigit('G')); | |
65 | } | |
66 | ||
67 | TEST(IsXDigitTest, ReturnsFalseForNarrowNonAscii) { | |
1e59de90 | 68 | EXPECT_FALSE(IsXDigit(static_cast<char>('\x80'))); |
31f18b77 FG |
69 | EXPECT_FALSE(IsXDigit(static_cast<char>('0' | '\x80'))); |
70 | } | |
71 | ||
72 | TEST(IsXDigitTest, WorksForWideAscii) { | |
73 | EXPECT_TRUE(IsXDigit(L'0')); | |
74 | EXPECT_TRUE(IsXDigit(L'9')); | |
75 | EXPECT_TRUE(IsXDigit(L'A')); | |
76 | EXPECT_TRUE(IsXDigit(L'F')); | |
77 | EXPECT_TRUE(IsXDigit(L'a')); | |
78 | EXPECT_TRUE(IsXDigit(L'f')); | |
79 | ||
80 | EXPECT_FALSE(IsXDigit(L'-')); | |
81 | EXPECT_FALSE(IsXDigit(L'g')); | |
82 | EXPECT_FALSE(IsXDigit(L'G')); | |
83 | } | |
84 | ||
85 | TEST(IsXDigitTest, ReturnsFalseForWideNonAscii) { | |
86 | EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(0x80))); | |
87 | EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(L'0' | 0x80))); | |
88 | EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(L'0' | 0x100))); | |
89 | } | |
90 | ||
91 | class Base { | |
92 | public: | |
31f18b77 FG |
93 | Base() : member_(0) {} |
94 | explicit Base(int n) : member_(n) {} | |
1e59de90 TL |
95 | Base(const Base&) = default; |
96 | Base& operator=(const Base&) = default; | |
31f18b77 FG |
97 | virtual ~Base() {} |
98 | int member() { return member_; } | |
99 | ||
100 | private: | |
101 | int member_; | |
102 | }; | |
103 | ||
104 | class Derived : public Base { | |
105 | public: | |
106 | explicit Derived(int n) : Base(n) {} | |
107 | }; | |
108 | ||
109 | TEST(ImplicitCastTest, ConvertsPointers) { | |
110 | Derived derived(0); | |
111 | EXPECT_TRUE(&derived == ::testing::internal::ImplicitCast_<Base*>(&derived)); | |
112 | } | |
113 | ||
114 | TEST(ImplicitCastTest, CanUseInheritance) { | |
115 | Derived derived(1); | |
116 | Base base = ::testing::internal::ImplicitCast_<Base>(derived); | |
117 | EXPECT_EQ(derived.member(), base.member()); | |
118 | } | |
119 | ||
120 | class Castable { | |
121 | public: | |
122 | explicit Castable(bool* converted) : converted_(converted) {} | |
123 | operator Base() { | |
124 | *converted_ = true; | |
125 | return Base(); | |
126 | } | |
127 | ||
128 | private: | |
129 | bool* converted_; | |
130 | }; | |
131 | ||
132 | TEST(ImplicitCastTest, CanUseNonConstCastOperator) { | |
133 | bool converted = false; | |
134 | Castable castable(&converted); | |
135 | Base base = ::testing::internal::ImplicitCast_<Base>(castable); | |
136 | EXPECT_TRUE(converted); | |
137 | } | |
138 | ||
139 | class ConstCastable { | |
140 | public: | |
141 | explicit ConstCastable(bool* converted) : converted_(converted) {} | |
142 | operator Base() const { | |
143 | *converted_ = true; | |
144 | return Base(); | |
145 | } | |
146 | ||
147 | private: | |
148 | bool* converted_; | |
149 | }; | |
150 | ||
151 | TEST(ImplicitCastTest, CanUseConstCastOperatorOnConstValues) { | |
152 | bool converted = false; | |
153 | const ConstCastable const_castable(&converted); | |
154 | Base base = ::testing::internal::ImplicitCast_<Base>(const_castable); | |
155 | EXPECT_TRUE(converted); | |
156 | } | |
157 | ||
158 | class ConstAndNonConstCastable { | |
159 | public: | |
160 | ConstAndNonConstCastable(bool* converted, bool* const_converted) | |
161 | : converted_(converted), const_converted_(const_converted) {} | |
162 | operator Base() { | |
163 | *converted_ = true; | |
164 | return Base(); | |
165 | } | |
166 | operator Base() const { | |
167 | *const_converted_ = true; | |
168 | return Base(); | |
169 | } | |
170 | ||
171 | private: | |
172 | bool* converted_; | |
173 | bool* const_converted_; | |
174 | }; | |
175 | ||
176 | TEST(ImplicitCastTest, CanSelectBetweenConstAndNonConstCasrAppropriately) { | |
177 | bool converted = false; | |
178 | bool const_converted = false; | |
179 | ConstAndNonConstCastable castable(&converted, &const_converted); | |
180 | Base base = ::testing::internal::ImplicitCast_<Base>(castable); | |
181 | EXPECT_TRUE(converted); | |
182 | EXPECT_FALSE(const_converted); | |
183 | ||
184 | converted = false; | |
185 | const_converted = false; | |
186 | const ConstAndNonConstCastable const_castable(&converted, &const_converted); | |
187 | base = ::testing::internal::ImplicitCast_<Base>(const_castable); | |
188 | EXPECT_FALSE(converted); | |
189 | EXPECT_TRUE(const_converted); | |
190 | } | |
191 | ||
192 | class To { | |
193 | public: | |
194 | To(bool* converted) { *converted = true; } // NOLINT | |
195 | }; | |
196 | ||
197 | TEST(ImplicitCastTest, CanUseImplicitConstructor) { | |
198 | bool converted = false; | |
199 | To to = ::testing::internal::ImplicitCast_<To>(&converted); | |
200 | (void)to; | |
201 | EXPECT_TRUE(converted); | |
202 | } | |
203 | ||
1e59de90 TL |
204 | // The following code intentionally tests a suboptimal syntax. |
205 | #ifdef __GNUC__ | |
206 | #pragma GCC diagnostic push | |
207 | #pragma GCC diagnostic ignored "-Wdangling-else" | |
208 | #pragma GCC diagnostic ignored "-Wempty-body" | |
209 | #pragma GCC diagnostic ignored "-Wpragmas" | |
210 | #endif | |
31f18b77 FG |
211 | TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) { |
212 | if (AlwaysFalse()) | |
213 | GTEST_CHECK_(false) << "This should never be executed; " | |
214 | "It's a compilation test only."; | |
215 | ||
216 | if (AlwaysTrue()) | |
217 | GTEST_CHECK_(true); | |
218 | else | |
219 | ; // NOLINT | |
220 | ||
221 | if (AlwaysFalse()) | |
222 | ; // NOLINT | |
223 | else | |
224 | GTEST_CHECK_(true) << ""; | |
225 | } | |
1e59de90 TL |
226 | #ifdef __GNUC__ |
227 | #pragma GCC diagnostic pop | |
228 | #endif | |
31f18b77 FG |
229 | |
230 | TEST(GtestCheckSyntaxTest, WorksWithSwitch) { | |
231 | switch (0) { | |
232 | case 1: | |
233 | break; | |
234 | default: | |
235 | GTEST_CHECK_(true); | |
236 | } | |
237 | ||
238 | switch (0) | |
239 | case 0: | |
240 | GTEST_CHECK_(true) << "Check failed in switch case"; | |
241 | } | |
242 | ||
243 | // Verifies behavior of FormatFileLocation. | |
244 | TEST(FormatFileLocationTest, FormatsFileLocation) { | |
245 | EXPECT_PRED_FORMAT2(IsSubstring, "foo.cc", FormatFileLocation("foo.cc", 42)); | |
246 | EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation("foo.cc", 42)); | |
247 | } | |
248 | ||
249 | TEST(FormatFileLocationTest, FormatsUnknownFile) { | |
1e59de90 TL |
250 | EXPECT_PRED_FORMAT2(IsSubstring, "unknown file", |
251 | FormatFileLocation(nullptr, 42)); | |
252 | EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation(nullptr, 42)); | |
31f18b77 FG |
253 | } |
254 | ||
255 | TEST(FormatFileLocationTest, FormatsUknownLine) { | |
256 | EXPECT_EQ("foo.cc:", FormatFileLocation("foo.cc", -1)); | |
257 | } | |
258 | ||
259 | TEST(FormatFileLocationTest, FormatsUknownFileAndLine) { | |
1e59de90 | 260 | EXPECT_EQ("unknown file:", FormatFileLocation(nullptr, -1)); |
31f18b77 FG |
261 | } |
262 | ||
263 | // Verifies behavior of FormatCompilerIndependentFileLocation. | |
264 | TEST(FormatCompilerIndependentFileLocationTest, FormatsFileLocation) { | |
265 | EXPECT_EQ("foo.cc:42", FormatCompilerIndependentFileLocation("foo.cc", 42)); | |
266 | } | |
267 | ||
268 | TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFile) { | |
269 | EXPECT_EQ("unknown file:42", | |
1e59de90 | 270 | FormatCompilerIndependentFileLocation(nullptr, 42)); |
31f18b77 FG |
271 | } |
272 | ||
273 | TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownLine) { | |
274 | EXPECT_EQ("foo.cc", FormatCompilerIndependentFileLocation("foo.cc", -1)); | |
275 | } | |
276 | ||
277 | TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) { | |
1e59de90 | 278 | EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(nullptr, -1)); |
31f18b77 FG |
279 | } |
280 | ||
1e59de90 TL |
281 | #if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA || \ |
282 | GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ | |
283 | GTEST_OS_NETBSD || GTEST_OS_OPENBSD | |
31f18b77 FG |
284 | void* ThreadFunc(void* data) { |
285 | internal::Mutex* mutex = static_cast<internal::Mutex*>(data); | |
286 | mutex->Lock(); | |
287 | mutex->Unlock(); | |
1e59de90 | 288 | return nullptr; |
31f18b77 FG |
289 | } |
290 | ||
291 | TEST(GetThreadCountTest, ReturnsCorrectValue) { | |
292 | const size_t starting_count = GetThreadCount(); | |
293 | pthread_t thread_id; | |
294 | ||
295 | internal::Mutex mutex; | |
296 | { | |
297 | internal::MutexLock lock(&mutex); | |
298 | pthread_attr_t attr; | |
299 | ASSERT_EQ(0, pthread_attr_init(&attr)); | |
300 | ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)); | |
301 | ||
302 | const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex); | |
303 | ASSERT_EQ(0, pthread_attr_destroy(&attr)); | |
304 | ASSERT_EQ(0, status); | |
305 | EXPECT_EQ(starting_count + 1, GetThreadCount()); | |
306 | } | |
307 | ||
308 | void* dummy; | |
309 | ASSERT_EQ(0, pthread_join(thread_id, &dummy)); | |
310 | ||
311 | // The OS may not immediately report the updated thread count after | |
312 | // joining a thread, causing flakiness in this test. To counter that, we | |
313 | // wait for up to .5 seconds for the OS to report the correct value. | |
314 | for (int i = 0; i < 5; ++i) { | |
315 | if (GetThreadCount() == starting_count) | |
316 | break; | |
317 | ||
318 | SleepMilliseconds(100); | |
319 | } | |
320 | ||
321 | EXPECT_EQ(starting_count, GetThreadCount()); | |
322 | } | |
323 | #else | |
324 | TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) { | |
325 | EXPECT_EQ(0U, GetThreadCount()); | |
326 | } | |
1e59de90 | 327 | #endif // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA |
31f18b77 FG |
328 | |
329 | TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) { | |
330 | const bool a_false_condition = false; | |
331 | const char regex[] = | |
332 | #ifdef _MSC_VER | |
1e59de90 | 333 | "googletest-port-test\\.cc\\(\\d+\\):" |
31f18b77 | 334 | #elif GTEST_USES_POSIX_RE |
1e59de90 | 335 | "googletest-port-test\\.cc:[0-9]+" |
31f18b77 | 336 | #else |
1e59de90 | 337 | "googletest-port-test\\.cc:\\d+" |
31f18b77 FG |
338 | #endif // _MSC_VER |
339 | ".*a_false_condition.*Extra info.*"; | |
340 | ||
341 | EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info", | |
342 | regex); | |
343 | } | |
344 | ||
345 | #if GTEST_HAS_DEATH_TEST | |
346 | ||
347 | TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) { | |
348 | EXPECT_EXIT({ | |
349 | GTEST_CHECK_(true) << "Extra info"; | |
350 | ::std::cerr << "Success\n"; | |
351 | exit(0); }, | |
352 | ::testing::ExitedWithCode(0), "Success"); | |
353 | } | |
354 | ||
355 | #endif // GTEST_HAS_DEATH_TEST | |
356 | ||
357 | // Verifies that Google Test choose regular expression engine appropriate to | |
358 | // the platform. The test will produce compiler errors in case of failure. | |
359 | // For simplicity, we only cover the most important platforms here. | |
360 | TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) { | |
361 | #if !GTEST_USES_PCRE | |
362 | # if GTEST_HAS_POSIX_RE | |
363 | ||
364 | EXPECT_TRUE(GTEST_USES_POSIX_RE); | |
365 | ||
366 | # else | |
367 | ||
368 | EXPECT_TRUE(GTEST_USES_SIMPLE_RE); | |
369 | ||
370 | # endif | |
371 | #endif // !GTEST_USES_PCRE | |
372 | } | |
373 | ||
374 | #if GTEST_USES_POSIX_RE | |
375 | ||
31f18b77 FG |
376 | template <typename Str> |
377 | class RETest : public ::testing::Test {}; | |
378 | ||
379 | // Defines StringTypes as the list of all string types that class RE | |
380 | // supports. | |
1e59de90 | 381 | typedef testing::Types< ::std::string, const char*> StringTypes; |
31f18b77 | 382 | |
1e59de90 | 383 | TYPED_TEST_SUITE(RETest, StringTypes); |
31f18b77 FG |
384 | |
385 | // Tests RE's implicit constructors. | |
386 | TYPED_TEST(RETest, ImplicitConstructorWorks) { | |
387 | const RE empty(TypeParam("")); | |
388 | EXPECT_STREQ("", empty.pattern()); | |
389 | ||
390 | const RE simple(TypeParam("hello")); | |
391 | EXPECT_STREQ("hello", simple.pattern()); | |
392 | ||
393 | const RE normal(TypeParam(".*(\\w+)")); | |
394 | EXPECT_STREQ(".*(\\w+)", normal.pattern()); | |
395 | } | |
396 | ||
397 | // Tests that RE's constructors reject invalid regular expressions. | |
398 | TYPED_TEST(RETest, RejectsInvalidRegex) { | |
399 | EXPECT_NONFATAL_FAILURE({ | |
400 | const RE invalid(TypeParam("?")); | |
401 | }, "\"?\" is not a valid POSIX Extended regular expression."); | |
402 | } | |
403 | ||
404 | // Tests RE::FullMatch(). | |
405 | TYPED_TEST(RETest, FullMatchWorks) { | |
406 | const RE empty(TypeParam("")); | |
407 | EXPECT_TRUE(RE::FullMatch(TypeParam(""), empty)); | |
408 | EXPECT_FALSE(RE::FullMatch(TypeParam("a"), empty)); | |
409 | ||
410 | const RE re(TypeParam("a.*z")); | |
411 | EXPECT_TRUE(RE::FullMatch(TypeParam("az"), re)); | |
412 | EXPECT_TRUE(RE::FullMatch(TypeParam("axyz"), re)); | |
413 | EXPECT_FALSE(RE::FullMatch(TypeParam("baz"), re)); | |
414 | EXPECT_FALSE(RE::FullMatch(TypeParam("azy"), re)); | |
415 | } | |
416 | ||
417 | // Tests RE::PartialMatch(). | |
418 | TYPED_TEST(RETest, PartialMatchWorks) { | |
419 | const RE empty(TypeParam("")); | |
420 | EXPECT_TRUE(RE::PartialMatch(TypeParam(""), empty)); | |
421 | EXPECT_TRUE(RE::PartialMatch(TypeParam("a"), empty)); | |
422 | ||
423 | const RE re(TypeParam("a.*z")); | |
424 | EXPECT_TRUE(RE::PartialMatch(TypeParam("az"), re)); | |
425 | EXPECT_TRUE(RE::PartialMatch(TypeParam("axyz"), re)); | |
426 | EXPECT_TRUE(RE::PartialMatch(TypeParam("baz"), re)); | |
427 | EXPECT_TRUE(RE::PartialMatch(TypeParam("azy"), re)); | |
428 | EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re)); | |
429 | } | |
430 | ||
31f18b77 FG |
431 | #elif GTEST_USES_SIMPLE_RE |
432 | ||
433 | TEST(IsInSetTest, NulCharIsNotInAnySet) { | |
434 | EXPECT_FALSE(IsInSet('\0', "")); | |
435 | EXPECT_FALSE(IsInSet('\0', "\0")); | |
436 | EXPECT_FALSE(IsInSet('\0', "a")); | |
437 | } | |
438 | ||
439 | TEST(IsInSetTest, WorksForNonNulChars) { | |
440 | EXPECT_FALSE(IsInSet('a', "Ab")); | |
441 | EXPECT_FALSE(IsInSet('c', "")); | |
442 | ||
443 | EXPECT_TRUE(IsInSet('b', "bcd")); | |
444 | EXPECT_TRUE(IsInSet('b', "ab")); | |
445 | } | |
446 | ||
447 | TEST(IsAsciiDigitTest, IsFalseForNonDigit) { | |
448 | EXPECT_FALSE(IsAsciiDigit('\0')); | |
449 | EXPECT_FALSE(IsAsciiDigit(' ')); | |
450 | EXPECT_FALSE(IsAsciiDigit('+')); | |
451 | EXPECT_FALSE(IsAsciiDigit('-')); | |
452 | EXPECT_FALSE(IsAsciiDigit('.')); | |
453 | EXPECT_FALSE(IsAsciiDigit('a')); | |
454 | } | |
455 | ||
456 | TEST(IsAsciiDigitTest, IsTrueForDigit) { | |
457 | EXPECT_TRUE(IsAsciiDigit('0')); | |
458 | EXPECT_TRUE(IsAsciiDigit('1')); | |
459 | EXPECT_TRUE(IsAsciiDigit('5')); | |
460 | EXPECT_TRUE(IsAsciiDigit('9')); | |
461 | } | |
462 | ||
463 | TEST(IsAsciiPunctTest, IsFalseForNonPunct) { | |
464 | EXPECT_FALSE(IsAsciiPunct('\0')); | |
465 | EXPECT_FALSE(IsAsciiPunct(' ')); | |
466 | EXPECT_FALSE(IsAsciiPunct('\n')); | |
467 | EXPECT_FALSE(IsAsciiPunct('a')); | |
468 | EXPECT_FALSE(IsAsciiPunct('0')); | |
469 | } | |
470 | ||
471 | TEST(IsAsciiPunctTest, IsTrueForPunct) { | |
472 | for (const char* p = "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"; *p; p++) { | |
473 | EXPECT_PRED1(IsAsciiPunct, *p); | |
474 | } | |
475 | } | |
476 | ||
477 | TEST(IsRepeatTest, IsFalseForNonRepeatChar) { | |
478 | EXPECT_FALSE(IsRepeat('\0')); | |
479 | EXPECT_FALSE(IsRepeat(' ')); | |
480 | EXPECT_FALSE(IsRepeat('a')); | |
481 | EXPECT_FALSE(IsRepeat('1')); | |
482 | EXPECT_FALSE(IsRepeat('-')); | |
483 | } | |
484 | ||
485 | TEST(IsRepeatTest, IsTrueForRepeatChar) { | |
486 | EXPECT_TRUE(IsRepeat('?')); | |
487 | EXPECT_TRUE(IsRepeat('*')); | |
488 | EXPECT_TRUE(IsRepeat('+')); | |
489 | } | |
490 | ||
491 | TEST(IsAsciiWhiteSpaceTest, IsFalseForNonWhiteSpace) { | |
492 | EXPECT_FALSE(IsAsciiWhiteSpace('\0')); | |
493 | EXPECT_FALSE(IsAsciiWhiteSpace('a')); | |
494 | EXPECT_FALSE(IsAsciiWhiteSpace('1')); | |
495 | EXPECT_FALSE(IsAsciiWhiteSpace('+')); | |
496 | EXPECT_FALSE(IsAsciiWhiteSpace('_')); | |
497 | } | |
498 | ||
499 | TEST(IsAsciiWhiteSpaceTest, IsTrueForWhiteSpace) { | |
500 | EXPECT_TRUE(IsAsciiWhiteSpace(' ')); | |
501 | EXPECT_TRUE(IsAsciiWhiteSpace('\n')); | |
502 | EXPECT_TRUE(IsAsciiWhiteSpace('\r')); | |
503 | EXPECT_TRUE(IsAsciiWhiteSpace('\t')); | |
504 | EXPECT_TRUE(IsAsciiWhiteSpace('\v')); | |
505 | EXPECT_TRUE(IsAsciiWhiteSpace('\f')); | |
506 | } | |
507 | ||
508 | TEST(IsAsciiWordCharTest, IsFalseForNonWordChar) { | |
509 | EXPECT_FALSE(IsAsciiWordChar('\0')); | |
510 | EXPECT_FALSE(IsAsciiWordChar('+')); | |
511 | EXPECT_FALSE(IsAsciiWordChar('.')); | |
512 | EXPECT_FALSE(IsAsciiWordChar(' ')); | |
513 | EXPECT_FALSE(IsAsciiWordChar('\n')); | |
514 | } | |
515 | ||
516 | TEST(IsAsciiWordCharTest, IsTrueForLetter) { | |
517 | EXPECT_TRUE(IsAsciiWordChar('a')); | |
518 | EXPECT_TRUE(IsAsciiWordChar('b')); | |
519 | EXPECT_TRUE(IsAsciiWordChar('A')); | |
520 | EXPECT_TRUE(IsAsciiWordChar('Z')); | |
521 | } | |
522 | ||
523 | TEST(IsAsciiWordCharTest, IsTrueForDigit) { | |
524 | EXPECT_TRUE(IsAsciiWordChar('0')); | |
525 | EXPECT_TRUE(IsAsciiWordChar('1')); | |
526 | EXPECT_TRUE(IsAsciiWordChar('7')); | |
527 | EXPECT_TRUE(IsAsciiWordChar('9')); | |
528 | } | |
529 | ||
530 | TEST(IsAsciiWordCharTest, IsTrueForUnderscore) { | |
531 | EXPECT_TRUE(IsAsciiWordChar('_')); | |
532 | } | |
533 | ||
534 | TEST(IsValidEscapeTest, IsFalseForNonPrintable) { | |
535 | EXPECT_FALSE(IsValidEscape('\0')); | |
536 | EXPECT_FALSE(IsValidEscape('\007')); | |
537 | } | |
538 | ||
539 | TEST(IsValidEscapeTest, IsFalseForDigit) { | |
540 | EXPECT_FALSE(IsValidEscape('0')); | |
541 | EXPECT_FALSE(IsValidEscape('9')); | |
542 | } | |
543 | ||
544 | TEST(IsValidEscapeTest, IsFalseForWhiteSpace) { | |
545 | EXPECT_FALSE(IsValidEscape(' ')); | |
546 | EXPECT_FALSE(IsValidEscape('\n')); | |
547 | } | |
548 | ||
549 | TEST(IsValidEscapeTest, IsFalseForSomeLetter) { | |
550 | EXPECT_FALSE(IsValidEscape('a')); | |
551 | EXPECT_FALSE(IsValidEscape('Z')); | |
552 | } | |
553 | ||
554 | TEST(IsValidEscapeTest, IsTrueForPunct) { | |
555 | EXPECT_TRUE(IsValidEscape('.')); | |
556 | EXPECT_TRUE(IsValidEscape('-')); | |
557 | EXPECT_TRUE(IsValidEscape('^')); | |
558 | EXPECT_TRUE(IsValidEscape('$')); | |
559 | EXPECT_TRUE(IsValidEscape('(')); | |
560 | EXPECT_TRUE(IsValidEscape(']')); | |
561 | EXPECT_TRUE(IsValidEscape('{')); | |
562 | EXPECT_TRUE(IsValidEscape('|')); | |
563 | } | |
564 | ||
565 | TEST(IsValidEscapeTest, IsTrueForSomeLetter) { | |
566 | EXPECT_TRUE(IsValidEscape('d')); | |
567 | EXPECT_TRUE(IsValidEscape('D')); | |
568 | EXPECT_TRUE(IsValidEscape('s')); | |
569 | EXPECT_TRUE(IsValidEscape('S')); | |
570 | EXPECT_TRUE(IsValidEscape('w')); | |
571 | EXPECT_TRUE(IsValidEscape('W')); | |
572 | } | |
573 | ||
574 | TEST(AtomMatchesCharTest, EscapedPunct) { | |
575 | EXPECT_FALSE(AtomMatchesChar(true, '\\', '\0')); | |
576 | EXPECT_FALSE(AtomMatchesChar(true, '\\', ' ')); | |
577 | EXPECT_FALSE(AtomMatchesChar(true, '_', '.')); | |
578 | EXPECT_FALSE(AtomMatchesChar(true, '.', 'a')); | |
579 | ||
580 | EXPECT_TRUE(AtomMatchesChar(true, '\\', '\\')); | |
581 | EXPECT_TRUE(AtomMatchesChar(true, '_', '_')); | |
582 | EXPECT_TRUE(AtomMatchesChar(true, '+', '+')); | |
583 | EXPECT_TRUE(AtomMatchesChar(true, '.', '.')); | |
584 | } | |
585 | ||
586 | TEST(AtomMatchesCharTest, Escaped_d) { | |
587 | EXPECT_FALSE(AtomMatchesChar(true, 'd', '\0')); | |
588 | EXPECT_FALSE(AtomMatchesChar(true, 'd', 'a')); | |
589 | EXPECT_FALSE(AtomMatchesChar(true, 'd', '.')); | |
590 | ||
591 | EXPECT_TRUE(AtomMatchesChar(true, 'd', '0')); | |
592 | EXPECT_TRUE(AtomMatchesChar(true, 'd', '9')); | |
593 | } | |
594 | ||
595 | TEST(AtomMatchesCharTest, Escaped_D) { | |
596 | EXPECT_FALSE(AtomMatchesChar(true, 'D', '0')); | |
597 | EXPECT_FALSE(AtomMatchesChar(true, 'D', '9')); | |
598 | ||
599 | EXPECT_TRUE(AtomMatchesChar(true, 'D', '\0')); | |
600 | EXPECT_TRUE(AtomMatchesChar(true, 'D', 'a')); | |
601 | EXPECT_TRUE(AtomMatchesChar(true, 'D', '-')); | |
602 | } | |
603 | ||
604 | TEST(AtomMatchesCharTest, Escaped_s) { | |
605 | EXPECT_FALSE(AtomMatchesChar(true, 's', '\0')); | |
606 | EXPECT_FALSE(AtomMatchesChar(true, 's', 'a')); | |
607 | EXPECT_FALSE(AtomMatchesChar(true, 's', '.')); | |
608 | EXPECT_FALSE(AtomMatchesChar(true, 's', '9')); | |
609 | ||
610 | EXPECT_TRUE(AtomMatchesChar(true, 's', ' ')); | |
611 | EXPECT_TRUE(AtomMatchesChar(true, 's', '\n')); | |
612 | EXPECT_TRUE(AtomMatchesChar(true, 's', '\t')); | |
613 | } | |
614 | ||
615 | TEST(AtomMatchesCharTest, Escaped_S) { | |
616 | EXPECT_FALSE(AtomMatchesChar(true, 'S', ' ')); | |
617 | EXPECT_FALSE(AtomMatchesChar(true, 'S', '\r')); | |
618 | ||
619 | EXPECT_TRUE(AtomMatchesChar(true, 'S', '\0')); | |
620 | EXPECT_TRUE(AtomMatchesChar(true, 'S', 'a')); | |
621 | EXPECT_TRUE(AtomMatchesChar(true, 'S', '9')); | |
622 | } | |
623 | ||
624 | TEST(AtomMatchesCharTest, Escaped_w) { | |
625 | EXPECT_FALSE(AtomMatchesChar(true, 'w', '\0')); | |
626 | EXPECT_FALSE(AtomMatchesChar(true, 'w', '+')); | |
627 | EXPECT_FALSE(AtomMatchesChar(true, 'w', ' ')); | |
628 | EXPECT_FALSE(AtomMatchesChar(true, 'w', '\n')); | |
629 | ||
630 | EXPECT_TRUE(AtomMatchesChar(true, 'w', '0')); | |
631 | EXPECT_TRUE(AtomMatchesChar(true, 'w', 'b')); | |
632 | EXPECT_TRUE(AtomMatchesChar(true, 'w', 'C')); | |
633 | EXPECT_TRUE(AtomMatchesChar(true, 'w', '_')); | |
634 | } | |
635 | ||
636 | TEST(AtomMatchesCharTest, Escaped_W) { | |
637 | EXPECT_FALSE(AtomMatchesChar(true, 'W', 'A')); | |
638 | EXPECT_FALSE(AtomMatchesChar(true, 'W', 'b')); | |
639 | EXPECT_FALSE(AtomMatchesChar(true, 'W', '9')); | |
640 | EXPECT_FALSE(AtomMatchesChar(true, 'W', '_')); | |
641 | ||
642 | EXPECT_TRUE(AtomMatchesChar(true, 'W', '\0')); | |
643 | EXPECT_TRUE(AtomMatchesChar(true, 'W', '*')); | |
644 | EXPECT_TRUE(AtomMatchesChar(true, 'W', '\n')); | |
645 | } | |
646 | ||
647 | TEST(AtomMatchesCharTest, EscapedWhiteSpace) { | |
648 | EXPECT_FALSE(AtomMatchesChar(true, 'f', '\0')); | |
649 | EXPECT_FALSE(AtomMatchesChar(true, 'f', '\n')); | |
650 | EXPECT_FALSE(AtomMatchesChar(true, 'n', '\0')); | |
651 | EXPECT_FALSE(AtomMatchesChar(true, 'n', '\r')); | |
652 | EXPECT_FALSE(AtomMatchesChar(true, 'r', '\0')); | |
653 | EXPECT_FALSE(AtomMatchesChar(true, 'r', 'a')); | |
654 | EXPECT_FALSE(AtomMatchesChar(true, 't', '\0')); | |
655 | EXPECT_FALSE(AtomMatchesChar(true, 't', 't')); | |
656 | EXPECT_FALSE(AtomMatchesChar(true, 'v', '\0')); | |
657 | EXPECT_FALSE(AtomMatchesChar(true, 'v', '\f')); | |
658 | ||
659 | EXPECT_TRUE(AtomMatchesChar(true, 'f', '\f')); | |
660 | EXPECT_TRUE(AtomMatchesChar(true, 'n', '\n')); | |
661 | EXPECT_TRUE(AtomMatchesChar(true, 'r', '\r')); | |
662 | EXPECT_TRUE(AtomMatchesChar(true, 't', '\t')); | |
663 | EXPECT_TRUE(AtomMatchesChar(true, 'v', '\v')); | |
664 | } | |
665 | ||
666 | TEST(AtomMatchesCharTest, UnescapedDot) { | |
667 | EXPECT_FALSE(AtomMatchesChar(false, '.', '\n')); | |
668 | ||
669 | EXPECT_TRUE(AtomMatchesChar(false, '.', '\0')); | |
670 | EXPECT_TRUE(AtomMatchesChar(false, '.', '.')); | |
671 | EXPECT_TRUE(AtomMatchesChar(false, '.', 'a')); | |
672 | EXPECT_TRUE(AtomMatchesChar(false, '.', ' ')); | |
673 | } | |
674 | ||
675 | TEST(AtomMatchesCharTest, UnescapedChar) { | |
676 | EXPECT_FALSE(AtomMatchesChar(false, 'a', '\0')); | |
677 | EXPECT_FALSE(AtomMatchesChar(false, 'a', 'b')); | |
678 | EXPECT_FALSE(AtomMatchesChar(false, '$', 'a')); | |
679 | ||
680 | EXPECT_TRUE(AtomMatchesChar(false, '$', '$')); | |
681 | EXPECT_TRUE(AtomMatchesChar(false, '5', '5')); | |
682 | EXPECT_TRUE(AtomMatchesChar(false, 'Z', 'Z')); | |
683 | } | |
684 | ||
685 | TEST(ValidateRegexTest, GeneratesFailureAndReturnsFalseForInvalid) { | |
686 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(NULL)), | |
687 | "NULL is not a valid simple regular expression"); | |
688 | EXPECT_NONFATAL_FAILURE( | |
689 | ASSERT_FALSE(ValidateRegex("a\\")), | |
690 | "Syntax error at index 1 in simple regular expression \"a\\\": "); | |
691 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a\\")), | |
692 | "'\\' cannot appear at the end"); | |
693 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\n\\")), | |
694 | "'\\' cannot appear at the end"); | |
695 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\s\\hb")), | |
696 | "invalid escape sequence \"\\h\""); | |
697 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^^")), | |
698 | "'^' can only appear at the beginning"); | |
699 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(".*^b")), | |
700 | "'^' can only appear at the beginning"); | |
701 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("$$")), | |
702 | "'$' can only appear at the end"); | |
703 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^$a")), | |
704 | "'$' can only appear at the end"); | |
705 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a(b")), | |
706 | "'(' is unsupported"); | |
707 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("ab)")), | |
708 | "')' is unsupported"); | |
709 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("[ab")), | |
710 | "'[' is unsupported"); | |
711 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a{2")), | |
712 | "'{' is unsupported"); | |
713 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("?")), | |
714 | "'?' can only follow a repeatable token"); | |
715 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^*")), | |
716 | "'*' can only follow a repeatable token"); | |
717 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("5*+")), | |
718 | "'+' can only follow a repeatable token"); | |
719 | } | |
720 | ||
721 | TEST(ValidateRegexTest, ReturnsTrueForValid) { | |
722 | EXPECT_TRUE(ValidateRegex("")); | |
723 | EXPECT_TRUE(ValidateRegex("a")); | |
724 | EXPECT_TRUE(ValidateRegex(".*")); | |
725 | EXPECT_TRUE(ValidateRegex("^a_+")); | |
726 | EXPECT_TRUE(ValidateRegex("^a\\t\\&?")); | |
727 | EXPECT_TRUE(ValidateRegex("09*$")); | |
728 | EXPECT_TRUE(ValidateRegex("^Z$")); | |
729 | EXPECT_TRUE(ValidateRegex("a\\^Z\\$\\(\\)\\|\\[\\]\\{\\}")); | |
730 | } | |
731 | ||
732 | TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrOne) { | |
733 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "a", "ba")); | |
734 | // Repeating more than once. | |
735 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "aab")); | |
736 | ||
737 | // Repeating zero times. | |
738 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ba")); | |
739 | // Repeating once. | |
740 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ab")); | |
741 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '#', '?', ".", "##")); | |
742 | } | |
743 | ||
744 | TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrMany) { | |
745 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '*', "a$", "baab")); | |
746 | ||
747 | // Repeating zero times. | |
748 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "bc")); | |
749 | // Repeating once. | |
750 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "abc")); | |
751 | // Repeating more than once. | |
752 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '*', "-", "ab_1-g")); | |
753 | } | |
754 | ||
755 | TEST(MatchRepetitionAndRegexAtHeadTest, WorksForOneOrMany) { | |
756 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "a$", "baab")); | |
757 | // Repeating zero times. | |
758 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "bc")); | |
759 | ||
760 | // Repeating once. | |
761 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "abc")); | |
762 | // Repeating more than once. | |
763 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '+', "-", "ab_1-g")); | |
764 | } | |
765 | ||
766 | TEST(MatchRegexAtHeadTest, ReturnsTrueForEmptyRegex) { | |
767 | EXPECT_TRUE(MatchRegexAtHead("", "")); | |
768 | EXPECT_TRUE(MatchRegexAtHead("", "ab")); | |
769 | } | |
770 | ||
771 | TEST(MatchRegexAtHeadTest, WorksWhenDollarIsInRegex) { | |
772 | EXPECT_FALSE(MatchRegexAtHead("$", "a")); | |
773 | ||
774 | EXPECT_TRUE(MatchRegexAtHead("$", "")); | |
775 | EXPECT_TRUE(MatchRegexAtHead("a$", "a")); | |
776 | } | |
777 | ||
778 | TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithEscapeSequence) { | |
779 | EXPECT_FALSE(MatchRegexAtHead("\\w", "+")); | |
780 | EXPECT_FALSE(MatchRegexAtHead("\\W", "ab")); | |
781 | ||
782 | EXPECT_TRUE(MatchRegexAtHead("\\sa", "\nab")); | |
783 | EXPECT_TRUE(MatchRegexAtHead("\\d", "1a")); | |
784 | } | |
785 | ||
786 | TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) { | |
787 | EXPECT_FALSE(MatchRegexAtHead(".+a", "abc")); | |
788 | EXPECT_FALSE(MatchRegexAtHead("a?b", "aab")); | |
789 | ||
790 | EXPECT_TRUE(MatchRegexAtHead(".*a", "bc12-ab")); | |
791 | EXPECT_TRUE(MatchRegexAtHead("a?b", "b")); | |
792 | EXPECT_TRUE(MatchRegexAtHead("a?b", "ab")); | |
793 | } | |
794 | ||
795 | TEST(MatchRegexAtHeadTest, | |
796 | WorksWhenRegexStartsWithRepetionOfEscapeSequence) { | |
797 | EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc")); | |
798 | EXPECT_FALSE(MatchRegexAtHead("\\s?b", " b")); | |
799 | ||
800 | EXPECT_TRUE(MatchRegexAtHead("\\(*a", "((((ab")); | |
801 | EXPECT_TRUE(MatchRegexAtHead("\\^?b", "^b")); | |
802 | EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "b")); | |
803 | EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "\\b")); | |
804 | } | |
805 | ||
806 | TEST(MatchRegexAtHeadTest, MatchesSequentially) { | |
807 | EXPECT_FALSE(MatchRegexAtHead("ab.*c", "acabc")); | |
808 | ||
809 | EXPECT_TRUE(MatchRegexAtHead("ab.*c", "ab-fsc")); | |
810 | } | |
811 | ||
812 | TEST(MatchRegexAnywhereTest, ReturnsFalseWhenStringIsNull) { | |
813 | EXPECT_FALSE(MatchRegexAnywhere("", NULL)); | |
814 | } | |
815 | ||
816 | TEST(MatchRegexAnywhereTest, WorksWhenRegexStartsWithCaret) { | |
817 | EXPECT_FALSE(MatchRegexAnywhere("^a", "ba")); | |
818 | EXPECT_FALSE(MatchRegexAnywhere("^$", "a")); | |
819 | ||
820 | EXPECT_TRUE(MatchRegexAnywhere("^a", "ab")); | |
821 | EXPECT_TRUE(MatchRegexAnywhere("^", "ab")); | |
822 | EXPECT_TRUE(MatchRegexAnywhere("^$", "")); | |
823 | } | |
824 | ||
825 | TEST(MatchRegexAnywhereTest, ReturnsFalseWhenNoMatch) { | |
826 | EXPECT_FALSE(MatchRegexAnywhere("a", "bcde123")); | |
827 | EXPECT_FALSE(MatchRegexAnywhere("a.+a", "--aa88888888")); | |
828 | } | |
829 | ||
830 | TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingPrefix) { | |
831 | EXPECT_TRUE(MatchRegexAnywhere("\\w+", "ab1_ - 5")); | |
832 | EXPECT_TRUE(MatchRegexAnywhere(".*=", "=")); | |
833 | EXPECT_TRUE(MatchRegexAnywhere("x.*ab?.*bc", "xaaabc")); | |
834 | } | |
835 | ||
836 | TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) { | |
837 | EXPECT_TRUE(MatchRegexAnywhere("\\w+", "$$$ ab1_ - 5")); | |
838 | EXPECT_TRUE(MatchRegexAnywhere("\\.+=", "= ...=")); | |
839 | } | |
840 | ||
841 | // Tests RE's implicit constructors. | |
842 | TEST(RETest, ImplicitConstructorWorks) { | |
843 | const RE empty(""); | |
844 | EXPECT_STREQ("", empty.pattern()); | |
845 | ||
846 | const RE simple("hello"); | |
847 | EXPECT_STREQ("hello", simple.pattern()); | |
848 | } | |
849 | ||
850 | // Tests that RE's constructors reject invalid regular expressions. | |
851 | TEST(RETest, RejectsInvalidRegex) { | |
852 | EXPECT_NONFATAL_FAILURE({ | |
853 | const RE normal(NULL); | |
854 | }, "NULL is not a valid simple regular expression"); | |
855 | ||
856 | EXPECT_NONFATAL_FAILURE({ | |
857 | const RE normal(".*(\\w+"); | |
858 | }, "'(' is unsupported"); | |
859 | ||
860 | EXPECT_NONFATAL_FAILURE({ | |
861 | const RE invalid("^?"); | |
862 | }, "'?' can only follow a repeatable token"); | |
863 | } | |
864 | ||
865 | // Tests RE::FullMatch(). | |
866 | TEST(RETest, FullMatchWorks) { | |
867 | const RE empty(""); | |
868 | EXPECT_TRUE(RE::FullMatch("", empty)); | |
869 | EXPECT_FALSE(RE::FullMatch("a", empty)); | |
870 | ||
871 | const RE re1("a"); | |
872 | EXPECT_TRUE(RE::FullMatch("a", re1)); | |
873 | ||
874 | const RE re("a.*z"); | |
875 | EXPECT_TRUE(RE::FullMatch("az", re)); | |
876 | EXPECT_TRUE(RE::FullMatch("axyz", re)); | |
877 | EXPECT_FALSE(RE::FullMatch("baz", re)); | |
878 | EXPECT_FALSE(RE::FullMatch("azy", re)); | |
879 | } | |
880 | ||
881 | // Tests RE::PartialMatch(). | |
882 | TEST(RETest, PartialMatchWorks) { | |
883 | const RE empty(""); | |
884 | EXPECT_TRUE(RE::PartialMatch("", empty)); | |
885 | EXPECT_TRUE(RE::PartialMatch("a", empty)); | |
886 | ||
887 | const RE re("a.*z"); | |
888 | EXPECT_TRUE(RE::PartialMatch("az", re)); | |
889 | EXPECT_TRUE(RE::PartialMatch("axyz", re)); | |
890 | EXPECT_TRUE(RE::PartialMatch("baz", re)); | |
891 | EXPECT_TRUE(RE::PartialMatch("azy", re)); | |
892 | EXPECT_FALSE(RE::PartialMatch("zza", re)); | |
893 | } | |
894 | ||
895 | #endif // GTEST_USES_POSIX_RE | |
896 | ||
897 | #if !GTEST_OS_WINDOWS_MOBILE | |
898 | ||
899 | TEST(CaptureTest, CapturesStdout) { | |
900 | CaptureStdout(); | |
901 | fprintf(stdout, "abc"); | |
902 | EXPECT_STREQ("abc", GetCapturedStdout().c_str()); | |
903 | ||
904 | CaptureStdout(); | |
905 | fprintf(stdout, "def%cghi", '\0'); | |
906 | EXPECT_EQ(::std::string("def\0ghi", 7), ::std::string(GetCapturedStdout())); | |
907 | } | |
908 | ||
909 | TEST(CaptureTest, CapturesStderr) { | |
910 | CaptureStderr(); | |
911 | fprintf(stderr, "jkl"); | |
912 | EXPECT_STREQ("jkl", GetCapturedStderr().c_str()); | |
913 | ||
914 | CaptureStderr(); | |
915 | fprintf(stderr, "jkl%cmno", '\0'); | |
916 | EXPECT_EQ(::std::string("jkl\0mno", 7), ::std::string(GetCapturedStderr())); | |
917 | } | |
918 | ||
919 | // Tests that stdout and stderr capture don't interfere with each other. | |
920 | TEST(CaptureTest, CapturesStdoutAndStderr) { | |
921 | CaptureStdout(); | |
922 | CaptureStderr(); | |
923 | fprintf(stdout, "pqr"); | |
924 | fprintf(stderr, "stu"); | |
925 | EXPECT_STREQ("pqr", GetCapturedStdout().c_str()); | |
926 | EXPECT_STREQ("stu", GetCapturedStderr().c_str()); | |
927 | } | |
928 | ||
929 | TEST(CaptureDeathTest, CannotReenterStdoutCapture) { | |
930 | CaptureStdout(); | |
931 | EXPECT_DEATH_IF_SUPPORTED(CaptureStdout(), | |
932 | "Only one stdout capturer can exist at a time"); | |
933 | GetCapturedStdout(); | |
934 | ||
935 | // We cannot test stderr capturing using death tests as they use it | |
936 | // themselves. | |
937 | } | |
938 | ||
939 | #endif // !GTEST_OS_WINDOWS_MOBILE | |
940 | ||
941 | TEST(ThreadLocalTest, DefaultConstructorInitializesToDefaultValues) { | |
942 | ThreadLocal<int> t1; | |
943 | EXPECT_EQ(0, t1.get()); | |
944 | ||
945 | ThreadLocal<void*> t2; | |
1e59de90 | 946 | EXPECT_TRUE(t2.get() == nullptr); |
31f18b77 FG |
947 | } |
948 | ||
949 | TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) { | |
950 | ThreadLocal<int> t1(123); | |
951 | EXPECT_EQ(123, t1.get()); | |
952 | ||
953 | int i = 0; | |
954 | ThreadLocal<int*> t2(&i); | |
955 | EXPECT_EQ(&i, t2.get()); | |
956 | } | |
957 | ||
958 | class NoDefaultContructor { | |
959 | public: | |
960 | explicit NoDefaultContructor(const char*) {} | |
961 | NoDefaultContructor(const NoDefaultContructor&) {} | |
962 | }; | |
963 | ||
964 | TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) { | |
965 | ThreadLocal<NoDefaultContructor> bar(NoDefaultContructor("foo")); | |
966 | bar.pointer(); | |
967 | } | |
968 | ||
969 | TEST(ThreadLocalTest, GetAndPointerReturnSameValue) { | |
970 | ThreadLocal<std::string> thread_local_string; | |
971 | ||
972 | EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get())); | |
973 | ||
974 | // Verifies the condition still holds after calling set. | |
975 | thread_local_string.set("foo"); | |
976 | EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get())); | |
977 | } | |
978 | ||
979 | TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) { | |
980 | ThreadLocal<std::string> thread_local_string; | |
981 | const ThreadLocal<std::string>& const_thread_local_string = | |
982 | thread_local_string; | |
983 | ||
984 | EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer()); | |
985 | ||
986 | thread_local_string.set("foo"); | |
987 | EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer()); | |
988 | } | |
989 | ||
990 | #if GTEST_IS_THREADSAFE | |
991 | ||
992 | void AddTwo(int* param) { *param += 2; } | |
993 | ||
994 | TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) { | |
995 | int i = 40; | |
1e59de90 | 996 | ThreadWithParam<int*> thread(&AddTwo, &i, nullptr); |
31f18b77 FG |
997 | thread.Join(); |
998 | EXPECT_EQ(42, i); | |
999 | } | |
1000 | ||
1001 | TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) { | |
1002 | // AssertHeld() is flaky only in the presence of multiple threads accessing | |
1003 | // the lock. In this case, the test is robust. | |
1004 | EXPECT_DEATH_IF_SUPPORTED({ | |
1005 | Mutex m; | |
1006 | { MutexLock lock(&m); } | |
1007 | m.AssertHeld(); | |
1008 | }, | |
1009 | "thread .*hold"); | |
1010 | } | |
1011 | ||
1012 | TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) { | |
1013 | Mutex m; | |
1014 | MutexLock lock(&m); | |
1015 | m.AssertHeld(); | |
1016 | } | |
1017 | ||
1018 | class AtomicCounterWithMutex { | |
1019 | public: | |
1020 | explicit AtomicCounterWithMutex(Mutex* mutex) : | |
1021 | value_(0), mutex_(mutex), random_(42) {} | |
1022 | ||
1023 | void Increment() { | |
1024 | MutexLock lock(mutex_); | |
1025 | int temp = value_; | |
1026 | { | |
1027 | // We need to put up a memory barrier to prevent reads and writes to | |
1028 | // value_ rearranged with the call to SleepMilliseconds when observed | |
1029 | // from other threads. | |
1030 | #if GTEST_HAS_PTHREAD | |
1031 | // On POSIX, locking a mutex puts up a memory barrier. We cannot use | |
1032 | // Mutex and MutexLock here or rely on their memory barrier | |
1033 | // functionality as we are testing them here. | |
1034 | pthread_mutex_t memory_barrier_mutex; | |
1035 | GTEST_CHECK_POSIX_SUCCESS_( | |
1e59de90 | 1036 | pthread_mutex_init(&memory_barrier_mutex, nullptr)); |
31f18b77 FG |
1037 | GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex)); |
1038 | ||
1e59de90 | 1039 | SleepMilliseconds(static_cast<int>(random_.Generate(30))); |
31f18b77 FG |
1040 | |
1041 | GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex)); | |
1042 | GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex)); | |
1043 | #elif GTEST_OS_WINDOWS | |
1044 | // On Windows, performing an interlocked access puts up a memory barrier. | |
1045 | volatile LONG dummy = 0; | |
1046 | ::InterlockedIncrement(&dummy); | |
1e59de90 | 1047 | SleepMilliseconds(static_cast<int>(random_.Generate(30))); |
31f18b77 FG |
1048 | ::InterlockedIncrement(&dummy); |
1049 | #else | |
1050 | # error "Memory barrier not implemented on this platform." | |
1051 | #endif // GTEST_HAS_PTHREAD | |
1052 | } | |
1053 | value_ = temp + 1; | |
1054 | } | |
1055 | int value() const { return value_; } | |
1056 | ||
1057 | private: | |
1058 | volatile int value_; | |
1059 | Mutex* const mutex_; // Protects value_. | |
1060 | Random random_; | |
1061 | }; | |
1062 | ||
1063 | void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) { | |
1064 | for (int i = 0; i < param.second; ++i) | |
1065 | param.first->Increment(); | |
1066 | } | |
1067 | ||
1068 | // Tests that the mutex only lets one thread at a time to lock it. | |
1069 | TEST(MutexTest, OnlyOneThreadCanLockAtATime) { | |
1070 | Mutex mutex; | |
1071 | AtomicCounterWithMutex locked_counter(&mutex); | |
1072 | ||
1073 | typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType; | |
1074 | const int kCycleCount = 20; | |
1075 | const int kThreadCount = 7; | |
1e59de90 | 1076 | std::unique_ptr<ThreadType> counting_threads[kThreadCount]; |
31f18b77 FG |
1077 | Notification threads_can_start; |
1078 | // Creates and runs kThreadCount threads that increment locked_counter | |
1079 | // kCycleCount times each. | |
1080 | for (int i = 0; i < kThreadCount; ++i) { | |
1081 | counting_threads[i].reset(new ThreadType(&CountingThreadFunc, | |
1082 | make_pair(&locked_counter, | |
1083 | kCycleCount), | |
1084 | &threads_can_start)); | |
1085 | } | |
1086 | threads_can_start.Notify(); | |
1087 | for (int i = 0; i < kThreadCount; ++i) | |
1088 | counting_threads[i]->Join(); | |
1089 | ||
1090 | // If the mutex lets more than one thread to increment the counter at a | |
1091 | // time, they are likely to encounter a race condition and have some | |
1092 | // increments overwritten, resulting in the lower then expected counter | |
1093 | // value. | |
1094 | EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value()); | |
1095 | } | |
1096 | ||
1097 | template <typename T> | |
1098 | void RunFromThread(void (func)(T), T param) { | |
1e59de90 | 1099 | ThreadWithParam<T> thread(func, param, nullptr); |
31f18b77 FG |
1100 | thread.Join(); |
1101 | } | |
1102 | ||
1103 | void RetrieveThreadLocalValue( | |
1104 | pair<ThreadLocal<std::string>*, std::string*> param) { | |
1105 | *param.second = param.first->get(); | |
1106 | } | |
1107 | ||
1108 | TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) { | |
1109 | ThreadLocal<std::string> thread_local_string("foo"); | |
1110 | EXPECT_STREQ("foo", thread_local_string.get().c_str()); | |
1111 | ||
1112 | thread_local_string.set("bar"); | |
1113 | EXPECT_STREQ("bar", thread_local_string.get().c_str()); | |
1114 | ||
1115 | std::string result; | |
1116 | RunFromThread(&RetrieveThreadLocalValue, | |
1117 | make_pair(&thread_local_string, &result)); | |
1118 | EXPECT_STREQ("foo", result.c_str()); | |
1119 | } | |
1120 | ||
1121 | // Keeps track of whether of destructors being called on instances of | |
1122 | // DestructorTracker. On Windows, waits for the destructor call reports. | |
1123 | class DestructorCall { | |
1124 | public: | |
1125 | DestructorCall() { | |
1126 | invoked_ = false; | |
1127 | #if GTEST_OS_WINDOWS | |
1128 | wait_event_.Reset(::CreateEvent(NULL, TRUE, FALSE, NULL)); | |
1129 | GTEST_CHECK_(wait_event_.Get() != NULL); | |
1130 | #endif | |
1131 | } | |
1132 | ||
1133 | bool CheckDestroyed() const { | |
1134 | #if GTEST_OS_WINDOWS | |
1135 | if (::WaitForSingleObject(wait_event_.Get(), 1000) != WAIT_OBJECT_0) | |
1136 | return false; | |
1137 | #endif | |
1138 | return invoked_; | |
1139 | } | |
1140 | ||
1141 | void ReportDestroyed() { | |
1142 | invoked_ = true; | |
1143 | #if GTEST_OS_WINDOWS | |
1144 | ::SetEvent(wait_event_.Get()); | |
1145 | #endif | |
1146 | } | |
1147 | ||
1148 | static std::vector<DestructorCall*>& List() { return *list_; } | |
1149 | ||
1150 | static void ResetList() { | |
1151 | for (size_t i = 0; i < list_->size(); ++i) { | |
1152 | delete list_->at(i); | |
1153 | } | |
1154 | list_->clear(); | |
1155 | } | |
1156 | ||
1157 | private: | |
1158 | bool invoked_; | |
1159 | #if GTEST_OS_WINDOWS | |
1160 | AutoHandle wait_event_; | |
1161 | #endif | |
1162 | static std::vector<DestructorCall*>* const list_; | |
1163 | ||
1164 | GTEST_DISALLOW_COPY_AND_ASSIGN_(DestructorCall); | |
1165 | }; | |
1166 | ||
1167 | std::vector<DestructorCall*>* const DestructorCall::list_ = | |
1168 | new std::vector<DestructorCall*>; | |
1169 | ||
1170 | // DestructorTracker keeps track of whether its instances have been | |
1171 | // destroyed. | |
1172 | class DestructorTracker { | |
1173 | public: | |
1174 | DestructorTracker() : index_(GetNewIndex()) {} | |
1175 | DestructorTracker(const DestructorTracker& /* rhs */) | |
1176 | : index_(GetNewIndex()) {} | |
1177 | ~DestructorTracker() { | |
1178 | // We never access DestructorCall::List() concurrently, so we don't need | |
1e59de90 | 1179 | // to protect this access with a mutex. |
31f18b77 FG |
1180 | DestructorCall::List()[index_]->ReportDestroyed(); |
1181 | } | |
1182 | ||
1183 | private: | |
1184 | static size_t GetNewIndex() { | |
1185 | DestructorCall::List().push_back(new DestructorCall); | |
1186 | return DestructorCall::List().size() - 1; | |
1187 | } | |
1188 | const size_t index_; | |
31f18b77 FG |
1189 | }; |
1190 | ||
1191 | typedef ThreadLocal<DestructorTracker>* ThreadParam; | |
1192 | ||
1193 | void CallThreadLocalGet(ThreadParam thread_local_param) { | |
1194 | thread_local_param->get(); | |
1195 | } | |
1196 | ||
1197 | // Tests that when a ThreadLocal object dies in a thread, it destroys | |
1198 | // the managed object for that thread. | |
1199 | TEST(ThreadLocalTest, DestroysManagedObjectForOwnThreadWhenDying) { | |
1200 | DestructorCall::ResetList(); | |
1201 | ||
1202 | { | |
1203 | ThreadLocal<DestructorTracker> thread_local_tracker; | |
1204 | ASSERT_EQ(0U, DestructorCall::List().size()); | |
1205 | ||
1206 | // This creates another DestructorTracker object for the main thread. | |
1207 | thread_local_tracker.get(); | |
1208 | ASSERT_EQ(1U, DestructorCall::List().size()); | |
1209 | ASSERT_FALSE(DestructorCall::List()[0]->CheckDestroyed()); | |
1210 | } | |
1211 | ||
1212 | // Now thread_local_tracker has died. | |
1213 | ASSERT_EQ(1U, DestructorCall::List().size()); | |
1214 | EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed()); | |
1215 | ||
1216 | DestructorCall::ResetList(); | |
1217 | } | |
1218 | ||
1219 | // Tests that when a thread exits, the thread-local object for that | |
1220 | // thread is destroyed. | |
1221 | TEST(ThreadLocalTest, DestroysManagedObjectAtThreadExit) { | |
1222 | DestructorCall::ResetList(); | |
1223 | ||
1224 | { | |
1225 | ThreadLocal<DestructorTracker> thread_local_tracker; | |
1226 | ASSERT_EQ(0U, DestructorCall::List().size()); | |
1227 | ||
1228 | // This creates another DestructorTracker object in the new thread. | |
1e59de90 TL |
1229 | ThreadWithParam<ThreadParam> thread(&CallThreadLocalGet, |
1230 | &thread_local_tracker, nullptr); | |
31f18b77 FG |
1231 | thread.Join(); |
1232 | ||
1233 | // The thread has exited, and we should have a DestroyedTracker | |
1234 | // instance created for it. But it may not have been destroyed yet. | |
1235 | ASSERT_EQ(1U, DestructorCall::List().size()); | |
1236 | } | |
1237 | ||
1238 | // The thread has exited and thread_local_tracker has died. | |
1239 | ASSERT_EQ(1U, DestructorCall::List().size()); | |
1240 | EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed()); | |
1241 | ||
1242 | DestructorCall::ResetList(); | |
1243 | } | |
1244 | ||
1245 | TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) { | |
1246 | ThreadLocal<std::string> thread_local_string; | |
1247 | thread_local_string.set("Foo"); | |
1248 | EXPECT_STREQ("Foo", thread_local_string.get().c_str()); | |
1249 | ||
1250 | std::string result; | |
1251 | RunFromThread(&RetrieveThreadLocalValue, | |
1252 | make_pair(&thread_local_string, &result)); | |
1253 | EXPECT_TRUE(result.empty()); | |
1254 | } | |
1255 | ||
1256 | #endif // GTEST_IS_THREADSAFE | |
1257 | ||
1258 | #if GTEST_OS_WINDOWS | |
1259 | TEST(WindowsTypesTest, HANDLEIsVoidStar) { | |
1260 | StaticAssertTypeEq<HANDLE, void*>(); | |
1261 | } | |
1262 | ||
1e59de90 TL |
1263 | #if GTEST_OS_WINDOWS_MINGW && !defined(__MINGW64_VERSION_MAJOR) |
1264 | TEST(WindowsTypesTest, _CRITICAL_SECTIONIs_CRITICAL_SECTION) { | |
1265 | StaticAssertTypeEq<CRITICAL_SECTION, _CRITICAL_SECTION>(); | |
1266 | } | |
1267 | #else | |
31f18b77 FG |
1268 | TEST(WindowsTypesTest, CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION) { |
1269 | StaticAssertTypeEq<CRITICAL_SECTION, _RTL_CRITICAL_SECTION>(); | |
1270 | } | |
1e59de90 TL |
1271 | #endif |
1272 | ||
31f18b77 FG |
1273 | #endif // GTEST_OS_WINDOWS |
1274 | ||
1275 | } // namespace internal | |
1276 | } // namespace testing |