From 7ee25189c378b63c39c1696f1f78603b90f12746 Mon Sep 17 00:00:00 2001 From: Chen Weihang Date: Fri, 8 Nov 2019 08:32:17 +0800 Subject: [PATCH] Enrich the type of error and declare the error type interfaces (#21024) * Enrich the type of error and declare the error type interfaces, test=develop * adjust tests to adapt new form, test=develop * add inference deps with error_codes.pb.h, test=develop * restore stack iter start pos, test=develop * polish code based review comments, test=develop --- cmake/inference_lib.cmake | 4 +- paddle/fluid/framework/tensor_test.cc | 9 +- paddle/fluid/operators/mul_op.cc | 49 ++++++---- paddle/fluid/platform/CMakeLists.txt | 9 +- paddle/fluid/platform/enforce.h | 68 ++++++++----- paddle/fluid/platform/enforce_test.cc | 6 +- paddle/fluid/platform/error_codes.proto | 80 ++++++++++++++++ paddle/fluid/platform/errors.cc | 79 +++++++++++++++ paddle/fluid/platform/errors.h | 94 ++++++++++++++++++ paddle/fluid/platform/errors_test.cc | 122 ++++++++++++++++++++++++ 10 files changed, 465 insertions(+), 55 deletions(-) create mode 100644 paddle/fluid/platform/error_codes.proto create mode 100644 paddle/fluid/platform/errors.cc create mode 100644 paddle/fluid/platform/errors.h create mode 100644 paddle/fluid/platform/errors_test.cc diff --git a/cmake/inference_lib.cmake b/cmake/inference_lib.cmake index 418d2d41a55..262cf05cc61 100644 --- a/cmake/inference_lib.cmake +++ b/cmake/inference_lib.cmake @@ -207,8 +207,8 @@ set(module "platform") set(platform_lib_deps profiler_proto) add_dependencies(fluid_lib_dist ${platform_lib_deps}) copy(fluid_lib_dist - SRCS ${src_dir}/${module}/*.h ${src_dir}/${module}/dynload/*.h ${src_dir}/${module}/details/*.h ${PADDLE_BINARY_DIR}/paddle/fluid/platform/profiler.pb.h - DSTS ${dst_dir}/${module} ${dst_dir}/${module}/dynload ${dst_dir}/${module}/details ${dst_dir}/${module} + SRCS ${src_dir}/${module}/*.h ${src_dir}/${module}/dynload/*.h ${src_dir}/${module}/details/*.h ${PADDLE_BINARY_DIR}/paddle/fluid/platform/profiler.pb.h ${PADDLE_BINARY_DIR}/paddle/fluid/platform/error_codes.pb.h + DSTS ${dst_dir}/${module} ${dst_dir}/${module}/dynload ${dst_dir}/${module}/details ${dst_dir}/${module} ${dst_dir}/${module} ) set(module "string") diff --git a/paddle/fluid/framework/tensor_test.cc b/paddle/fluid/framework/tensor_test.cc index 8438feca652..84f98d339a2 100644 --- a/paddle/fluid/framework/tensor_test.cc +++ b/paddle/fluid/framework/tensor_test.cc @@ -39,8 +39,8 @@ TEST(Tensor, DataAssert) { } catch (platform::EnforceNotMet& err) { caught = true; std::string ex_msg = err.what(); - EXPECT_TRUE(ex_msg.find("holder_ should not be null\nTensor holds no " - "memory. Call " + EXPECT_TRUE(ex_msg.find("holder_ should not be null") != std::string::npos); + EXPECT_TRUE(ex_msg.find("Tensor holds no memory. Call " "Tensor::mutable_data first.") != std::string::npos); } @@ -154,8 +154,9 @@ TEST(Tensor, ShareDataWith) { } catch (paddle::platform::EnforceNotMet& err) { caught = true; std::string ex_msg = err.what(); - EXPECT_TRUE(ex_msg.find("holder_ should not be null\nTensor holds no " - "memory. Call " + EXPECT_TRUE(ex_msg.find("holder_ should not be null") != + std::string::npos); + EXPECT_TRUE(ex_msg.find("Tensor holds no memory. Call " "Tensor::mutable_data first.") != std::string::npos); } diff --git a/paddle/fluid/operators/mul_op.cc b/paddle/fluid/operators/mul_op.cc index 9de7717b8fc..45e85dd5b62 100644 --- a/paddle/fluid/operators/mul_op.cc +++ b/paddle/fluid/operators/mul_op.cc @@ -50,32 +50,41 @@ class MulOp : public framework::OperatorWithKernel { << " y_num_col_dims=" << y_num_col_dims; PADDLE_ENFORCE_NE(framework::product(y_dims), 0, - "Maybe the Input variable Y(%s) has not " - "been initialized. You may need to confirm " - "if you put exe.run(startup_program) " - "after optimizer.minimize function.", - ctx->Inputs("Y").front()); - PADDLE_ENFORCE_GT(x_dims.size(), x_num_col_dims, - "ShapeError: The input tensor X's dimensions of MulOp " - "should be larger than x_num_col_dims. But received X's " - "dimensions = %d, X's shape = [%s], x_num_col_dims = %d.", - x_dims.size(), x_dims, x_num_col_dims); - PADDLE_ENFORCE_GT(y_dims.size(), y_num_col_dims, - "ShapeError: The input tensor Y's dimensions of MulOp " - "should be larger than y_num_col_dims. But received Y's " - "dimensions = %d, Y's shape = [%s], y_num_col_dims = %d.", - y_dims.size(), y_dims, y_num_col_dims); + platform::errors::PreconditionNotMet( + "Maybe the Input variable Y(%s) has not " + "been initialized. You may need to confirm " + "if you put exe.run(startup_program) " + "after optimizer.minimize function.", + ctx->Inputs("Y").front())); + PADDLE_ENFORCE_GT( + x_dims.size(), x_num_col_dims, + platform::errors::InvalidArgument( + "The input tensor X's dimensions of MulOp " + "should be larger than x_num_col_dims. But received X's " + "dimensions = %d, X's shape = [%s], x_num_col_dims = %d.", + x_dims.size(), x_dims, x_num_col_dims)); + PADDLE_ENFORCE_GT( + y_dims.size(), y_num_col_dims, + platform::errors::InvalidArgument( + "The input tensor Y's dimensions of MulOp " + "should be larger than y_num_col_dims. But received Y's " + "dimensions = %d, Y's shape = [%s], y_num_col_dims = %d.", + y_dims.size(), y_dims, y_num_col_dims)); auto x_mat_dims = framework::flatten_to_2d(x_dims, x_num_col_dims); auto y_mat_dims = framework::flatten_to_2d(y_dims, y_num_col_dims); PADDLE_ENFORCE_EQ( x_mat_dims[1], y_mat_dims[0], - "ShapeError: After flatten the input tensor X and Y to 2-D dimensions " - "matrix X1 and Y1, the matrix X1's width must be equal with matrix " - "Y1's height. But received X's shape = [%s], X1's shape = [%s], X1's " - "width = %s; Y's shape = [%s], Y1's shape = [%s], Y1's height = %s.", - x_dims, x_mat_dims, x_mat_dims[1], y_dims, y_mat_dims, y_mat_dims[0]); + platform::errors::InvalidArgument( + "After flatten the input tensor X and Y to 2-D dimensions " + "matrix X1 and Y1, the matrix X1's width must be equal with matrix " + "Y1's height. But received X's shape = [%s], X1's shape = [%s], " + "X1's " + "width = %s; Y's shape = [%s], Y1's shape = [%s], Y1's height = " + "%s.", + x_dims, x_mat_dims, x_mat_dims[1], y_dims, y_mat_dims, + y_mat_dims[0])); std::vector output_dims; output_dims.reserve( static_cast(x_num_col_dims + y_dims.size() - y_num_col_dims)); diff --git a/paddle/fluid/platform/CMakeLists.txt b/paddle/fluid/platform/CMakeLists.txt index 744b4964874..2c94f939b74 100644 --- a/paddle/fluid/platform/CMakeLists.txt +++ b/paddle/fluid/platform/CMakeLists.txt @@ -1,8 +1,8 @@ proto_library(profiler_proto SRCS profiler.proto DEPS framework_proto simple_threadpool) py_proto_compile(profiler_py_proto SRCS profiler.proto) +proto_library(error_codes_proto SRCS error_codes.proto) add_custom_target(profiler_py_proto_init ALL COMMAND ${CMAKE_COMMAND} -E touch __init__.py) - add_dependencies(profiler_py_proto profiler_py_proto_init) if (NOT WIN32) @@ -22,10 +22,13 @@ endif(NOT WIN32) cc_library(flags SRCS flags.cc DEPS gflags) +cc_library(errors SRCS errors.cc DEPS error_codes_proto) +cc_test(errors_test SRCS errors_test.cc DEPS errors enforce) + if(WITH_GPU) - nv_library(enforce SRCS enforce.cc DEPS flags) + nv_library(enforce SRCS enforce.cc DEPS flags errors) else() - cc_library(enforce SRCS enforce.cc DEPS flags) + cc_library(enforce SRCS enforce.cc DEPS flags errors) endif() cc_test(enforce_test SRCS enforce_test.cc DEPS stringpiece enforce) diff --git a/paddle/fluid/platform/enforce.h b/paddle/fluid/platform/enforce.h index 5ede7220ba6..ac6e1e657bf 100644 --- a/paddle/fluid/platform/enforce.h +++ b/paddle/fluid/platform/enforce.h @@ -38,6 +38,7 @@ limitations under the License. */ #define GLOG_NO_ABBREVIATED_SEVERITIES // msvc conflict logging with windows.h #include "glog/logging.h" +#include "paddle/fluid/platform/errors.h" #include "paddle/fluid/platform/macros.h" #include "paddle/fluid/platform/port.h" #include "paddle/fluid/string/printf.h" @@ -194,8 +195,8 @@ inline std::string GetTraceBackString(StrType&& what, const char* file, #endif sout << "\n----------------------\nError Message " "Summary:\n----------------------\n"; - sout << string::Sprintf("PaddleCheckError: %s at [%s:%d]", - std::forward(what), file, line) + sout << string::Sprintf("%s at (%s:%d)", std::forward(what), file, + line) << std::endl; return sout.str(); } @@ -210,6 +211,14 @@ inline void throw_on_error(bool stat, const std::string& msg) { #endif } +inline void throw_on_error(const platform::ErrorSummary& error) { +#ifndef REPLACE_ENFORCE_GLOG + throw std::runtime_error(error.ToString()); +#else + LOG(FATAL) << error.ToString(); +#endif +} + /** ENFORCE EXCEPTION AND MACROS **/ struct EnforceNotMet : public std::exception { @@ -220,15 +229,25 @@ struct EnforceNotMet : public std::exception { err_str_ = GetTraceBackString(e.what(), file, line); } } + EnforceNotMet(const std::string& str, const char* file, int line) : err_str_(GetTraceBackString(str, file, line)) {} + EnforceNotMet(const platform::ErrorSummary& error, const char* file, int line) + : err_str_(GetTraceBackString(error.ToString(), file, line)) {} + const char* what() const noexcept override { return err_str_.c_str(); } std::string err_str_; }; -#define PADDLE_THROW(...) \ +#define PADDLE_THROW(...) \ + do { \ + throw ::paddle::platform::EnforceNotMet( \ + ::paddle::platform::ErrorSummary(__VA_ARGS__), __FILE__, __LINE__); \ + } while (0) + +#define PADDLE_THROW_ERROR(...) \ do { \ throw ::paddle::platform::EnforceNotMet( \ ::paddle::string::Sprintf(__VA_ARGS__), __FILE__, __LINE__); \ @@ -238,13 +257,13 @@ struct EnforceNotMet : public std::exception { // For cuda, the assertions can affect performance and it is therefore // recommended to disable them in production code // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#assertion -#define PADDLE_ENFORCE(_IS_NOT_ERROR, __FORMAT, ...) \ - do { \ - if (!(_IS_NOT_ERROR)) { \ - printf("Exception: %s:%d Assertion `%s` failed. " __FORMAT "\n", \ - __FILE__, __LINE__, #_IS_NOT_ERROR, ##__VA_ARGS__); \ - asm("trap;"); \ - } \ +#define PADDLE_ENFORCE(_IS_NOT_ERROR, __FORMAT, ...) \ + do { \ + if (!(_IS_NOT_ERROR)) { \ + printf("Error: %s:%d Assertion `%s` failed. " __FORMAT "\n", __FILE__, \ + __LINE__, #_IS_NOT_ERROR, ##__VA_ARGS__); \ + asm("trap;"); \ + } \ } while (0) #else #define PADDLE_ENFORCE(COND, ...) \ @@ -253,7 +272,7 @@ struct EnforceNotMet : public std::exception { if (UNLIKELY(::paddle::platform::is_error(__cond__))) { \ try { \ ::paddle::platform::throw_on_error( \ - __cond__, ::paddle::string::Sprintf(__VA_ARGS__)); \ + ::paddle::platform::ErrorSummary(__VA_ARGS__)); \ } catch (...) { \ throw ::paddle::platform::EnforceNotMet(std::current_exception(), \ __FILE__, __LINE__); \ @@ -275,12 +294,13 @@ struct EnforceNotMet : public std::exception { * extra messages is also supported, for example: * PADDLE_ENFORCE(a, b, "some simple enforce failed between %d numbers", 2) */ -#define PADDLE_ENFORCE_NOT_NULL(__VAL, ...) \ - do { \ - if (UNLIKELY(nullptr == (__VAL))) { \ - PADDLE_THROW(#__VAL " should not be null\n%s", \ - ::paddle::string::Sprintf(__VA_ARGS__)); \ - } \ +#define PADDLE_ENFORCE_NOT_NULL(__VAL, ...) \ + do { \ + if (UNLIKELY(nullptr == (__VAL))) { \ + PADDLE_THROW_ERROR( \ + "%s\n [Hint: " #__VAL " should not be null.]", \ + ::paddle::platform::ErrorSummary(__VA_ARGS__).ToString()); \ + } \ } while (0) #define __PADDLE_BINARY_COMPARE(__VAL1, __VAL2, __CMP, __INV_CMP, ...) \ @@ -299,14 +319,14 @@ struct EnforceNotMet : public std::exception { constexpr bool __kCanToString__ = \ ::paddle::platform::details::CanToString<__TYPE1__>::kValue && \ ::paddle::platform::details::CanToString<__TYPE2__>::kValue; \ - PADDLE_THROW("Expected %s " #__CMP " %s, but received %s " #__INV_CMP \ - " %s.\n%s", \ - #__VAL1, #__VAL2, \ - ::paddle::platform::details::BinaryCompareMessageConverter< \ + PADDLE_THROW_ERROR( \ + "%s\n [Hint: Expected %s " #__CMP \ + " %s, but received %s " #__INV_CMP " %s.]", \ + ::paddle::platform::ErrorSummary(__VA_ARGS__).ToString(), #__VAL1, \ + #__VAL2, ::paddle::platform::details::BinaryCompareMessageConverter< \ __kCanToString__>::Convert(#__VAL1, __val1), \ - ::paddle::platform::details::BinaryCompareMessageConverter< \ - __kCanToString__>::Convert(#__VAL2, __val2), \ - ::paddle::string::Sprintf(__VA_ARGS__)); \ + ::paddle::platform::details::BinaryCompareMessageConverter< \ + __kCanToString__>::Convert(#__VAL2, __val2)); \ } \ } while (0) diff --git a/paddle/fluid/platform/enforce_test.cc b/paddle/fluid/platform/enforce_test.cc index 8dedfe97049..24d8966e32e 100644 --- a/paddle/fluid/platform/enforce_test.cc +++ b/paddle/fluid/platform/enforce_test.cc @@ -87,8 +87,10 @@ TEST(ENFORCE_EQ, EXTRA_MSG_FAIL) { } catch (paddle::platform::EnforceNotMet& error) { caught_exception = true; std::string ex_msg = error.what(); - EXPECT_TRUE(ex_msg.find("Expected a == 1 + 3, but received a:2 != 1 + " - "3:4.\ntheir size not match") != std::string::npos); + EXPECT_TRUE(ex_msg.find("their size not match") != std::string::npos); + EXPECT_TRUE( + ex_msg.find("Expected a == 1 + 3, but received a:2 != 1 + 3:4.") != + std::string::npos); } EXPECT_TRUE(caught_exception); } diff --git a/paddle/fluid/platform/error_codes.proto b/paddle/fluid/platform/error_codes.proto new file mode 100644 index 00000000000..90ab93dd11d --- /dev/null +++ b/paddle/fluid/platform/error_codes.proto @@ -0,0 +1,80 @@ +/* Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +package paddle.platform.error; + +enum Code { + // Legacy error. + // Error type string: "Error" + LEGACY = 0; + + // Client specified an invalid argument. + // Error type string: "InvalidArgumentError" + INVALID_ARGUMENT = 1; + + // Some requested entity (e.g., file or directory) was not found. + // Error type string: "NotFoundError" + NOT_FOUND = 2; + + // Operation tried to iterate past the valid input range. E.g., seeking or + // reading past end of file. + // Error type string: "OutOfRangeError" + OUT_OF_RANGE = 3; + + // Some entity that we attempted to create (e.g., file or directory) + // already exists. + // Error type string: "AlreadyExistsError" + ALREADY_EXISTS = 4; + + // Some resource has been exhausted, perhaps a per-user quota, or + // perhaps the entire file system is out of space. + // Error type string: "ResourceExhaustedError" + RESOURCE_EXHAUSTED = 5; + + // Operation was rejected because the system is not in a state + // required for the operation's execution. + // Error type string: "PreconditionNotMetError" + PRECONDITION_NOT_MET = 6; + + // The caller does not have permission to execute the specified + // operation. + // Error type string: "PermissionDeniedError" + PERMISSION_DENIED = 7; + + // Deadline expired before operation could complete. + // Error type string: "ExecutionTimeout" + EXECUTION_TIMEOUT = 8; + + // Operation is not implemented or not supported/enabled in this service. + // Error type string: "UnimpelmentedError" + UNIMPLEMENTED = 9; + + // The service is currently unavailable. This is a most likely a + // transient condition and may be corrected by retrying with + // a backoff. + // Error type string: "UnavailableError" + UNAVAILABLE = 10; + + // Fatal errors. Means some invariant expected by the underlying + // system has been broken. If you see one of these errors, + // something is very broken. + // Error type string: "FatalError" + FATAL = 11; + + // Third-party library error. + // Error type string: "ExternalError" + EXTERNAL = 12; +} diff --git a/paddle/fluid/platform/errors.cc b/paddle/fluid/platform/errors.cc new file mode 100644 index 00000000000..85beefa59de --- /dev/null +++ b/paddle/fluid/platform/errors.cc @@ -0,0 +1,79 @@ +/* Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. + +licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include "paddle/fluid/platform/errors.h" + +#include + +namespace paddle { +namespace platform { + +typedef ::paddle::platform::error::Code Code; + +std::string error_name(Code code) { + switch (code) { + case paddle::platform::error::LEGACY: + return "Error"; + break; + case paddle::platform::error::INVALID_ARGUMENT: + return "InvalidArgumentError"; + break; + case paddle::platform::error::NOT_FOUND: + return "NotFoundError"; + break; + case paddle::platform::error::OUT_OF_RANGE: + return "OutOfRangeError"; + break; + case paddle::platform::error::ALREADY_EXISTS: + return "AlreadyExistsError"; + break; + case paddle::platform::error::RESOURCE_EXHAUSTED: + return "ResourceExhaustedError"; + break; + case paddle::platform::error::PRECONDITION_NOT_MET: + return "PreconditionNotMetError"; + break; + case paddle::platform::error::PERMISSION_DENIED: + return "PermissionDeniedError"; + break; + case paddle::platform::error::EXECUTION_TIMEOUT: + return "ExecutionTimeoutError"; + break; + case paddle::platform::error::UNIMPLEMENTED: + return "UnimplementedError"; + break; + case paddle::platform::error::UNAVAILABLE: + return "UnavailableError"; + break; + case paddle::platform::error::FATAL: + return "FatalError"; + break; + case paddle::platform::error::EXTERNAL: + return "ExternalError"; + break; + default: + throw std::invalid_argument("The error type is undefined."); + break; + } +} + +std::string ErrorSummary::ToString() const { + std::string result(error_name(code())); + result += ": "; + result += error_message(); + return result; +} + +} // namespace platform +} // namespace paddle diff --git a/paddle/fluid/platform/errors.h b/paddle/fluid/platform/errors.h new file mode 100644 index 00000000000..c4184df9eff --- /dev/null +++ b/paddle/fluid/platform/errors.h @@ -0,0 +1,94 @@ +/* Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. + +licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once + +#include +#include +#include +#include +#include + +#include "paddle/fluid/platform/error_codes.pb.h" +#include "paddle/fluid/string/printf.h" + +namespace paddle { +namespace platform { + +typedef ::paddle::platform::error::Code Code; + +class ErrorSummary { + public: + // Note(chenweihang): Final deprecated constructor + // This constructor is only used to be compatible with + // current existing no error message PADDLE_ENFORCE_* + ErrorSummary() { + code_ = paddle::platform::error::LEGACY; + msg_ = + "Paddle internal Check failed. (Please help us create a new issue, " + "here we need to find the developer to add a user friendly error " + "message)"; + } + + // Note(chenweihang): Final deprecated constructor + // This constructor is used to be compatible with + // current existing untyped PADDLE_ENFORCE_* + // PADDLE_ENFORCE + template + explicit ErrorSummary(Args... args) { + code_ = paddle::platform::error::LEGACY; + msg_ = paddle::string::Sprintf(args...); + } + + // Note(chenweihang): Recommended constructor + explicit ErrorSummary(Code code, std::string msg) : code_(code), msg_(msg) {} + + Code code() const { return code_; } + + const std::string& error_message() const { return msg_; } + + std::string ToString() const; + + private: + Code code_; + std::string msg_; +}; + +namespace errors { + +#define REGISTER_ERROR(FUNC, CONST, ...) \ + template \ + ::paddle::platform::ErrorSummary FUNC(Args... args) { \ + return ::paddle::platform::ErrorSummary( \ + ::paddle::platform::error::CONST, ::paddle::string::Sprintf(args...)); \ + } + +REGISTER_ERROR(InvalidArgument, INVALID_ARGUMENT) +REGISTER_ERROR(NotFound, NOT_FOUND) +REGISTER_ERROR(OutOfRange, OUT_OF_RANGE) +REGISTER_ERROR(AlreadyExists, ALREADY_EXISTS) +REGISTER_ERROR(ResourceExhausted, RESOURCE_EXHAUSTED) +REGISTER_ERROR(PreconditionNotMet, PRECONDITION_NOT_MET) +REGISTER_ERROR(PermissionDenied, PERMISSION_DENIED) +REGISTER_ERROR(ExecutionTimeout, EXECUTION_TIMEOUT) +REGISTER_ERROR(Unimplemented, UNIMPLEMENTED) +REGISTER_ERROR(Unavailable, UNAVAILABLE) +REGISTER_ERROR(Fatal, FATAL) +REGISTER_ERROR(External, EXTERNAL) + +#undef REGISTER_ERROR + +} // namespace errors +} // namespace platform +} // namespace paddle diff --git a/paddle/fluid/platform/errors_test.cc b/paddle/fluid/platform/errors_test.cc new file mode 100644 index 00000000000..3c84215b5e5 --- /dev/null +++ b/paddle/fluid/platform/errors_test.cc @@ -0,0 +1,122 @@ +/* Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved. + +licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include +#include + +#include "gtest/gtest.h" +#include "paddle/fluid/platform/enforce.h" +#include "paddle/fluid/platform/errors.h" + +using namespace paddle::platform::errors; // NOLINT + +#define CHECK_PADDLE_THROW(EFUNC) \ + do { \ + bool caught_exception = false; \ + try { \ + PADDLE_THROW((EFUNC)("paddle throw test.")); \ + } catch (paddle::platform::EnforceNotMet & error) { \ + caught_exception = true; \ + std::string ex_msg = error.what(); \ + EXPECT_TRUE(ex_msg.find(#EFUNC "Error: paddle throw test.") != \ + std::string::npos); \ + } \ + EXPECT_TRUE(caught_exception); \ + } while (0) + +#define CHECK_PADDLE_ENFORCE(EFUNC) \ + do { \ + bool caught_exception = false; \ + try { \ + PADDLE_ENFORCE(false, (EFUNC)("paddle enforce test.")); \ + } catch (paddle::platform::EnforceNotMet & error) { \ + caught_exception = true; \ + std::string ex_msg = error.what(); \ + EXPECT_TRUE(ex_msg.find(#EFUNC "Error: paddle enforce test.") != \ + std::string::npos); \ + } \ + EXPECT_TRUE(caught_exception); \ + } while (0) + +#define CHECK_PADDLE_ENFORCE_NOT_NULL(EFUNC) \ + do { \ + bool caught_exception = false; \ + try { \ + PADDLE_ENFORCE_NOT_NULL(nullptr, \ + (EFUNC)("paddle enforce not null test.")); \ + } catch (paddle::platform::EnforceNotMet & error) { \ + caught_exception = true; \ + std::string ex_msg = error.what(); \ + EXPECT_TRUE( \ + ex_msg.find(#EFUNC "Error: paddle enforce not null test.") != \ + std::string::npos); \ + } \ + EXPECT_TRUE(caught_exception); \ + } while (0) + +#define CHECK_PADDLE_ENFORCE_EQ(EFUNC) \ + do { \ + bool caught_exception = false; \ + try { \ + PADDLE_ENFORCE_EQ(1, 2, (EFUNC)("paddle enforce equal test.")); \ + } catch (paddle::platform::EnforceNotMet & error) { \ + caught_exception = true; \ + std::string ex_msg = error.what(); \ + EXPECT_TRUE(ex_msg.find(#EFUNC "Error: paddle enforce equal test.") != \ + std::string::npos); \ + } \ + EXPECT_TRUE(caught_exception); \ + } while (0) + +#define CHECK_ALL_PADDLE_EXCEPTION_MACRO(EFUNC) \ + do { \ + CHECK_PADDLE_THROW(EFUNC); \ + CHECK_PADDLE_ENFORCE(EFUNC); \ + CHECK_PADDLE_ENFORCE_NOT_NULL(EFUNC); \ + CHECK_PADDLE_ENFORCE_EQ(EFUNC); \ + } while (0) + +TEST(Errors, InvalidArgument) { + CHECK_ALL_PADDLE_EXCEPTION_MACRO(InvalidArgument); +} + +TEST(Errors, NotFound) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(NotFound); } + +TEST(Errors, OutOfRange) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(OutOfRange); } + +TEST(Errors, AlreadExists) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(AlreadyExists); } + +TEST(Errors, ResourceExhausted) { + CHECK_ALL_PADDLE_EXCEPTION_MACRO(ResourceExhausted); +} + +TEST(Errors, PreconditionNotMet) { + CHECK_ALL_PADDLE_EXCEPTION_MACRO(PreconditionNotMet); +} + +TEST(Errors, PermissionDenied) { + CHECK_ALL_PADDLE_EXCEPTION_MACRO(PermissionDenied); +} + +TEST(Errors, ExecutionTimeout) { + CHECK_ALL_PADDLE_EXCEPTION_MACRO(ExecutionTimeout); +} + +TEST(Errors, Unimplemented) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(Unimplemented); } + +TEST(Errors, Unavailable) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(Unavailable); } + +TEST(Errors, Fatal) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(Fatal); } + +TEST(Errors, External) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(External); } -- GitLab