TEST simple_concurrency() { delete_file(); rliteContext *context1 = rliteConnect(FILEPATH, 0); rliteContext *context2 = rliteConnect(FILEPATH, 0); rliteReply* reply; size_t argvlen[100]; { char* argv[100] = {"GET", "key", NULL}; reply = rliteCommandArgv(context1, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_NIL(reply); rliteFreeReplyObject(reply); } { char* argv[100] = {"set", "key", "value", NULL}; reply = rliteCommandArgv(context2, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_STATUS(reply, "OK", 2); rliteFreeReplyObject(reply); } { char* argv[100] = {"GET", "key", NULL}; reply = rliteCommandArgv(context1, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_STR(reply, "value", 5); rliteFreeReplyObject(reply); } rliteFree(context1); rliteFree(context2); unlink(FILEPATH); PASS(); }
TEST test_sdiffstore() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; char *m1 = "mymember", *m2 = "member2", *s1 = "myset", *s2 = "myset2", *t = "target"; sadd(context, s1, m1); sadd(context, s1, m2); sadd(context, s2, m1); sadd(context, s2, "meh"); rliteReply* reply; { char* argv[100] = {"sdiffstore", t, s1, s2, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"smembers", t, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 1); EXPECT_REPLY_STR(reply->element[0], m2, strlen(m2)); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
TEST test_scard() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; if (randomSadd(context, "myset", 5) != 0) { return 1; } rliteReply* reply; char* argv[100] = {"scard", "myset", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 5); rliteFreeReplyObject(reply); if (randomSadd(context, "myset", 3) != 0) { return 1; } char* argv2[100] = {"scard", "myset", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv2, argvlen), argv2, argvlen); EXPECT_REPLY_INTEGER(reply, 8); rliteFreeReplyObject(reply); rliteFree(context); return 0; }
TEST test_sort_alpha() { rliteContext *context = rliteConnect(":memory:", 0); rliteReply* reply; size_t argvlen[100]; { char* argv[100] = {"sadd", "key", "31", "12", "41", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 3); rliteFreeReplyObject(reply); } { char* argv[100] = {"sort", "key", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 3); EXPECT_REPLY_STR(reply->element[0], "12", 2); EXPECT_REPLY_STR(reply->element[1], "31", 2); EXPECT_REPLY_STR(reply->element[2], "41", 2); rliteFreeReplyObject(reply); } rliteFree(context); PASS(); }
TEST test_sort_get_pattern_get_pound() { rliteContext *context = rliteConnect(":memory:", 0); rliteReply* reply; size_t argvlen[100]; { char* argv[100] = {"rpush", "key", "3", "1", "2", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 3); rliteFreeReplyObject(reply); } { char* argv[100] = {"sort", "key", "GET", "#", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 3); EXPECT_REPLY_STR(reply->element[0], "1", 1); EXPECT_REPLY_STR(reply->element[1], "2", 1); EXPECT_REPLY_STR(reply->element[2], "3", 1); rliteFreeReplyObject(reply); } rliteFree(context); PASS(); }
TEST test_srem() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; char *m1 = "mymember", *m2 = "member2"; sadd(context, "myset", m1); sadd(context, "myset", m2); rliteReply* reply; { char* argv[100] = {"srem", "myset", m1, "other", m2, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 2); rliteFreeReplyObject(reply); } { char* argv[100] = {"exists", "mykey", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 0); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
TEST test_echo_oom() { size_t argvlen[2]; char* argv[2]; rliteReply* reply; argvlen[0] = 4; argv[0] = "echo"; argvlen[1] = 11; argv[1] = "hello world"; rliteContext *context = rliteConnect(":memory:", 0); int i; for (i = 1;;i++) { test_mode = 1; test_mode_counter = i; reply = rliteCommandArgv(context, 2, argv, argvlen); if (reply != NULL) { if (i == 1) { fprintf(stderr, "No OOM triggered\n"); test_mode = 0; FAIL(); } EXPECT_REPLY_STR(reply, argv[1], argvlen[1]); break; } } test_mode = 0; rliteFreeReplyObject(reply); rliteFree(context); PASS(); }
TEST test_ping_oom() { size_t argvlen[2]; char* argv[2]; rliteReply* reply; argvlen[0] = 4; argv[0] = "PING"; rliteContext *context = rliteConnect(":memory:", 0); int i; for (i = 1;;i++) { test_mode = 1; test_mode_counter = i; reply = rliteCommandArgv(context, 1, argv, argvlen); if (reply != NULL) { if (i == 1) { fprintf(stderr, "No OOM triggered\n"); test_mode = 0; FAIL(); } EXPECT_REPLY_STATUS(reply, "PONG", 4); break; } } test_mode = 0; rliteFreeReplyObject(reply); rliteFree(context); PASS(); }
TEST test_echo_wrong_arity_oom() { size_t argvlen[2]; char* argv[2]; rliteReply* reply; argvlen[0] = 4; argv[0] = "echo"; rliteContext *context = rliteConnect(":memory:", 0); int i; for (i = 1;;i++) { test_mode = 1; test_mode_counter = i; reply = rliteCommandArgv(context, 1, argv, argvlen); if (reply != NULL) { if (i == 1) { fprintf(stderr, "No OOM triggered\n"); test_mode = 0; FAIL(); } EXPECT_REPLY_ERROR(reply); const char *err = "wrong number of arguments for 'echo' command"; ASSERT_EQ(memcmp(reply->str, err, strlen(err)), 0); break; } } test_mode = 0; rliteFreeReplyObject(reply); rliteFree(context); PASS(); }
static void sadd(rliteContext* context, char *key, char *element) { rliteReply* reply; size_t argvlen[100]; char* argv[100] = {"sadd", key, element, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); rliteFreeReplyObject(reply); }
TEST test_srandmember_10_non_unique() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; long i; char *m1 = "mymember", *m2 = "member2"; sadd(context, "myset", m1); sadd(context, "myset", m2); rliteReply* reply; { char* argv[100] = {"srandmember", "myset", "-10", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 10); for (i = 0; i < 10; i++) { if (!(reply->element[i]->len == (int)strlen(m1) && memcmp(reply->element[i]->str, m1, reply->element[i]->len) == 0) && !(reply->element[i]->len == (int)strlen(m2) && memcmp(reply->element[i]->str, m2, reply->element[i]->len) == 0)) { FAIL(); } } rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
static int randomSadd(rliteContext* context, char *key, int elements) { rliteReply* reply; if (elements == 0) { elements = 3; } char* argv[100] = {"sadd", key, NULL}; int i, j, len; for (i = 0; i < elements; i++) { len = 5 + floor(((float)rand() / RAND_MAX) * 10); argv[2 + i] = malloc(sizeof(char) * len); for (j = 0; j < len - 1; j++) { argv[2 + i][j] = 'a' + (int)floor(((float)rand() / RAND_MAX) * 25); } argv[2 + i][len - 1] = 0; } size_t argvlen[100]; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, elements); rliteFreeReplyObject(reply); for (i = 0; i < elements; i++) { free(argv[2 + i]); } return 0; }
TEST test_not_null_terminated_long() { size_t argvlen[4]; char* argv[4]; rliteReply* reply; argvlen[0] = 6; argv[0] = "lrange"; argvlen[1] = 3; argv[1] = "key"; argvlen[2] = 1; argv[2] = "0"; argvlen[3] = 2; argv[3] = malloc(sizeof(char) * 4); argv[3][0] = '-'; argv[3][1] = '1'; argv[3][2] = 'z'; rliteContext *context = rliteConnect(":memory:", 0); reply = rliteCommandArgv(context, 4, argv, argvlen); ASSERT_EQ(reply->type, RLITE_REPLY_ARRAY); rliteFreeReplyObject(reply); rliteFree(context); free(argv[3]); PASS(); }
TEST threads_concurrency() { delete_file(); rliteContext *context = rliteConnect(FILEPATH, 0); pthread_t thread; pthread_create(&thread, NULL, increment, NULL); rliteReply* reply; size_t argvlen[100]; char* argv[100] = {"GET", "key", NULL}; int argc = populateArgvlen(argv, argvlen); long long val; char tmp[40]; do { reply = rliteCommandArgv(context, argc, argv, argvlen); if (reply->type == RLITE_REPLY_NIL) { val = 0; } else if (reply->type != RLITE_REPLY_STRING) { fprintf(stderr, "Expected incremented value to be a string, got %d instead on line %d\n", reply->type, __LINE__); rliteFreeReplyObject(reply); break; } else { memcpy(tmp, reply->str, reply->len); tmp[reply->len] = 0; val = strtoll(tmp, NULL, 10); } rliteFreeReplyObject(reply); } while (val < INCREMENT_LIMIT); rliteFree(context); pthread_join(thread, NULL); PASS(); }
TEST test_sortby_hash() { rliteContext *context = rliteConnect(":memory:", 0); rliteReply* reply; size_t argvlen[100]; { char* argv[100] = {"hset", "wobj_a", "weight", "1", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"hset", "wobj_b", "weight", "2", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"hset", "wobj_c", "weight", "3", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"rpush", "key", "b", "a", "c", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 3); rliteFreeReplyObject(reply); } { char* argv[100] = {"sort", "key", "by", "wobj_*->weight", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 3); EXPECT_REPLY_STR(reply->element[0], "a", 1); EXPECT_REPLY_STR(reply->element[1], "b", 1); EXPECT_REPLY_STR(reply->element[2], "c", 1); rliteFreeReplyObject(reply); } rliteFree(context); PASS(); }
TEST test_smove() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; sadd(context, "myset", "mymember"); rliteReply* reply; { char* argv[100] = {"smove", "myset", "otherset", "mymember", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"sismember", "myset", "mymember", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 0); rliteFreeReplyObject(reply); } { char* argv[100] = {"sismember", "otherset", "mymember", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 1); rliteFreeReplyObject(reply); } { char* argv[100] = {"smove", "otherset", "myset", "member2", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 0); rliteFreeReplyObject(reply); } { char* argv[100] = {"sismember", "myset", "member2", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 0); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
TEST test_spop() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; char *m1 = "mymember", *m2 = "member2"; sadd(context, "myset", m1); sadd(context, "myset", m2); rliteReply* reply; { char* argv[100] = {"spop", "myset", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); ASSERT_EQ(reply->type, RLITE_REPLY_STRING); if (!(reply->len == (int)strlen(m1) && memcmp(reply->str, m1, reply->len) == 0) && !(reply->len == (int)strlen(m2) && memcmp(reply->str, m2, reply->len) == 0)) { FAIL(); } rliteFreeReplyObject(reply); } { char* argv[100] = {"spop", "myset", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); ASSERT_EQ(reply->type, RLITE_REPLY_STRING); if (!(reply->len == (int)strlen(m1) && memcmp(reply->str, m1, reply->len) == 0) && !(reply->len == (int)strlen(m2) && memcmp(reply->str, m2, reply->len) == 0)) { FAIL(); } rliteFreeReplyObject(reply); } { char* argv[100] = {"spop", "myset", NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_NIL(reply); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }
TEST test_sadd() { rliteContext *context = rliteConnect(":memory:", 0); rliteReply* reply; char* argv[100] = {"sadd", "myset", "member1", "member2", "anothermember", "member1", NULL}; size_t argvlen[100]; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_INTEGER(reply, 3); rliteFreeReplyObject(reply); rliteFree(context); return 0; }
TEST test_ping() { size_t argvlen[2]; char* argv[2]; rliteReply* reply; argvlen[0] = 4; argv[0] = "PING"; rliteContext *context = rliteConnect(":memory:", 0); reply = rliteCommandArgv(context, 1, argv, argvlen); EXPECT_REPLY_STATUS(reply, "PONG", 4); rliteFreeReplyObject(reply); rliteFree(context); PASS(); }
static PyObject *Rlite_command(hirlite_RliteObject *self, PyObject *args) { PyObject *object; int i, argc; char **argv; size_t *argvlen; PyObject *bytes; char *str; size_t len; rliteReply *reply; argc = (int)PyTuple_Size(args); argv = malloc(sizeof(char *) * argc); if (!argv) return NULL; argvlen = malloc(sizeof(size_t) * argc); if (!argvlen) { free(argv); return NULL; } for (i = 0; i < argc; i++) { object = PyTuple_GetItem(args, i); if (PyUnicode_Check(object)) bytes = PyUnicode_AsASCIIString(object); else bytes = PyObject_Bytes(object); if (bytes == NULL) return NULL; argvlen[i] = len = PyBytes_Size(bytes); str = PyBytes_AsString(bytes); argv[i] = (char*)malloc(len+1); memcpy(argv[i], str, len); argv[i][len] = '\0'; Py_DECREF(bytes); } reply = rliteCommandArgv(self->context, argc, argv, argvlen); object = replyToPyObject(self, reply); for (i = 0; i < argc; i++) { free(argv[i]); } free(argv); free(argvlen); rliteFreeReplyObject(reply); return object; }
TEST test_echo() { size_t argvlen[2]; char* argv[2]; rliteReply* reply; argvlen[0] = 4; argv[0] = "echo"; argvlen[1] = 11; argv[1] = "hello world"; rliteContext *context = rliteConnect(":memory:", 0); reply = rliteCommandArgv(context, 2, argv, argvlen); EXPECT_REPLY_STR(reply, argv[1], argvlen[1]); rliteFreeReplyObject(reply); rliteFree(context); PASS(); }
TEST test_echo_wrong_arity() { size_t argvlen[2]; char* argv[2]; rliteReply* reply; argvlen[0] = 4; argv[0] = "echo"; rliteContext *context = rliteConnect(":memory:", 0); reply = rliteCommandArgv(context, 1, argv, argvlen); EXPECT_REPLY_ERROR(reply); const char *err = "wrong number of arguments for 'echo' command"; ASSERT_EQ(memcmp(reply->str, err, strlen(err)), 0); rliteFreeReplyObject(reply); rliteFree(context); PASS(); }
static void *increment(void *UNUSED(arg)) { rliteContext *context = rliteConnect(FILEPATH, 0); rliteReply* reply; size_t argvlen[100]; char* argv[100] = {"INCR", "key", NULL}; int argc = populateArgvlen(argv, argvlen); long long val = 0; do { reply = rliteCommandArgv(context, argc, argv, argvlen); if (reply->type != RLITE_REPLY_INTEGER || reply->integer < val) { fprintf(stderr, "Expected incremented value to be an integer greater than %lld, got %d (%lld) instead\n", val, reply->type, reply->integer); val = INCREMENT_LIMIT; // break after free } else { val = reply->integer; } rliteFreeReplyObject(reply); } while (val < INCREMENT_LIMIT); rliteFree(context); return NULL; }
TEST test_sunion() { rliteContext *context = rliteConnect(":memory:", 0); size_t argvlen[100]; char *m1 = "mymember", *m2 = "member2", *s1 = "myset", *s2 = "myset2"; sadd(context, s1, m1); sadd(context, s1, m2); sadd(context, s2, m1); sadd(context, s2, "meh"); rliteReply* reply; { char* argv[100] = {"sunion", s1, s2, NULL}; reply = rliteCommandArgv(context, populateArgvlen(argv, argvlen), argv, argvlen); EXPECT_REPLY_LEN(reply, 3); rliteFreeReplyObject(reply); } rliteFree(context); return 0; }