1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker * Copyright 2017 Google LLC
3*14675a02SAndroid Build Coastguard Worker *
4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker *
8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker *
10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker */
16*14675a02SAndroid Build Coastguard Worker
17*14675a02SAndroid Build Coastguard Worker #ifndef FCP_TESTING_TESTING_H_
18*14675a02SAndroid Build Coastguard Worker #define FCP_TESTING_TESTING_H_
19*14675a02SAndroid Build Coastguard Worker
20*14675a02SAndroid Build Coastguard Worker #include <iostream>
21*14675a02SAndroid Build Coastguard Worker #include <memory>
22*14675a02SAndroid Build Coastguard Worker #include <string>
23*14675a02SAndroid Build Coastguard Worker #include <type_traits>
24*14675a02SAndroid Build Coastguard Worker
25*14675a02SAndroid Build Coastguard Worker #include "google/protobuf/util/message_differencer.h"
26*14675a02SAndroid Build Coastguard Worker #include "gmock/gmock.h"
27*14675a02SAndroid Build Coastguard Worker #include "gtest/gtest.h"
28*14675a02SAndroid Build Coastguard Worker #include "absl/status/status.h"
29*14675a02SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
30*14675a02SAndroid Build Coastguard Worker #include "fcp/base/error.h"
31*14675a02SAndroid Build Coastguard Worker #include "fcp/base/monitoring.h"
32*14675a02SAndroid Build Coastguard Worker #include "fcp/base/platform.h"
33*14675a02SAndroid Build Coastguard Worker #include "fcp/base/result.h"
34*14675a02SAndroid Build Coastguard Worker #include "fcp/base/source_location.h"
35*14675a02SAndroid Build Coastguard Worker #include "fcp/testing/result_matchers.h"
36*14675a02SAndroid Build Coastguard Worker
37*14675a02SAndroid Build Coastguard Worker #include "fcp/testing/parse_text_proto.h"
38*14675a02SAndroid Build Coastguard Worker
39*14675a02SAndroid Build Coastguard Worker // This file defines platform dependent utilities for testing,
40*14675a02SAndroid Build Coastguard Worker // based on the public version of googletest.
41*14675a02SAndroid Build Coastguard Worker
42*14675a02SAndroid Build Coastguard Worker namespace fcp {
43*14675a02SAndroid Build Coastguard Worker
44*14675a02SAndroid Build Coastguard Worker // A macro for use inside a GTest test that executes the provided code as a
45*14675a02SAndroid Build Coastguard Worker // function returning a Result and asserts that the return value is not an
46*14675a02SAndroid Build Coastguard Worker // Error.
47*14675a02SAndroid Build Coastguard Worker //
48*14675a02SAndroid Build Coastguard Worker // The code provided to the macro will be much like the code one would write in
49*14675a02SAndroid Build Coastguard Worker // the body of a regular test, with the differences being that the code must
50*14675a02SAndroid Build Coastguard Worker // return Result<Unit>, and only EXPECT_* statements are allowed, not ASSERT_*.
51*14675a02SAndroid Build Coastguard Worker //
52*14675a02SAndroid Build Coastguard Worker // This makes it possible to greatly simplify the test body by using FCP_TRY(),
53*14675a02SAndroid Build Coastguard Worker // rather than having to check in the test body that every return value of
54*14675a02SAndroid Build Coastguard Worker // Result type is not an error.
55*14675a02SAndroid Build Coastguard Worker //
56*14675a02SAndroid Build Coastguard Worker // Example:
57*14675a02SAndroid Build Coastguard Worker //
58*14675a02SAndroid Build Coastguard Worker // TEST(FooTest, GetFoo) {
59*14675a02SAndroid Build Coastguard Worker // FCP_EXPECT_NO_ERROR(
60*14675a02SAndroid Build Coastguard Worker // Foo foo = FCP_TRY(GetFoo());
61*14675a02SAndroid Build Coastguard Worker // EXPECT_TRUE(foo.HasBar());
62*14675a02SAndroid Build Coastguard Worker // return Unit{};
63*14675a02SAndroid Build Coastguard Worker // );
64*14675a02SAndroid Build Coastguard Worker // }
65*14675a02SAndroid Build Coastguard Worker #define FCP_EXPECT_NO_ERROR(test_contents) \
66*14675a02SAndroid Build Coastguard Worker auto test_fn = []() -> Result<Unit> test_contents; \
67*14675a02SAndroid Build Coastguard Worker ASSERT_THAT(test_fn(), testing::Not(IsError()))
68*14675a02SAndroid Build Coastguard Worker
69*14675a02SAndroid Build Coastguard Worker // Convenience macros for `EXPECT_THAT(s, IsOk())`, where `s` is either
70*14675a02SAndroid Build Coastguard Worker // a `Status` or a `StatusOr<T>`.
71*14675a02SAndroid Build Coastguard Worker // Old versions of the protobuf library define EXPECT_OK as well, so we only
72*14675a02SAndroid Build Coastguard Worker // conditionally define our version.
73*14675a02SAndroid Build Coastguard Worker #if !defined(EXPECT_OK)
74*14675a02SAndroid Build Coastguard Worker #define EXPECT_OK(result) EXPECT_THAT(result, fcp::IsOk())
75*14675a02SAndroid Build Coastguard Worker #endif
76*14675a02SAndroid Build Coastguard Worker #define ASSERT_OK(result) ASSERT_THAT(result, fcp::IsOk())
77*14675a02SAndroid Build Coastguard Worker
78*14675a02SAndroid Build Coastguard Worker /** Returns the current test's name. */
79*14675a02SAndroid Build Coastguard Worker std::string TestName();
80*14675a02SAndroid Build Coastguard Worker
81*14675a02SAndroid Build Coastguard Worker /**
82*14675a02SAndroid Build Coastguard Worker * Gets path to a test data file based on a path relative to project root.
83*14675a02SAndroid Build Coastguard Worker */
84*14675a02SAndroid Build Coastguard Worker std::string GetTestDataPath(absl::string_view relative_path);
85*14675a02SAndroid Build Coastguard Worker
86*14675a02SAndroid Build Coastguard Worker /**
87*14675a02SAndroid Build Coastguard Worker * Creates a temporary file name with given suffix unique for the running test.
88*14675a02SAndroid Build Coastguard Worker */
89*14675a02SAndroid Build Coastguard Worker std::string TemporaryTestFile(absl::string_view suffix);
90*14675a02SAndroid Build Coastguard Worker
91*14675a02SAndroid Build Coastguard Worker /**
92*14675a02SAndroid Build Coastguard Worker * Verifies a provided content against an expected stored in a baseline file.
93*14675a02SAndroid Build Coastguard Worker * Returns an empty string if both are identical, otherwise a diagnostic
94*14675a02SAndroid Build Coastguard Worker * message for error reports.
95*14675a02SAndroid Build Coastguard Worker *
96*14675a02SAndroid Build Coastguard Worker * A return status of not ok indicates an operational error which made the
97*14675a02SAndroid Build Coastguard Worker * comparison impossible.
98*14675a02SAndroid Build Coastguard Worker *
99*14675a02SAndroid Build Coastguard Worker * The baseline file name must be provided relative to the project root.
100*14675a02SAndroid Build Coastguard Worker */
101*14675a02SAndroid Build Coastguard Worker StatusOr<std::string> VerifyAgainstBaseline(absl::string_view baseline_file,
102*14675a02SAndroid Build Coastguard Worker absl::string_view content);
103*14675a02SAndroid Build Coastguard Worker
104*14675a02SAndroid Build Coastguard Worker /**
105*14675a02SAndroid Build Coastguard Worker * Polymorphic matchers for Status or StatusOr on status code.
106*14675a02SAndroid Build Coastguard Worker */
107*14675a02SAndroid Build Coastguard Worker template <typename T>
IsCode(StatusOr<T> const & x,StatusCode code)108*14675a02SAndroid Build Coastguard Worker bool IsCode(StatusOr<T> const& x, StatusCode code) {
109*14675a02SAndroid Build Coastguard Worker return x.status().code() == code;
110*14675a02SAndroid Build Coastguard Worker }
IsCode(Status const & x,StatusCode code)111*14675a02SAndroid Build Coastguard Worker inline bool IsCode(Status const& x, StatusCode code) {
112*14675a02SAndroid Build Coastguard Worker return x.code() == code;
113*14675a02SAndroid Build Coastguard Worker }
114*14675a02SAndroid Build Coastguard Worker
115*14675a02SAndroid Build Coastguard Worker template <typename T>
116*14675a02SAndroid Build Coastguard Worker class StatusMatcherImpl : public ::testing::MatcherInterface<T> {
117*14675a02SAndroid Build Coastguard Worker public:
StatusMatcherImpl(StatusCode code)118*14675a02SAndroid Build Coastguard Worker explicit StatusMatcherImpl(StatusCode code) : code_(code) {}
DescribeTo(::std::ostream * os)119*14675a02SAndroid Build Coastguard Worker void DescribeTo(::std::ostream* os) const override {
120*14675a02SAndroid Build Coastguard Worker *os << "is " << absl::StatusCodeToString(code_);
121*14675a02SAndroid Build Coastguard Worker }
DescribeNegationTo(::std::ostream * os)122*14675a02SAndroid Build Coastguard Worker void DescribeNegationTo(::std::ostream* os) const override {
123*14675a02SAndroid Build Coastguard Worker *os << "is not " << absl::StatusCodeToString(code_);
124*14675a02SAndroid Build Coastguard Worker }
MatchAndExplain(T x,::testing::MatchResultListener * listener)125*14675a02SAndroid Build Coastguard Worker bool MatchAndExplain(
126*14675a02SAndroid Build Coastguard Worker T x, ::testing::MatchResultListener* listener) const override {
127*14675a02SAndroid Build Coastguard Worker return IsCode(x, code_);
128*14675a02SAndroid Build Coastguard Worker }
129*14675a02SAndroid Build Coastguard Worker
130*14675a02SAndroid Build Coastguard Worker private:
131*14675a02SAndroid Build Coastguard Worker StatusCode code_;
132*14675a02SAndroid Build Coastguard Worker };
133*14675a02SAndroid Build Coastguard Worker
134*14675a02SAndroid Build Coastguard Worker class StatusMatcher {
135*14675a02SAndroid Build Coastguard Worker public:
StatusMatcher(StatusCode code)136*14675a02SAndroid Build Coastguard Worker explicit StatusMatcher(StatusCode code) : code_(code) {}
137*14675a02SAndroid Build Coastguard Worker
138*14675a02SAndroid Build Coastguard Worker template <typename T>
139*14675a02SAndroid Build Coastguard Worker operator testing::Matcher<T>() const { // NOLINT
140*14675a02SAndroid Build Coastguard Worker return ::testing::MakeMatcher(new StatusMatcherImpl<T>(code_));
141*14675a02SAndroid Build Coastguard Worker }
142*14675a02SAndroid Build Coastguard Worker
143*14675a02SAndroid Build Coastguard Worker private:
144*14675a02SAndroid Build Coastguard Worker StatusCode code_;
145*14675a02SAndroid Build Coastguard Worker };
146*14675a02SAndroid Build Coastguard Worker
147*14675a02SAndroid Build Coastguard Worker StatusMatcher IsCode(StatusCode code);
148*14675a02SAndroid Build Coastguard Worker StatusMatcher IsOk();
149*14675a02SAndroid Build Coastguard Worker
150*14675a02SAndroid Build Coastguard Worker template <typename T>
151*14675a02SAndroid Build Coastguard Worker class ProtoMatcherImpl : public ::testing::MatcherInterface<T> {
152*14675a02SAndroid Build Coastguard Worker public:
ProtoMatcherImpl(const google::protobuf::Message & arg)153*14675a02SAndroid Build Coastguard Worker explicit ProtoMatcherImpl(const google::protobuf::Message& arg)
154*14675a02SAndroid Build Coastguard Worker : arg_(CloneMessage(arg)) {}
155*14675a02SAndroid Build Coastguard Worker
ProtoMatcherImpl(const std::string & arg)156*14675a02SAndroid Build Coastguard Worker explicit ProtoMatcherImpl(const std::string& arg) : arg_(ParseMessage(arg)) {}
157*14675a02SAndroid Build Coastguard Worker
DescribeTo(::std::ostream * os)158*14675a02SAndroid Build Coastguard Worker void DescribeTo(::std::ostream* os) const override {
159*14675a02SAndroid Build Coastguard Worker *os << "is " << arg_->DebugString();
160*14675a02SAndroid Build Coastguard Worker }
DescribeNegationTo(::std::ostream * os)161*14675a02SAndroid Build Coastguard Worker void DescribeNegationTo(::std::ostream* os) const override {
162*14675a02SAndroid Build Coastguard Worker *os << "is not " << arg_->DebugString();
163*14675a02SAndroid Build Coastguard Worker }
MatchAndExplain(T x,::testing::MatchResultListener * listener)164*14675a02SAndroid Build Coastguard Worker bool MatchAndExplain(
165*14675a02SAndroid Build Coastguard Worker T x, ::testing::MatchResultListener* listener) const override {
166*14675a02SAndroid Build Coastguard Worker if (x.GetDescriptor()->full_name() != arg_->GetDescriptor()->full_name()) {
167*14675a02SAndroid Build Coastguard Worker *listener << "Argument proto is of type "
168*14675a02SAndroid Build Coastguard Worker << arg_->GetDescriptor()->full_name()
169*14675a02SAndroid Build Coastguard Worker << " but expected proto of type "
170*14675a02SAndroid Build Coastguard Worker << x.GetDescriptor()->full_name();
171*14675a02SAndroid Build Coastguard Worker return false;
172*14675a02SAndroid Build Coastguard Worker }
173*14675a02SAndroid Build Coastguard Worker
174*14675a02SAndroid Build Coastguard Worker google::protobuf::util::MessageDifferencer differencer;
175*14675a02SAndroid Build Coastguard Worker std::string reported_differences;
176*14675a02SAndroid Build Coastguard Worker differencer.ReportDifferencesToString(&reported_differences);
177*14675a02SAndroid Build Coastguard Worker if (!differencer.Compare(*arg_, x)) {
178*14675a02SAndroid Build Coastguard Worker *listener << reported_differences;
179*14675a02SAndroid Build Coastguard Worker return false;
180*14675a02SAndroid Build Coastguard Worker }
181*14675a02SAndroid Build Coastguard Worker return true;
182*14675a02SAndroid Build Coastguard Worker }
183*14675a02SAndroid Build Coastguard Worker
184*14675a02SAndroid Build Coastguard Worker private:
CloneMessage(const google::protobuf::Message & message)185*14675a02SAndroid Build Coastguard Worker static std::unique_ptr<google::protobuf::Message> CloneMessage(
186*14675a02SAndroid Build Coastguard Worker const google::protobuf::Message& message) {
187*14675a02SAndroid Build Coastguard Worker std::unique_ptr<google::protobuf::Message> copy_of_message =
188*14675a02SAndroid Build Coastguard Worker absl::WrapUnique(message.New());
189*14675a02SAndroid Build Coastguard Worker copy_of_message->CopyFrom(message);
190*14675a02SAndroid Build Coastguard Worker return copy_of_message;
191*14675a02SAndroid Build Coastguard Worker }
192*14675a02SAndroid Build Coastguard Worker
ParseMessage(const std::string & proto_text)193*14675a02SAndroid Build Coastguard Worker static std::unique_ptr<google::protobuf::Message> ParseMessage(
194*14675a02SAndroid Build Coastguard Worker const std::string& proto_text) {
195*14675a02SAndroid Build Coastguard Worker using V = std::remove_cv_t<std::remove_reference_t<T>>;
196*14675a02SAndroid Build Coastguard Worker std::unique_ptr<V> message = std::make_unique<V>();
197*14675a02SAndroid Build Coastguard Worker *message = PARSE_TEXT_PROTO(proto_text);
198*14675a02SAndroid Build Coastguard Worker return message;
199*14675a02SAndroid Build Coastguard Worker }
200*14675a02SAndroid Build Coastguard Worker
201*14675a02SAndroid Build Coastguard Worker std::unique_ptr<google::protobuf::Message> arg_;
202*14675a02SAndroid Build Coastguard Worker };
203*14675a02SAndroid Build Coastguard Worker
204*14675a02SAndroid Build Coastguard Worker template <typename T>
205*14675a02SAndroid Build Coastguard Worker class ProtoMatcher {
206*14675a02SAndroid Build Coastguard Worker public:
ProtoMatcher(const T & arg)207*14675a02SAndroid Build Coastguard Worker explicit ProtoMatcher(const T& arg) : arg_(arg) {}
208*14675a02SAndroid Build Coastguard Worker
209*14675a02SAndroid Build Coastguard Worker template <typename U>
210*14675a02SAndroid Build Coastguard Worker operator testing::Matcher<U>() const { // NOLINT
211*14675a02SAndroid Build Coastguard Worker using V = std::remove_cv_t<std::remove_reference_t<U>>;
212*14675a02SAndroid Build Coastguard Worker static_assert(std::is_base_of<google::protobuf::Message, V>::value &&
213*14675a02SAndroid Build Coastguard Worker !std::is_same<google::protobuf::Message, V>::value);
214*14675a02SAndroid Build Coastguard Worker return ::testing::MakeMatcher(new ProtoMatcherImpl<U>(arg_));
215*14675a02SAndroid Build Coastguard Worker }
216*14675a02SAndroid Build Coastguard Worker
217*14675a02SAndroid Build Coastguard Worker private:
218*14675a02SAndroid Build Coastguard Worker T arg_;
219*14675a02SAndroid Build Coastguard Worker };
220*14675a02SAndroid Build Coastguard Worker
221*14675a02SAndroid Build Coastguard Worker // Proto matcher that takes another proto message reference as an argument.
222*14675a02SAndroid Build Coastguard Worker template <class T,
223*14675a02SAndroid Build Coastguard Worker typename std::enable_if<std::is_base_of<google::protobuf::Message, T>::value &&
224*14675a02SAndroid Build Coastguard Worker !std::is_same<google::protobuf::Message, T>::value,
225*14675a02SAndroid Build Coastguard Worker int>::type = 0>
EqualsProto(const T & arg)226*14675a02SAndroid Build Coastguard Worker inline ProtoMatcher<T> EqualsProto(const T& arg) {
227*14675a02SAndroid Build Coastguard Worker return ProtoMatcher<T>(arg);
228*14675a02SAndroid Build Coastguard Worker }
229*14675a02SAndroid Build Coastguard Worker
230*14675a02SAndroid Build Coastguard Worker // Proto matcher that takes a text proto as an argument.
EqualsProto(const std::string & arg)231*14675a02SAndroid Build Coastguard Worker inline ProtoMatcher<std::string> EqualsProto(const std::string& arg) {
232*14675a02SAndroid Build Coastguard Worker return ProtoMatcher<std::string>(arg);
233*14675a02SAndroid Build Coastguard Worker }
234*14675a02SAndroid Build Coastguard Worker
235*14675a02SAndroid Build Coastguard Worker // Utility function which creates and traces an instance of test error
236*14675a02SAndroid Build Coastguard Worker Error TraceTestError(SourceLocation loc = SourceLocation::current());
237*14675a02SAndroid Build Coastguard Worker
238*14675a02SAndroid Build Coastguard Worker } // namespace fcp
239*14675a02SAndroid Build Coastguard Worker
240*14675a02SAndroid Build Coastguard Worker #endif // FCP_TESTING_TESTING_H_
241