1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ASSERTOK_H
17 #define ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ASSERTOK_H
18 
19 #include <algorithm>
20 #include <initializer_list>
21 
22 #include <hidl/Status.h>
23 
24 namespace android {
25 namespace hardware {
26 namespace audio {
27 namespace common {
28 namespace test {
29 namespace utility {
30 
31 namespace detail {
32 
33 // This is a detail namespace, thus it is OK to import a class as nobody else is
34 // allowed to use it
35 using ::android::hardware::Return;
36 
37 template <class T>
assertIsOk(const char * expr,const Return<T> & ret)38 inline ::testing::AssertionResult assertIsOk(const char* expr, const Return<T>& ret) {
39     return ::testing::AssertionResult(ret.isOk())
40            << "Expected: " << expr << "\n to be an OK Return but it is not: " << ret.description();
41 }
42 
43 // Call continuation if the provided result isOk
44 template <class T, class Continuation>
continueIfIsOk(const char * expr,const Return<T> & ret,Continuation continuation)45 inline ::testing::AssertionResult continueIfIsOk(const char* expr, const Return<T>& ret,
46                                                  Continuation continuation) {
47     auto isOkStatus = assertIsOk(expr, ret);
48     return !isOkStatus ? isOkStatus : continuation();
49 }
50 
51 // Expect two equal Results
52 template <class Result>
assertResult(const char * e_expr,const char * r_expr,Result expected,Result result)53 inline ::testing::AssertionResult assertResult(const char* e_expr, const char* r_expr,
54                                                Result expected, Result result) {
55     return ::testing::AssertionResult(expected == result)
56            << "Value of: " << r_expr << "\n  Actual: " << ::testing::PrintToString(result)
57            << "\nExpected: " << e_expr << "\nWhich is: " << ::testing::PrintToString(expected);
58 }
59 
60 // Expect two equal Results one being wrapped in an OK Return
61 template <class Result>
assertResult(const char * e_expr,const char * r_expr,Result expected,const Return<Result> & ret)62 inline ::testing::AssertionResult assertResult(const char* e_expr, const char* r_expr,
63                                                Result expected, const Return<Result>& ret) {
64     return continueIfIsOk(r_expr, ret,
65                           [&] { return assertResult(e_expr, r_expr, expected, Result{ret}); });
66 }
67 
68 // Expect a Result to be part of a list of Results
69 template <class Result>
assertResult(const char * e_expr,const char * r_expr,const std::initializer_list<Result> & expected,Result result)70 inline ::testing::AssertionResult assertResult(const char* e_expr, const char* r_expr,
71                                                const std::initializer_list<Result>& expected,
72                                                Result result) {
73     if (std::find(expected.begin(), expected.end(), result) != expected.end()) {
74         return ::testing::AssertionSuccess();  // result is in expected
75     }
76     return ::testing::AssertionFailure()
77            << "Value of: " << r_expr << "\n  Actual: " << ::testing::PrintToString(result)
78            << "\nExpected one of: " << e_expr
79            << "\n       Which is: " << ::testing::PrintToString(expected);
80 }
81 
82 // Expect a Result wrapped in an OK Return to be part of a list of Results
83 template <class Result>
assertResult(const char * e_expr,const char * r_expr,const std::initializer_list<Result> & expected,const Return<Result> & ret)84 inline ::testing::AssertionResult assertResult(const char* e_expr, const char* r_expr,
85                                                const std::initializer_list<Result>& expected,
86                                                const Return<Result>& ret) {
87     return continueIfIsOk(r_expr, ret,
88                           [&] { return assertResult(e_expr, r_expr, expected, Result{ret}); });
89 }
90 
assertOk(const char * expr,const Return<void> & ret)91 inline ::testing::AssertionResult assertOk(const char* expr, const Return<void>& ret) {
92     return assertIsOk(expr, ret);
93 }
94 
95 template <class Result>
assertOk(const char * expr,Result result)96 inline ::testing::AssertionResult assertOk(const char* expr, Result result) {
97     return ::testing::AssertionResult(result == Result::OK)
98            << "Expected success: " << expr << "\nActual: " << ::testing::PrintToString(result);
99 }
100 
101 template <class Result>
assertOk(const char * expr,const Return<Result> & ret)102 inline ::testing::AssertionResult assertOk(const char* expr, const Return<Result>& ret) {
103     return continueIfIsOk(expr, ret, [&] { return assertOk(expr, Result{ret}); });
104 }
105 }  // namespace detail
106 
107 #define ASSERT_IS_OK(ret) ASSERT_PRED_FORMAT1(detail::assertIsOk, ret)
108 #define EXPECT_IS_OK(ret) EXPECT_PRED_FORMAT1(detail::assertIsOk, ret)
109 
110 // Test anything provided is and contains only OK
111 #define ASSERT_OK(ret) ASSERT_PRED_FORMAT1(detail::assertOk, ret)
112 #define EXPECT_OK(ret) EXPECT_PRED_FORMAT1(detail::assertOk, ret)
113 
114 #define ASSERT_RESULT(expected, ret) ASSERT_PRED_FORMAT2(detail::assertResult, expected, ret)
115 #define EXPECT_RESULT(expected, ret) EXPECT_PRED_FORMAT2(detail::assertResult, expected, ret)
116 
117 /** Unpack the provided result.
118  * If the result is not OK, register a failure and return the default initializer value. */
119 template <class R>
extract(const Return<R> & ret)120 static R extract(const Return<R>& ret) {
121     if (!ret.isOk()) {
122         EXPECT_IS_OK(ret);
123         return R{};
124     }
125     return ret;
126 }
127 
128 template <class Result, class Value>
expectValueOrFailure(Result res,Value expectedValue,Value actualValue,Result expectedFailure)129 static void expectValueOrFailure(Result res, Value expectedValue, Value actualValue,
130                                  Result expectedFailure) {
131     if (res == Result::OK) {
132         ASSERT_EQ(expectedValue, actualValue);
133     } else {
134         ASSERT_EQ(expectedFailure, res) << "Unexpected result " << toString(res);
135     }
136 }
137 
138 }  // namespace utility
139 }  // namespace test
140 }  // namespace common
141 }  // namespace audio
142 }  // namespace hardware
143 }  // namespace android
144 
145 #endif  // ANDROID_HARDWARE_AUDIO_COMMON_TEST_UTILITY_ASSERTOK_H
146