From 665985f71e64b6ea16fe5b88c6e65708e6baaf85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= Date: Mon, 1 Jul 2024 12:55:08 +0200 Subject: [PATCH] Refactor the parsing of a key in a command (#37) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The number of elements in the array of keys is either one or none in the command struct, so this change removes the array and refactors the code. Additional changes: - Remove `vkarray.c/.h` - Remove unused `remain_len` from `struct keypos` - Remove unused `remain_len` from `struct keypos` - Remove unused `reply` from `struct cmd` - Remove unused `quit` and `noforward` from `struct cmd` - Remove unused command `type` from `struct cmd` - Remove unused `id` from `struct cmd` - Remove unused `narg` from `struct cmd` - Remove unused `frag_seq` from `struct cmd` Signed-off-by: Björn Svensson --- CMakeLists.txt | 1 - src/command.c | 75 +++---------- src/command.h | 26 +---- src/valkeycluster.c | 7 +- src/vkarray.c | 180 ------------------------------ src/vkarray.h | 79 ------------- src/vkutil.h | 3 - tests/ct_out_of_memory_handling.c | 36 +++--- tests/ut_parse_cmd.c | 61 ++++------ 9 files changed, 65 insertions(+), 403 deletions(-) delete mode 100644 src/vkarray.c delete mode 100644 src/vkarray.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 566d9a01..c1480cb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,6 @@ SET(valkey_sources src/sockcompat.c src/valkey.c src/valkeycluster.c - src/vkarray.c src/vkutil.c) IF(WIN32) diff --git a/src/command.c b/src/command.c index f56675d6..577e43d2 100644 --- a/src/command.c +++ b/src/command.c @@ -40,19 +40,18 @@ #else #include #endif +#include #include #include "alloc.h" #include "command.h" -#include "vkarray.h" +#include "sds.h" #include "vkutil.h" #include "win32.h" #define LF (uint8_t)10 #define CR (uint8_t)13 -static uint64_t cmd_id = 0; /* command id counter */ - typedef enum { KEYPOS_NONE, KEYPOS_UNKNOWN, @@ -93,9 +92,8 @@ static inline void to_upper(char *dst, const char *src, uint32_t len) { } /* Looks up a command or subcommand in the command table. Arg0 and arg1 are used - * to lookup the command. The function returns CMD_UNKNOWN on failure. On - * success, the command type is returned and *firstkey and *arity are - * populated. */ + * to lookup the command. The function returns the cmddef for a found command, + * or NULL on failure. */ cmddef *valkey_lookup_cmd(const char *arg0, uint32_t arg0_len, const char *arg1, uint32_t arg1_len) { int num_commands = sizeof(server_commands) / sizeof(cmddef); @@ -167,15 +165,6 @@ char *valkey_parse_bulk(char *p, char *end, char **str, uint32_t *len) { return p; } -static inline int push_keypos(struct cmd *r, char *arg, uint32_t arglen) { - struct keypos *kpos = vkarray_push(r->keys); - if (kpos == NULL) - return 0; - kpos->start = arg; - kpos->end = arg + arglen; - return 1; -} - /* * Reference: https://valkey.io/docs/topics/protocol/ * @@ -217,7 +206,6 @@ void valkey_parse_cmd(struct cmd *r) { goto error; if (rnarg == 0) goto error; - r->narg = rnarg; /* Parse the first two args. */ if ((p = valkey_parse_bulk(p, end, &arg0, &arg0_len)) == NULL) @@ -232,7 +220,6 @@ void valkey_parse_cmd(struct cmd *r) { /* Lookup command. */ if ((info = valkey_lookup_cmd(arg0, arg0_len, arg1, arg1_len)) == NULL) goto error; /* Command not found. */ - r->type = info->type; /* Arity check (negative arity means minimum num args) */ if ((info->arity >= 0 && (int)rnarg != info->arity) || @@ -251,10 +238,10 @@ void valkey_parse_cmd(struct cmd *r) { /* Keyword-based first key position */ const char *keyword; int startfrom; - if (r->type == CMD_REQ_VALKEY_XREAD) { + if (info->type == CMD_REQ_VALKEY_XREAD) { keyword = "STREAMS"; startfrom = 1; - } else if (r->type == CMD_REQ_VALKEY_XREADGROUP) { + } else if (info->type == CMD_REQ_VALKEY_XREADGROUP) { keyword = "STREAMS"; startfrom = 4; } else { @@ -274,8 +261,9 @@ void valkey_parse_cmd(struct cmd *r) { /* Keyword found. Now the first key is the next arg. */ if ((p = valkey_parse_bulk(p, end, &arg, &arglen)) == NULL) goto error; - if (!push_keypos(r, arg, arglen)) - goto oom; + /* Keep found key. */ + r->key.start = arg; + r->key.len = arglen; goto done; } } @@ -317,9 +305,9 @@ void valkey_parse_cmd(struct cmd *r) { * from the end of the command line. This is not implemented. */ goto error; } - - if (!push_keypos(r, arg, arglen)) - goto oom; + /* Keep found key. */ + r->key.start = arg; + r->key.len = arglen; done: ASSERT(r->type > CMD_UNKNOWN && r->type < CMD_SENTINEL); @@ -333,7 +321,8 @@ void valkey_parse_cmd(struct cmd *r) { if (r->errstr == NULL) { r->errstr = vk_malloc(errmaxlen); if (r->errstr == NULL) { - goto oom; + r->result = CMD_PARSE_ENOMEM; + return; } } @@ -343,17 +332,14 @@ void valkey_parse_cmd(struct cmd *r) { else if (info != NULL) snprintf(r->errstr, errmaxlen, "Failed to find keys of command %s", info->name); - else if (r->type == CMD_UNKNOWN && arg0 != NULL && arg1 != NULL) + else if (info == NULL && arg0 != NULL && arg1 != NULL) snprintf(r->errstr, errmaxlen, "Unknown command %.*s %.*s", arg0_len, arg0, arg1_len, arg1); - else if (r->type == CMD_UNKNOWN && arg0 != NULL) + else if (info == NULL && arg0 != NULL) snprintf(r->errstr, errmaxlen, "Unknown command %.*s", arg0_len, arg0); else snprintf(r->errstr, errmaxlen, "Command parse error"); return; - -oom: - r->result = CMD_PARSE_ENOMEM; } struct cmd *command_get(void) { @@ -363,27 +349,15 @@ struct cmd *command_get(void) { return NULL; } - command->id = ++cmd_id; command->result = CMD_PARSE_OK; command->errstr = NULL; - command->type = CMD_UNKNOWN; command->cmd = NULL; command->clen = 0; - command->keys = NULL; - command->narg = 0; - command->quit = 0; - command->noforward = 0; + command->key.start = NULL; + command->key.len = 0; command->slot_num = -1; - command->frag_seq = NULL; - command->reply = NULL; command->node_addr = NULL; - command->keys = vkarray_create(1, sizeof(struct keypos)); - if (command->keys == NULL) { - vk_free(command); - return NULL; - } - return command; } @@ -402,19 +376,6 @@ void command_destroy(struct cmd *command) { command->errstr = NULL; } - if (command->keys != NULL) { - command->keys->nelem = 0; - vkarray_destroy(command->keys); - command->keys = NULL; - } - - if (command->frag_seq != NULL) { - vk_free(command->frag_seq); - command->frag_seq = NULL; - } - - freeReplyObject(command->reply); - if (command->node_addr != NULL) { sdsfree(command->node_addr); command->node_addr = NULL; diff --git a/src/command.h b/src/command.h index eafd90a3..bc62d017 100644 --- a/src/command.h +++ b/src/command.h @@ -34,9 +34,6 @@ #include -#include "adlist.h" -#include "valkey.h" - typedef enum cmd_parse_result { CMD_PARSE_OK, /* parsing ok */ CMD_PARSE_ENOMEM, /* out of memory */ @@ -62,41 +59,24 @@ typedef enum cmd_type { } cmd_type_t; struct keypos { - char *start; /* key start pos */ - char *end; /* key end pos */ - uint32_t remain_len; /* remain length after keypos->end for more key-value - pairs in command, like mset */ + char *start; /* key start pos */ + uint32_t len; /* Length of key */ }; struct cmd { - - uint64_t id; /* command id */ - cmd_parse_result_t result; /* command parsing result */ char *errstr; /* error info when the command parse failed */ - cmd_type_t type; /* command type */ - char *cmd; uint32_t clen; /* command length */ - struct vkarray *keys; /* array of keypos, for req */ - - uint32_t narg; /* # arguments (valkey) */ - - unsigned quit : 1; /* quit request? */ - unsigned noforward : 1; /* not need forward (example: ping) */ + struct keypos key; /* First found key in command. */ /* Command destination */ int slot_num; /* Command should be sent to slot. * Set to -1 if command is sent to a given node, * or if a slot can not be found or calculated. */ char *node_addr; /* Command sent to this node address */ - - struct cmd * - *frag_seq; /* sequence of fragment command, map from keys to fragments*/ - - valkeyReply *reply; }; void valkey_parse_cmd(struct cmd *r); diff --git a/src/valkeycluster.c b/src/valkeycluster.c index 03fa592d..1ca0327e 100644 --- a/src/valkeycluster.c +++ b/src/valkeycluster.c @@ -43,7 +43,6 @@ #include "command.h" #include "dict.h" #include "valkeycluster.h" -#include "vkarray.h" #include "vkutil.h" #include "win32.h" @@ -2302,15 +2301,13 @@ static int prepareCommand(valkeyClusterContext *cc, struct cmd *command) { __valkeyClusterSetError(cc, VALKEY_ERR_PROTOCOL, command->errstr); return VALKEY_ERR; } - if (vkarray_n(command->keys) <= 0) { + if (command->key.len == 0) { __valkeyClusterSetError( cc, VALKEY_ERR_OTHER, "No keys in command(must have keys for valkey cluster mode)"); return VALKEY_ERR; } - - struct keypos *kp = vkarray_get(command->keys, 0); - command->slot_num = keyHashSlot(kp->start, kp->end - kp->start); + command->slot_num = keyHashSlot(command->key.start, command->key.len); return VALKEY_OK; } diff --git a/src/vkarray.c b/src/vkarray.c deleted file mode 100644 index 7acd40af..00000000 --- a/src/vkarray.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2015-2017, Ieshen Zheng - * Copyright (c) 2020, Nick - * Copyright (c) 2020-2021, Bjorn Svensson - * Copyright (c) 2020-2021, Viktor Söderqvist - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include - -#include "alloc.h" -#include "vkarray.h" -#include "vkutil.h" - -struct vkarray *vkarray_create(uint32_t n, size_t size) { - struct vkarray *a; - - ASSERT(n != 0 && size != 0); - - a = vk_malloc(sizeof(*a)); - if (a == NULL) { - return NULL; - } - - a->elem = vk_malloc(n * size); - if (a->elem == NULL) { - vk_free(a); - return NULL; - } - - a->nelem = 0; - a->size = size; - a->nalloc = n; - - return a; -} - -void vkarray_destroy(struct vkarray *a) { - vkarray_deinit(a); - vk_free(a); -} - -void vkarray_deinit(struct vkarray *a) { - ASSERT(a->nelem == 0); - - vk_free(a->elem); - a->elem = NULL; -} - -uint32_t vkarray_idx(struct vkarray *a, void *elem) { - uint8_t *p, *q; - uint32_t off, idx; - - ASSERT(elem >= a->elem); - - p = a->elem; - q = elem; - off = (uint32_t)(q - p); - - ASSERT(off % (uint32_t)a->size == 0); - - idx = off / (uint32_t)a->size; - - return idx; -} - -void *vkarray_push(struct vkarray *a) { - void *elem, *new; - size_t size; - - if (a->nelem == a->nalloc) { - - /* the array is full; allocate new array */ - size = a->size * a->nalloc; - new = vk_realloc(a->elem, 2 * size); - if (new == NULL) { - return NULL; - } - - a->elem = new; - a->nalloc *= 2; - } - - elem = (uint8_t *)a->elem + a->size * a->nelem; - a->nelem++; - - return elem; -} - -void *vkarray_pop(struct vkarray *a) { - void *elem; - - ASSERT(a->nelem != 0); - - a->nelem--; - elem = (uint8_t *)a->elem + a->size * a->nelem; - - return elem; -} - -void *vkarray_get(struct vkarray *a, uint32_t idx) { - void *elem; - - ASSERT(a->nelem != 0); - ASSERT(idx < a->nelem); - - elem = (uint8_t *)a->elem + (a->size * idx); - - return elem; -} - -void *vkarray_top(struct vkarray *a) { - ASSERT(a->nelem != 0); - - return vkarray_get(a, a->nelem - 1); -} - -void vkarray_swap(struct vkarray *a, struct vkarray *b) { - struct vkarray tmp; - - tmp = *a; - *a = *b; - *b = tmp; -} - -/* - * Sort nelem elements of the array in ascending order based on the - * compare comparator. - */ -void vkarray_sort(struct vkarray *a, vkarray_compare_t compare) { - ASSERT(a->nelem != 0); - - qsort(a->elem, a->nelem, a->size, compare); -} - -/* - * Calls the func once for each element in the array as long as func returns - * success. On failure short-circuits and returns the error status. - */ -int vkarray_each(struct vkarray *a, vkarray_each_t func, void *data) { - uint32_t i, nelem; - - ASSERT(vkarray_n(a) != 0); - ASSERT(func != NULL); - - for (i = 0, nelem = vkarray_n(a); i < nelem; i++) { - void *elem = vkarray_get(a, i); - rstatus_t status; - - status = func(elem, data); - if (status != VK_OK) { - return status; - } - } - - return VK_OK; -} diff --git a/src/vkarray.h b/src/vkarray.h deleted file mode 100644 index 4f5f02ed..00000000 --- a/src/vkarray.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2015-2017, Ieshen Zheng - * Copyright (c) 2020-2021, Bjorn Svensson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Redis nor the names of its contributors may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __VKARRAY_H_ -#define __VKARRAY_H_ - -#include - -typedef int (*vkarray_compare_t)(const void *, const void *); -typedef int (*vkarray_each_t)(void *, void *); - -struct vkarray { - uint32_t nelem; /* # element */ - void *elem; /* element */ - size_t size; /* element size */ - uint32_t nalloc; /* # allocated element */ -}; - -#define null_vkarray \ - { 0, NULL, 0, 0 } - -static inline void vkarray_null(struct vkarray *a) { - a->nelem = 0; - a->elem = NULL; - a->size = 0; - a->nalloc = 0; -} - -static inline void vkarray_set(struct vkarray *a, void *elem, size_t size, - uint32_t nalloc) { - a->nelem = 0; - a->elem = elem; - a->size = size; - a->nalloc = nalloc; -} - -static inline uint32_t vkarray_n(const struct vkarray *a) { return a->nelem; } - -struct vkarray *vkarray_create(uint32_t n, size_t size); -void vkarray_destroy(struct vkarray *a); -void vkarray_deinit(struct vkarray *a); - -uint32_t vkarray_idx(struct vkarray *a, void *elem); -void *vkarray_push(struct vkarray *a); -void *vkarray_pop(struct vkarray *a); -void *vkarray_get(struct vkarray *a, uint32_t idx); -void *vkarray_top(struct vkarray *a); -void vkarray_swap(struct vkarray *a, struct vkarray *b); -void vkarray_sort(struct vkarray *a, vkarray_compare_t compare); -int vkarray_each(struct vkarray *a, vkarray_each_t func, void *data); - -#endif diff --git a/src/vkutil.h b/src/vkutil.h index 06f7d0f3..2d289946 100644 --- a/src/vkutil.h +++ b/src/vkutil.h @@ -36,12 +36,9 @@ #include #include -#define VK_OK 0 #define VK_ERROR -1 #define VK_EAGAIN -2 -typedef int rstatus_t; /* return type */ - #define VK_INET4_ADDRSTRLEN (sizeof("255.255.255.255") - 1) #define VK_INET6_ADDRSTRLEN \ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1) diff --git a/tests/ct_out_of_memory_handling.c b/tests/ct_out_of_memory_handling.c index c1fa837d..64e5618f 100644 --- a/tests/ct_out_of_memory_handling.c +++ b/tests/ct_out_of_memory_handling.c @@ -184,14 +184,14 @@ void test_alloc_failure_handling(void) { valkeyReply *reply; const char *cmd = "SET key value"; - for (int i = 0; i < 35; ++i) { + for (int i = 0; i < 33; ++i) { prepare_allocation_test(cc, i); reply = (valkeyReply *)valkeyClusterCommand(cc, cmd); assert(reply == NULL); ASSERT_STR_EQ(cc->errstr, "Out of memory"); } - prepare_allocation_test(cc, 35); + prepare_allocation_test(cc, 33); reply = (valkeyReply *)valkeyClusterCommand(cc, cmd); CHECK_REPLY_OK(cc, reply); freeReplyObject(reply); @@ -225,7 +225,7 @@ void test_alloc_failure_handling(void) { valkeyReply *reply; const char *cmd = "SET foo one"; - for (int i = 0; i < 36; ++i) { + for (int i = 0; i < 34; ++i) { prepare_allocation_test(cc, i); result = valkeyClusterAppendCommand(cc, cmd); assert(result == VALKEY_ERR); @@ -237,7 +237,7 @@ void test_alloc_failure_handling(void) { for (int i = 0; i < 4; ++i) { // Appended command lost when receiving error from valkey // during a GetReply, needs a new append for each test loop - prepare_allocation_test(cc, 36); + prepare_allocation_test(cc, 34); result = valkeyClusterAppendCommand(cc, cmd); assert(result == VALKEY_OK); @@ -249,7 +249,7 @@ void test_alloc_failure_handling(void) { valkeyClusterReset(cc); } - prepare_allocation_test(cc, 36); + prepare_allocation_test(cc, 34); result = valkeyClusterAppendCommand(cc, cmd); assert(result == VALKEY_OK); @@ -269,7 +269,7 @@ void test_alloc_failure_handling(void) { assert(node); // OOM failing appends - for (int i = 0; i < 37; ++i) { + for (int i = 0; i < 35; ++i) { prepare_allocation_test(cc, i); result = valkeyClusterAppendCommandToNode(cc, node, cmd); assert(result == VALKEY_ERR); @@ -281,7 +281,7 @@ void test_alloc_failure_handling(void) { // OOM failing GetResults for (int i = 0; i < 4; ++i) { // First a successful append - prepare_allocation_test(cc, 37); + prepare_allocation_test(cc, 35); result = valkeyClusterAppendCommandToNode(cc, node, cmd); assert(result == VALKEY_OK); @@ -294,7 +294,7 @@ void test_alloc_failure_handling(void) { } // Successful append and GetReply - prepare_allocation_test(cc, 37); + prepare_allocation_test(cc, 35); result = valkeyClusterAppendCommandToNode(cc, node, cmd); assert(result == VALKEY_OK); @@ -354,7 +354,7 @@ void test_alloc_failure_handling(void) { freeReplyObject(reply); /* Test ASK reply handling with OOM */ - for (int i = 0; i < 49; ++i) { + for (int i = 0; i < 47; ++i) { prepare_allocation_test(cc, i); reply = valkeyClusterCommand(cc, "GET foo"); assert(reply == NULL); @@ -362,7 +362,7 @@ void test_alloc_failure_handling(void) { } /* Test ASK reply handling without OOM */ - prepare_allocation_test(cc, 49); + prepare_allocation_test(cc, 47); reply = valkeyClusterCommand(cc, "GET foo"); CHECK_REPLY_STR(cc, reply, "one"); freeReplyObject(reply); @@ -383,7 +383,7 @@ void test_alloc_failure_handling(void) { freeReplyObject(reply); /* Test MOVED reply handling with OOM */ - for (int i = 0; i < 33; ++i) { + for (int i = 0; i < 31; ++i) { prepare_allocation_test(cc, i); reply = valkeyClusterCommand(cc, "GET foo"); assert(reply == NULL); @@ -391,7 +391,7 @@ void test_alloc_failure_handling(void) { } /* Test MOVED reply handling without OOM */ - prepare_allocation_test(cc, 33); + prepare_allocation_test(cc, 31); reply = valkeyClusterCommand(cc, "GET foo"); CHECK_REPLY_STR(cc, reply, "one"); freeReplyObject(reply); @@ -539,18 +539,18 @@ void test_alloc_failure_handling_async(void) { { const char *cmd1 = "SET foo one"; - for (int i = 0; i < 37; ++i) { + for (int i = 0; i < 35; ++i) { prepare_allocation_test_async(acc, i); result = valkeyClusterAsyncCommand(acc, commandCallback, &r1, cmd1); assert(result == VALKEY_ERR); - if (i != 35) { + if (i != 33) { ASSERT_STR_EQ(acc->errstr, "Out of memory"); } else { ASSERT_STR_EQ(acc->errstr, "Failed to attach event adapter"); } } - prepare_allocation_test_async(acc, 37); + prepare_allocation_test_async(acc, 35); result = valkeyClusterAsyncCommand(acc, commandCallback, &r1, cmd1); ASSERT_MSG(result == VALKEY_OK, acc->errstr); } @@ -561,16 +561,16 @@ void test_alloc_failure_handling_async(void) { { const char *cmd2 = "GET foo"; - for (int i = 0; i < 14; ++i) { + for (int i = 0; i < 12; ++i) { prepare_allocation_test_async(acc, i); result = valkeyClusterAsyncCommand(acc, commandCallback, &r2, cmd2); assert(result == VALKEY_ERR); ASSERT_STR_EQ(acc->errstr, "Out of memory"); } - /* Skip iteration 14, errstr not set by libvalkey when valkeyFormatSdsCommandArgv() fails. */ + /* Skip iteration 12, errstr not set by libvalkey when valkeyFormatSdsCommandArgv() fails. */ - prepare_allocation_test_async(acc, 15); + prepare_allocation_test_async(acc, 13); result = valkeyClusterAsyncCommand(acc, commandCallback, &r2, cmd2); ASSERT_MSG(result == VALKEY_OK, acc->errstr); } diff --git a/tests/ut_parse_cmd.c b/tests/ut_parse_cmd.c index 8c3532d3..d9637dde 100644 --- a/tests/ut_parse_cmd.c +++ b/tests/ut_parse_cmd.c @@ -3,47 +3,34 @@ #include "command.h" #include "test_utils.h" #include "valkeycluster.h" -#include "vkarray.h" #include "win32.h" #include #include #include #include -/* Helper for the macro ASSERT_KEYS below. */ -void check_keys(char **keys, int numkeys, struct cmd *command, char *file, - int line) { +/* Helper for the macro ASSERT_KEY below. */ +void check_key(char *key, struct cmd *command, char *file, int line) { if (command->result != CMD_PARSE_OK) { fprintf(stderr, "%s:%d: Command parsing failed: %s\n", file, line, command->errstr); assert(0); } - int actual_numkeys = (int)vkarray_n(command->keys); - if (actual_numkeys != numkeys) { - fprintf(stderr, "%s:%d: Expected %d keys but got %d\n", file, line, - numkeys, actual_numkeys); - assert(actual_numkeys == numkeys); - } - for (int i = 0; i < numkeys; i++) { - struct keypos *kpos = vkarray_get(command->keys, i); - char *actual_key = kpos->start; - int actual_keylen = (int)(kpos->end - kpos->start); - if ((int)strlen(keys[i]) != actual_keylen || - strncmp(keys[i], actual_key, actual_keylen)) { - fprintf(stderr, - "%s:%d: Expected key %d to be \"%s\" but got \"%.*s\"\n", - file, line, i, keys[i], actual_keylen, actual_key); - assert(0); - } + char *actual_key = command->key.start; + int actual_keylen = command->key.len; + if ((int)strlen(key) != actual_keylen || + strncmp(key, actual_key, actual_keylen)) { + fprintf(stderr, + "%s:%d: Expected key to be \"%s\" but got \"%.*s\"\n", + file, line, key, actual_keylen, actual_key); + assert(0); } } -/* Checks that a command (struct cmd *) has the given keys (strings). */ -#define ASSERT_KEYS(command, ...) \ - do { \ - char *expected_keys[] = {__VA_ARGS__}; \ - size_t n = sizeof(expected_keys) / sizeof(char *); \ - check_keys(expected_keys, n, command, __FILE__, __LINE__); \ +/* Checks that a command (struct cmd *) has the given key (string). */ +#define ASSERT_KEY(command, key) \ + do { \ + check_key(key, command, __FILE__, __LINE__); \ } while (0) void test_valkey_parse_error_nonresp(void) { @@ -64,7 +51,7 @@ void test_valkey_parse_cmd_get(void) { c->clen = len; valkey_parse_cmd(c); ASSERT_MSG(c->result == CMD_PARSE_OK, "Parse not OK"); - ASSERT_KEYS(c, "foo"); + ASSERT_KEY(c, "foo"); command_destroy(c); } @@ -75,7 +62,7 @@ void test_valkey_parse_cmd_mset(void) { c->clen = len; valkey_parse_cmd(c); ASSERT_MSG(c->result == CMD_PARSE_OK, "Parse not OK"); - ASSERT_KEYS(c, "foo"); + ASSERT_KEY(c, "foo"); command_destroy(c); } @@ -86,7 +73,7 @@ void test_valkey_parse_cmd_eval_1(void) { c->clen = len; valkey_parse_cmd(c); ASSERT_MSG(c->result == CMD_PARSE_OK, "Parse not OK"); - ASSERT_KEYS(c, "foo"); + ASSERT_KEY(c, "foo"); command_destroy(c); } @@ -97,7 +84,7 @@ void test_valkey_parse_cmd_eval_0(void) { c->clen = len; valkey_parse_cmd(c); ASSERT_MSG(c->result == CMD_PARSE_OK, "Parse not OK"); - ASSERT_MSG(vkarray_n(c->keys) == 0, "Nonzero number of keys"); + ASSERT_MSG(c->key.len == 0, "Unexpected key found"); command_destroy(c); } @@ -132,7 +119,7 @@ void test_valkey_parse_cmd_xgroup_destroy_ok(void) { ASSERT_MSG(len >= 0, "Format command error"); c->clen = len; valkey_parse_cmd(c); - ASSERT_KEYS(c, "mystream"); + ASSERT_KEY(c, "mystream"); command_destroy(c); } @@ -145,7 +132,7 @@ void test_valkey_parse_cmd_xreadgroup_ok(void) { ASSERT_MSG(len >= 0, "Format command error"); c->clen = len; valkey_parse_cmd(c); - ASSERT_KEYS(c, "mystream"); + ASSERT_KEY(c, "mystream"); command_destroy(c); } @@ -156,7 +143,7 @@ void test_valkey_parse_cmd_xread_ok(void) { ASSERT_MSG(len >= 0, "Format command error"); c->clen = len; valkey_parse_cmd(c); - ASSERT_KEYS(c, "mystream"); + ASSERT_KEY(c, "mystream"); command_destroy(c); } @@ -168,7 +155,7 @@ void test_valkey_parse_cmd_restore_ok(void) { ASSERT_MSG(len >= 0, "Format command error"); c->clen = len; valkey_parse_cmd(c); - ASSERT_KEYS(c, "k"); + ASSERT_KEY(c, "k"); command_destroy(c); } @@ -180,7 +167,7 @@ void test_valkey_parse_cmd_restore_asking_ok(void) { ASSERT_MSG(len >= 0, "Format command error"); c->clen = len; valkey_parse_cmd(c); - ASSERT_KEYS(c, "k"); + ASSERT_KEY(c, "k"); command_destroy(c); } @@ -192,7 +179,7 @@ void test_valkey_parse_cmd_georadius_ro_ok(void) { ASSERT_MSG(len >= 0, "Format command error"); c->clen = len; valkey_parse_cmd(c); - ASSERT_KEYS(c, "k"); + ASSERT_KEY(c, "k"); command_destroy(c); }