Migrate ziplist.c unit tests to new framework (#486)
Issue #428. Moved the SERVER_TEST block from ziplist.c into unit tests in test_ziplist.c. I left the benchmark related tasks alone in their own test, as I am not sure what to do with them. Some of the assertions are a little vague/useless, but I will try to refine them. --------- Signed-off-by: Mason Hall <hallmason17@gmail.com>
This commit is contained in:
parent
005a018db6
commit
72538622ff
@ -6929,7 +6929,6 @@ struct serverTest {
|
||||
serverTestProc *proc;
|
||||
int failed;
|
||||
} serverTests[] = {
|
||||
{"ziplist", ziplistTest},
|
||||
{"quicklist", quicklistTest},
|
||||
{"zipmap", zipmapTest},
|
||||
{"dict", dictTest},
|
||||
|
@ -30,6 +30,42 @@ int test_ll2string(int argc, char **argv, int flags);
|
||||
int test_ld2string(int argc, char **argv, int flags);
|
||||
int test_fixedpoint_d2string(int argc, char **argv, int flags);
|
||||
int test_reclaimFilePageCache(int argc, char **argv, int flags);
|
||||
int test_ziplistCreateIntList(int argc, char **argv, int flags);
|
||||
int test_ziplistPop(int argc, char **argv, int flags);
|
||||
int test_ziplistGetElementAtIndex3(int argc, char **argv, int flags);
|
||||
int test_ziplistGetElementOutOfRange(int argc, char **argv, int flags);
|
||||
int test_ziplistGetLastElement(int argc, char **argv, int flags);
|
||||
int test_ziplistGetFirstElement(int argc, char **argv, int flags);
|
||||
int test_ziplistGetElementOutOfRangeReverse(int argc, char **argv, int flags);
|
||||
int test_ziplistIterateThroughFullList(int argc, char **argv, int flags);
|
||||
int test_ziplistIterateThroughListFrom1ToEnd(int argc, char **argv, int flags);
|
||||
int test_ziplistIterateThroughListFrom2ToEnd(int argc, char **argv, int flags);
|
||||
int test_ziplistIterateThroughStartOutOfRange(int argc, char **argv, int flags);
|
||||
int test_ziplistIterateBackToFront(int argc, char **argv, int flags);
|
||||
int test_ziplistIterateBackToFrontDeletingAllItems(int argc, char **argv, int flags);
|
||||
int test_ziplistDeleteInclusiveRange0To0(int argc, char **argv, int flags);
|
||||
int test_ziplistDeleteInclusiveRange0To1(int argc, char **argv, int flags);
|
||||
int test_ziplistDeleteInclusiveRange1To2(int argc, char **argv, int flags);
|
||||
int test_ziplistDeleteWithStartIndexOutOfRange(int argc, char **argv, int flags);
|
||||
int test_ziplistDeleteWithNumOverflow(int argc, char **argv, int flags);
|
||||
int test_ziplistDeleteFooWhileIterating(int argc, char **argv, int flags);
|
||||
int test_ziplistReplaceWithSameSize(int argc, char **argv, int flags);
|
||||
int test_ziplistReplaceWithDifferentSize(int argc, char **argv, int flags);
|
||||
int test_ziplistRegressionTestForOver255ByteStrings(int argc, char **argv, int flags);
|
||||
int test_ziplistRegressionTestDeleteNextToLastEntries(int argc, char **argv, int flags);
|
||||
int test_ziplistCreateLongListAndCheckIndices(int argc, char **argv, int flags);
|
||||
int test_ziplistCompareStringWithZiplistEntries(int argc, char **argv, int flags);
|
||||
int test_ziplistMergeTest(int argc, char **argv, int flags);
|
||||
int test_ziplistStressWithRandomPayloadsOfDifferentEncoding(int argc, char **argv, int flags);
|
||||
int test_ziplistCascadeUpdateEdgeCases(int argc, char **argv, int flags);
|
||||
int test_ziplistInsertEdgeCase(int argc, char **argv, int flags);
|
||||
int test_ziplistStressWithVariableSize(int argc, char **argv, int flags);
|
||||
int test_BenchmarkziplistFind(int argc, char **argv, int flags);
|
||||
int test_BenchmarkziplistIndex(int argc, char **argv, int flags);
|
||||
int test_BenchmarkziplistValidateIntegrity(int argc, char **argv, int flags);
|
||||
int test_BenchmarkziplistCompareWithString(int argc, char **argv, int flags);
|
||||
int test_BenchmarkziplistCompareWithNumber(int argc, char **argv, int flags);
|
||||
int test_ziplistStress__ziplistCascadeUpdate(int argc, char **argv, int flags);
|
||||
int test_zmallocInitialUsedMemory(int argc, char **argv, int flags);
|
||||
int test_zmallocAllocReallocCallocAndFree(int argc, char **argv, int flags);
|
||||
int test_zmallocAllocZeroByteAndFree(int argc, char **argv, int flags);
|
||||
@ -42,6 +78,7 @@ unitTest __test_kvstore_c[] = {{"test_kvstoreAdd16Keys", test_kvstoreAdd16Keys},
|
||||
unitTest __test_sds_c[] = {{"test_sds", test_sds}, {NULL, NULL}};
|
||||
unitTest __test_sha1_c[] = {{"test_sha1", test_sha1}, {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}};
|
||||
unitTest __test_ziplist_c[] = {{"test_ziplistCreateIntList", test_ziplistCreateIntList}, {"test_ziplistPop", test_ziplistPop}, {"test_ziplistGetElementAtIndex3", test_ziplistGetElementAtIndex3}, {"test_ziplistGetElementOutOfRange", test_ziplistGetElementOutOfRange}, {"test_ziplistGetLastElement", test_ziplistGetLastElement}, {"test_ziplistGetFirstElement", test_ziplistGetFirstElement}, {"test_ziplistGetElementOutOfRangeReverse", test_ziplistGetElementOutOfRangeReverse}, {"test_ziplistIterateThroughFullList", test_ziplistIterateThroughFullList}, {"test_ziplistIterateThroughListFrom1ToEnd", test_ziplistIterateThroughListFrom1ToEnd}, {"test_ziplistIterateThroughListFrom2ToEnd", test_ziplistIterateThroughListFrom2ToEnd}, {"test_ziplistIterateThroughStartOutOfRange", test_ziplistIterateThroughStartOutOfRange}, {"test_ziplistIterateBackToFront", test_ziplistIterateBackToFront}, {"test_ziplistIterateBackToFrontDeletingAllItems", test_ziplistIterateBackToFrontDeletingAllItems}, {"test_ziplistDeleteInclusiveRange0To0", test_ziplistDeleteInclusiveRange0To0}, {"test_ziplistDeleteInclusiveRange0To1", test_ziplistDeleteInclusiveRange0To1}, {"test_ziplistDeleteInclusiveRange1To2", test_ziplistDeleteInclusiveRange1To2}, {"test_ziplistDeleteWithStartIndexOutOfRange", test_ziplistDeleteWithStartIndexOutOfRange}, {"test_ziplistDeleteWithNumOverflow", test_ziplistDeleteWithNumOverflow}, {"test_ziplistDeleteFooWhileIterating", test_ziplistDeleteFooWhileIterating}, {"test_ziplistReplaceWithSameSize", test_ziplistReplaceWithSameSize}, {"test_ziplistReplaceWithDifferentSize", test_ziplistReplaceWithDifferentSize}, {"test_ziplistRegressionTestForOver255ByteStrings", test_ziplistRegressionTestForOver255ByteStrings}, {"test_ziplistRegressionTestDeleteNextToLastEntries", test_ziplistRegressionTestDeleteNextToLastEntries}, {"test_ziplistCreateLongListAndCheckIndices", test_ziplistCreateLongListAndCheckIndices}, {"test_ziplistCompareStringWithZiplistEntries", test_ziplistCompareStringWithZiplistEntries}, {"test_ziplistMergeTest", test_ziplistMergeTest}, {"test_ziplistStressWithRandomPayloadsOfDifferentEncoding", test_ziplistStressWithRandomPayloadsOfDifferentEncoding}, {"test_ziplistCascadeUpdateEdgeCases", test_ziplistCascadeUpdateEdgeCases}, {"test_ziplistInsertEdgeCase", test_ziplistInsertEdgeCase}, {"test_ziplistStressWithVariableSize", test_ziplistStressWithVariableSize}, {"test_BenchmarkziplistFind", test_BenchmarkziplistFind}, {"test_BenchmarkziplistIndex", test_BenchmarkziplistIndex}, {"test_BenchmarkziplistValidateIntegrity", test_BenchmarkziplistValidateIntegrity}, {"test_BenchmarkziplistCompareWithString", test_BenchmarkziplistCompareWithString}, {"test_BenchmarkziplistCompareWithNumber", test_BenchmarkziplistCompareWithNumber}, {"test_ziplistStress__ziplistCascadeUpdate", test_ziplistStress__ziplistCascadeUpdate}, {NULL, NULL}};
|
||||
unitTest __test_zmalloc_c[] = {{"test_zmallocInitialUsedMemory", test_zmallocInitialUsedMemory}, {"test_zmallocAllocReallocCallocAndFree", test_zmallocAllocReallocCallocAndFree}, {"test_zmallocAllocZeroByteAndFree", test_zmallocAllocZeroByteAndFree}, {NULL, NULL}};
|
||||
|
||||
struct unitTestSuite {
|
||||
@ -56,5 +93,6 @@ struct unitTestSuite {
|
||||
{"test_sds.c", __test_sds_c},
|
||||
{"test_sha1.c", __test_sha1_c},
|
||||
{"test_util.c", __test_util_c},
|
||||
{"test_ziplist.c", __test_ziplist_c},
|
||||
{"test_zmalloc.c", __test_zmalloc_c},
|
||||
};
|
||||
|
1049
src/unit/test_ziplist.c
Normal file
1049
src/unit/test_ziplist.c
Normal file
File diff suppressed because it is too large
Load Diff
979
src/ziplist.c
979
src/ziplist.c
@ -1687,982 +1687,3 @@ unsigned int ziplistRandomPairsUnique(unsigned char *zl, unsigned int count, zip
|
||||
}
|
||||
return picked;
|
||||
}
|
||||
|
||||
#ifdef SERVER_TEST
|
||||
#include <sys/time.h>
|
||||
#include "adlist.h"
|
||||
#include "sds.h"
|
||||
#include "testhelp.h"
|
||||
|
||||
#define debug(f, ...) { if (DEBUG) printf(f, __VA_ARGS__); }
|
||||
|
||||
static unsigned char *createList(void) {
|
||||
unsigned char *zl = ziplistNew();
|
||||
zl = ziplistPush(zl, (unsigned char*)"foo", 3, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"quux", 4, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"hello", 5, ZIPLIST_HEAD);
|
||||
zl = ziplistPush(zl, (unsigned char*)"1024", 4, ZIPLIST_TAIL);
|
||||
return zl;
|
||||
}
|
||||
|
||||
static unsigned char *createIntList(void) {
|
||||
unsigned char *zl = ziplistNew();
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), "100");
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);
|
||||
snprintf(buf, sizeof(buf), "128000");
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);
|
||||
snprintf(buf, sizeof(buf), "-100");
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_HEAD);
|
||||
snprintf(buf, sizeof(buf), "4294967296");
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_HEAD);
|
||||
snprintf(buf, sizeof(buf), "non integer");
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);
|
||||
snprintf(buf,sizeof(buf), "much much longer non integer");
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, strlen(buf), ZIPLIST_TAIL);
|
||||
return zl;
|
||||
}
|
||||
|
||||
static long long usec(void) {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv,NULL);
|
||||
return (((long long)tv.tv_sec)*1000000)+tv.tv_usec;
|
||||
}
|
||||
|
||||
static void stress(int pos, int num, int maxsize, int dnum) {
|
||||
int i,j,k;
|
||||
unsigned char *zl;
|
||||
char posstr[2][5] = { "HEAD", "TAIL" };
|
||||
long long start;
|
||||
for (i = 0; i < maxsize; i+=dnum) {
|
||||
zl = ziplistNew();
|
||||
for (j = 0; j < i; j++) {
|
||||
zl = ziplistPush(zl,(unsigned char*)"quux",4,ZIPLIST_TAIL);
|
||||
}
|
||||
|
||||
/* Do num times a push+pop from pos */
|
||||
start = usec();
|
||||
for (k = 0; k < num; k++) {
|
||||
zl = ziplistPush(zl,(unsigned char*)"quux",4,pos);
|
||||
zl = ziplistDeleteRange(zl,0,1);
|
||||
}
|
||||
printf("List size: %8d, bytes: %8d, %dx push+pop (%s): %6lld usec\n",
|
||||
i,intrev32ifbe(ZIPLIST_BYTES(zl)),num,posstr[pos],usec()-start);
|
||||
zfree(zl);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char *pop(unsigned char *zl, int where) {
|
||||
unsigned char *p, *vstr;
|
||||
unsigned int vlen;
|
||||
long long vlong = 0;
|
||||
|
||||
p = ziplistIndex(zl,where == ZIPLIST_HEAD ? 0 : -1);
|
||||
if (ziplistGet(p,&vstr,&vlen,&vlong)) {
|
||||
if (where == ZIPLIST_HEAD)
|
||||
printf("Pop head: ");
|
||||
else
|
||||
printf("Pop tail: ");
|
||||
|
||||
if (vstr) {
|
||||
if (vlen && fwrite(vstr,vlen,1,stdout) == 0) perror("fwrite");
|
||||
}
|
||||
else {
|
||||
printf("%lld", vlong);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
return ziplistDelete(zl,&p);
|
||||
} else {
|
||||
printf("ERROR: Could not pop\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static int randstring(char *target, unsigned int min, unsigned int max) {
|
||||
int p = 0;
|
||||
int len = min+rand()%(max-min+1);
|
||||
int minval, maxval;
|
||||
switch(rand() % 3) {
|
||||
case 0:
|
||||
minval = 0;
|
||||
maxval = 255;
|
||||
break;
|
||||
case 1:
|
||||
minval = 48;
|
||||
maxval = 122;
|
||||
break;
|
||||
case 2:
|
||||
minval = 48;
|
||||
maxval = 52;
|
||||
break;
|
||||
default:
|
||||
assert(NULL);
|
||||
}
|
||||
|
||||
while(p < len)
|
||||
target[p++] = minval+rand()%(maxval-minval+1);
|
||||
return len;
|
||||
}
|
||||
|
||||
static void verify(unsigned char *zl, zlentry *e) {
|
||||
int len = ziplistLen(zl);
|
||||
zlentry _e;
|
||||
|
||||
ZIPLIST_ENTRY_ZERO(&_e);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
memset(&e[i], 0, sizeof(zlentry));
|
||||
zipEntry(ziplistIndex(zl, i), &e[i]);
|
||||
|
||||
memset(&_e, 0, sizeof(zlentry));
|
||||
zipEntry(ziplistIndex(zl, -len+i), &_e);
|
||||
|
||||
assert(memcmp(&e[i], &_e, sizeof(zlentry)) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char *insertHelper(unsigned char *zl, char ch, size_t len, unsigned char *pos) {
|
||||
assert(len <= ZIP_BIG_PREVLEN);
|
||||
unsigned char data[ZIP_BIG_PREVLEN] = {0};
|
||||
memset(data, ch, len);
|
||||
return ziplistInsert(zl, pos, data, len);
|
||||
}
|
||||
|
||||
static int compareHelper(unsigned char *zl, char ch, size_t len, int index) {
|
||||
assert(len <= ZIP_BIG_PREVLEN);
|
||||
unsigned char data[ZIP_BIG_PREVLEN] = {0};
|
||||
memset(data, ch, len);
|
||||
unsigned char *p = ziplistIndex(zl, index);
|
||||
assert(p != NULL);
|
||||
return ziplistCompare(p, data, len);
|
||||
}
|
||||
|
||||
static size_t strEntryBytesSmall(size_t slen) {
|
||||
return slen + zipStorePrevEntryLength(NULL, 0) + zipStoreEntryEncoding(NULL, 0, slen);
|
||||
}
|
||||
|
||||
static size_t strEntryBytesLarge(size_t slen) {
|
||||
return slen + zipStorePrevEntryLength(NULL, ZIP_BIG_PREVLEN) + zipStoreEntryEncoding(NULL, 0, slen);
|
||||
}
|
||||
|
||||
/* ./valkey-server test ziplist <randomseed> */
|
||||
int ziplistTest(int argc, char **argv, int flags) {
|
||||
int accurate = (flags & TEST_ACCURATE);
|
||||
unsigned char *zl, *p;
|
||||
unsigned char *entry;
|
||||
unsigned int elen;
|
||||
long long value;
|
||||
int iteration;
|
||||
|
||||
/* If an argument is given, use it as the random seed. */
|
||||
if (argc >= 4)
|
||||
srand(atoi(argv[3]));
|
||||
|
||||
zl = createIntList();
|
||||
ziplistRepr(zl);
|
||||
|
||||
zfree(zl);
|
||||
|
||||
zl = createList();
|
||||
ziplistRepr(zl);
|
||||
|
||||
zl = pop(zl,ZIPLIST_TAIL);
|
||||
ziplistRepr(zl);
|
||||
|
||||
zl = pop(zl,ZIPLIST_HEAD);
|
||||
ziplistRepr(zl);
|
||||
|
||||
zl = pop(zl,ZIPLIST_TAIL);
|
||||
ziplistRepr(zl);
|
||||
|
||||
zl = pop(zl,ZIPLIST_TAIL);
|
||||
ziplistRepr(zl);
|
||||
|
||||
zfree(zl);
|
||||
|
||||
printf("Get element at index 3:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, 3);
|
||||
if (!ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("ERROR: Could not access index 3\n");
|
||||
return 1;
|
||||
}
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%lld\n", value);
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Get element at index 4 (out of range):\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, 4);
|
||||
if (p == NULL) {
|
||||
printf("No entry\n");
|
||||
} else {
|
||||
printf("ERROR: Out of range index should return NULL, returned offset: %ld\n", (long)(p-zl));
|
||||
return 1;
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Get element at index -1 (last element):\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, -1);
|
||||
if (!ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("ERROR: Could not access index -1\n");
|
||||
return 1;
|
||||
}
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%lld\n", value);
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Get element at index -4 (first element):\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, -4);
|
||||
if (!ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("ERROR: Could not access index -4\n");
|
||||
return 1;
|
||||
}
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
|
||||
printf("\n");
|
||||
} else {
|
||||
printf("%lld\n", value);
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Get element at index -5 (reverse out of range):\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, -5);
|
||||
if (p == NULL) {
|
||||
printf("No entry\n");
|
||||
} else {
|
||||
printf("ERROR: Out of range index should return NULL, returned offset: %ld\n", (long)(p-zl));
|
||||
return 1;
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Iterate list from 0 to end:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, 0);
|
||||
while (ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("Entry: ");
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
|
||||
} else {
|
||||
printf("%lld", value);
|
||||
}
|
||||
p = ziplistNext(zl,p);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Iterate list from 1 to end:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, 1);
|
||||
while (ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("Entry: ");
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
|
||||
} else {
|
||||
printf("%lld", value);
|
||||
}
|
||||
p = ziplistNext(zl,p);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Iterate list from 2 to end:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, 2);
|
||||
while (ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("Entry: ");
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
|
||||
} else {
|
||||
printf("%lld", value);
|
||||
}
|
||||
p = ziplistNext(zl,p);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Iterate starting out of range:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, 4);
|
||||
if (!ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("No entry\n");
|
||||
} else {
|
||||
printf("ERROR\n");
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Iterate from back to front:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, -1);
|
||||
while (ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("Entry: ");
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
|
||||
} else {
|
||||
printf("%lld", value);
|
||||
}
|
||||
p = ziplistPrev(zl,p);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Iterate from back to front, deleting all items:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl, -1);
|
||||
while (ziplistGet(p, &entry, &elen, &value)) {
|
||||
printf("Entry: ");
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0) perror("fwrite");
|
||||
} else {
|
||||
printf("%lld", value);
|
||||
}
|
||||
zl = ziplistDelete(zl,&p);
|
||||
p = ziplistPrev(zl,p);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Delete inclusive range 0,0:\n");
|
||||
{
|
||||
zl = createList();
|
||||
zl = ziplistDeleteRange(zl, 0, 1);
|
||||
ziplistRepr(zl);
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Delete inclusive range 0,1:\n");
|
||||
{
|
||||
zl = createList();
|
||||
zl = ziplistDeleteRange(zl, 0, 2);
|
||||
ziplistRepr(zl);
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Delete inclusive range 1,2:\n");
|
||||
{
|
||||
zl = createList();
|
||||
zl = ziplistDeleteRange(zl, 1, 2);
|
||||
ziplistRepr(zl);
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Delete with start index out of range:\n");
|
||||
{
|
||||
zl = createList();
|
||||
zl = ziplistDeleteRange(zl, 5, 1);
|
||||
ziplistRepr(zl);
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Delete with num overflow:\n");
|
||||
{
|
||||
zl = createList();
|
||||
zl = ziplistDeleteRange(zl, 1, 5);
|
||||
ziplistRepr(zl);
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Delete foo while iterating:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl,0);
|
||||
while (ziplistGet(p,&entry,&elen,&value)) {
|
||||
if (entry && strncmp("foo",(char*)entry,elen) == 0) {
|
||||
printf("Delete foo\n");
|
||||
zl = ziplistDelete(zl,&p);
|
||||
} else {
|
||||
printf("Entry: ");
|
||||
if (entry) {
|
||||
if (elen && fwrite(entry,elen,1,stdout) == 0)
|
||||
perror("fwrite");
|
||||
} else {
|
||||
printf("%lld",value);
|
||||
}
|
||||
p = ziplistNext(zl,p);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
ziplistRepr(zl);
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Replace with same size:\n");
|
||||
{
|
||||
zl = createList(); /* "hello", "foo", "quux", "1024" */
|
||||
unsigned char *orig_zl = zl;
|
||||
p = ziplistIndex(zl, 0);
|
||||
zl = ziplistReplace(zl, p, (unsigned char*)"zoink", 5);
|
||||
p = ziplistIndex(zl, 3);
|
||||
zl = ziplistReplace(zl, p, (unsigned char*)"yy", 2);
|
||||
p = ziplistIndex(zl, 1);
|
||||
zl = ziplistReplace(zl, p, (unsigned char*)"65536", 5);
|
||||
p = ziplistIndex(zl, 0);
|
||||
assert(!memcmp((char*)p,
|
||||
"\x00\x05zoink"
|
||||
"\x07\xf0\x00\x00\x01" /* 65536 as int24 */
|
||||
"\x05\x04quux" "\x06\x02yy" "\xff",
|
||||
23));
|
||||
assert(zl == orig_zl); /* no reallocations have happened */
|
||||
zfree(zl);
|
||||
printf("SUCCESS\n\n");
|
||||
}
|
||||
|
||||
printf("Replace with different size:\n");
|
||||
{
|
||||
zl = createList(); /* "hello", "foo", "quux", "1024" */
|
||||
p = ziplistIndex(zl, 1);
|
||||
zl = ziplistReplace(zl, p, (unsigned char*)"squirrel", 8);
|
||||
p = ziplistIndex(zl, 0);
|
||||
assert(!strncmp((char*)p,
|
||||
"\x00\x05hello" "\x07\x08squirrel" "\x0a\x04quux"
|
||||
"\x06\xc0\x00\x04" "\xff",
|
||||
28));
|
||||
zfree(zl);
|
||||
printf("SUCCESS\n\n");
|
||||
}
|
||||
|
||||
printf("Regression test for >255 byte strings:\n");
|
||||
{
|
||||
char v1[257] = {0}, v2[257] = {0};
|
||||
memset(v1,'x',256);
|
||||
memset(v2,'y',256);
|
||||
zl = ziplistNew();
|
||||
zl = ziplistPush(zl,(unsigned char*)v1,strlen(v1),ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl,(unsigned char*)v2,strlen(v2),ZIPLIST_TAIL);
|
||||
|
||||
/* Pop values again and compare their value. */
|
||||
p = ziplistIndex(zl,0);
|
||||
assert(ziplistGet(p,&entry,&elen,&value));
|
||||
assert(strncmp(v1,(char*)entry,elen) == 0);
|
||||
p = ziplistIndex(zl,1);
|
||||
assert(ziplistGet(p,&entry,&elen,&value));
|
||||
assert(strncmp(v2,(char*)entry,elen) == 0);
|
||||
printf("SUCCESS\n\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Regression test deleting next to last entries:\n");
|
||||
{
|
||||
char v[3][257] = {{0}};
|
||||
zlentry e[3] = {{.prevrawlensize = 0, .prevrawlen = 0, .lensize = 0,
|
||||
.len = 0, .headersize = 0, .encoding = 0, .p = NULL}};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {
|
||||
memset(v[i], 'a' + i, sizeof(v[0]));
|
||||
}
|
||||
|
||||
v[0][256] = '\0';
|
||||
v[1][ 1] = '\0';
|
||||
v[2][256] = '\0';
|
||||
|
||||
zl = ziplistNew();
|
||||
for (i = 0; i < (sizeof(v)/sizeof(v[0])); i++) {
|
||||
zl = ziplistPush(zl, (unsigned char *) v[i], strlen(v[i]), ZIPLIST_TAIL);
|
||||
}
|
||||
|
||||
verify(zl, e);
|
||||
|
||||
assert(e[0].prevrawlensize == 1);
|
||||
assert(e[1].prevrawlensize == 5);
|
||||
assert(e[2].prevrawlensize == 1);
|
||||
|
||||
/* Deleting entry 1 will increase `prevrawlensize` for entry 2 */
|
||||
unsigned char *p = e[1].p;
|
||||
zl = ziplistDelete(zl, &p);
|
||||
|
||||
verify(zl, e);
|
||||
|
||||
assert(e[0].prevrawlensize == 1);
|
||||
assert(e[1].prevrawlensize == 5);
|
||||
|
||||
printf("SUCCESS\n\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Create long list and check indices:\n");
|
||||
{
|
||||
unsigned long long start = usec();
|
||||
zl = ziplistNew();
|
||||
char buf[32];
|
||||
int i,len;
|
||||
for (i = 0; i < 1000; i++) {
|
||||
len = snprintf(buf,sizeof(buf),"%d",i);
|
||||
zl = ziplistPush(zl,(unsigned char*)buf,len,ZIPLIST_TAIL);
|
||||
}
|
||||
for (i = 0; i < 1000; i++) {
|
||||
p = ziplistIndex(zl,i);
|
||||
assert(ziplistGet(p,NULL,NULL,&value));
|
||||
assert(i == value);
|
||||
|
||||
p = ziplistIndex(zl,-i-1);
|
||||
assert(ziplistGet(p,NULL,NULL,&value));
|
||||
assert(999-i == value);
|
||||
}
|
||||
printf("SUCCESS. usec=%lld\n\n", usec()-start);
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Compare strings with ziplist entries:\n");
|
||||
{
|
||||
zl = createList();
|
||||
p = ziplistIndex(zl,0);
|
||||
if (!ziplistCompare(p,(unsigned char*)"hello",5)) {
|
||||
printf("ERROR: not \"hello\"\n");
|
||||
return 1;
|
||||
}
|
||||
if (ziplistCompare(p,(unsigned char*)"hella",5)) {
|
||||
printf("ERROR: \"hella\"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = ziplistIndex(zl,3);
|
||||
if (!ziplistCompare(p,(unsigned char*)"1024",4)) {
|
||||
printf("ERROR: not \"1024\"\n");
|
||||
return 1;
|
||||
}
|
||||
if (ziplistCompare(p,(unsigned char*)"1025",4)) {
|
||||
printf("ERROR: \"1025\"\n");
|
||||
return 1;
|
||||
}
|
||||
printf("SUCCESS\n\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Merge test:\n");
|
||||
{
|
||||
/* create list gives us: [hello, foo, quux, 1024] */
|
||||
zl = createList();
|
||||
unsigned char *zl2 = createList();
|
||||
|
||||
unsigned char *zl3 = ziplistNew();
|
||||
unsigned char *zl4 = ziplistNew();
|
||||
|
||||
if (ziplistMerge(&zl4, &zl4)) {
|
||||
printf("ERROR: Allowed merging of one ziplist into itself.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Merge two empty ziplists, get empty result back. */
|
||||
zl4 = ziplistMerge(&zl3, &zl4);
|
||||
ziplistRepr(zl4);
|
||||
if (ziplistLen(zl4)) {
|
||||
printf("ERROR: Merging two empty ziplists created entries.\n");
|
||||
return 1;
|
||||
}
|
||||
zfree(zl4);
|
||||
|
||||
zl2 = ziplistMerge(&zl, &zl2);
|
||||
/* merge gives us: [hello, foo, quux, 1024, hello, foo, quux, 1024] */
|
||||
ziplistRepr(zl2);
|
||||
|
||||
if (ziplistLen(zl2) != 8) {
|
||||
printf("ERROR: Merged length not 8, but: %u\n", ziplistLen(zl2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = ziplistIndex(zl2,0);
|
||||
if (!ziplistCompare(p,(unsigned char*)"hello",5)) {
|
||||
printf("ERROR: not \"hello\"\n");
|
||||
return 1;
|
||||
}
|
||||
if (ziplistCompare(p,(unsigned char*)"hella",5)) {
|
||||
printf("ERROR: \"hella\"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = ziplistIndex(zl2,3);
|
||||
if (!ziplistCompare(p,(unsigned char*)"1024",4)) {
|
||||
printf("ERROR: not \"1024\"\n");
|
||||
return 1;
|
||||
}
|
||||
if (ziplistCompare(p,(unsigned char*)"1025",4)) {
|
||||
printf("ERROR: \"1025\"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = ziplistIndex(zl2,4);
|
||||
if (!ziplistCompare(p,(unsigned char*)"hello",5)) {
|
||||
printf("ERROR: not \"hello\"\n");
|
||||
return 1;
|
||||
}
|
||||
if (ziplistCompare(p,(unsigned char*)"hella",5)) {
|
||||
printf("ERROR: \"hella\"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = ziplistIndex(zl2,7);
|
||||
if (!ziplistCompare(p,(unsigned char*)"1024",4)) {
|
||||
printf("ERROR: not \"1024\"\n");
|
||||
return 1;
|
||||
}
|
||||
if (ziplistCompare(p,(unsigned char*)"1025",4)) {
|
||||
printf("ERROR: \"1025\"\n");
|
||||
return 1;
|
||||
}
|
||||
printf("SUCCESS\n\n");
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Stress with random payloads of different encoding:\n");
|
||||
{
|
||||
unsigned long long start = usec();
|
||||
int i,j,len,where;
|
||||
unsigned char *p;
|
||||
char buf[1024];
|
||||
int buflen;
|
||||
list *ref;
|
||||
listNode *refnode;
|
||||
|
||||
/* Hold temp vars from ziplist */
|
||||
unsigned char *sstr;
|
||||
unsigned int slen;
|
||||
long long sval;
|
||||
|
||||
iteration = accurate ? 20000 : 20;
|
||||
for (i = 0; i < iteration; i++) {
|
||||
zl = ziplistNew();
|
||||
ref = listCreate();
|
||||
listSetFreeMethod(ref,(void (*)(void*))sdsfree);
|
||||
len = rand() % 256;
|
||||
|
||||
/* Create lists */
|
||||
for (j = 0; j < len; j++) {
|
||||
where = (rand() & 1) ? ZIPLIST_HEAD : ZIPLIST_TAIL;
|
||||
if (rand() % 2) {
|
||||
buflen = randstring(buf,1,sizeof(buf)-1);
|
||||
} else {
|
||||
switch(rand() % 3) {
|
||||
case 0:
|
||||
buflen = snprintf(buf,sizeof(buf),"%lld",(0LL + rand()) >> 20);
|
||||
break;
|
||||
case 1:
|
||||
buflen = snprintf(buf,sizeof(buf),"%lld",(0LL + rand()));
|
||||
break;
|
||||
case 2:
|
||||
buflen = snprintf(buf,sizeof(buf),"%lld",(0LL + rand()) << 20);
|
||||
break;
|
||||
default:
|
||||
assert(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add to ziplist */
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, buflen, where);
|
||||
|
||||
/* Add to reference list */
|
||||
if (where == ZIPLIST_HEAD) {
|
||||
listAddNodeHead(ref,sdsnewlen(buf, buflen));
|
||||
} else if (where == ZIPLIST_TAIL) {
|
||||
listAddNodeTail(ref,sdsnewlen(buf, buflen));
|
||||
} else {
|
||||
assert(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
assert(listLength(ref) == ziplistLen(zl));
|
||||
for (j = 0; j < len; j++) {
|
||||
/* Naive way to get elements, but similar to the stresser
|
||||
* executed from the Tcl test suite. */
|
||||
p = ziplistIndex(zl,j);
|
||||
refnode = listIndex(ref,j);
|
||||
|
||||
assert(ziplistGet(p,&sstr,&slen,&sval));
|
||||
if (sstr == NULL) {
|
||||
buflen = snprintf(buf,sizeof(buf),"%lld",sval);
|
||||
} else {
|
||||
buflen = slen;
|
||||
memcpy(buf,sstr,buflen);
|
||||
buf[buflen] = '\0';
|
||||
}
|
||||
assert(memcmp(buf,listNodeValue(refnode),buflen) == 0);
|
||||
}
|
||||
zfree(zl);
|
||||
listRelease(ref);
|
||||
}
|
||||
printf("Done. usec=%lld\n\n", usec()-start);
|
||||
}
|
||||
|
||||
printf("Stress with variable ziplist size:\n");
|
||||
{
|
||||
unsigned long long start = usec();
|
||||
int maxsize = accurate ? 16384 : 16;
|
||||
stress(ZIPLIST_HEAD,100000,maxsize,256);
|
||||
stress(ZIPLIST_TAIL,100000,maxsize,256);
|
||||
printf("Done. usec=%lld\n\n", usec()-start);
|
||||
}
|
||||
|
||||
/* Benchmarks */
|
||||
{
|
||||
zl = ziplistNew();
|
||||
iteration = accurate ? 100000 : 100;
|
||||
for (int i=0; i<iteration; i++) {
|
||||
char buf[4096] = "asdf";
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, 4, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, 40, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, 400, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)buf, 4000, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"1", 1, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"10", 2, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"100", 3, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"1000", 4, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"10000", 5, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"100000", 6, ZIPLIST_TAIL);
|
||||
}
|
||||
|
||||
printf("Benchmark ziplistFind:\n");
|
||||
{
|
||||
unsigned long long start = usec();
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
unsigned char *fptr = ziplistIndex(zl, ZIPLIST_HEAD);
|
||||
fptr = ziplistFind(zl, fptr, (unsigned char*)"nothing", 7, 1);
|
||||
}
|
||||
printf("%lld\n", usec()-start);
|
||||
}
|
||||
|
||||
printf("Benchmark ziplistIndex:\n");
|
||||
{
|
||||
unsigned long long start = usec();
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
ziplistIndex(zl, 99999);
|
||||
}
|
||||
printf("%lld\n", usec()-start);
|
||||
}
|
||||
|
||||
printf("Benchmark ziplistValidateIntegrity:\n");
|
||||
{
|
||||
unsigned long long start = usec();
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
ziplistValidateIntegrity(zl, ziplistBlobLen(zl), 1, NULL, NULL);
|
||||
}
|
||||
printf("%lld\n", usec()-start);
|
||||
}
|
||||
|
||||
printf("Benchmark ziplistCompare with string\n");
|
||||
{
|
||||
unsigned long long start = usec();
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
unsigned char *eptr = ziplistIndex(zl,0);
|
||||
while (eptr != NULL) {
|
||||
ziplistCompare(eptr,(unsigned char*)"nothing",7);
|
||||
eptr = ziplistNext(zl,eptr);
|
||||
}
|
||||
}
|
||||
printf("Done. usec=%lld\n", usec()-start);
|
||||
}
|
||||
|
||||
printf("Benchmark ziplistCompare with number\n");
|
||||
{
|
||||
unsigned long long start = usec();
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
unsigned char *eptr = ziplistIndex(zl,0);
|
||||
while (eptr != NULL) {
|
||||
ziplistCompare(eptr,(unsigned char*)"99999",5);
|
||||
eptr = ziplistNext(zl,eptr);
|
||||
}
|
||||
}
|
||||
printf("Done. usec=%lld\n", usec()-start);
|
||||
}
|
||||
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Stress __ziplistCascadeUpdate:\n");
|
||||
{
|
||||
char data[ZIP_BIG_PREVLEN];
|
||||
zl = ziplistNew();
|
||||
iteration = accurate ? 100000 : 100;
|
||||
for (int i = 0; i < iteration; i++) {
|
||||
zl = ziplistPush(zl, (unsigned char*)data, ZIP_BIG_PREVLEN-4, ZIPLIST_TAIL);
|
||||
}
|
||||
unsigned long long start = usec();
|
||||
zl = ziplistPush(zl, (unsigned char*)data, ZIP_BIG_PREVLEN-3, ZIPLIST_HEAD);
|
||||
printf("Done. usec=%lld\n\n", usec()-start);
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("Edge cases of __ziplistCascadeUpdate:\n");
|
||||
{
|
||||
/* Inserting a entry with data length greater than ZIP_BIG_PREVLEN-4
|
||||
* will leads to cascade update. */
|
||||
size_t s1 = ZIP_BIG_PREVLEN-4, s2 = ZIP_BIG_PREVLEN-3;
|
||||
zl = ziplistNew();
|
||||
|
||||
zlentry e[4] = {{.prevrawlensize = 0, .prevrawlen = 0, .lensize = 0,
|
||||
.len = 0, .headersize = 0, .encoding = 0, .p = NULL}};
|
||||
|
||||
zl = insertHelper(zl, 'a', s1, ZIPLIST_ENTRY_HEAD(zl));
|
||||
verify(zl, e);
|
||||
|
||||
assert(e[0].prevrawlensize == 1 && e[0].prevrawlen == 0);
|
||||
assert(compareHelper(zl, 'a', s1, 0));
|
||||
ziplistRepr(zl);
|
||||
|
||||
/* No expand. */
|
||||
zl = insertHelper(zl, 'b', s1, ZIPLIST_ENTRY_HEAD(zl));
|
||||
verify(zl, e);
|
||||
|
||||
assert(e[0].prevrawlensize == 1 && e[0].prevrawlen == 0);
|
||||
assert(compareHelper(zl, 'b', s1, 0));
|
||||
|
||||
assert(e[1].prevrawlensize == 1 && e[1].prevrawlen == strEntryBytesSmall(s1));
|
||||
assert(compareHelper(zl, 'a', s1, 1));
|
||||
|
||||
ziplistRepr(zl);
|
||||
|
||||
/* Expand(tail included). */
|
||||
zl = insertHelper(zl, 'c', s2, ZIPLIST_ENTRY_HEAD(zl));
|
||||
verify(zl, e);
|
||||
|
||||
assert(e[0].prevrawlensize == 1 && e[0].prevrawlen == 0);
|
||||
assert(compareHelper(zl, 'c', s2, 0));
|
||||
|
||||
assert(e[1].prevrawlensize == 5 && e[1].prevrawlen == strEntryBytesSmall(s2));
|
||||
assert(compareHelper(zl, 'b', s1, 1));
|
||||
|
||||
assert(e[2].prevrawlensize == 5 && e[2].prevrawlen == strEntryBytesLarge(s1));
|
||||
assert(compareHelper(zl, 'a', s1, 2));
|
||||
|
||||
ziplistRepr(zl);
|
||||
|
||||
/* Expand(only previous head entry). */
|
||||
zl = insertHelper(zl, 'd', s2, ZIPLIST_ENTRY_HEAD(zl));
|
||||
verify(zl, e);
|
||||
|
||||
assert(e[0].prevrawlensize == 1 && e[0].prevrawlen == 0);
|
||||
assert(compareHelper(zl, 'd', s2, 0));
|
||||
|
||||
assert(e[1].prevrawlensize == 5 && e[1].prevrawlen == strEntryBytesSmall(s2));
|
||||
assert(compareHelper(zl, 'c', s2, 1));
|
||||
|
||||
assert(e[2].prevrawlensize == 5 && e[2].prevrawlen == strEntryBytesLarge(s2));
|
||||
assert(compareHelper(zl, 'b', s1, 2));
|
||||
|
||||
assert(e[3].prevrawlensize == 5 && e[3].prevrawlen == strEntryBytesLarge(s1));
|
||||
assert(compareHelper(zl, 'a', s1, 3));
|
||||
|
||||
ziplistRepr(zl);
|
||||
|
||||
/* Delete from mid. */
|
||||
unsigned char *p = ziplistIndex(zl, 2);
|
||||
zl = ziplistDelete(zl, &p);
|
||||
verify(zl, e);
|
||||
|
||||
assert(e[0].prevrawlensize == 1 && e[0].prevrawlen == 0);
|
||||
assert(compareHelper(zl, 'd', s2, 0));
|
||||
|
||||
assert(e[1].prevrawlensize == 5 && e[1].prevrawlen == strEntryBytesSmall(s2));
|
||||
assert(compareHelper(zl, 'c', s2, 1));
|
||||
|
||||
assert(e[2].prevrawlensize == 5 && e[2].prevrawlen == strEntryBytesLarge(s2));
|
||||
assert(compareHelper(zl, 'a', s1, 2));
|
||||
|
||||
ziplistRepr(zl);
|
||||
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("__ziplistInsert nextdiff == -4 && reqlen < 4 (issue #7170):\n");
|
||||
{
|
||||
zl = ziplistNew();
|
||||
|
||||
/* We set some values to almost reach the critical point - 254 */
|
||||
char A_252[253] = {0}, A_250[251] = {0};
|
||||
memset(A_252, 'A', 252);
|
||||
memset(A_250, 'A', 250);
|
||||
|
||||
/* After the rpush, the list look like: [one two A_252 A_250 three 10] */
|
||||
zl = ziplistPush(zl, (unsigned char*)"one", 3, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"two", 3, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)A_252, strlen(A_252), ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)A_250, strlen(A_250), ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"three", 5, ZIPLIST_TAIL);
|
||||
zl = ziplistPush(zl, (unsigned char*)"10", 2, ZIPLIST_TAIL);
|
||||
ziplistRepr(zl);
|
||||
|
||||
p = ziplistIndex(zl, 2);
|
||||
if (!ziplistCompare(p, (unsigned char*)A_252, strlen(A_252))) {
|
||||
printf("ERROR: not \"A_252\"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* When we remove A_252, the list became: [one two A_250 three 10]
|
||||
* A_250's prev node became node two, because node two quite small
|
||||
* So A_250's prevlenSize shrink to 1, A_250's total size became 253(1+2+250)
|
||||
* The prev node of node three is still node A_250.
|
||||
* We will not shrink the node three's prevlenSize, keep it at 5 bytes */
|
||||
zl = ziplistDelete(zl, &p);
|
||||
ziplistRepr(zl);
|
||||
|
||||
p = ziplistIndex(zl, 3);
|
||||
if (!ziplistCompare(p, (unsigned char*)"three", 5)) {
|
||||
printf("ERROR: not \"three\"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We want to insert a node after A_250, the list became: [one two A_250 10 three 10]
|
||||
* Because the new node is quite small, node three prevlenSize will shrink to 1 */
|
||||
zl = ziplistInsert(zl, p, (unsigned char*)"10", 2);
|
||||
ziplistRepr(zl);
|
||||
|
||||
/* Last element should equal 10 */
|
||||
p = ziplistIndex(zl, -1);
|
||||
if (!ziplistCompare(p, (unsigned char*)"10", 2)) {
|
||||
printf("ERROR: not \"10\"\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
zfree(zl);
|
||||
}
|
||||
|
||||
printf("ALL TESTS PASSED!\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -67,8 +67,4 @@ void ziplistRandomPairs(unsigned char *zl, unsigned int count, ziplistEntry *key
|
||||
unsigned int ziplistRandomPairsUnique(unsigned char *zl, unsigned int count, ziplistEntry *keys, ziplistEntry *vals);
|
||||
int ziplistSafeToAdd(unsigned char* zl, size_t add);
|
||||
|
||||
#ifdef SERVER_TEST
|
||||
int ziplistTest(int argc, char *argv[], int flags);
|
||||
#endif
|
||||
|
||||
#endif /* _ZIPLIST_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user