Migrate kvstore.c unit tests to new test framework. (#446)

This PR migrates all tests related to kvstore into new test framework as
part of the parent issue https://github.com/valkey-io/valkey/issues/428.

---------

Signed-off-by: Karthick Ariyaratnam <karthyuom@gmail.com>
Signed-off-by: Madelyn Olson <madelyneolson@gmail.com>
Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
This commit is contained in:
Karthick Ariyaratnam 2024-05-07 19:49:24 -04:00 committed by GitHub
parent 1aca85e3de
commit 4e944cedee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 212 additions and 152 deletions

View File

@ -865,150 +865,3 @@ int kvstoreDictDelete(kvstore *kvs, int didx, const void *key) {
}
return ret;
}
#ifdef SERVER_TEST
#include <stdio.h>
#include "testhelp.h"
#define TEST(name) printf("test — %s\n", name);
uint64_t hashTestCallback(const void *key) {
return dictGenHashFunction((unsigned char*)key, strlen((char*)key));
}
void freeTestCallback(dict *d, void *val) {
UNUSED(d);
zfree(val);
}
dictType KvstoreDictTestType = {
hashTestCallback,
NULL,
NULL,
NULL,
freeTestCallback,
NULL,
NULL
};
char *stringFromInt(int value) {
char buf[32];
int len;
char *s;
len = snprintf(buf, sizeof(buf), "%d",value);
s = zmalloc(len+1);
memcpy(s, buf, len);
s[len] = '\0';
return s;
}
/* ./valkey-server test kvstore */
int kvstoreTest(int argc, char **argv, int flags) {
UNUSED(argc);
UNUSED(argv);
UNUSED(flags);
int i;
void *key;
dictEntry *de;
kvstoreIterator *kvs_it;
kvstoreDictIterator *kvs_di;
int didx = 0;
int curr_slot = 0;
kvstore *kvs1 = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND);
kvstore *kvs2 = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND | KVSTORE_FREE_EMPTY_DICTS);
TEST("Add 16 keys") {
for (i = 0; i < 16; i++) {
de = kvstoreDictAddRaw(kvs1, didx, stringFromInt(i), NULL);
assert(de != NULL);
de = kvstoreDictAddRaw(kvs2, didx, stringFromInt(i), NULL);
assert(de != NULL);
}
assert(kvstoreDictSize(kvs1, didx) == 16);
assert(kvstoreSize(kvs1) == 16);
assert(kvstoreDictSize(kvs2, didx) == 16);
assert(kvstoreSize(kvs2) == 16);
}
TEST("kvstoreIterator case 1: removing all keys does not delete the empty dict") {
kvs_it = kvstoreIteratorInit(kvs1);
while((de = kvstoreIteratorNext(kvs_it)) != NULL) {
curr_slot = kvstoreIteratorGetCurrentDictIndex(kvs_it);
key = dictGetKey(de);
assert(kvstoreDictDelete(kvs1, curr_slot, key) == DICT_OK);
}
kvstoreIteratorRelease(kvs_it);
dict *d = kvstoreGetDict(kvs1, didx);
assert(d != NULL);
assert(kvstoreDictSize(kvs1, didx) == 0);
assert(kvstoreSize(kvs1) == 0);
}
TEST("kvstoreIterator case 2: removing all keys will delete the empty dict") {
kvs_it = kvstoreIteratorInit(kvs2);
while((de = kvstoreIteratorNext(kvs_it)) != NULL) {
curr_slot = kvstoreIteratorGetCurrentDictIndex(kvs_it);
key = dictGetKey(de);
assert(kvstoreDictDelete(kvs2, curr_slot, key) == DICT_OK);
}
kvstoreIteratorRelease(kvs_it);
/* Make sure the dict was removed from the rehashing list. */
while (kvstoreIncrementallyRehash(kvs2, 1000)) {}
dict *d = kvstoreGetDict(kvs2, didx);
assert(d == NULL);
assert(kvstoreDictSize(kvs2, didx) == 0);
assert(kvstoreSize(kvs2) == 0);
}
TEST("Add 16 keys again") {
for (i = 0; i < 16; i++) {
de = kvstoreDictAddRaw(kvs1, didx, stringFromInt(i), NULL);
assert(de != NULL);
de = kvstoreDictAddRaw(kvs2, didx, stringFromInt(i), NULL);
assert(de != NULL);
}
assert(kvstoreDictSize(kvs1, didx) == 16);
assert(kvstoreSize(kvs1) == 16);
assert(kvstoreDictSize(kvs2, didx) == 16);
assert(kvstoreSize(kvs2) == 16);
}
TEST("kvstoreDictIterator case 1: removing all keys does not delete the empty dict") {
kvs_di = kvstoreGetDictSafeIterator(kvs1, didx);
while((de = kvstoreDictIteratorNext(kvs_di)) != NULL) {
key = dictGetKey(de);
assert(kvstoreDictDelete(kvs1, didx, key) == DICT_OK);
}
kvstoreReleaseDictIterator(kvs_di);
dict *d = kvstoreGetDict(kvs1, didx);
assert(d != NULL);
assert(kvstoreDictSize(kvs1, didx) == 0);
assert(kvstoreSize(kvs1) == 0);
}
TEST("kvstoreDictIterator case 2: removing all keys will delete the empty dict") {
kvs_di = kvstoreGetDictSafeIterator(kvs2, didx);
while((de = kvstoreDictIteratorNext(kvs_di)) != NULL) {
key = dictGetKey(de);
assert(kvstoreDictDelete(kvs2, didx, key) == DICT_OK);
}
kvstoreReleaseDictIterator(kvs_di);
dict *d = kvstoreGetDict(kvs2, didx);
assert(d == NULL);
assert(kvstoreDictSize(kvs2, didx) == 0);
assert(kvstoreSize(kvs2) == 0);
}
kvstoreRelease(kvs1);
kvstoreRelease(kvs2);
return 0;
}
#endif

