60 {
61
62
63
64
65
66
67
68
69
70
71
72
73class MatchResultListener {
74 public:
75
76
77
78 explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
79 virtual ~MatchResultListener() = 0;
80
81
82
83 template <typename T>
85 if (stream_ !=
nullptr) *stream_ <<
x;
86 return *this;
87 }
88
89
90 ::std::ostream* stream() { return stream_; }
91
92
93
94
95
96 bool IsInterested() const { return stream_ != nullptr; }
97
98 private:
99 ::std::ostream* const stream_;
100
102};
103
104inline MatchResultListener::~MatchResultListener() {
105}
106
107
108
110 public:
111 virtual ~MatcherDescriberInterface() {}
112
113
114
115
116
117
118 virtual void DescribeTo(::std::ostream* os) const = 0;
119
120
121
122
123
124
125
126 virtual void DescribeNegationTo(::std::ostream* os) const {
127 *os << "not (";
128 DescribeTo(os);
129 *os << ")";
130 }
131};
132
133
134template <typename T>
135class MatcherInterface : public MatcherDescriberInterface {
136 public:
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 virtual bool MatchAndExplain(T
x, MatchResultListener* listener)
const = 0;
169
170
171
172
173};
174
175namespace internal {
176
177struct AnyEq {
178 template <typename A, typename B>
179 bool operator()(const A& a, const B& b) const { return a == b; }
180};
181struct AnyNe {
182 template <typename A, typename B>
183 bool operator()(const A& a, const B& b) const { return a != b; }
184};
185struct AnyLt {
186 template <typename A, typename B>
187 bool operator()(const A& a, const B& b) const { return a < b; }
188};
189struct AnyGt {
190 template <typename A, typename B>
191 bool operator()(const A& a, const B& b) const { return a > b; }
192};
193struct AnyLe {
194 template <typename A, typename B>
195 bool operator()(const A& a, const B& b) const { return a <= b; }
196};
197struct AnyGe {
198 template <typename A, typename B>
199 bool operator()(const A& a, const B& b) const { return a >= b; }
200};
201
202
203class DummyMatchResultListener : public MatchResultListener {
204 public:
205 DummyMatchResultListener() : MatchResultListener(nullptr) {}
206
207 private:
209};
210
211
212
213
214class StreamMatchResultListener : public MatchResultListener {
215 public:
216 explicit StreamMatchResultListener(::std::ostream* os)
217 : MatchResultListener(os) {}
218
219 private:
221};
222
223struct SharedPayloadBase {
224 std::atomic<int> ref{1};
225 void Ref() { ref.fetch_add(1, std::memory_order_relaxed); }
226 bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; }
227};
228
229template <typename T>
230struct SharedPayload : SharedPayloadBase {
231 explicit SharedPayload(
const T& v) :
value(v) {}
232 explicit SharedPayload(T&& v) :
value(
std::move(v)) {}
233
234 static void Destroy(SharedPayloadBase* shared) {
235 delete static_cast<SharedPayload*>(shared);
236 }
237
239};
240
241
242
243
244template <typename T>
245class MatcherBase : private MatcherDescriberInterface {
246 public:
247
248
249 bool MatchAndExplain(
const T&
x, MatchResultListener* listener)
const {
251 return vtable_->match_and_explain(*
this,
x, listener);
252 }
253
254
255 bool Matches(
const T&
x)
const {
256 DummyMatchResultListener dummy;
257 return MatchAndExplain(
x, &dummy);
258 }
259
260
261 void DescribeTo(::std::ostream* os) const final {
263 vtable_->describe(*this, os, false);
264 }
265
266
267 void DescribeNegationTo(::std::ostream* os) const final {
269 vtable_->describe(*this, os, true);
270 }
271
272
273 void ExplainMatchResultTo(
const T&
x, ::std::ostream* os)
const {
274 StreamMatchResultListener listener(os);
275 MatchAndExplain(
x, &listener);
276 }
277
278
279
280
281 const MatcherDescriberInterface* GetDescriber() const {
282 if (vtable_ == nullptr) return nullptr;
283 return vtable_->get_describer(*this);
284 }
285
286 protected:
287 MatcherBase() : vtable_(nullptr) {}
288
289
290 template <typename U>
291 explicit MatcherBase(const MatcherInterface<U>* impl) {
292 Init(impl);
293 }
294
295 template <typename M, typename = typename std::remove_reference<
296 M>::type::is_gtest_matcher>
297 MatcherBase(M&& m) {
298 Init(std::forward<M>(m));
299 }
300
301 MatcherBase(const MatcherBase& other)
302 : vtable_(other.vtable_), buffer_(other.buffer_) {
303 if (IsShared()) buffer_.shared->Ref();
304 }
305
306 MatcherBase& operator=(const MatcherBase& other) {
307 if (this == &other) return *this;
308 Destroy();
309 vtable_ = other.vtable_;
310 buffer_ = other.buffer_;
311 if (IsShared()) buffer_.shared->Ref();
312 return *this;
313 }
314
315 MatcherBase(MatcherBase&& other)
316 : vtable_(other.vtable_), buffer_(other.buffer_) {
317 other.vtable_ = nullptr;
318 }
319
320 MatcherBase& operator=(MatcherBase&& other) {
321 if (this == &other) return *this;
322 Destroy();
323 vtable_ = other.vtable_;
324 buffer_ = other.buffer_;
325 other.vtable_ = nullptr;
326 return *this;
327 }
328
329 ~MatcherBase() override { Destroy(); }
330
331 private:
332 struct VTable {
333 bool (*match_and_explain)(const MatcherBase&, const T&,
334 MatchResultListener*);
335 void (*describe)(const MatcherBase&, std::ostream*, bool negation);
336
337
338 const MatcherDescriberInterface* (*get_describer)(const MatcherBase&);
339
340 void (*shared_destroy)(SharedPayloadBase*);
341 };
342
343 bool IsShared() const {
344 return vtable_ != nullptr && vtable_->shared_destroy != nullptr;
345 }
346
347
348 template <typename P>
349 static auto MatchAndExplainImpl(
const MatcherBase& m,
const T&
value,
350 MatchResultListener* listener)
351 ->
decltype(P::Get(m).MatchAndExplain(
value, listener->stream())) {
352 return P::Get(m).MatchAndExplain(
value, listener->stream());
353 }
354
355 template <typename P>
356 static auto MatchAndExplainImpl(
const MatcherBase& m,
const T&
value,
357 MatchResultListener* listener)
358 ->
decltype(P::Get(m).MatchAndExplain(
value, listener)) {
359 return P::Get(m).MatchAndExplain(
value, listener);
360 }
361
362 template <typename P>
363 static void DescribeImpl(const MatcherBase& m, std::ostream* os,
364 bool negation) {
365 if (negation) {
366 P::Get(m).DescribeNegationTo(os);
367 } else {
368 P::Get(m).DescribeTo(os);
369 }
370 }
371
372 template <typename P>
373 static const MatcherDescriberInterface* GetDescriberImpl(
374 const MatcherBase& m) {
375
376
377
378
379
380
381 return std::get<(
382 std::is_convertible<decltype(&P::Get(m)),
383 const MatcherDescriberInterface*>
::value
384 ? 1
385 : 0)>(std::make_tuple(&m, &P::Get(m)));
386 }
387
388 template <typename P>
389 const VTable* GetVTable() {
390 static constexpr VTable kVTable = {&MatchAndExplainImpl<P>,
391 &DescribeImpl<P>, &GetDescriberImpl<P>,
392 P::shared_destroy};
393 return &kVTable;
394 }
395
396 union Buffer {
397
398 void* ptr;
399 double d;
401
402 SharedPayloadBase* shared;
403 };
404
405 void Destroy() {
406 if (IsShared() && buffer_.shared->Unref()) {
407 vtable_->shared_destroy(buffer_.shared);
408 }
409 }
410
411 template <typename M>
412 static constexpr bool IsInlined() {
413 return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) &&
416 }
417
418 template <typename M, bool = MatcherBase::IsInlined<M>()>
419 struct ValuePolicy {
420 static const M& Get(const MatcherBase& m) {
421
422
423 const M *ptr = static_cast<const M*>(
424 static_cast<const void*>(&m.buffer_));
425 return *ptr;
426 }
427 static void Init(MatcherBase& m, M impl) {
428 ::new (static_cast<void*>(&m.buffer_)) M(impl);
429 }
430 static constexpr auto shared_destroy = nullptr;
431 };
432
433 template <typename M>
434 struct ValuePolicy<M, false> {
435 using Shared = SharedPayload<M>;
436 static const M& Get(const MatcherBase& m) {
437 return static_cast<Shared*
>(m.buffer_.shared)->
value;
438 }
439 template <typename Arg>
440 static void Init(MatcherBase& m, Arg&& arg) {
441 m.buffer_.shared = new Shared(std::forward<Arg>(arg));
442 }
443 static constexpr auto shared_destroy = &Shared::Destroy;
444 };
445
446 template <typename U, bool B>
447 struct ValuePolicy<
const MatcherInterface<U>*, B> {
448 using M = const MatcherInterface<U>;
449 using Shared = SharedPayload<std::unique_ptr<M>>;
450 static const M& Get(const MatcherBase& m) {
451 return *
static_cast<Shared*
>(m.buffer_.shared)->
value;
452 }
453 static void Init(MatcherBase& m, M* impl) {
454 m.buffer_.shared = new Shared(std::unique_ptr<M>(impl));
455 }
456
457 static constexpr auto shared_destroy = &Shared::Destroy;
458 };
459
460 template <typename M>
461 void Init(M&& m) {
463 using Policy = ValuePolicy<MM>;
464 vtable_ = GetVTable<Policy>();
465 Policy::Init(*this, std::forward<M>(m));
466 }
467
468 const VTable* vtable_;
469 Buffer buffer_;
470};
471
472}
473
474
475
476
477
478template <typename T>
479class Matcher : public internal::MatcherBase<T> {
480 public:
481
482
483
484 explicit Matcher() {}
485
486
487 explicit Matcher(const MatcherInterface<const T&>* impl)
488 : internal::MatcherBase<T>(impl) {}
489
490 template <typename U>
491 explicit Matcher(
492 const MatcherInterface<U>* impl,
494 nullptr)
495 : internal::MatcherBase<T>(impl) {}
496
497 template <typename M, typename = typename std::remove_reference<
498 M>::type::is_gtest_matcher>
499 Matcher(M&& m) : internal::MatcherBase<T>(
std::forward<M>(m)) {}
500
501
502
504};
505
506
507
508
509template <>
511 : public internal::MatcherBase<const std::string&> {
512 public:
513 Matcher() {}
514
515 explicit Matcher(const MatcherInterface<const std::string&>* impl)
516 : internal::MatcherBase<
const std::string&>(impl) {}
517
518 template <typename M, typename = typename std::remove_reference<
519 M>::type::is_gtest_matcher>
520 Matcher(M&& m)
521 : internal::MatcherBase<
const std::string&>(
std::forward<M>(m)) {}
522
523
524
525 Matcher(const std::string& s);
526
527
528 Matcher(const char* s);
529};
530
531template <>
533 : public internal::MatcherBase<std::string> {
534 public:
535 Matcher() {}
536
537 explicit Matcher(const MatcherInterface<const std::string&>* impl)
538 : internal::MatcherBase<
std::string>(impl) {}
539 explicit Matcher(const MatcherInterface<std::string>* impl)
540 : internal::MatcherBase<
std::string>(impl) {}
541
542 template <typename M, typename = typename std::remove_reference<
543 M>::type::is_gtest_matcher>
544 Matcher(M&& m)
545 : internal::MatcherBase<
std::string>(
std::forward<M>(m)) {}
546
547
548
549 Matcher(const std::string& s);
550
551
552 Matcher(const char* s);
553};
554
555#if GTEST_INTERNAL_HAS_STRING_VIEW
556
557
558
559template <>
561 : public internal::MatcherBase<const internal::StringView&> {
562 public:
563 Matcher() {}
564
565 explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
566 : internal::MatcherBase<
const internal::StringView&>(impl) {}
567
568 template <typename M, typename = typename std::remove_reference<
569 M>::type::is_gtest_matcher>
570 Matcher(M&& m)
571 : internal::MatcherBase<
const internal::StringView&>(
std::forward<M>(m)) {
572 }
573
574
575
576 Matcher(const std::string& s);
577
578
579 Matcher(const char* s);
580
581
582 Matcher(internal::StringView s);
583};
584
585template <>
587 : public internal::MatcherBase<internal::StringView> {
588 public:
589 Matcher() {}
590
591 explicit Matcher(const MatcherInterface<const internal::StringView&>* impl)
592 : internal::MatcherBase<internal::StringView>(impl) {}
593 explicit Matcher(const MatcherInterface<internal::StringView>* impl)
594 : internal::MatcherBase<internal::StringView>(impl) {}
595
596 template <typename M, typename = typename std::remove_reference<
597 M>::type::is_gtest_matcher>
598 Matcher(M&& m)
599 : internal::MatcherBase<internal::StringView>(
std::forward<M>(m)) {}
600
601
602
603 Matcher(const std::string& s);
604
605
606 Matcher(const char* s);
607
608
609 Matcher(internal::StringView s);
610};
611#endif
612
613
614template <typename T>
615std::ostream&
operator<<(std::ostream& os,
const Matcher<T>& matcher) {
616 matcher.DescribeTo(&os);
617 return os;
618}
619
620
621
622
623
624
625
626
627
628
629
630
631
632template <class Impl>
633class PolymorphicMatcher {
634 public:
635 explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
636
637
638
639 Impl& mutable_impl() { return impl_; }
640
641
642
643 const Impl& impl() const { return impl_; }
644
645 template <typename T>
646 operator Matcher<T>() const {
647 return Matcher<T>(new MonomorphicImpl<const T&>(impl_));
648 }
649
650 private:
651 template <typename T>
652 class MonomorphicImpl : public MatcherInterface<T> {
653 public:
654 explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
655
656 void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); }
657
658 void DescribeNegationTo(::std::ostream* os) const override {
659 impl_.DescribeNegationTo(os);
660 }
661
662 bool MatchAndExplain(T
x, MatchResultListener* listener)
const override {
663 return impl_.MatchAndExplain(
x, listener);
664 }
665
666 private:
667 const Impl impl_;
668 };
669
670 Impl impl_;
671};
672
673
674
675
676
677
678
679template <typename T>
680inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
681 return Matcher<T>(impl);
682}
683
684
685
686
687
688
689
690
691template <class Impl>
692inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
693 return PolymorphicMatcher<Impl>(impl);
694}
695
696namespace internal {
697
698
699
700
701
702
703
704
705
706
707template <typename D, typename Rhs, typename Op>
708class ComparisonBase {
709 public:
710 explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
711
712 using is_gtest_matcher = void;
713
714 template <typename Lhs>
715 bool MatchAndExplain(const Lhs& lhs, std::ostream*) const {
716 return Op()(lhs, Unwrap(rhs_));
717 }
718 void DescribeTo(std::ostream* os) const {
719 *os << D::Desc() << " ";
721 }
722 void DescribeNegationTo(std::ostream* os) const {
723 *os << D::NegatedDesc() << " ";
725 }
726
727 private:
728 template <typename T>
729 static const T& Unwrap(const T& v) {
730 return v;
731 }
732 template <typename T>
733 static const T& Unwrap(std::reference_wrapper<T> v) {
734 return v;
735 }
736
737 Rhs rhs_;
738};
739
740template <typename Rhs>
741class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
742 public:
743 explicit EqMatcher(const Rhs& rhs)
744 : ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { }
745 static const char* Desc() { return "is equal to"; }
746 static const char* NegatedDesc() { return "isn't equal to"; }
747};
748template <typename Rhs>
749class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
750 public:
751 explicit NeMatcher(const Rhs& rhs)
752 : ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { }
753 static const char* Desc() { return "isn't equal to"; }
754 static const char* NegatedDesc() { return "is equal to"; }
755};
756template <typename Rhs>
757class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
758 public:
759 explicit LtMatcher(const Rhs& rhs)
760 : ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { }
761 static const char* Desc() { return "is <"; }
762 static const char* NegatedDesc() { return "isn't <"; }
763};
764template <typename Rhs>
765class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
766 public:
767 explicit GtMatcher(const Rhs& rhs)
768 : ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { }
769 static const char* Desc() { return "is >"; }
770 static const char* NegatedDesc() { return "isn't >"; }
771};
772template <typename Rhs>
773class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
774 public:
775 explicit LeMatcher(const Rhs& rhs)
776 : ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { }
777 static const char* Desc() { return "is <="; }
778 static const char* NegatedDesc() { return "isn't <="; }
779};
780template <typename Rhs>
781class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
782 public:
783 explicit GeMatcher(const Rhs& rhs)
784 : ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { }
785 static const char* Desc() { return "is >="; }
786 static const char* NegatedDesc() { return "isn't >="; }
787};
788
789template <typename T, typename = typename std::enable_if<
791using StringLike = T;
792
793
794
795
796class MatchesRegexMatcher {
797 public:
798 MatchesRegexMatcher(const RE* regex, bool full_match)
799 : regex_(regex), full_match_(full_match) {}
800
801#if GTEST_INTERNAL_HAS_STRING_VIEW
802 bool MatchAndExplain(const internal::StringView& s,
803 MatchResultListener* listener) const {
804 return MatchAndExplain(std::string(s), listener);
805 }
806#endif
807
808
809
810
811
812
813 template <typename CharType>
814 bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
815 return s != nullptr && MatchAndExplain(std::string(s), listener);
816 }
817
818
819
820
821
822 template <class MatcheeStringType>
823 bool MatchAndExplain(const MatcheeStringType& s,
824 MatchResultListener* ) const {
825 const std::string& s2(s);
826 return full_match_ ? RE::FullMatch(s2, *regex_)
827 : RE::PartialMatch(s2, *regex_);
828 }
829
830 void DescribeTo(::std::ostream* os) const {
831 *os << (full_match_ ? "matches" : "contains") << " regular expression ";
833 }
834
835 void DescribeNegationTo(::std::ostream* os) const {
836 *os << "doesn't " << (full_match_ ? "match" : "contain")
837 << " regular expression ";
839 }
840
841 private:
842 const std::shared_ptr<const RE> regex_;
843 const bool full_match_;
844};
845}
846
847
848
849inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
850 const internal::RE* regex) {
851 return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
852}
853template <typename T = std::string>
854PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
855 const internal::StringLike<T>& regex) {
856 return MatchesRegex(new internal::RE(std::string(regex)));
857}
858
859
860
861inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
862 const internal::RE* regex) {
863 return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
864}
865template <typename T = std::string>
866PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
867 const internal::StringLike<T>& regex) {
868 return ContainsRegex(new internal::RE(std::string(regex)));
869}
870
871
872
873
874template <typename T>
875inline internal::EqMatcher<T> Eq(T
x) {
return internal::EqMatcher<T>(
x); }
876
877
878
879template <typename T>
880Matcher<T>::Matcher(T
value) { *
this = Eq(
value); }
881
882
883
884
885
886
887
888
889
890
891
892
893
894template <typename Lhs, typename Rhs>
895inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
896
897
898template <typename Rhs>
899inline internal::GeMatcher<Rhs> Ge(Rhs
x) {
900 return internal::GeMatcher<Rhs>(
x);
901}
902
903
904template <typename Rhs>
905inline internal::GtMatcher<Rhs> Gt(Rhs
x) {
906 return internal::GtMatcher<Rhs>(
x);
907}
908
909
910template <typename Rhs>
911inline internal::LeMatcher<Rhs> Le(Rhs
x) {
912 return internal::LeMatcher<Rhs>(
x);
913}
914
915
916template <typename Rhs>
917inline internal::LtMatcher<Rhs> Lt(Rhs
x) {
918 return internal::LtMatcher<Rhs>(
x);
919}
920
921
922template <typename Rhs>
923inline internal::NeMatcher<Rhs> Ne(Rhs
x) {
924 return internal::NeMatcher<Rhs>(
x);
925}
926}
#define GTEST_CHECK_(condition)
#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)
std::ostream & operator<<(std::ostream &os, const Message &sb)
void UniversalPrint(const T &value, ::std::ostream *os)
std::string Print(const T &value)