diff options
author | Jason Carey <jcarey@argv.me> | 2019-02-22 16:17:42 -0500 |
---|---|---|
committer | Jason Carey <jcarey@argv.me> | 2019-03-06 11:51:29 -0500 |
commit | 5926b6e06fec4f37e13740dc2eef8b5c7a806138 (patch) | |
tree | 217489bf4174dffd510320d243a4a199fc87911e | |
parent | 50f6bd4d6a9428a6f1df22db792d7b55d773762c (diff) | |
download | mongo-5926b6e06fec4f37e13740dc2eef8b5c7a806138.tar.gz |
SERVER-39688 Support namespaces for ErrorExtraInfo
Adds support for ErrorExtraInfo types that are not directly in the mongo
namespace. I.e. something like mongo::nested::namespace::MyExtraInfo
-rw-r--r-- | src/mongo/base/error_codes.err | 1 | ||||
-rw-r--r-- | src/mongo/base/error_codes.tpl.h | 8 | ||||
-rw-r--r-- | src/mongo/base/error_extra_info.cpp | 20 | ||||
-rw-r--r-- | src/mongo/base/error_extra_info.h | 35 | ||||
-rw-r--r-- | src/mongo/base/generate_error_codes.py | 14 | ||||
-rw-r--r-- | src/mongo/base/status_test.cpp | 18 |
6 files changed, 95 insertions, 1 deletions
diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err index 068d3a15224..c5e6a5a698e 100644 --- a/src/mongo/base/error_codes.err +++ b/src/mongo/base/error_codes.err @@ -282,6 +282,7 @@ error_code("ChangeStreamFatalError", 280) error_code("TransactionCoordinatorSteppingDown", 281) # Gets converted to InterruptedDueToStepDown error_code("TransactionCoordinatorReachedAbortDecision", 282) error_code("WouldChangeOwningShard", 283, extra="WouldChangeOwningShardInfo") +error_code("ForTestingErrorExtraInfoWithExtraInfoInNamespace", 284, extra="nested::twice::NestedErrorExtraInfoExample") # Error codes 4000-8999 are reserved. diff --git a/src/mongo/base/error_codes.tpl.h b/src/mongo/base/error_codes.tpl.h index 3f8d40c490d..b2c0ea617ba 100644 --- a/src/mongo/base/error_codes.tpl.h +++ b/src/mongo/base/error_codes.tpl.h @@ -43,7 +43,13 @@ class Status; // ErrorExtraInfo subclasses: //#for $ec in $codes: //#if $ec.extra -class $ec.extra; +//#if $ec.extra_ns +namespace $ec.extra_ns { + //#end if + class $ec.extra_class; + //#if $ec.extra_ns +} // namespace $ec.extra_ns +//#end if //#end if //#end for diff --git a/src/mongo/base/error_extra_info.cpp b/src/mongo/base/error_extra_info.cpp index 5c844bb4b8c..822904464c7 100644 --- a/src/mongo/base/error_extra_info.cpp +++ b/src/mongo/base/error_extra_info.cpp @@ -51,4 +51,24 @@ std::shared_ptr<const ErrorExtraInfo> ErrorExtraInfoExample::parse(const BSONObj MONGO_INIT_REGISTER_ERROR_EXTRA_INFO(ErrorExtraInfoExample); +namespace nested::twice { + +bool NestedErrorExtraInfoExample::isParserEnabledForTest = false; + +void NestedErrorExtraInfoExample::serialize(BSONObjBuilder* builder) const { + builder->append("data", data); +} + +std::shared_ptr<const ErrorExtraInfo> NestedErrorExtraInfoExample::parse(const BSONObj& obj) { + uassert(51100, + "ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace is only for testing", + isParserEnabledForTest); + + return std::make_shared<NestedErrorExtraInfoExample>(obj["data"].Int()); +} + +MONGO_INIT_REGISTER_ERROR_EXTRA_INFO(NestedErrorExtraInfoExample); + +} // namespace nested::twice + } // namespace mongo diff --git a/src/mongo/base/error_extra_info.h b/src/mongo/base/error_extra_info.h index bcaca9e890e..8f6bd54df1f 100644 --- a/src/mongo/base/error_extra_info.h +++ b/src/mongo/base/error_extra_info.h @@ -137,4 +137,39 @@ public: private: static bool isParserEnabledForTest; }; + +namespace nested::twice { + +/** + * This is an example ErrorExtraInfo subclass. It is used for testing the ErrorExtraInfoHandling. + * + * It is meant to be a duplicate of ErrorExtraInfoExample, except that it is within a namespace + * (and so exercises a different codepath in the parser). + */ +class NestedErrorExtraInfoExample final : public ErrorExtraInfo { +public: + static constexpr auto code = ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace; + + void serialize(BSONObjBuilder*) const override; + static std::shared_ptr<const ErrorExtraInfo> parse(const BSONObj&); + + // Everything else in this class is just for testing and shouldn't by copied by users. + + struct EnableParserForTest { + EnableParserForTest() { + isParserEnabledForTest = true; + } + ~EnableParserForTest() { + isParserEnabledForTest = false; + } + }; + + NestedErrorExtraInfoExample(int data) : data(data) {} + int data; // This uses the fieldname "data". +private: + static bool isParserEnabledForTest; +}; + +} // namespace nested::twice + } // namespace mongo diff --git a/src/mongo/base/generate_error_codes.py b/src/mongo/base/generate_error_codes.py index a26627fd06d..57b88957dde 100644 --- a/src/mongo/base/generate_error_codes.py +++ b/src/mongo/base/generate_error_codes.py @@ -66,6 +66,20 @@ class ErrorCode: self.name = name self.code = code self.extra = extra + if extra: + split = extra.split('::') + if not split[0]: + die("Error for %s with extra info %s: fully qualified namespaces aren't supported" + % (name, extra)) + if split[0] == "mongo": + die("Error for %s with extra info %s: don't include the mongo namespace" + % (name, extra)) + if len(split) > 1: + self.extra_class = split.pop() + self.extra_ns = "::".join(split) + else: + self.extra_class = extra + self.extra_ns = None self.categories = [] class ErrorClass: diff --git a/src/mongo/base/status_test.cpp b/src/mongo/base/status_test.cpp index 5bc73efbdcf..eeff3daae91 100644 --- a/src/mongo/base/status_test.cpp +++ b/src/mongo/base/status_test.cpp @@ -319,5 +319,23 @@ TEST(ErrorExtraInfo, StatusParserWorks) { ASSERT_EQ(status.extraInfo<ErrorExtraInfoExample>()->data, 123); } +TEST(ErrorExtraInfo, StatusParserWorksNested) { + nested::twice::NestedErrorExtraInfoExample::EnableParserForTest whenInScope; + auto status = Status( + ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace, "", fromjson("{data: 123}")); + ASSERT_EQ(status, ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace); + ASSERT(status.extraInfo()); + ASSERT(status.extraInfo<nested::twice::NestedErrorExtraInfoExample>()); + ASSERT_EQ(status.extraInfo<nested::twice::NestedErrorExtraInfoExample>()->data, 123); +} + +TEST(ErrorExtraInfo, StatusWhenParserThrowsNested) { + auto status = Status( + ErrorCodes::ForTestingErrorExtraInfoWithExtraInfoInNamespace, "", fromjson("{data: 123}")); + ASSERT_EQ(status, ErrorCodes::duplicateCodeForTest(51100)); + ASSERT(!status.extraInfo()); + ASSERT(!status.extraInfo<nested::twice::NestedErrorExtraInfoExample>()); +} + } // namespace } // namespace mongo |