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