From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 191456F3E5; Sat, 6 Nov 2021 02:59:22 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 191456F3E5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1636156762; bh=3x0rH67ZpOMYDsdI6hdLh4oiVfkYEGOGzhPku4SZMGA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=l1t1aa/rvprXBUZZ6uujIwcwlTvuXjgNJGREC7SK3bSIjutsrjKRmFhcIqVBr3+zL xl3ZsSHro2TQv8q7DLXyaBFhhQDaeuXGcV0vbGwBl1TpOALxRRMmgNuXJGQMjWp+hU biI0wSO2hNJ8dk83K9NMSbpJXhmUIWZue/FXwbVs= Received: from smtpng3.i.mail.ru (smtpng3.i.mail.ru [94.100.177.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 6DDCF6CE31 for ; Sat, 6 Nov 2021 02:56:48 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 6DDCF6CE31 Received: by smtpng3.m.smailru.net with esmtpa (envelope-from ) id 1mj94h-0006s6-5D; Sat, 06 Nov 2021 02:56:47 +0300 To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org, vdavydov@tarantool.org Date: Sat, 6 Nov 2021 00:56:36 +0100 Message-Id: <7adc72ff7c2de0a662e2591234eade251fb83f27.1636156453.git.v.shpilevoy@tarantool.org> X-Mailer: git-send-email 2.24.3 (Apple Git-128) In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD9F9D976862A30D4FE73DAF5629B89E81F7BE3C6ABECA89A3F182A05F538085040D2CD459C0BE49B6B0A33893A70895F402AE7E00C65237D57194B14ECC52BFF3B X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7922E451CE6E839B1EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637C83F54BD885518138638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D8BD3343CAB943E48C6D23F2A7A0775506117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BAA867293B0326636D2E47CDBA5A96583BA9C0B312567BB231DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B62CFFCC7B69C47339089D37D7C0E48F6C5571747095F342E88FB05168BE4CE3AF X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C4173B97CBE165B82D912AB7649887A206BC0994F947283B77A9D420A4CFB5DD3E96BAC2615DD8185F63171F5B0540C207A29A39D7CD174FC3D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA75C69C5C0DDE134364410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D347215713CF3EEE9D128F381578C9943084DDF70962CD5D5B2821ED0422DDD8725B08A730A93AEF6641D7E09C32AA3244C7FBBC949AE61BDD11FF162C5BC68AFD7725D5B54B2FE4575FACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj75A/c671lqV/THiwNOjRpg== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5DD3A4E7CADBB0CF1795FEC8A475EC17583841015FED1DE5223CC9A89AB576DD93FB559BB5D741EB963CF37A108A312F5C27E8A8C3839CE0E267EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH 5/9] error: use error_payload in MessagePack codecs X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Vladislav Shpilevoy via Tarantool-patches Reply-To: Vladislav Shpilevoy Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Before this patch mp_error API could only encode and decode hardcoded fields from the C++ classes inheriting struct error. The fields are gone from the classes in a previous patch - moved into error_payload. Now to be able to support arbitrary fields in the payload the MessagePack encoding/decoding must use its content instead of hardcoded fields depending on error type. Part of #5568 --- src/box/error.cc | 7 -- src/box/error.h | 28 +++++- src/box/mp_error.cc | 194 +++++++++++--------------------------- src/lib/core/diag.c | 17 ++-- src/lib/core/diag.h | 9 ++ src/lib/core/exception.h | 66 +++++++++++++ test/unit/mp_error.cc | 76 ++++++++++++++- test/unit/mp_error.result | 27 +++++- 8 files changed, 262 insertions(+), 162 deletions(-) diff --git a/src/box/error.cc b/src/box/error.cc index 629ec703f..be3b3b6f5 100644 --- a/src/box/error.cc +++ b/src/box/error.cc @@ -256,13 +256,6 @@ XlogGapError::XlogGapError(const char *file, unsigned line, (long long) vclock_sum(to), s_to ? s_to : ""); } -XlogGapError::XlogGapError(const char *file, unsigned line, - const char *msg) - : XlogError(&type_XlogGapError, file, line) -{ - error_format_msg(this, "%s", msg); -} - struct error * BuildXlogGapError(const char *file, unsigned line, const struct vclock *from, const struct vclock *to) diff --git a/src/box/error.h b/src/box/error.h index 43faaea70..c2ccf48bb 100644 --- a/src/box/error.h +++ b/src/box/error.h @@ -213,6 +213,11 @@ public: ClientError(const char *file, unsigned line, uint32_t errcode, ...); + ClientError() + :Exception(&type_ClientError, NULL, 0) + { + } + static uint32_t get_errcode(const struct error *e); protected: ClientError(const type_info *type, const char *file, unsigned line, @@ -243,6 +248,11 @@ public: const char *object_name, const char *user_name, bool run_trigers = true); + AccessDeniedError() + :ClientError(&type_AccessDeniedError, NULL, 0, 0) + { + } + const char * object_type() const { @@ -276,6 +286,12 @@ struct XlogError: public Exception { error_vformat_msg(this, format, ap); } + + XlogError() + :Exception(&type_XlogError, NULL, 0) + { + } + XlogError(const struct type_info *type, const char *file, unsigned line) :Exception(type, file, line) @@ -289,8 +305,11 @@ struct XlogGapError: public XlogError { XlogGapError(const char *file, unsigned line, const struct vclock *from, const struct vclock *to); - XlogGapError(const char *file, unsigned line, - const char *msg); + + XlogGapError() + :XlogError(&type_XlogGapError, NULL, 0) + { + } virtual void raise() { throw this; } }; @@ -301,6 +320,11 @@ public: CustomError(const char *file, unsigned int line, const char *custom_type, uint32_t errcode); + CustomError() + :ClientError(&type_CustomError, NULL, 0, 0) + { + } + virtual void log() const; const char* diff --git a/src/box/mp_error.cc b/src/box/mp_error.cc index 35c770400..fba562a84 100644 --- a/src/box/mp_error.cc +++ b/src/box/mp_error.cc @@ -118,35 +118,31 @@ struct mp_error { const char *type; const char *file; const char *message; - const char *custom_type; - const char *ad_object_type; - const char *ad_object_name; - const char *ad_access_type; + struct error_payload payload; }; static void mp_error_create(struct mp_error *mp_error) { memset(mp_error, 0, sizeof(*mp_error)); + error_payload_create(&mp_error->payload); +} + +static void +mp_error_destroy(struct mp_error *mp_error) +{ + error_payload_destroy(&mp_error->payload); } static uint32_t mp_sizeof_error_one(const struct error *error) { uint32_t errcode = box_error_code(error); - - bool is_custom = false; - bool is_access_denied = false; - - if (strcmp(error->type->name, "CustomError") == 0) { - is_custom = true; - } else if (strcmp(error->type->name, "AccessDeniedError") == 0) { - is_access_denied = true; - } - - uint32_t details_num = 6; + int field_count = error->payload.count; + uint32_t map_size = 6 + (field_count > 0); uint32_t data_size = 0; + data_size += mp_sizeof_map(map_size); data_size += mp_sizeof_uint(MP_ERROR_TYPE); data_size += mp_sizeof_str(strlen(error->type->name)); data_size += mp_sizeof_uint(MP_ERROR_LINE); @@ -160,28 +156,15 @@ mp_sizeof_error_one(const struct error *error) data_size += mp_sizeof_uint(MP_ERROR_CODE); data_size += mp_sizeof_uint(errcode); - if (is_access_denied) { - ++details_num; - data_size += mp_sizeof_uint(MP_ERROR_FIELDS); - data_size += mp_sizeof_map(3); - AccessDeniedError *ad_err = type_cast(AccessDeniedError, error); - data_size += mp_sizeof_str(strlen("object_type")); - data_size += mp_sizeof_str(strlen(ad_err->object_type())); - data_size += mp_sizeof_str(strlen("object_name")); - data_size += mp_sizeof_str(strlen(ad_err->object_name())); - data_size += mp_sizeof_str(strlen("access_type")); - data_size += mp_sizeof_str(strlen(ad_err->access_type())); - } else if (is_custom) { - ++details_num; + if (field_count > 0) { data_size += mp_sizeof_uint(MP_ERROR_FIELDS); - data_size += mp_sizeof_map(1); - data_size += mp_sizeof_str(strlen("custom_type")); - data_size += - mp_sizeof_str(strlen(box_error_custom_type(error))); + data_size += mp_sizeof_map(field_count); + for (int i = 0; i < field_count; ++i) { + const struct error_field *f = error->payload.fields[i]; + data_size += mp_sizeof_str(strlen(f->name)); + data_size += f->size; + } } - - data_size += mp_sizeof_map(details_num); - return data_size; } @@ -195,21 +178,10 @@ static char * mp_encode_error_one(char *data, const struct error *error) { uint32_t errcode = box_error_code(error); + int field_count = error->payload.count; + uint32_t map_size = 6 + (field_count > 0); - bool is_custom = false; - bool is_access_denied = false; - - if (strcmp(error->type->name, "CustomError") == 0) { - is_custom = true; - } else if (strcmp(error->type->name, "AccessDeniedError") == 0) { - is_access_denied = true; - } - - uint32_t details_num = 6; - if (is_access_denied || is_custom) - ++details_num; - - data = mp_encode_map(data, details_num); + data = mp_encode_map(data, map_size); data = mp_encode_uint(data, MP_ERROR_TYPE); data = mp_encode_str0(data, error->type->name); data = mp_encode_uint(data, MP_ERROR_LINE); @@ -223,21 +195,15 @@ mp_encode_error_one(char *data, const struct error *error) data = mp_encode_uint(data, MP_ERROR_CODE); data = mp_encode_uint(data, errcode); - if (is_access_denied) { - data = mp_encode_uint(data, MP_ERROR_FIELDS); - data = mp_encode_map(data, 3); - AccessDeniedError *ad_err = type_cast(AccessDeniedError, error); - data = mp_encode_str0(data, "object_type"); - data = mp_encode_str0(data, ad_err->object_type()); - data = mp_encode_str0(data, "object_name"); - data = mp_encode_str0(data, ad_err->object_name()); - data = mp_encode_str0(data, "access_type"); - data = mp_encode_str0(data, ad_err->access_type()); - } else if (is_custom) { + if (field_count > 0) { data = mp_encode_uint(data, MP_ERROR_FIELDS); - data = mp_encode_map(data, 1); - data = mp_encode_str0(data, "custom_type"); - data = mp_encode_str0(data, box_error_custom_type(error)); + data = mp_encode_map(data, field_count); + for (int i = 0; i < field_count; ++i) { + const struct error_field *f = error->payload.fields[i]; + data = mp_encode_str0(data, f->name); + memcpy(data, f->data, f->size); + data += f->size; + } } return data; } @@ -254,72 +220,50 @@ error_build_xc(struct mp_error *mp_error) struct error *err = NULL; if (mp_error->type == NULL || mp_error->message == NULL || mp_error->file == NULL) { -missing_fields: diag_set(ClientError, ER_INVALID_MSGPACK, "Missing mandatory error fields"); return NULL; } if (strcmp(mp_error->type, "ClientError") == 0) { - err = new ClientError(mp_error->file, mp_error->line, - ER_UNKNOWN); + err = new ClientError(); } else if (strcmp(mp_error->type, "CustomError") == 0) { - if (mp_error->custom_type == NULL) - goto missing_fields; - err = new CustomError(mp_error->file, mp_error->line, - mp_error->custom_type, mp_error->code); + err = new CustomError(); } else if (strcmp(mp_error->type, "AccessDeniedError") == 0) { - if (mp_error->ad_access_type == NULL || - mp_error->ad_object_type == NULL || - mp_error->ad_object_name == NULL) - goto missing_fields; - err = new AccessDeniedError(mp_error->file, mp_error->line, - mp_error->ad_access_type, - mp_error->ad_object_type, - mp_error->ad_object_name, "", - false); + err = new AccessDeniedError(); } else if (strcmp(mp_error->type, "XlogError") == 0) { - err = new XlogError(&type_XlogError, mp_error->file, - mp_error->line); + err = new XlogError(); } else if (strcmp(mp_error->type, "XlogGapError") == 0) { - err = new XlogGapError(mp_error->file, mp_error->line, - mp_error->message); + err = new XlogGapError(); } else if (strcmp(mp_error->type, "SystemError") == 0) { - err = new SystemError(mp_error->file, mp_error->line, - "%s", mp_error->message); + err = new SystemError(); } else if (strcmp(mp_error->type, "SocketError") == 0) { - err = new SocketError(mp_error->file, mp_error->line, "", ""); - error_format_msg(err, "%s", mp_error->message); + err = new SocketError(); } else if (strcmp(mp_error->type, "OutOfMemory") == 0) { - err = new OutOfMemory(mp_error->file, mp_error->line, - 0, "", ""); + err = new OutOfMemory(); } else if (strcmp(mp_error->type, "TimedOut") == 0) { - err = new TimedOut(mp_error->file, mp_error->line); + err = new TimedOut(); } else if (strcmp(mp_error->type, "ChannelIsClosed") == 0) { - err = new ChannelIsClosed(mp_error->file, mp_error->line); + err = new ChannelIsClosed(); } else if (strcmp(mp_error->type, "FiberIsCancelled") == 0) { - err = new FiberIsCancelled(mp_error->file, mp_error->line); + err = new FiberIsCancelled(); } else if (strcmp(mp_error->type, "LuajitError") == 0) { - err = new LuajitError(mp_error->file, mp_error->line, - mp_error->message); + err = new LuajitError(); } else if (strcmp(mp_error->type, "IllegalParams") == 0) { - err = new IllegalParams(mp_error->file, mp_error->line, - "%s", mp_error->message); + err = new IllegalParams(); } else if (strcmp(mp_error->type, "CollationError") == 0) { - err = new CollationError(mp_error->file, mp_error->line, - "%s", mp_error->message); + err = new CollationError(); } else if (strcmp(mp_error->type, "SwimError") == 0) { - err = new SwimError(mp_error->file, mp_error->line, - "%s", mp_error->message); + err = new SwimError(); } else if (strcmp(mp_error->type, "CryptoError") == 0) { - err = new CryptoError(mp_error->file, mp_error->line, - "%s", mp_error->message); + err = new CryptoError(); } else { - err = new ClientError(mp_error->file, mp_error->line, - ER_UNKNOWN); + err = new ClientError(); } err->code = mp_error->code; err->saved_errno = mp_error->saved_errno; + error_set_location(err, mp_error->file, mp_error->line); + error_move_payload(err, &mp_error->payload); error_format_msg(err, "%s", mp_error->message); return err; } @@ -350,12 +294,6 @@ mp_decode_and_copy_str(const char **data, struct region *region) return region_strdup(region, str, str_len);; } -static inline bool -str_nonterm_is_eq(const char *l, const char *r, uint32_t r_len) -{ - return r_len == strlen(l) && memcmp(l, r, r_len) == 0; -} - static int mp_decode_error_fields(const char **data, struct mp_error *mp_err, struct region *region) @@ -363,35 +301,16 @@ mp_decode_error_fields(const char **data, struct mp_error *mp_err, if (mp_typeof(**data) != MP_MAP) return -1; uint32_t map_sz = mp_decode_map(data); - const char *key; - uint32_t key_len; for (uint32_t i = 0; i < map_sz; ++i) { - if (mp_typeof(**data) != MP_STR) + uint32_t svp = region_used(region); + const char *key = mp_decode_and_copy_str(data, region); + if (key == NULL) return -1; - key = mp_decode_str(data, &key_len); - if (str_nonterm_is_eq("object_type", key, key_len)) { - mp_err->ad_object_type = - mp_decode_and_copy_str(data, region); - if (mp_err->ad_object_type == NULL) - return -1; - } else if (str_nonterm_is_eq("object_name", key, key_len)) { - mp_err->ad_object_name = - mp_decode_and_copy_str(data, region); - if (mp_err->ad_object_name == NULL) - return -1; - } else if (str_nonterm_is_eq("access_type", key, key_len)) { - mp_err->ad_access_type = - mp_decode_and_copy_str(data, region); - if (mp_err->ad_access_type == NULL) - return -1; - } else if (str_nonterm_is_eq("custom_type", key, key_len)) { - mp_err->custom_type = - mp_decode_and_copy_str(data, region); - if (mp_err->custom_type == NULL) - return -1; - } else { - mp_next(data); - } + const char *value = *data; + mp_next(data); + uint32_t value_len = *data - value; + error_payload_set_mp(&mp_err->payload, key, value, value_len); + region_truncate(region, svp); } return 0; } @@ -462,6 +381,7 @@ mp_decode_error_one(const char **data) } finish: region_truncate(region, region_svp); + mp_error_destroy(&mp_err); return err; error: diff --git a/src/lib/core/diag.c b/src/lib/core/diag.c index 217c3ae7e..b6fa1f5bb 100644 --- a/src/lib/core/diag.c +++ b/src/lib/core/diag.c @@ -119,18 +119,21 @@ error_create(struct error *e, e->saved_errno = 0; e->code = 0; error_payload_create(&e->payload); - if (file != NULL) { - snprintf(e->file, sizeof(e->file), "%s", file); - e->line = line; - } else { - e->file[0] = '\0'; - e->line = 0; - } + if (file == NULL) + file = ""; + error_set_location(e, file, line); e->errmsg[0] = '\0'; e->cause = NULL; e->effect = NULL; } +void +error_set_location(struct error *e, const char *file, int line) +{ + snprintf(e->file, sizeof(e->file), "%s", file); + e->line = line; +} + struct diag * diag_get(void) { diff --git a/src/lib/core/diag.h b/src/lib/core/diag.h index 03bd223e1..40d934c19 100644 --- a/src/lib/core/diag.h +++ b/src/lib/core/diag.h @@ -190,6 +190,12 @@ error_field_unset(struct error *e, const char *name) error_payload_unset(&e->payload, name); } +static inline void +error_move_payload(struct error *e, struct error_payload *src) +{ + error_payload_move(&e->payload, src); +} + /** * Unlink error from its effect. For instance: * e1 -> e2 -> e3 -> e4 (e1:set_prev(e2); e2:set_prev(e3) ...) @@ -243,6 +249,9 @@ error_create(struct error *e, const struct type_info *type, const char *file, unsigned line); +void +error_set_location(struct error *e, const char *file, int line); + void error_format_msg(struct error *e, const char *format, ...); diff --git a/src/lib/core/exception.h b/src/lib/core/exception.h index 7277b2784..28bc7ef05 100644 --- a/src/lib/core/exception.h +++ b/src/lib/core/exception.h @@ -91,6 +91,12 @@ public: SystemError(const char *file, unsigned line, const char *format, ...); + + SystemError() + :Exception(&type_SystemError, NULL, 0) + { + } + protected: SystemError(const struct type_info *type, const char *file, unsigned line); }; @@ -100,6 +106,12 @@ class SocketError: public SystemError { public: SocketError(const char *file, unsigned line, const char *socketname, const char *format, ...); + + SocketError() + :SystemError(&type_SocketError, file, line) + { + } + virtual void raise() { throw this; @@ -111,18 +123,36 @@ public: OutOfMemory(const char *file, unsigned line, size_t amount, const char *allocator, const char *object); + + OutOfMemory() + :SystemError(&type_OutOfMemory, NULL, 0) + { + } + virtual void raise() { throw this; } }; class TimedOut: public SystemError { public: TimedOut(const char *file, unsigned line); + + TimedOut() + :SystemError(&type_TimedOut, NULL, 0) + { + } + virtual void raise() { throw this; } }; class ChannelIsClosed: public Exception { public: ChannelIsClosed(const char *file, unsigned line); + + ChannelIsClosed() + :Exception(&type_ChannelIsClosed, NULL, 0) + { + } + virtual void raise() { throw this; } }; @@ -133,6 +163,12 @@ public: class FiberIsCancelled: public Exception { public: FiberIsCancelled(const char *file, unsigned line); + + FiberIsCancelled() + :Exception(&type_FiberIsCancelled, NULL, 0) + { + } + virtual void log() const; virtual void raise() { throw this; } }; @@ -141,12 +177,24 @@ class LuajitError: public Exception { public: LuajitError(const char *file, unsigned line, const char *msg); + + LuajitError() + :Exception(&type_LuajitError, NULL, 0) + { + } + virtual void raise() { throw this; } }; class IllegalParams: public Exception { public: IllegalParams(const char *file, unsigned line, const char *format, ...); + + IllegalParams() + :Exception(&type_IllegalParams, NULL, 0) + { + } + virtual void raise() { throw this; } }; @@ -154,18 +202,36 @@ class CollationError: public Exception { public: CollationError(const char *file, unsigned line, const char *format, ...); + + CollationError() + :Exception(&type_CollationError, NULL, 0) + { + } + virtual void raise() { throw this; } }; class SwimError: public Exception { public: SwimError(const char *file, unsigned line, const char *format, ...); + + SwimError() + :Exception(&type_SwimError, NULL, 0) + { + } + virtual void raise() { throw this; } }; class CryptoError: public Exception { public: CryptoError(const char *file, unsigned line, const char *format, ...); + + CryptoError() + :Exception(&type_CryptoError, NULL, 0) + { + } + virtual void raise() { throw this; } }; diff --git a/test/unit/mp_error.cc b/test/unit/mp_error.cc index fe0cd49b9..e6560883e 100644 --- a/test/unit/mp_error.cc +++ b/test/unit/mp_error.cc @@ -34,9 +34,11 @@ #include "memory.h" #include "msgpuck.h" #include "mp_extension_types.h" +#include "random.h" #include "tt_static.h" #include "small/ibuf.h" #include "mpstream/mpstream.h" +#include "uuid/tt_uuid.h" #include "box/error.h" #include "box/mp_error.h" @@ -362,7 +364,7 @@ void test_fail_not_enough_fields() { header(); - plan(2); + plan(4); char buffer[2048]; memset(buffer, 0, sizeof(buffer)); @@ -383,8 +385,12 @@ test_fail_not_enough_fields() const char *pos = buffer; struct error *unpacked = error_unpack(&pos, len); - is(unpacked, NULL, "check not enough additional fields"); - ok(!diag_is_empty(diag_get()), "error about parsing problem is set"); + isnt(unpacked, NULL, "check lack of fields"); + is(strcmp(error_field_get_str(unpacked, "object_type"), + err.ad_object_type), 0, "object type"); + is(strcmp(error_field_get_str(unpacked, "access_type"), + err.ad_access_type), 0, "access type"); + is(error_field_get_str(unpacked, "object_name"), NULL, "object name"); check_plan(); footer(); } @@ -455,6 +461,65 @@ test_unknown_additional_fields() footer(); } +static void +test_payload(void) +{ + header(); + plan(11); + char buffer[2048]; + memset(buffer, 0, sizeof(buffer)); + + struct error *e = new ClientError(); + error_ref(e); + e->code = 42; + e->saved_errno = 1; + error_format_msg(e, "msg"); + error_set_location(e, "file", 2); + error_field_set_str(e, "key1", "1"); + error_field_set_uint(e, "key2", 1); + error_field_set_int(e, "key3", -1); + error_field_set_double(e, "key4", 1.5); + error_field_set_bool(e, "key5", true); + struct tt_uuid uuid; + tt_uuid_create(&uuid); + error_field_set_uuid(e, "key6", &uuid); + + mp_encode_error(buffer, e); + error_unref(e); + + int8_t type; + const char *data = buffer; + mp_decode_extl(&data, &type); + e = error_unpack_unsafe(&data); + error_ref(e); + + is(e->code, 42, "code"); + is(e->saved_errno, 1, "errno"); + is(strcmp(e->errmsg, "msg"), 0, "msg"); + is(e->line, 2, "line"); + is(strcmp(e->file, "file"), 0, "file"); + is(strcmp(error_field_get_str(e, "key1"), "1"), 0, "key str"); + uint64_t val_uint; + ok(error_field_get_uint(e, "key2", &val_uint) && val_uint == 1, + "key uint"); + int64_t val_int; + ok(error_field_get_int(e, "key3", &val_int) && val_int == -1, + "key int"); + double val_dbl; + ok(error_field_get_double(e, "key4", &val_dbl) && val_dbl == 1.5, + "key double"); + bool val_bool; + ok(error_field_get_bool(e, "key5", &val_bool) && val_bool, "key bool"); + struct tt_uuid val_uuid; + ok(error_field_get_uuid(e, "key6", &val_uuid) && + tt_uuid_is_equal(&uuid, &val_uuid), "key uuid"); + + error_unref(e); + + check_plan(); + footer(); +} + static int mp_fprint_ext_test(FILE *file, const char **data, int depth) { @@ -723,7 +788,8 @@ int main(void) { header(); - plan(6); + plan(7); + random_init(); memory_init(); fiber_init(fiber_c_invoke); @@ -732,10 +798,12 @@ main(void) test_fail_not_enough_fields(); test_unknown_fields(); test_unknown_additional_fields(); + test_payload(); test_mp_print(); fiber_free(); memory_free(); + random_free(); footer(); return check_plan(); } diff --git a/test/unit/mp_error.result b/test/unit/mp_error.result index 0582458d3..356d2dc97 100644 --- a/test/unit/mp_error.result +++ b/test/unit/mp_error.result @@ -1,5 +1,5 @@ *** main *** -1..6 +1..7 *** test_stack_error_decode *** 1..17 ok 1 - check CustomError @@ -27,9 +27,11 @@ ok 1 - subtests ok 2 - subtests *** test_decode_unknown_type: done *** *** test_fail_not_enough_fields *** - 1..2 - ok 1 - check not enough additional fields - ok 2 - error about parsing problem is set + 1..4 + ok 1 - check lack of fields + ok 2 - object type + ok 3 - access type + ok 4 - object name ok 3 - subtests *** test_fail_not_enough_fields: done *** *** test_unknown_fields *** @@ -41,6 +43,21 @@ ok 4 - subtests ok 1 - check unknown additional field ok 5 - subtests *** test_unknown_additional_fields: done *** + *** test_payload *** + 1..11 + ok 1 - code + ok 2 - errno + ok 3 - msg + ok 4 - line + ok 5 - file + ok 6 - key str + ok 7 - key uint + ok 8 - key int + ok 9 - key double + ok 10 - key bool + ok 11 - key uuid +ok 6 - subtests + *** test_payload: done *** *** test_mp_print *** 1..60 # zero depth, normal error @@ -109,6 +126,6 @@ ok 5 - subtests ok 58 - mp_fprint depth 0 correct length ok 59 - mp_fprint depth 0 correct prefix and suffix ok 60 - mp_fprint depth 0 correct object in the middle -ok 6 - subtests +ok 7 - subtests *** test_mp_print: done *** *** main: done *** -- 2.24.3 (Apple Git-128)