View File

@ -72,8 +72,4 @@ dictEntry *kvstoreDictTwoPhaseUnlinkFind(kvstore *kvs, int didx, const void *key
void kvstoreDictTwoPhaseUnlinkFree(kvstore *kvs, int didx, dictEntry *he, dictEntry **plink, int table_index);
int kvstoreDictDelete(kvstore *kvs, int didx, const void *key);
#ifdef SERVER_TEST
int kvstoreTest(int argc, char *argv[], int flags);
#endif
#endif /* DICTARRAY_H_ */

View File

@ -6911,7 +6911,6 @@ struct serverTest {
{"sds", sdsTest},
{"dict", dictTest},
{"listpack", listpackTest},
{"kvstore", kvstoreTest},
};
serverTestProc *getTestProcByName(const char *name) {
int numtests = sizeof(serverTests)/sizeof(struct serverTest);

View File

@ -16,6 +16,11 @@ int test_intsetUpgradeFromint16Toint64(int argc, char **argv, int flags);
int test_intsetUpgradeFromint32Toint64(int argc, char **argv, int flags);
int test_intsetStressLookups(int argc, char **argv, int flags);
int test_intsetStressAddDelete(int argc, char **argv, int flags);
int test_kvstoreAdd16Keys(int argc, char **argv, int flags);
int test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict(int argc, char **argv, int flags);
int test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict(int argc, char **argv, int flags);
int test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict(int argc, char **argv, int flags);
int test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict(int argc, char **argv, int flags);
int test_string2ll(int argc, char **argv, int flags);
int test_string2l(int argc, char **argv, int flags);
int test_ll2string(int argc, char **argv, int flags);
@ -26,6 +31,7 @@ int test_reclaimFilePageCache(int argc, char **argv, int flags);
unitTest __test_crc64_c[] = {{"test_crc64", test_crc64}, {NULL, NULL}};
unitTest __test_crc64combine_c[] = {{"test_crc64combine", test_crc64combine}, {NULL, NULL}};
unitTest __test_intset_c[] = {{"test_intsetValueEncodings", test_intsetValueEncodings}, {"test_intsetBasicAdding", test_intsetBasicAdding}, {"test_intsetLargeNumberRandomAdd", test_intsetLargeNumberRandomAdd}, {"test_intsetUpgradeFromint16Toint32", test_intsetUpgradeFromint16Toint32}, {"test_intsetUpgradeFromint16Toint64", test_intsetUpgradeFromint16Toint64}, {"test_intsetUpgradeFromint32Toint64", test_intsetUpgradeFromint32Toint64}, {"test_intsetStressLookups", test_intsetStressLookups}, {"test_intsetStressAddDelete", test_intsetStressAddDelete}, {NULL, NULL}};
unitTest __test_kvstore_c[] = {{"test_kvstoreAdd16Keys", test_kvstoreAdd16Keys}, {"test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict", test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict}, {"test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict", test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict}, {"test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict", test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict}, {"test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict", test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict}, {NULL, NULL}};
unitTest __test_util_c[] = {{"test_string2ll", test_string2ll}, {"test_string2l", test_string2l}, {"test_ll2string", test_ll2string}, {"test_ld2string", test_ld2string}, {"test_fixedpoint_d2string", test_fixedpoint_d2string}, {"test_reclaimFilePageCache", test_reclaimFilePageCache}, {NULL, NULL}};
struct unitTestSuite {
@ -35,5 +41,6 @@ struct unitTestSuite {
{"test_crc64.c", __test_crc64_c},
{"test_crc64combine.c", __test_crc64combine_c},
{"test_intset.c", __test_intset_c},
{"test_kvstore.c", __test_kvstore_c},
{"test_util.c", __test_util_c},
};

205
src/unit/test_kvstore.c Normal file
View File

@ -0,0 +1,205 @@
#include "../kvstore.c"
#undef UNUSED
#include "test_help.h"
uint64_t hashTestCallback(const void *key) {
return dictGenHashFunction((unsigned char*)key, strlen((char*)key));
}
void freeTestCallback(dict *d, void *val) {
UNUSED(d);
zfree(val);
}
dictType KvstoreDictTestType = {
hashTestCallback,
NULL,
NULL,
NULL,
freeTestCallback,
NULL,
NULL
};
char *stringFromInt(int value) {
char buf[32];
int len;
char *s;
len = snprintf(buf, sizeof(buf), "%d",value);
s = zmalloc(len+1);
memcpy(s, buf, len);
s[len] = '\0';
return s;
}
int test_kvstoreAdd16Keys(int argc, char **argv, int flags) {
UNUSED(argc);
UNUSED(argv);
UNUSED(flags);
int i;
dictEntry *de;
int didx = 0;
kvstore *kvs1 = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND);
kvstore *kvs2 = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND | KVSTORE_FREE_EMPTY_DICTS);
for (i = 0; i < 16; i++) {
de = kvstoreDictAddRaw(kvs1, didx, stringFromInt(i), NULL);
TEST_ASSERT(de != NULL);
de = kvstoreDictAddRaw(kvs2, didx, stringFromInt(i), NULL);
TEST_ASSERT(de != NULL);
}
TEST_ASSERT(kvstoreDictSize(kvs1, didx) == 16);
TEST_ASSERT(kvstoreSize(kvs1) == 16);
TEST_ASSERT(kvstoreDictSize(kvs2, didx) == 16);
TEST_ASSERT(kvstoreSize(kvs2) == 16);
kvstoreRelease(kvs1);
kvstoreRelease(kvs2);
return 0;
}
int test_kvstoreIteratorRemoveAllKeysNoDeleteEmptyDict(int argc, char **argv, int flags) {
UNUSED(argc);
UNUSED(argv);
UNUSED(flags);
int i;
void *key;
dictEntry *de;
kvstoreIterator *kvs_it;
int didx = 0;
int curr_slot = 0;
kvstore *kvs1 = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND);
for (i = 0; i < 16; i++) {
de = kvstoreDictAddRaw(kvs1, didx, stringFromInt(i), NULL);
TEST_ASSERT(de != NULL);
}
kvs_it = kvstoreIteratorInit(kvs1);
while((de = kvstoreIteratorNext(kvs_it)) != NULL) {
curr_slot = kvstoreIteratorGetCurrentDictIndex(kvs_it);
key = dictGetKey(de);
TEST_ASSERT(kvstoreDictDelete(kvs1, curr_slot, key) == DICT_OK);
}
kvstoreIteratorRelease(kvs_it);
dict *d = kvstoreGetDict(kvs1, didx);
TEST_ASSERT(d != NULL);
TEST_ASSERT(kvstoreDictSize(kvs1, didx) == 0);
TEST_ASSERT(kvstoreSize(kvs1) == 0);
kvstoreRelease(kvs1);
return 0;
}
int test_kvstoreIteratorRemoveAllKeysDeleteEmptyDict(int argc, char **argv, int flags) {
UNUSED(argc);
UNUSED(argv);
UNUSED(flags);
int i;
void *key;
dictEntry *de;
kvstoreIterator *kvs_it;
int didx = 0;
int curr_slot = 0;
kvstore *kvs2 = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND | KVSTORE_FREE_EMPTY_DICTS);
for (i = 0; i < 16; i++) {
de = kvstoreDictAddRaw(kvs2, didx, stringFromInt(i), NULL);
TEST_ASSERT(de != NULL);
}
kvs_it = kvstoreIteratorInit(kvs2);
while((de = kvstoreIteratorNext(kvs_it)) != NULL) {
curr_slot = kvstoreIteratorGetCurrentDictIndex(kvs_it);
key = dictGetKey(de);
TEST_ASSERT(kvstoreDictDelete(kvs2, curr_slot, key) == DICT_OK);
}
kvstoreIteratorRelease(kvs_it);
/* Make sure the dict was removed from the rehashing list. */
while (kvstoreIncrementallyRehash(kvs2, 1000)) {}
dict *d = kvstoreGetDict(kvs2, didx);
TEST_ASSERT(d == NULL);
TEST_ASSERT(kvstoreDictSize(kvs2, didx) == 0);
TEST_ASSERT(kvstoreSize(kvs2) == 0);
kvstoreRelease(kvs2);
return 0;
}
int test_kvstoreDictIteratorRemoveAllKeysNoDeleteEmptyDict(int argc, char **argv, int flags) {
UNUSED(argc);
UNUSED(argv);
UNUSED(flags);
int i;
void *key;
dictEntry *de;
kvstoreDictIterator *kvs_di;
int didx = 0;
kvstore *kvs1 = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND);
for (i = 0; i < 16; i++) {
de = kvstoreDictAddRaw(kvs1, didx, stringFromInt(i), NULL);
TEST_ASSERT(de != NULL);
}
kvs_di = kvstoreGetDictSafeIterator(kvs1, didx);
while((de = kvstoreDictIteratorNext(kvs_di)) != NULL) {
key = dictGetKey(de);
TEST_ASSERT(kvstoreDictDelete(kvs1, didx, key) == DICT_OK);
}
kvstoreReleaseDictIterator(kvs_di);
dict *d = kvstoreGetDict(kvs1, didx);
TEST_ASSERT(d != NULL);
TEST_ASSERT(kvstoreDictSize(kvs1, didx) == 0);
TEST_ASSERT(kvstoreSize(kvs1) == 0);
kvstoreRelease(kvs1);
return 0;
}
int test_kvstoreDictIteratorRemoveAllKeysDeleteEmptyDict(int argc, char **argv, int flags) {
UNUSED(argc);
UNUSED(argv);
UNUSED(flags);
int i;
void *key;
dictEntry *de;
kvstoreDictIterator *kvs_di;
int didx = 0;
kvstore *kvs2 = kvstoreCreate(&KvstoreDictTestType, 0, KVSTORE_ALLOCATE_DICTS_ON_DEMAND | KVSTORE_FREE_EMPTY_DICTS);
for (i = 0; i < 16; i++) {
de = kvstoreDictAddRaw(kvs2, didx, stringFromInt(i), NULL);
TEST_ASSERT(de != NULL);
}
kvs_di = kvstoreGetDictSafeIterator(kvs2, didx);
while((de = kvstoreDictIteratorNext(kvs_di)) != NULL) {
key = dictGetKey(de);
TEST_ASSERT(kvstoreDictDelete(kvs2, didx, key) == DICT_OK);
}
kvstoreReleaseDictIterator(kvs_di);
dict *d = kvstoreGetDict(kvs2, didx);
TEST_ASSERT(d == NULL);
TEST_ASSERT(kvstoreDictSize(kvs2, didx) == 0);
TEST_ASSERT(kvstoreSize(kvs2) == 0);
kvstoreRelease(kvs2);
return 0;
}