1 // Copyright 2018 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <gtest/gtest.h>
16 
17 #include "dawn_native/Error.h"
18 #include "dawn_native/ErrorData.h"
19 
20 using namespace dawn_native;
21 
22 namespace {
23 
24     int dummySuccess = 0xbeef;
25     const char* dummyErrorMessage = "I am an error message :3";
26 
27     // Check returning a success MaybeError with {};
TEST(ErrorTests,Error_Success)28     TEST(ErrorTests, Error_Success) {
29         auto ReturnSuccess = []() -> MaybeError { return {}; };
30 
31         MaybeError result = ReturnSuccess();
32         ASSERT_TRUE(result.IsSuccess());
33     }
34 
35     // Check returning an error MaybeError with "return DAWN_VALIDATION_ERROR"
TEST(ErrorTests,Error_Error)36     TEST(ErrorTests, Error_Error) {
37         auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
38 
39         MaybeError result = ReturnError();
40         ASSERT_TRUE(result.IsError());
41 
42         std::unique_ptr<ErrorData> errorData = result.AcquireError();
43         ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
44     }
45 
46     // Check returning a success ResultOrError with an implicit conversion
TEST(ErrorTests,ResultOrError_Success)47     TEST(ErrorTests, ResultOrError_Success) {
48         auto ReturnSuccess = []() -> ResultOrError<int*> { return &dummySuccess; };
49 
50         ResultOrError<int*> result = ReturnSuccess();
51         ASSERT_TRUE(result.IsSuccess());
52         ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
53     }
54 
55     // Check returning an error ResultOrError with "return DAWN_VALIDATION_ERROR"
TEST(ErrorTests,ResultOrError_Error)56     TEST(ErrorTests, ResultOrError_Error) {
57         auto ReturnError = []() -> ResultOrError<int*> {
58             return DAWN_VALIDATION_ERROR(dummyErrorMessage);
59         };
60 
61         ResultOrError<int*> result = ReturnError();
62         ASSERT_TRUE(result.IsError());
63 
64         std::unique_ptr<ErrorData> errorData = result.AcquireError();
65         ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
66     }
67 
68     // Check DAWN_TRY handles successes correctly.
TEST(ErrorTests,TRY_Success)69     TEST(ErrorTests, TRY_Success) {
70         auto ReturnSuccess = []() -> MaybeError { return {}; };
71 
72         // We need to check that DAWN_TRY doesn't return on successes
73         bool tryReturned = true;
74 
75         auto Try = [ReturnSuccess, &tryReturned]() -> MaybeError {
76             DAWN_TRY(ReturnSuccess());
77             tryReturned = false;
78             return {};
79         };
80 
81         MaybeError result = Try();
82         ASSERT_TRUE(result.IsSuccess());
83         ASSERT_FALSE(tryReturned);
84     }
85 
86     // Check DAWN_TRY handles errors correctly.
TEST(ErrorTests,TRY_Error)87     TEST(ErrorTests, TRY_Error) {
88         auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
89 
90         auto Try = [ReturnError]() -> MaybeError {
91             DAWN_TRY(ReturnError());
92             // DAWN_TRY should return before this point
93             EXPECT_FALSE(true);
94             return {};
95         };
96 
97         MaybeError result = Try();
98         ASSERT_TRUE(result.IsError());
99 
100         std::unique_ptr<ErrorData> errorData = result.AcquireError();
101         ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
102     }
103 
104     // Check DAWN_TRY adds to the backtrace.
TEST(ErrorTests,TRY_AddsToBacktrace)105     TEST(ErrorTests, TRY_AddsToBacktrace) {
106         auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
107 
108         auto SingleTry = [ReturnError]() -> MaybeError {
109             DAWN_TRY(ReturnError());
110             return {};
111         };
112 
113         auto DoubleTry = [SingleTry]() -> MaybeError {
114             DAWN_TRY(SingleTry());
115             return {};
116         };
117 
118         MaybeError singleResult = SingleTry();
119         ASSERT_TRUE(singleResult.IsError());
120 
121         MaybeError doubleResult = DoubleTry();
122         ASSERT_TRUE(doubleResult.IsError());
123 
124         std::unique_ptr<ErrorData> singleData = singleResult.AcquireError();
125         std::unique_ptr<ErrorData> doubleData = doubleResult.AcquireError();
126 
127         ASSERT_EQ(singleData->GetBacktrace().size() + 1, doubleData->GetBacktrace().size());
128     }
129 
130     // Check DAWN_TRY_ASSIGN handles successes correctly.
TEST(ErrorTests,TRY_RESULT_Success)131     TEST(ErrorTests, TRY_RESULT_Success) {
132         auto ReturnSuccess = []() -> ResultOrError<int*> { return &dummySuccess; };
133 
134         // We need to check that DAWN_TRY doesn't return on successes
135         bool tryReturned = true;
136 
137         auto Try = [ReturnSuccess, &tryReturned]() -> ResultOrError<int*> {
138             int* result = nullptr;
139             DAWN_TRY_ASSIGN(result, ReturnSuccess());
140             tryReturned = false;
141 
142             EXPECT_EQ(result, &dummySuccess);
143             return result;
144         };
145 
146         ResultOrError<int*> result = Try();
147         ASSERT_TRUE(result.IsSuccess());
148         ASSERT_FALSE(tryReturned);
149         ASSERT_EQ(result.AcquireSuccess(), &dummySuccess);
150     }
151 
152     // Check DAWN_TRY_ASSIGN handles errors correctly.
TEST(ErrorTests,TRY_RESULT_Error)153     TEST(ErrorTests, TRY_RESULT_Error) {
154         auto ReturnError = []() -> ResultOrError<int*> {
155             return DAWN_VALIDATION_ERROR(dummyErrorMessage);
156         };
157 
158         auto Try = [ReturnError]() -> ResultOrError<int*> {
159             int* result = nullptr;
160             DAWN_TRY_ASSIGN(result, ReturnError());
161             DAWN_UNUSED(result);
162 
163             // DAWN_TRY should return before this point
164             EXPECT_FALSE(true);
165             return &dummySuccess;
166         };
167 
168         ResultOrError<int*> result = Try();
169         ASSERT_TRUE(result.IsError());
170 
171         std::unique_ptr<ErrorData> errorData = result.AcquireError();
172         ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
173     }
174 
175     // Check DAWN_TRY_ASSIGN adds to the backtrace.
TEST(ErrorTests,TRY_RESULT_AddsToBacktrace)176     TEST(ErrorTests, TRY_RESULT_AddsToBacktrace) {
177         auto ReturnError = []() -> ResultOrError<int*> {
178             return DAWN_VALIDATION_ERROR(dummyErrorMessage);
179         };
180 
181         auto SingleTry = [ReturnError]() -> ResultOrError<int*> {
182             DAWN_TRY(ReturnError());
183             return &dummySuccess;
184         };
185 
186         auto DoubleTry = [SingleTry]() -> ResultOrError<int*> {
187             DAWN_TRY(SingleTry());
188             return &dummySuccess;
189         };
190 
191         ResultOrError<int*> singleResult = SingleTry();
192         ASSERT_TRUE(singleResult.IsError());
193 
194         ResultOrError<int*> doubleResult = DoubleTry();
195         ASSERT_TRUE(doubleResult.IsError());
196 
197         std::unique_ptr<ErrorData> singleData = singleResult.AcquireError();
198         std::unique_ptr<ErrorData> doubleData = doubleResult.AcquireError();
199 
200         ASSERT_EQ(singleData->GetBacktrace().size() + 1, doubleData->GetBacktrace().size());
201     }
202 
203     // Check a ResultOrError can be DAWN_TRY_ASSIGNED in a function that returns an Error
TEST(ErrorTests,TRY_RESULT_ConversionToError)204     TEST(ErrorTests, TRY_RESULT_ConversionToError) {
205         auto ReturnError = []() -> ResultOrError<int*> {
206             return DAWN_VALIDATION_ERROR(dummyErrorMessage);
207         };
208 
209         auto Try = [ReturnError]() -> MaybeError {
210             int* result = nullptr;
211             DAWN_TRY_ASSIGN(result, ReturnError());
212             DAWN_UNUSED(result);
213 
214             return {};
215         };
216 
217         MaybeError result = Try();
218         ASSERT_TRUE(result.IsError());
219 
220         std::unique_ptr<ErrorData> errorData = result.AcquireError();
221         ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
222     }
223 
224     // Check a ResultOrError can be DAWN_TRY_ASSIGNED in a function that returns an Error
225     // Version without Result<E*, T*>
TEST(ErrorTests,TRY_RESULT_ConversionToErrorNonPointer)226     TEST(ErrorTests, TRY_RESULT_ConversionToErrorNonPointer) {
227         auto ReturnError = []() -> ResultOrError<int> {
228             return DAWN_VALIDATION_ERROR(dummyErrorMessage);
229         };
230 
231         auto Try = [ReturnError]() -> MaybeError {
232             int result = 0;
233             DAWN_TRY_ASSIGN(result, ReturnError());
234             DAWN_UNUSED(result);
235 
236             return {};
237         };
238 
239         MaybeError result = Try();
240         ASSERT_TRUE(result.IsError());
241 
242         std::unique_ptr<ErrorData> errorData = result.AcquireError();
243         ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
244     }
245 
246     // Check a MaybeError can be DAWN_TRIED in a function that returns an ResultOrError
247     // Check DAWN_TRY handles errors correctly.
TEST(ErrorTests,TRY_ConversionToErrorOrResult)248     TEST(ErrorTests, TRY_ConversionToErrorOrResult) {
249         auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
250 
251         auto Try = [ReturnError]() -> ResultOrError<int*> {
252             DAWN_TRY(ReturnError());
253             return &dummySuccess;
254         };
255 
256         ResultOrError<int*> result = Try();
257         ASSERT_TRUE(result.IsError());
258 
259         std::unique_ptr<ErrorData> errorData = result.AcquireError();
260         ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
261     }
262 
263     // Check a MaybeError can be DAWN_TRIED in a function that returns an ResultOrError
264     // Check DAWN_TRY handles errors correctly. Version without Result<E*, T*>
TEST(ErrorTests,TRY_ConversionToErrorOrResultNonPointer)265     TEST(ErrorTests, TRY_ConversionToErrorOrResultNonPointer) {
266         auto ReturnError = []() -> MaybeError { return DAWN_VALIDATION_ERROR(dummyErrorMessage); };
267 
268         auto Try = [ReturnError]() -> ResultOrError<int> {
269             DAWN_TRY(ReturnError());
270             return 42;
271         };
272 
273         ResultOrError<int> result = Try();
274         ASSERT_TRUE(result.IsError());
275 
276         std::unique_ptr<ErrorData> errorData = result.AcquireError();
277         ASSERT_EQ(errorData->GetMessage(), dummyErrorMessage);
278     }
279 
280 }  // anonymous namespace
281