]>
Commit | Line | Data |
---|---|---|
7c673cae 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 | // | |
7c673cae | 30 | // This file tests the internal cross-platform support utilities. |
9f95a23c | 31 | #include <stdio.h> |
7c673cae FG |
32 | |
33 | #include "gtest/internal/gtest-port.h" | |
34 | ||
7c673cae FG |
35 | #if GTEST_OS_MAC |
36 | # include <time.h> | |
37 | #endif // GTEST_OS_MAC | |
38 | ||
39 | #include <list> | |
9f95a23c | 40 | #include <memory> |
7c673cae 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" | |
7c673cae | 46 | #include "src/gtest-internal-inl.h" |
7c673cae 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) { | |
9f95a23c | 68 | EXPECT_FALSE(IsXDigit(static_cast<char>('\x80'))); |
7c673cae 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: | |
7c673cae FG |
93 | Base() : member_(0) {} |
94 | explicit Base(int n) : member_(n) {} | |
f67539c2 TL |
95 | Base(const Base&) = default; |
96 | Base& operator=(const Base&) = default; | |
7c673cae 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 | ||
f67539c2 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 | |
7c673cae 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 | } | |
f67539c2 TL |
226 | #ifdef __GNUC__ |
227 | #pragma GCC diagnostic pop | |
228 | #endif | |
7c673cae 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) { | |
9f95a23c TL |
250 | EXPECT_PRED_FORMAT2(IsSubstring, "unknown file", |
251 | FormatFileLocation(nullptr, 42)); | |
252 | EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation(nullptr, 42)); | |
7c673cae FG |
253 | } |
254 | ||
255 | TEST(FormatFileLocationTest, FormatsUknownLine) { | |
256 | EXPECT_EQ("foo.cc:", FormatFileLocation("foo.cc", -1)); | |
257 | } | |
258 | ||
259 | TEST(FormatFileLocationTest, FormatsUknownFileAndLine) { | |
9f95a23c | 260 | EXPECT_EQ("unknown file:", FormatFileLocation(nullptr, -1)); |
7c673cae 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", | |
9f95a23c | 270 | FormatCompilerIndependentFileLocation(nullptr, 42)); |
7c673cae FG |
271 | } |
272 | ||
273 | TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownLine) { | |
274 | EXPECT_EQ("foo.cc", FormatCompilerIndependentFileLocation("foo.cc", -1)); | |
275 | } | |
276 | ||
277 | TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) { | |
9f95a23c | 278 | EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(nullptr, -1)); |
7c673cae FG |
279 | } |
280 | ||
9f95a23c 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 | |
7c673cae FG |
284 | void* ThreadFunc(void* data) { |
285 | internal::Mutex* mutex = static_cast<internal::Mutex*>(data); | |
286 | mutex->Lock(); | |
287 | mutex->Unlock(); | |
9f95a23c | 288 | return nullptr; |
7c673cae 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 | } | |
9f95a23c | 327 | #endif // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA |
7c673cae FG |
328 | |
329 | TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) { | |
330 | const bool a_false_condition = false; | |
331 | const char regex[] = | |
332 | #ifdef _MSC_VER | |
9f95a23c | 333 | "googletest-port-test\\.cc\\(\\d+\\):" |
7c673cae | 334 | #elif GTEST_USES_POSIX_RE |
9f95a23c | 335 | "googletest-port-test\\.cc:[0-9]+" |
7c673cae | 336 | #else |
9f95a23c | 337 | "googletest-port-test\\.cc:\\d+" |
7c673cae 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 | ||
376 | # if GTEST_HAS_TYPED_TEST | |
377 | ||
378 | template <typename Str> | |
379 | class RETest : public ::testing::Test {}; | |
380 | ||
381 | // Defines StringTypes as the list of all string types that class RE | |
382 | // supports. | |
9f95a23c | 383 | typedef testing::Types< ::std::string, const char*> StringTypes; |
7c673cae | 384 | |
9f95a23c | 385 | TYPED_TEST_SUITE(RETest, StringTypes); |
7c673cae FG |
386 | |
387 | // Tests RE's implicit constructors. | |
388 | TYPED_TEST(RETest, ImplicitConstructorWorks) { | |
389 | const RE empty(TypeParam("")); | |
390 | EXPECT_STREQ("", empty.pattern()); | |
391 | ||
392 | const RE simple(TypeParam("hello")); | |
393 | EXPECT_STREQ("hello", simple.pattern()); | |
394 | ||
395 | const RE normal(TypeParam(".*(\\w+)")); | |
396 | EXPECT_STREQ(".*(\\w+)", normal.pattern()); | |
397 | } | |
398 | ||
399 | // Tests that RE's constructors reject invalid regular expressions. | |
400 | TYPED_TEST(RETest, RejectsInvalidRegex) { | |
401 | EXPECT_NONFATAL_FAILURE({ | |
402 | const RE invalid(TypeParam("?")); | |
403 | }, "\"?\" is not a valid POSIX Extended regular expression."); | |
404 | } | |
405 | ||
406 | // Tests RE::FullMatch(). | |
407 | TYPED_TEST(RETest, FullMatchWorks) { | |
408 | const RE empty(TypeParam("")); | |
409 | EXPECT_TRUE(RE::FullMatch(TypeParam(""), empty)); | |
410 | EXPECT_FALSE(RE::FullMatch(TypeParam("a"), empty)); | |
411 | ||
412 | const RE re(TypeParam("a.*z")); | |
413 | EXPECT_TRUE(RE::FullMatch(TypeParam("az"), re)); | |
414 | EXPECT_TRUE(RE::FullMatch(TypeParam("axyz"), re)); | |
415 | EXPECT_FALSE(RE::FullMatch(TypeParam("baz"), re)); | |
416 | EXPECT_FALSE(RE::FullMatch(TypeParam("azy"), re)); | |
417 | } | |
418 | ||
419 | // Tests RE::PartialMatch(). | |
420 | TYPED_TEST(RETest, PartialMatchWorks) { | |
421 | const RE empty(TypeParam("")); | |
422 | EXPECT_TRUE(RE::PartialMatch(TypeParam(""), empty)); | |
423 | EXPECT_TRUE(RE::PartialMatch(TypeParam("a"), empty)); | |
424 | ||
425 | const RE re(TypeParam("a.*z")); | |
426 | EXPECT_TRUE(RE::PartialMatch(TypeParam("az"), re)); | |
427 | EXPECT_TRUE(RE::PartialMatch(TypeParam("axyz"), re)); | |
428 | EXPECT_TRUE(RE::PartialMatch(TypeParam("baz"), re)); | |
429 | EXPECT_TRUE(RE::PartialMatch(TypeParam("azy"), re)); | |
430 | EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re)); | |
431 | } | |
432 | ||
433 | # endif // GTEST_HAS_TYPED_TEST | |
434 | ||
435 | #elif GTEST_USES_SIMPLE_RE | |
436 | ||
437 | TEST(IsInSetTest, NulCharIsNotInAnySet) { | |
438 | EXPECT_FALSE(IsInSet('\0', "")); | |
439 | EXPECT_FALSE(IsInSet('\0', "\0")); | |
440 | EXPECT_FALSE(IsInSet('\0', "a")); | |
441 | } | |
442 | ||
443 | TEST(IsInSetTest, WorksForNonNulChars) { | |
444 | EXPECT_FALSE(IsInSet('a', "Ab")); | |
445 | EXPECT_FALSE(IsInSet('c', "")); | |
446 | ||
447 | EXPECT_TRUE(IsInSet('b', "bcd")); | |
448 | EXPECT_TRUE(IsInSet('b', "ab")); | |
449 | } | |
450 | ||
451 | TEST(IsAsciiDigitTest, IsFalseForNonDigit) { | |
452 | EXPECT_FALSE(IsAsciiDigit('\0')); | |
453 | EXPECT_FALSE(IsAsciiDigit(' ')); | |
454 | EXPECT_FALSE(IsAsciiDigit('+')); | |
455 | EXPECT_FALSE(IsAsciiDigit('-')); | |
456 | EXPECT_FALSE(IsAsciiDigit('.')); | |
457 | EXPECT_FALSE(IsAsciiDigit('a')); | |
458 | } | |
459 | ||
460 | TEST(IsAsciiDigitTest, IsTrueForDigit) { | |
461 | EXPECT_TRUE(IsAsciiDigit('0')); | |
462 | EXPECT_TRUE(IsAsciiDigit('1')); | |
463 | EXPECT_TRUE(IsAsciiDigit('5')); | |
464 | EXPECT_TRUE(IsAsciiDigit('9')); | |
465 | } | |
466 | ||
467 | TEST(IsAsciiPunctTest, IsFalseForNonPunct) { | |
468 | EXPECT_FALSE(IsAsciiPunct('\0')); | |
469 | EXPECT_FALSE(IsAsciiPunct(' ')); | |
470 | EXPECT_FALSE(IsAsciiPunct('\n')); | |
471 | EXPECT_FALSE(IsAsciiPunct('a')); | |
472 | EXPECT_FALSE(IsAsciiPunct('0')); | |
473 | } | |
474 | ||
475 | TEST(IsAsciiPunctTest, IsTrueForPunct) { | |
476 | for (const char* p = "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"; *p; p++) { | |
477 | EXPECT_PRED1(IsAsciiPunct, *p); | |
478 | } | |
479 | } | |
480 | ||
481 | TEST(IsRepeatTest, IsFalseForNonRepeatChar) { | |
482 | EXPECT_FALSE(IsRepeat('\0')); | |
483 | EXPECT_FALSE(IsRepeat(' ')); | |
484 | EXPECT_FALSE(IsRepeat('a')); | |
485 | EXPECT_FALSE(IsRepeat('1')); | |
486 | EXPECT_FALSE(IsRepeat('-')); | |
487 | } | |
488 | ||
489 | TEST(IsRepeatTest, IsTrueForRepeatChar) { | |
490 | EXPECT_TRUE(IsRepeat('?')); | |
491 | EXPECT_TRUE(IsRepeat('*')); | |
492 | EXPECT_TRUE(IsRepeat('+')); | |
493 | } | |
494 | ||
495 | TEST(IsAsciiWhiteSpaceTest, IsFalseForNonWhiteSpace) { | |
496 | EXPECT_FALSE(IsAsciiWhiteSpace('\0')); | |
497 | EXPECT_FALSE(IsAsciiWhiteSpace('a')); | |
498 | EXPECT_FALSE(IsAsciiWhiteSpace('1')); | |
499 | EXPECT_FALSE(IsAsciiWhiteSpace('+')); | |
500 | EXPECT_FALSE(IsAsciiWhiteSpace('_')); | |
501 | } | |
502 | ||
503 | TEST(IsAsciiWhiteSpaceTest, IsTrueForWhiteSpace) { | |
504 | EXPECT_TRUE(IsAsciiWhiteSpace(' ')); | |
505 | EXPECT_TRUE(IsAsciiWhiteSpace('\n')); | |
506 | EXPECT_TRUE(IsAsciiWhiteSpace('\r')); | |
507 | EXPECT_TRUE(IsAsciiWhiteSpace('\t')); | |
508 | EXPECT_TRUE(IsAsciiWhiteSpace('\v')); | |
509 | EXPECT_TRUE(IsAsciiWhiteSpace('\f')); | |
510 | } | |
511 | ||
512 | TEST(IsAsciiWordCharTest, IsFalseForNonWordChar) { | |
513 | EXPECT_FALSE(IsAsciiWordChar('\0')); | |
514 | EXPECT_FALSE(IsAsciiWordChar('+')); | |
515 | EXPECT_FALSE(IsAsciiWordChar('.')); | |
516 | EXPECT_FALSE(IsAsciiWordChar(' ')); | |
517 | EXPECT_FALSE(IsAsciiWordChar('\n')); | |
518 | } | |
519 | ||
520 | TEST(IsAsciiWordCharTest, IsTrueForLetter) { | |
521 | EXPECT_TRUE(IsAsciiWordChar('a')); | |
522 | EXPECT_TRUE(IsAsciiWordChar('b')); | |
523 | EXPECT_TRUE(IsAsciiWordChar('A')); | |
524 | EXPECT_TRUE(IsAsciiWordChar('Z')); | |
525 | } | |
526 | ||
527 | TEST(IsAsciiWordCharTest, IsTrueForDigit) { | |
528 | EXPECT_TRUE(IsAsciiWordChar('0')); | |
529 | EXPECT_TRUE(IsAsciiWordChar('1')); | |
530 | EXPECT_TRUE(IsAsciiWordChar('7')); | |
531 | EXPECT_TRUE(IsAsciiWordChar('9')); | |
532 | } | |
533 | ||
534 | TEST(IsAsciiWordCharTest, IsTrueForUnderscore) { | |
535 | EXPECT_TRUE(IsAsciiWordChar('_')); | |
536 | } | |
537 | ||
538 | TEST(IsValidEscapeTest, IsFalseForNonPrintable) { | |
539 | EXPECT_FALSE(IsValidEscape('\0')); | |
540 | EXPECT_FALSE(IsValidEscape('\007')); | |
541 | } | |
542 | ||
543 | TEST(IsValidEscapeTest, IsFalseForDigit) { | |
544 | EXPECT_FALSE(IsValidEscape('0')); | |
545 | EXPECT_FALSE(IsValidEscape('9')); | |
546 | } | |
547 | ||
548 | TEST(IsValidEscapeTest, IsFalseForWhiteSpace) { | |
549 | EXPECT_FALSE(IsValidEscape(' ')); | |
550 | EXPECT_FALSE(IsValidEscape('\n')); | |
551 | } | |
552 | ||
553 | TEST(IsValidEscapeTest, IsFalseForSomeLetter) { | |
554 | EXPECT_FALSE(IsValidEscape('a')); | |
555 | EXPECT_FALSE(IsValidEscape('Z')); | |
556 | } | |
557 | ||
558 | TEST(IsValidEscapeTest, IsTrueForPunct) { | |
559 | EXPECT_TRUE(IsValidEscape('.')); | |
560 | EXPECT_TRUE(IsValidEscape('-')); | |
561 | EXPECT_TRUE(IsValidEscape('^')); | |
562 | EXPECT_TRUE(IsValidEscape('$')); | |
563 | EXPECT_TRUE(IsValidEscape('(')); | |
564 | EXPECT_TRUE(IsValidEscape(']')); | |
565 | EXPECT_TRUE(IsValidEscape('{')); | |
566 | EXPECT_TRUE(IsValidEscape('|')); | |
567 | } | |
568 | ||
569 | TEST(IsValidEscapeTest, IsTrueForSomeLetter) { | |
570 | EXPECT_TRUE(IsValidEscape('d')); | |
571 | EXPECT_TRUE(IsValidEscape('D')); | |
572 | EXPECT_TRUE(IsValidEscape('s')); | |
573 | EXPECT_TRUE(IsValidEscape('S')); | |
574 | EXPECT_TRUE(IsValidEscape('w')); | |
575 | EXPECT_TRUE(IsValidEscape('W')); | |
576 | } | |
577 | ||
578 | TEST(AtomMatchesCharTest, EscapedPunct) { | |
579 | EXPECT_FALSE(AtomMatchesChar(true, '\\', '\0')); | |
580 | EXPECT_FALSE(AtomMatchesChar(true, '\\', ' ')); | |
581 | EXPECT_FALSE(AtomMatchesChar(true, '_', '.')); | |
582 | EXPECT_FALSE(AtomMatchesChar(true, '.', 'a')); | |
583 | ||
584 | EXPECT_TRUE(AtomMatchesChar(true, '\\', '\\')); | |
585 | EXPECT_TRUE(AtomMatchesChar(true, '_', '_')); | |
586 | EXPECT_TRUE(AtomMatchesChar(true, '+', '+')); | |
587 | EXPECT_TRUE(AtomMatchesChar(true, '.', '.')); | |
588 | } | |
589 | ||
590 | TEST(AtomMatchesCharTest, Escaped_d) { | |
591 | EXPECT_FALSE(AtomMatchesChar(true, 'd', '\0')); | |
592 | EXPECT_FALSE(AtomMatchesChar(true, 'd', 'a')); | |
593 | EXPECT_FALSE(AtomMatchesChar(true, 'd', '.')); | |
594 | ||
595 | EXPECT_TRUE(AtomMatchesChar(true, 'd', '0')); | |
596 | EXPECT_TRUE(AtomMatchesChar(true, 'd', '9')); | |
597 | } | |
598 | ||
599 | TEST(AtomMatchesCharTest, Escaped_D) { | |
600 | EXPECT_FALSE(AtomMatchesChar(true, 'D', '0')); | |
601 | EXPECT_FALSE(AtomMatchesChar(true, 'D', '9')); | |
602 | ||
603 | EXPECT_TRUE(AtomMatchesChar(true, 'D', '\0')); | |
604 | EXPECT_TRUE(AtomMatchesChar(true, 'D', 'a')); | |
605 | EXPECT_TRUE(AtomMatchesChar(true, 'D', '-')); | |
606 | } | |
607 | ||
608 | TEST(AtomMatchesCharTest, Escaped_s) { | |
609 | EXPECT_FALSE(AtomMatchesChar(true, 's', '\0')); | |
610 | EXPECT_FALSE(AtomMatchesChar(true, 's', 'a')); | |
611 | EXPECT_FALSE(AtomMatchesChar(true, 's', '.')); | |
612 | EXPECT_FALSE(AtomMatchesChar(true, 's', '9')); | |
613 | ||
614 | EXPECT_TRUE(AtomMatchesChar(true, 's', ' ')); | |
615 | EXPECT_TRUE(AtomMatchesChar(true, 's', '\n')); | |
616 | EXPECT_TRUE(AtomMatchesChar(true, 's', '\t')); | |
617 | } | |
618 | ||
619 | TEST(AtomMatchesCharTest, Escaped_S) { | |
620 | EXPECT_FALSE(AtomMatchesChar(true, 'S', ' ')); | |
621 | EXPECT_FALSE(AtomMatchesChar(true, 'S', '\r')); | |
622 | ||
623 | EXPECT_TRUE(AtomMatchesChar(true, 'S', '\0')); | |
624 | EXPECT_TRUE(AtomMatchesChar(true, 'S', 'a')); | |
625 | EXPECT_TRUE(AtomMatchesChar(true, 'S', '9')); | |
626 | } | |
627 | ||
628 | TEST(AtomMatchesCharTest, Escaped_w) { | |
629 | EXPECT_FALSE(AtomMatchesChar(true, 'w', '\0')); | |
630 | EXPECT_FALSE(AtomMatchesChar(true, 'w', '+')); | |
631 | EXPECT_FALSE(AtomMatchesChar(true, 'w', ' ')); | |
632 | EXPECT_FALSE(AtomMatchesChar(true, 'w', '\n')); | |
633 | ||
634 | EXPECT_TRUE(AtomMatchesChar(true, 'w', '0')); | |
635 | EXPECT_TRUE(AtomMatchesChar(true, 'w', 'b')); | |
636 | EXPECT_TRUE(AtomMatchesChar(true, 'w', 'C')); | |
637 | EXPECT_TRUE(AtomMatchesChar(true, 'w', '_')); | |
638 | } | |
639 | ||
640 | TEST(AtomMatchesCharTest, Escaped_W) { | |
641 | EXPECT_FALSE(AtomMatchesChar(true, 'W', 'A')); | |
642 | EXPECT_FALSE(AtomMatchesChar(true, 'W', 'b')); | |
643 | EXPECT_FALSE(AtomMatchesChar(true, 'W', '9')); | |
644 | EXPECT_FALSE(AtomMatchesChar(true, 'W', '_')); | |
645 | ||
646 | EXPECT_TRUE(AtomMatchesChar(true, 'W', '\0')); | |
647 | EXPECT_TRUE(AtomMatchesChar(true, 'W', '*')); | |
648 | EXPECT_TRUE(AtomMatchesChar(true, 'W', '\n')); | |
649 | } | |
650 | ||
651 | TEST(AtomMatchesCharTest, EscapedWhiteSpace) { | |
652 | EXPECT_FALSE(AtomMatchesChar(true, 'f', '\0')); | |
653 | EXPECT_FALSE(AtomMatchesChar(true, 'f', '\n')); | |
654 | EXPECT_FALSE(AtomMatchesChar(true, 'n', '\0')); | |
655 | EXPECT_FALSE(AtomMatchesChar(true, 'n', '\r')); | |
656 | EXPECT_FALSE(AtomMatchesChar(true, 'r', '\0')); | |
657 | EXPECT_FALSE(AtomMatchesChar(true, 'r', 'a')); | |
658 | EXPECT_FALSE(AtomMatchesChar(true, 't', '\0')); | |
659 | EXPECT_FALSE(AtomMatchesChar(true, 't', 't')); | |
660 | EXPECT_FALSE(AtomMatchesChar(true, 'v', '\0')); | |
661 | EXPECT_FALSE(AtomMatchesChar(true, 'v', '\f')); | |
662 | ||
663 | EXPECT_TRUE(AtomMatchesChar(true, 'f', '\f')); | |
664 | EXPECT_TRUE(AtomMatchesChar(true, 'n', '\n')); | |
665 | EXPECT_TRUE(AtomMatchesChar(true, 'r', '\r')); | |
666 | EXPECT_TRUE(AtomMatchesChar(true, 't', '\t')); | |
667 | EXPECT_TRUE(AtomMatchesChar(true, 'v', '\v')); | |
668 | } | |
669 | ||
670 | TEST(AtomMatchesCharTest, UnescapedDot) { | |
671 | EXPECT_FALSE(AtomMatchesChar(false, '.', '\n')); | |
672 | ||
673 | EXPECT_TRUE(AtomMatchesChar(false, '.', '\0')); | |
674 | EXPECT_TRUE(AtomMatchesChar(false, '.', '.')); | |
675 | EXPECT_TRUE(AtomMatchesChar(false, '.', 'a')); | |
676 | EXPECT_TRUE(AtomMatchesChar(false, '.', ' ')); | |
677 | } | |
678 | ||
679 | TEST(AtomMatchesCharTest, UnescapedChar) { | |
680 | EXPECT_FALSE(AtomMatchesChar(false, 'a', '\0')); | |
681 | EXPECT_FALSE(AtomMatchesChar(false, 'a', 'b')); | |
682 | EXPECT_FALSE(AtomMatchesChar(false, '$', 'a')); | |
683 | ||
684 | EXPECT_TRUE(AtomMatchesChar(false, '$', '$')); | |
685 | EXPECT_TRUE(AtomMatchesChar(false, '5', '5')); | |
686 | EXPECT_TRUE(AtomMatchesChar(false, 'Z', 'Z')); | |
687 | } | |
688 | ||
689 | TEST(ValidateRegexTest, GeneratesFailureAndReturnsFalseForInvalid) { | |
690 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(NULL)), | |
691 | "NULL is not a valid simple regular expression"); | |
692 | EXPECT_NONFATAL_FAILURE( | |
693 | ASSERT_FALSE(ValidateRegex("a\\")), | |
694 | "Syntax error at index 1 in simple regular expression \"a\\\": "); | |
695 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a\\")), | |
696 | "'\\' cannot appear at the end"); | |
697 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\n\\")), | |
698 | "'\\' cannot appear at the end"); | |
699 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\s\\hb")), | |
700 | "invalid escape sequence \"\\h\""); | |
701 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^^")), | |
702 | "'^' can only appear at the beginning"); | |
703 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(".*^b")), | |
704 | "'^' can only appear at the beginning"); | |
705 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("$$")), | |
706 | "'$' can only appear at the end"); | |
707 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^$a")), | |
708 | "'$' can only appear at the end"); | |
709 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a(b")), | |
710 | "'(' is unsupported"); | |
711 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("ab)")), | |
712 | "')' is unsupported"); | |
713 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("[ab")), | |
714 | "'[' is unsupported"); | |
715 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a{2")), | |
716 | "'{' is unsupported"); | |
717 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("?")), | |
718 | "'?' can only follow a repeatable token"); | |
719 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^*")), | |
720 | "'*' can only follow a repeatable token"); | |
721 | EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("5*+")), | |
722 | "'+' can only follow a repeatable token"); | |
723 | } | |
724 | ||
725 | TEST(ValidateRegexTest, ReturnsTrueForValid) { | |
726 | EXPECT_TRUE(ValidateRegex("")); | |
727 | EXPECT_TRUE(ValidateRegex("a")); | |
728 | EXPECT_TRUE(ValidateRegex(".*")); | |
729 | EXPECT_TRUE(ValidateRegex("^a_+")); | |
730 | EXPECT_TRUE(ValidateRegex("^a\\t\\&?")); | |
731 | EXPECT_TRUE(ValidateRegex("09*$")); | |
732 | EXPECT_TRUE(ValidateRegex("^Z$")); | |
733 | EXPECT_TRUE(ValidateRegex("a\\^Z\\$\\(\\)\\|\\[\\]\\{\\}")); | |
734 | } | |
735 | ||
736 | TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrOne) { | |
737 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "a", "ba")); | |
738 | // Repeating more than once. | |
739 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "aab")); | |
740 | ||
741 | // Repeating zero times. | |
742 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ba")); | |
743 | // Repeating once. | |
744 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ab")); | |
745 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '#', '?', ".", "##")); | |
746 | } | |
747 | ||
748 | TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrMany) { | |
749 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '*', "a$", "baab")); | |
750 | ||
751 | // Repeating zero times. | |
752 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "bc")); | |
753 | // Repeating once. | |
754 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "abc")); | |
755 | // Repeating more than once. | |
756 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '*', "-", "ab_1-g")); | |
757 | } | |
758 | ||
759 | TEST(MatchRepetitionAndRegexAtHeadTest, WorksForOneOrMany) { | |
760 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "a$", "baab")); | |
761 | // Repeating zero times. | |
762 | EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "bc")); | |
763 | ||
764 | // Repeating once. | |
765 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "abc")); | |
766 | // Repeating more than once. | |
767 | EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '+', "-", "ab_1-g")); | |
768 | } | |
769 | ||
770 | TEST(MatchRegexAtHeadTest, ReturnsTrueForEmptyRegex) { | |
771 | EXPECT_TRUE(MatchRegexAtHead("", "")); | |
772 | EXPECT_TRUE(MatchRegexAtHead("", "ab")); | |
773 | } | |
774 | ||
775 | TEST(MatchRegexAtHeadTest, WorksWhenDollarIsInRegex) { | |
776 | EXPECT_FALSE(MatchRegexAtHead("$", "a")); | |
777 | ||
778 | EXPECT_TRUE(MatchRegexAtHead("$", "")); | |
779 | EXPECT_TRUE(MatchRegexAtHead("a$", "a")); | |
780 | } | |
781 | ||
782 | TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithEscapeSequence) { | |
783 | EXPECT_FALSE(MatchRegexAtHead("\\w", "+")); | |
784 | EXPECT_FALSE(MatchRegexAtHead("\\W", "ab")); | |
785 | ||
786 | EXPECT_TRUE(MatchRegexAtHead("\\sa", "\nab")); | |
787 | EXPECT_TRUE(MatchRegexAtHead("\\d", "1a")); | |
788 | } | |
789 | ||
790 | TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) { | |
791 | EXPECT_FALSE(MatchRegexAtHead(".+a", "abc")); | |
792 | EXPECT_FALSE(MatchRegexAtHead("a?b", "aab")); | |
793 | ||
794 | EXPECT_TRUE(MatchRegexAtHead(".*a", "bc12-ab")); | |
795 | EXPECT_TRUE(MatchRegexAtHead("a?b", "b")); | |
796 | EXPECT_TRUE(MatchRegexAtHead("a?b", "ab")); | |
797 | } | |
798 | ||
799 | TEST(MatchRegexAtHeadTest, | |
800 | WorksWhenRegexStartsWithRepetionOfEscapeSequence) { | |
801 | EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc")); | |
802 | EXPECT_FALSE(MatchRegexAtHead("\\s?b", " b")); | |
803 | ||
804 | EXPECT_TRUE(MatchRegexAtHead("\\(*a", "((((ab")); | |
805 | EXPECT_TRUE(MatchRegexAtHead("\\^?b", "^b")); | |
806 | EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "b")); | |
807 | EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "\\b")); | |
808 | } | |
809 | ||
810 | TEST(MatchRegexAtHeadTest, MatchesSequentially) { | |
811 | EXPECT_FALSE(MatchRegexAtHead("ab.*c", "acabc")); | |
812 | ||
813 | EXPECT_TRUE(MatchRegexAtHead("ab.*c", "ab-fsc")); | |
814 | } | |
815 | ||
816 | TEST(MatchRegexAnywhereTest, ReturnsFalseWhenStringIsNull) { | |
817 | EXPECT_FALSE(MatchRegexAnywhere("", NULL)); | |
818 | } | |
819 | ||
820 | TEST(MatchRegexAnywhereTest, WorksWhenRegexStartsWithCaret) { | |
821 | EXPECT_FALSE(MatchRegexAnywhere("^a", "ba")); | |
822 | EXPECT_FALSE(MatchRegexAnywhere("^$", "a")); | |
823 | ||
824 | EXPECT_TRUE(MatchRegexAnywhere("^a", "ab")); | |
825 | EXPECT_TRUE(MatchRegexAnywhere("^", "ab")); | |
826 | EXPECT_TRUE(MatchRegexAnywhere("^$", "")); | |
827 | } | |
828 | ||
829 | TEST(MatchRegexAnywhereTest, ReturnsFalseWhenNoMatch) { | |
830 | EXPECT_FALSE(MatchRegexAnywhere("a", "bcde123")); | |
831 | EXPECT_FALSE(MatchRegexAnywhere("a.+a", "--aa88888888")); | |
832 | } | |
833 | ||
834 | TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingPrefix) { | |
835 | EXPECT_TRUE(MatchRegexAnywhere("\\w+", "ab1_ - 5")); | |
836 | EXPECT_TRUE(MatchRegexAnywhere(".*=", "=")); | |
837 | EXPECT_TRUE(MatchRegexAnywhere("x.*ab?.*bc", "xaaabc")); | |
838 | } | |
839 | ||
840 | TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) { | |
841 | EXPECT_TRUE(MatchRegexAnywhere("\\w+", "$$$ ab1_ - 5")); | |
842 | EXPECT_TRUE(MatchRegexAnywhere("\\.+=", "= ...=")); | |
843 | } | |
844 | ||
845 | // Tests RE's implicit constructors. | |
846 | TEST(RETest, ImplicitConstructorWorks) { | |
847 | const RE empty(""); | |
848 | EXPECT_STREQ("", empty.pattern()); | |
849 | ||
850 | const RE simple("hello"); | |
851 | EXPECT_STREQ("hello", simple.pattern()); | |
852 | } | |
853 | ||
854 | // Tests that RE's constructors reject invalid regular expressions. | |
855 | TEST(RETest, RejectsInvalidRegex) { | |
856 | EXPECT_NONFATAL_FAILURE({ | |
857 | const RE normal(NULL); | |
858 | }, "NULL is not a valid simple regular expression"); | |
859 | ||
860 | EXPECT_NONFATAL_FAILURE({ | |
861 | const RE normal(".*(\\w+"); | |
862 | }, "'(' is unsupported"); | |
863 | ||
864 | EXPECT_NONFATAL_FAILURE({ | |
865 | const RE invalid("^?"); | |
866 | }, "'?' can only follow a repeatable token"); | |
867 | } | |
868 | ||
869 | // Tests RE::FullMatch(). | |
870 | TEST(RETest, FullMatchWorks) { | |
871 | const RE empty(""); | |
872 | EXPECT_TRUE(RE::FullMatch("", empty)); | |
873 | EXPECT_FALSE(RE::FullMatch("a", empty)); | |
874 | ||
875 | const RE re1("a"); | |
876 | EXPECT_TRUE(RE::FullMatch("a", re1)); | |
877 | ||
878 | const RE re("a.*z"); | |
879 | EXPECT_TRUE(RE::FullMatch("az", re)); | |
880 | EXPECT_TRUE(RE::FullMatch("axyz", re)); | |
881 | EXPECT_FALSE(RE::FullMatch("baz", re)); | |
882 | EXPECT_FALSE(RE::FullMatch("azy", re)); | |
883 | } | |
884 | ||
885 | // Tests RE::PartialMatch(). | |
886 | TEST(RETest, PartialMatchWorks) { | |
887 | const RE empty(""); | |
888 | EXPECT_TRUE(RE::PartialMatch("", empty)); | |
889 | EXPECT_TRUE(RE::PartialMatch("a", empty)); | |
890 | ||
891 | const RE re("a.*z"); | |
892 | EXPECT_TRUE(RE::PartialMatch("az", re)); | |
893 | EXPECT_TRUE(RE::PartialMatch("axyz", re)); | |
894 | EXPECT_TRUE(RE::PartialMatch("baz", re)); | |
895 | EXPECT_TRUE(RE::PartialMatch("azy", re)); | |
896 | EXPECT_FALSE(RE::PartialMatch("zza", re)); | |
897 | } | |
898 | ||
899 | #endif // GTEST_USES_POSIX_RE | |
900 | ||
901 | #if !GTEST_OS_WINDOWS_MOBILE | |
902 | ||
903 | TEST(CaptureTest, CapturesStdout) { | |
904 | CaptureStdout(); | |
905 | fprintf(stdout, "abc"); | |
906 | EXPECT_STREQ("abc", GetCapturedStdout().c_str()); | |
907 | ||
908 | CaptureStdout(); | |
909 | fprintf(stdout, "def%cghi", '\0'); | |
910 | EXPECT_EQ(::std::string("def\0ghi", 7), ::std::string(GetCapturedStdout())); | |
911 | } | |
912 | ||
913 | TEST(CaptureTest, CapturesStderr) { | |
914 | CaptureStderr(); | |
915 | fprintf(stderr, "jkl"); | |
916 | EXPECT_STREQ("jkl", GetCapturedStderr().c_str()); | |
917 | ||
918 | CaptureStderr(); | |
919 | fprintf(stderr, "jkl%cmno", '\0'); | |
920 | EXPECT_EQ(::std::string("jkl\0mno", 7), ::std::string(GetCapturedStderr())); | |
921 | } | |
922 | ||
923 | // Tests that stdout and stderr capture don't interfere with each other. | |
924 | TEST(CaptureTest, CapturesStdoutAndStderr) { | |
925 | CaptureStdout(); | |
926 | CaptureStderr(); | |
927 | fprintf(stdout, "pqr"); | |
928 | fprintf(stderr, "stu"); | |
929 | EXPECT_STREQ("pqr", GetCapturedStdout().c_str()); | |
930 | EXPECT_STREQ("stu", GetCapturedStderr().c_str()); | |
931 | } | |
932 | ||
933 | TEST(CaptureDeathTest, CannotReenterStdoutCapture) { | |
934 | CaptureStdout(); | |
935 | EXPECT_DEATH_IF_SUPPORTED(CaptureStdout(), | |
936 | "Only one stdout capturer can exist at a time"); | |
937 | GetCapturedStdout(); | |
938 | ||
939 | // We cannot test stderr capturing using death tests as they use it | |
940 | // themselves. | |
941 | } | |
942 | ||
943 | #endif // !GTEST_OS_WINDOWS_MOBILE | |
944 | ||
945 | TEST(ThreadLocalTest, DefaultConstructorInitializesToDefaultValues) { | |
946 | ThreadLocal<int> t1; | |
947 | EXPECT_EQ(0, t1.get()); | |
948 | ||
949 | ThreadLocal<void*> t2; | |
9f95a23c | 950 | EXPECT_TRUE(t2.get() == nullptr); |
7c673cae FG |
951 | } |
952 | ||
953 | TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) { | |
954 | ThreadLocal<int> t1(123); | |
955 | EXPECT_EQ(123, t1.get()); | |
956 | ||
957 | int i = 0; | |
958 | ThreadLocal<int*> t2(&i); | |
959 | EXPECT_EQ(&i, t2.get()); | |
960 | } | |
961 | ||
962 | class NoDefaultContructor { | |
963 | public: | |
964 | explicit NoDefaultContructor(const char*) {} | |
965 | NoDefaultContructor(const NoDefaultContructor&) {} | |
966 | }; | |
967 | ||
968 | TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) { | |
969 | ThreadLocal<NoDefaultContructor> bar(NoDefaultContructor("foo")); | |
970 | bar.pointer(); | |
971 | } | |
972 | ||
973 | TEST(ThreadLocalTest, GetAndPointerReturnSameValue) { | |
974 | ThreadLocal<std::string> thread_local_string; | |
975 | ||
976 | EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get())); | |
977 | ||
978 | // Verifies the condition still holds after calling set. | |
979 | thread_local_string.set("foo"); | |
980 | EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get())); | |
981 | } | |
982 | ||
983 | TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) { | |
984 | ThreadLocal<std::string> thread_local_string; | |
985 | const ThreadLocal<std::string>& const_thread_local_string = | |
986 | thread_local_string; | |
987 | ||
988 | EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer()); | |
989 | ||
990 | thread_local_string.set("foo"); | |
991 | EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer()); | |
992 | } | |
993 | ||
994 | #if GTEST_IS_THREADSAFE | |
995 | ||
996 | void AddTwo(int* param) { *param += 2; } | |
997 | ||
998 | TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) { | |
999 | int i = 40; | |
9f95a23c | 1000 | ThreadWithParam<int*> thread(&AddTwo, &i, nullptr); |
7c673cae FG |
1001 | thread.Join(); |
1002 | EXPECT_EQ(42, i); | |
1003 | } | |
1004 | ||
1005 | TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) { | |
1006 | // AssertHeld() is flaky only in the presence of multiple threads accessing | |
1007 | // the lock. In this case, the test is robust. | |
1008 | EXPECT_DEATH_IF_SUPPORTED({ | |
1009 | Mutex m; | |
1010 | { MutexLock lock(&m); } | |
1011 | m.AssertHeld(); | |
1012 | }, | |
1013 | "thread .*hold"); | |
1014 | } | |
1015 | ||
1016 | TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) { | |
1017 | Mutex m; | |
1018 | MutexLock lock(&m); | |
1019 | m.AssertHeld(); | |
1020 | } | |
1021 | ||
1022 | class AtomicCounterWithMutex { | |
1023 | public: | |
1024 | explicit AtomicCounterWithMutex(Mutex* mutex) : | |
1025 | value_(0), mutex_(mutex), random_(42) {} | |
1026 | ||
1027 | void Increment() { | |
1028 | MutexLock lock(mutex_); | |
1029 | int temp = value_; | |
1030 | { | |
1031 | // We need to put up a memory barrier to prevent reads and writes to | |
1032 | // value_ rearranged with the call to SleepMilliseconds when observed | |
1033 | // from other threads. | |
1034 | #if GTEST_HAS_PTHREAD | |
1035 | // On POSIX, locking a mutex puts up a memory barrier. We cannot use | |
1036 | // Mutex and MutexLock here or rely on their memory barrier | |
1037 | // functionality as we are testing them here. | |
1038 | pthread_mutex_t memory_barrier_mutex; | |
1039 | GTEST_CHECK_POSIX_SUCCESS_( | |
9f95a23c | 1040 | pthread_mutex_init(&memory_barrier_mutex, nullptr)); |
7c673cae FG |
1041 | GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex)); |
1042 | ||
9f95a23c | 1043 | SleepMilliseconds(static_cast<int>(random_.Generate(30))); |
7c673cae FG |
1044 | |
1045 | GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex)); | |
1046 | GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex)); | |
1047 | #elif GTEST_OS_WINDOWS | |
1048 | // On Windows, performing an interlocked access puts up a memory barrier. | |
1049 | volatile LONG dummy = 0; | |
1050 | ::InterlockedIncrement(&dummy); | |
9f95a23c | 1051 | SleepMilliseconds(static_cast<int>(random_.Generate(30))); |
7c673cae FG |
1052 | ::InterlockedIncrement(&dummy); |
1053 | #else | |
1054 | # error "Memory barrier not implemented on this platform." | |
1055 | #endif // GTEST_HAS_PTHREAD | |
1056 | } | |
1057 | value_ = temp + 1; | |
1058 | } | |
1059 | int value() const { return value_; } | |
1060 | ||
1061 | private: | |
1062 | volatile int value_; | |
1063 | Mutex* const mutex_; // Protects value_. | |
1064 | Random random_; | |
1065 | }; | |
1066 | ||
1067 | void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) { | |
1068 | for (int i = 0; i < param.second; ++i) | |
1069 | param.first->Increment(); | |
1070 | } | |
1071 | ||
1072 | // Tests that the mutex only lets one thread at a time to lock it. | |
1073 | TEST(MutexTest, OnlyOneThreadCanLockAtATime) { | |
1074 | Mutex mutex; | |
1075 | AtomicCounterWithMutex locked_counter(&mutex); | |
1076 | ||
1077 | typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType; | |
1078 | const int kCycleCount = 20; | |
1079 | const int kThreadCount = 7; | |
9f95a23c | 1080 | std::unique_ptr<ThreadType> counting_threads[kThreadCount]; |
7c673cae FG |
1081 | Notification threads_can_start; |
1082 | // Creates and runs kThreadCount threads that increment locked_counter | |
1083 | // kCycleCount times each. | |
1084 | for (int i = 0; i < kThreadCount; ++i) { | |
1085 | counting_threads[i].reset(new ThreadType(&CountingThreadFunc, | |
1086 | make_pair(&locked_counter, | |
1087 | kCycleCount), | |
1088 | &threads_can_start)); | |
1089 | } | |
1090 | threads_can_start.Notify(); | |
1091 | for (int i = 0; i < kThreadCount; ++i) | |
1092 | counting_threads[i]->Join(); | |
1093 | ||
1094 | // If the mutex lets more than one thread to increment the counter at a | |
1095 | // time, they are likely to encounter a race condition and have some | |
1096 | // increments overwritten, resulting in the lower then expected counter | |
1097 | // value. | |
1098 | EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value()); | |
1099 | } | |
1100 | ||
1101 | template <typename T> | |
1102 | void RunFromThread(void (func)(T), T param) { | |
9f95a23c | 1103 | ThreadWithParam<T> thread(func, param, nullptr); |
7c673cae FG |
1104 | thread.Join(); |
1105 | } | |
1106 | ||
1107 | void RetrieveThreadLocalValue( | |
1108 | pair<ThreadLocal<std::string>*, std::string*> param) { | |
1109 | *param.second = param.first->get(); | |
1110 | } | |
1111 | ||
1112 | TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) { | |
1113 | ThreadLocal<std::string> thread_local_string("foo"); | |
1114 | EXPECT_STREQ("foo", thread_local_string.get().c_str()); | |
1115 | ||
1116 | thread_local_string.set("bar"); | |
1117 | EXPECT_STREQ("bar", thread_local_string.get().c_str()); | |
1118 | ||
1119 | std::string result; | |
1120 | RunFromThread(&RetrieveThreadLocalValue, | |
1121 | make_pair(&thread_local_string, &result)); | |
1122 | EXPECT_STREQ("foo", result.c_str()); | |
1123 | } | |
1124 | ||
1125 | // Keeps track of whether of destructors being called on instances of | |
1126 | // DestructorTracker. On Windows, waits for the destructor call reports. | |
1127 | class DestructorCall { | |
1128 | public: | |
1129 | DestructorCall() { | |
1130 | invoked_ = false; | |
1131 | #if GTEST_OS_WINDOWS | |
1132 | wait_event_.Reset(::CreateEvent(NULL, TRUE, FALSE, NULL)); | |
1133 | GTEST_CHECK_(wait_event_.Get() != NULL); | |
1134 | #endif | |
1135 | } | |
1136 | ||
1137 | bool CheckDestroyed() const { | |
1138 | #if GTEST_OS_WINDOWS | |
1139 | if (::WaitForSingleObject(wait_event_.Get(), 1000) != WAIT_OBJECT_0) | |
1140 | return false; | |
1141 | #endif | |
1142 | return invoked_; | |
1143 | } | |
1144 | ||
1145 | void ReportDestroyed() { | |
1146 | invoked_ = true; | |
1147 | #if GTEST_OS_WINDOWS | |
1148 | ::SetEvent(wait_event_.Get()); | |
1149 | #endif | |
1150 | } | |
1151 | ||
1152 | static std::vector<DestructorCall*>& List() { return *list_; } | |
1153 | ||
1154 | static void ResetList() { | |
1155 | for (size_t i = 0; i < list_->size(); ++i) { | |
1156 | delete list_->at(i); | |
1157 | } | |
1158 | list_->clear(); | |
1159 | } | |
1160 | ||
1161 | private: | |
1162 | bool invoked_; | |
1163 | #if GTEST_OS_WINDOWS | |
1164 | AutoHandle wait_event_; | |
1165 | #endif | |
1166 | static std::vector<DestructorCall*>* const list_; | |
1167 | ||
1168 | GTEST_DISALLOW_COPY_AND_ASSIGN_(DestructorCall); | |
1169 | }; | |
1170 | ||
1171 | std::vector<DestructorCall*>* const DestructorCall::list_ = | |
1172 | new std::vector<DestructorCall*>; | |
1173 | ||
1174 | // DestructorTracker keeps track of whether its instances have been | |
1175 | // destroyed. | |
1176 | class DestructorTracker { | |
1177 | public: | |
1178 | DestructorTracker() : index_(GetNewIndex()) {} | |
1179 | DestructorTracker(const DestructorTracker& /* rhs */) | |
1180 | : index_(GetNewIndex()) {} | |
1181 | ~DestructorTracker() { | |
1182 | // We never access DestructorCall::List() concurrently, so we don't need | |
9f95a23c | 1183 | // to protect this access with a mutex. |
7c673cae FG |
1184 | DestructorCall::List()[index_]->ReportDestroyed(); |
1185 | } | |
1186 | ||
1187 | private: | |
1188 | static size_t GetNewIndex() { | |
1189 | DestructorCall::List().push_back(new DestructorCall); | |
1190 | return DestructorCall::List().size() - 1; | |
1191 | } | |
1192 | const size_t index_; | |
7c673cae FG |
1193 | }; |
1194 | ||
1195 | typedef ThreadLocal<DestructorTracker>* ThreadParam; | |
1196 | ||
1197 | void CallThreadLocalGet(ThreadParam thread_local_param) { | |
1198 | thread_local_param->get(); | |
1199 | } | |
1200 | ||
1201 | // Tests that when a ThreadLocal object dies in a thread, it destroys | |
1202 | // the managed object for that thread. | |
1203 | TEST(ThreadLocalTest, DestroysManagedObjectForOwnThreadWhenDying) { | |
1204 | DestructorCall::ResetList(); | |
1205 | ||
1206 | { | |
1207 | ThreadLocal<DestructorTracker> thread_local_tracker; | |
1208 | ASSERT_EQ(0U, DestructorCall::List().size()); | |
1209 | ||
1210 | // This creates another DestructorTracker object for the main thread. | |
1211 | thread_local_tracker.get(); | |
1212 | ASSERT_EQ(1U, DestructorCall::List().size()); | |
1213 | ASSERT_FALSE(DestructorCall::List()[0]->CheckDestroyed()); | |
1214 | } | |
1215 | ||
1216 | // Now thread_local_tracker has died. | |
1217 | ASSERT_EQ(1U, DestructorCall::List().size()); | |
1218 | EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed()); | |
1219 | ||
1220 | DestructorCall::ResetList(); | |
1221 | } | |
1222 | ||
1223 | // Tests that when a thread exits, the thread-local object for that | |
1224 | // thread is destroyed. | |
1225 | TEST(ThreadLocalTest, DestroysManagedObjectAtThreadExit) { | |
1226 | DestructorCall::ResetList(); | |
1227 | ||
1228 | { | |
1229 | ThreadLocal<DestructorTracker> thread_local_tracker; | |
1230 | ASSERT_EQ(0U, DestructorCall::List().size()); | |
1231 | ||
1232 | // This creates another DestructorTracker object in the new thread. | |
9f95a23c TL |
1233 | ThreadWithParam<ThreadParam> thread(&CallThreadLocalGet, |
1234 | &thread_local_tracker, nullptr); | |
7c673cae FG |
1235 | thread.Join(); |
1236 | ||
1237 | // The thread has exited, and we should have a DestroyedTracker | |
1238 | // instance created for it. But it may not have been destroyed yet. | |
1239 | ASSERT_EQ(1U, DestructorCall::List().size()); | |
1240 | } | |
1241 | ||
1242 | // The thread has exited and thread_local_tracker has died. | |
1243 | ASSERT_EQ(1U, DestructorCall::List().size()); | |
1244 | EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed()); | |
1245 | ||
1246 | DestructorCall::ResetList(); | |
1247 | } | |
1248 | ||
1249 | TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) { | |
1250 | ThreadLocal<std::string> thread_local_string; | |
1251 | thread_local_string.set("Foo"); | |
1252 | EXPECT_STREQ("Foo", thread_local_string.get().c_str()); | |
1253 | ||
1254 | std::string result; | |
1255 | RunFromThread(&RetrieveThreadLocalValue, | |
1256 | make_pair(&thread_local_string, &result)); | |
1257 | EXPECT_TRUE(result.empty()); | |
1258 | } | |
1259 | ||
1260 | #endif // GTEST_IS_THREADSAFE | |
1261 | ||
1262 | #if GTEST_OS_WINDOWS | |
1263 | TEST(WindowsTypesTest, HANDLEIsVoidStar) { | |
1264 | StaticAssertTypeEq<HANDLE, void*>(); | |
1265 | } | |
1266 | ||
9f95a23c TL |
1267 | #if GTEST_OS_WINDOWS_MINGW && !defined(__MINGW64_VERSION_MAJOR) |
1268 | TEST(WindowsTypesTest, _CRITICAL_SECTIONIs_CRITICAL_SECTION) { | |
1269 | StaticAssertTypeEq<CRITICAL_SECTION, _CRITICAL_SECTION>(); | |
1270 | } | |
1271 | #else | |
7c673cae FG |
1272 | TEST(WindowsTypesTest, CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION) { |
1273 | StaticAssertTypeEq<CRITICAL_SECTION, _RTL_CRITICAL_SECTION>(); | |
1274 | } | |
9f95a23c TL |
1275 | #endif |
1276 | ||
7c673cae FG |
1277 | #endif // GTEST_OS_WINDOWS |
1278 | ||
1279 | } // namespace internal | |
1280 | } // namespace testing |