xref: /aosp_15_r20/external/federated-compute/fcp/base/match_test.cc (revision 14675a029014e728ec732f129a32e299b2da0601)
1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker  * Copyright 2019 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 #include "fcp/base/match.h"
18*14675a02SAndroid Build Coastguard Worker 
19*14675a02SAndroid Build Coastguard Worker #include <memory>
20*14675a02SAndroid Build Coastguard Worker #include <optional>
21*14675a02SAndroid Build Coastguard Worker #include <variant>
22*14675a02SAndroid Build Coastguard Worker 
23*14675a02SAndroid Build Coastguard Worker #include "gmock/gmock.h"
24*14675a02SAndroid Build Coastguard Worker #include "gtest/gtest.h"
25*14675a02SAndroid Build Coastguard Worker #include "fcp/base/result.h"
26*14675a02SAndroid Build Coastguard Worker #include "fcp/testing/result_matchers.h"
27*14675a02SAndroid Build Coastguard Worker #include "fcp/testing/testing.h"
28*14675a02SAndroid Build Coastguard Worker 
29*14675a02SAndroid Build Coastguard Worker namespace fcp {
30*14675a02SAndroid Build Coastguard Worker 
31*14675a02SAndroid Build Coastguard Worker namespace {
32*14675a02SAndroid Build Coastguard Worker 
33*14675a02SAndroid Build Coastguard Worker using ::testing::Eq;
34*14675a02SAndroid Build Coastguard Worker using ::testing::Optional;
35*14675a02SAndroid Build Coastguard Worker 
36*14675a02SAndroid Build Coastguard Worker struct X {
37*14675a02SAndroid Build Coastguard Worker   int x;
38*14675a02SAndroid Build Coastguard Worker };
39*14675a02SAndroid Build Coastguard Worker 
40*14675a02SAndroid Build Coastguard Worker struct Y {
41*14675a02SAndroid Build Coastguard Worker   int y;
42*14675a02SAndroid Build Coastguard Worker };
43*14675a02SAndroid Build Coastguard Worker 
44*14675a02SAndroid Build Coastguard Worker struct Z {
45*14675a02SAndroid Build Coastguard Worker   int z;
46*14675a02SAndroid Build Coastguard Worker };
47*14675a02SAndroid Build Coastguard Worker 
48*14675a02SAndroid Build Coastguard Worker using V = std::variant<X, Y, Z>;
49*14675a02SAndroid Build Coastguard Worker 
50*14675a02SAndroid Build Coastguard Worker using VMoveOnly =
51*14675a02SAndroid Build Coastguard Worker     std::variant<std::unique_ptr<X>, std::unique_ptr<Y>, std::unique_ptr<Z>>;
52*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,AllDefault)53*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, AllDefault) {
54*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher =
55*14675a02SAndroid Build Coastguard Worker       MakeMatcher<V>([](Default, V const&) { return 1; });
56*14675a02SAndroid Build Coastguard Worker 
57*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(X{}) == 1);
58*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(Z{}) == 1);
59*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(Y{}) == 1);
60*14675a02SAndroid Build Coastguard Worker }
61*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,SingleDefault)62*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, SingleDefault) {
63*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher = MakeMatcher<V>(
64*14675a02SAndroid Build Coastguard Worker       [](X const& x) { return 10 + x.x; },  //
65*14675a02SAndroid Build Coastguard Worker       [](Z const& z) { return 20 + z.z; },
66*14675a02SAndroid Build Coastguard Worker       [](Default, V const& v) { return 30 + absl::get<Y>(v).y; });
67*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(X{1}) == 11);
68*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(Z{2}) == 22);
69*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(Y{3}) == 33);
70*14675a02SAndroid Build Coastguard Worker }
71*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,SingleDefault_Pointer)72*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, SingleDefault_Pointer) {
73*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher =
74*14675a02SAndroid Build Coastguard Worker       MakeMatcher<V>([](X* x) { return 10 + x->x; },  //
75*14675a02SAndroid Build Coastguard Worker                      [](Z* z) { return 20 + z->z; },
76*14675a02SAndroid Build Coastguard Worker                      [](Default, V* v) { return 30 + absl::get<Y>(*v).y; });
77*14675a02SAndroid Build Coastguard Worker 
78*14675a02SAndroid Build Coastguard Worker   V x = X{1};
79*14675a02SAndroid Build Coastguard Worker   V z = Z{2};
80*14675a02SAndroid Build Coastguard Worker   V y = Y{3};
81*14675a02SAndroid Build Coastguard Worker 
82*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&x), Eq(11));
83*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&z), Eq(22));
84*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&y), Eq(33));
85*14675a02SAndroid Build Coastguard Worker }
86*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Exhaustive)87*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Exhaustive) {
88*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher = MakeMatcher<V>(
89*14675a02SAndroid Build Coastguard Worker       [](X const& x) { return 10 + x.x; }, [](Z const& z) { return 20 + z.z; },
90*14675a02SAndroid Build Coastguard Worker       [](Y const& y) { return 30 + y.y; });
91*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(X{1}) == 11);
92*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(Z{2}) == 22);
93*14675a02SAndroid Build Coastguard Worker   static_assert(matcher.Match(Y{3}) == 33);
94*14675a02SAndroid Build Coastguard Worker }
95*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Exhaustive_Pointer)96*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Exhaustive_Pointer) {
97*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher = MakeMatcher<V>([](X* x) { return 10 + x->x; },
98*14675a02SAndroid Build Coastguard Worker                                           [](Z* z) { return 20 + z->z; },
99*14675a02SAndroid Build Coastguard Worker                                           [](Y* y) { return 30 + y->y; });
100*14675a02SAndroid Build Coastguard Worker 
101*14675a02SAndroid Build Coastguard Worker   V x = X{1};
102*14675a02SAndroid Build Coastguard Worker   V z = Z{2};
103*14675a02SAndroid Build Coastguard Worker   V y = Y{3};
104*14675a02SAndroid Build Coastguard Worker 
105*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&x), Eq(11));
106*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&z), Eq(22));
107*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&y), Eq(33));
108*14675a02SAndroid Build Coastguard Worker }
109*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Exhaustive_MatchInsteadOfMatcher)110*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Exhaustive_MatchInsteadOfMatcher) {
111*14675a02SAndroid Build Coastguard Worker   constexpr auto do_match = [](V const& v) {
112*14675a02SAndroid Build Coastguard Worker     return Match(
113*14675a02SAndroid Build Coastguard Worker         v,  //
114*14675a02SAndroid Build Coastguard Worker         [](X const& x) { return 10 + x.x; },
115*14675a02SAndroid Build Coastguard Worker         [](Z const& z) { return 20 + z.z; },
116*14675a02SAndroid Build Coastguard Worker         [](Y const& y) { return 30 + y.y; });
117*14675a02SAndroid Build Coastguard Worker   };
118*14675a02SAndroid Build Coastguard Worker 
119*14675a02SAndroid Build Coastguard Worker   static_assert(do_match(X{1}) == 11);
120*14675a02SAndroid Build Coastguard Worker   static_assert(do_match(Z{2}) == 22);
121*14675a02SAndroid Build Coastguard Worker   static_assert(do_match(Y{3}) == 33);
122*14675a02SAndroid Build Coastguard Worker }
123*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,CoerceViaExplicitReturnType)124*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, CoerceViaExplicitReturnType) {
125*14675a02SAndroid Build Coastguard Worker   constexpr auto do_match = [](V const& v) {
126*14675a02SAndroid Build Coastguard Worker     return Match<std::optional<int>>(
127*14675a02SAndroid Build Coastguard Worker         v,  //
128*14675a02SAndroid Build Coastguard Worker         [](X const& x) { return 10 + x.x; },
129*14675a02SAndroid Build Coastguard Worker         [](Z const& z) { return 20 + z.z; },
130*14675a02SAndroid Build Coastguard Worker         [](Y const& y) { return std::nullopt; });
131*14675a02SAndroid Build Coastguard Worker   };
132*14675a02SAndroid Build Coastguard Worker 
133*14675a02SAndroid Build Coastguard Worker   static_assert(*do_match(X{1}) == 11);
134*14675a02SAndroid Build Coastguard Worker   static_assert(*do_match(Z{2}) == 22);
135*14675a02SAndroid Build Coastguard Worker   static_assert(!do_match(Y{3}).has_value());
136*14675a02SAndroid Build Coastguard Worker }
137*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,MoveOnly_Borrow_Exhaustive)138*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, MoveOnly_Borrow_Exhaustive) {
139*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher = MakeMatcher<VMoveOnly>(
140*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<X> const& x) { return 10 + x->x; },
141*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<Z> const& z) { return 20 + z->z; },
142*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<Y> const& y) { return 30 + y->y; });
143*14675a02SAndroid Build Coastguard Worker 
144*14675a02SAndroid Build Coastguard Worker   VMoveOnly v_x = std::make_unique<X>(X{1});
145*14675a02SAndroid Build Coastguard Worker   VMoveOnly v_z = std::make_unique<Z>(Z{2});
146*14675a02SAndroid Build Coastguard Worker   VMoveOnly v_y = std::make_unique<Y>(Y{3});
147*14675a02SAndroid Build Coastguard Worker 
148*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(v_x), Eq(11));
149*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(v_z), Eq(22));
150*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(v_y), Eq(33));
151*14675a02SAndroid Build Coastguard Worker }
152*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,MoveOnly_Consume_Exhaustive)153*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, MoveOnly_Consume_Exhaustive) {
154*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher = MakeMatcher<VMoveOnly>(
155*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<X> x) { return 10 + x->x; },
156*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<Z> z) { return 20 + z->z; },
157*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<Y> y) { return 30 + y->y; });
158*14675a02SAndroid Build Coastguard Worker 
159*14675a02SAndroid Build Coastguard Worker   VMoveOnly v_x = std::make_unique<X>(X{1});
160*14675a02SAndroid Build Coastguard Worker   VMoveOnly v_z = std::make_unique<Z>(Z{2});
161*14675a02SAndroid Build Coastguard Worker   VMoveOnly v_y = std::make_unique<Y>(Y{3});
162*14675a02SAndroid Build Coastguard Worker 
163*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(std::move(v_x)), Eq(11));
164*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(std::move(v_z)), Eq(22));
165*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(std::move(v_y)), Eq(33));
166*14675a02SAndroid Build Coastguard Worker }
167*14675a02SAndroid Build Coastguard Worker 
168*14675a02SAndroid Build Coastguard Worker // std::optional is handled with a special MatchTraits implementation.
169*14675a02SAndroid Build Coastguard Worker // The corresponding std::variant has to be synthesized on the fly, so that
170*14675a02SAndroid Build Coastguard Worker // implementation is trickier than usual.
171*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Optional_Ref)172*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Optional_Ref) {
173*14675a02SAndroid Build Coastguard Worker   using O = std::optional<std::unique_ptr<X>>;
174*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher =
175*14675a02SAndroid Build Coastguard Worker       MakeMatcher<O>([](std::unique_ptr<X> const& x) { return x->x; },
176*14675a02SAndroid Build Coastguard Worker                      [](std::nullopt_t) { return 0; });
177*14675a02SAndroid Build Coastguard Worker 
178*14675a02SAndroid Build Coastguard Worker   O const engaged = std::make_unique<X>(X{123});
179*14675a02SAndroid Build Coastguard Worker   O const empty = std::nullopt;
180*14675a02SAndroid Build Coastguard Worker 
181*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(engaged), Eq(123));
182*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(empty), Eq(0));
183*14675a02SAndroid Build Coastguard Worker }
184*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Optional_Pointer)185*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Optional_Pointer) {
186*14675a02SAndroid Build Coastguard Worker   using O = std::optional<std::unique_ptr<X>>;
187*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher = MakeMatcher<O>(
188*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<X>* x) {
189*14675a02SAndroid Build Coastguard Worker         int v = (*x)->x;
190*14675a02SAndroid Build Coastguard Worker         x->reset();
191*14675a02SAndroid Build Coastguard Worker         return v;
192*14675a02SAndroid Build Coastguard Worker       },
193*14675a02SAndroid Build Coastguard Worker       [](std::nullopt_t) { return 0; });
194*14675a02SAndroid Build Coastguard Worker 
195*14675a02SAndroid Build Coastguard Worker   O engaged = std::make_unique<X>(X{123});
196*14675a02SAndroid Build Coastguard Worker   O empty = std::nullopt;
197*14675a02SAndroid Build Coastguard Worker 
198*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&engaged), Eq(123));
199*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(engaged, Optional(Eq(nullptr)));
200*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&empty), Eq(0));
201*14675a02SAndroid Build Coastguard Worker }
202*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Optional_Consume)203*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Optional_Consume) {
204*14675a02SAndroid Build Coastguard Worker   using O = std::optional<std::unique_ptr<X>>;
205*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher =
206*14675a02SAndroid Build Coastguard Worker       MakeMatcher<O>([](std::unique_ptr<X> x) { return x->x; },
207*14675a02SAndroid Build Coastguard Worker                      [](std::nullopt_t) { return 0; });
208*14675a02SAndroid Build Coastguard Worker 
209*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(O{std::make_unique<X>(X{123})}), Eq(123));
210*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(O{std::nullopt}), Eq(0));
211*14675a02SAndroid Build Coastguard Worker }
212*14675a02SAndroid Build Coastguard Worker 
213*14675a02SAndroid Build Coastguard Worker // Result<T> uses the extensibility mechanism provided by MatchTrait
214*14675a02SAndroid Build Coastguard Worker // (VariantType alias and a variant() accessor). These tests demonstrate that
215*14675a02SAndroid Build Coastguard Worker // MatchTraits is extensible (in addition to testing the particular
216*14675a02SAndroid Build Coastguard Worker // implementation for Result).
217*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Result_Ref)218*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Result_Ref) {
219*14675a02SAndroid Build Coastguard Worker   using R = Result<std::unique_ptr<X>>;
220*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher =
221*14675a02SAndroid Build Coastguard Worker       MakeMatcher<R>([](std::unique_ptr<X> const& x) { return x->x; },
222*14675a02SAndroid Build Coastguard Worker                      [](Error) { return 0; });
223*14675a02SAndroid Build Coastguard Worker 
224*14675a02SAndroid Build Coastguard Worker   R const val = std::make_unique<X>(X{123});
225*14675a02SAndroid Build Coastguard Worker   R const err = TraceTestError();
226*14675a02SAndroid Build Coastguard Worker 
227*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(val), Eq(123));
228*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(err), Eq(0));
229*14675a02SAndroid Build Coastguard Worker }
230*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Result_Pointer)231*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Result_Pointer) {
232*14675a02SAndroid Build Coastguard Worker   using R = Result<std::unique_ptr<X>>;
233*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher = MakeMatcher<R>(
234*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<X>* x) {
235*14675a02SAndroid Build Coastguard Worker         int v = (*x)->x;
236*14675a02SAndroid Build Coastguard Worker         x->reset();
237*14675a02SAndroid Build Coastguard Worker         return v;
238*14675a02SAndroid Build Coastguard Worker       },
239*14675a02SAndroid Build Coastguard Worker       [](Error*) { return 0; });
240*14675a02SAndroid Build Coastguard Worker 
241*14675a02SAndroid Build Coastguard Worker   R val = std::make_unique<X>(X{123});
242*14675a02SAndroid Build Coastguard Worker   R err = TraceTestError();
243*14675a02SAndroid Build Coastguard Worker 
244*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&val), Eq(123));
245*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(val, HasValue(Eq(nullptr)));
246*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(&err), Eq(0));
247*14675a02SAndroid Build Coastguard Worker }
248*14675a02SAndroid Build Coastguard Worker 
TEST(MatchTest,Result_Consume)249*14675a02SAndroid Build Coastguard Worker TEST(MatchTest, Result_Consume) {
250*14675a02SAndroid Build Coastguard Worker   using R = Result<std::unique_ptr<X>>;
251*14675a02SAndroid Build Coastguard Worker   constexpr auto matcher = MakeMatcher<R>(
252*14675a02SAndroid Build Coastguard Worker       [](std::unique_ptr<X> x) { return x->x; }, [](Error) { return 0; });
253*14675a02SAndroid Build Coastguard Worker 
254*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(R(std::make_unique<X>(X{123}))), Eq(123));
255*14675a02SAndroid Build Coastguard Worker   EXPECT_THAT(matcher.Match(R(TraceTestError())), Eq(0));
256*14675a02SAndroid Build Coastguard Worker }
257*14675a02SAndroid Build Coastguard Worker 
258*14675a02SAndroid Build Coastguard Worker }  // namespace
259*14675a02SAndroid Build Coastguard Worker 
260*14675a02SAndroid Build Coastguard Worker }  // namespace fcp
261