Function quicklistDelEntry() doesn't keep iterator behavior as expected. Here is the code:

    TEST("quicklistDelEntry()") {
        quicklist *ql = quicklistNew(-2, 1);
        quicklistPushTail(ql, "aa", 3);
        quicklistPushTail(ql, "bb", 3);
        quicklistPushTail(ql, "cc", 3);
        quicklistPushTail(ql, "dd", 3);
        quicklistPushTail(ql, "ee", 3);
        quicklistIter *iter = quicklistGetIteratorAtIdx(ql, AL_START_TAIL, 2);
        quicklistEntry entry;
        assert(quicklistNext(iter, &entry));
        quicklistDelEntry(iter, &entry);
        assert(quicklistNext(iter, &entry));
        assert(strcmp((char *)entry.value, "bb") == 0);
        quicklistReleaseIterator(iter);
        quicklistRelease(ql);
    }

I think function quicklistGetIteratorAtIdx() should be rewrite to meet the following assertion:

assert((quicklistIter->derection == AL_START_HEAD && quicklistIter->offset >= 0) || 
(quicklistIter->derection == AL_START_TAIL && quicklistIter->offset < 0))

Comment From: sundb

Indeed, the quicklistIterator can be confusing in its current location after deletion. When position 2 is deleted, it points to dd (the new position 2), not bb. But I can think of another confusion when using quicklistGetIteratorAtIdx(ql, AL_START_TAIL, -3);, when position -3 is deleted, it points to bb(the new position -3). Although 2 and -3 are in the same position, they have different results.

I'm not sure we should fix this, today, we haven't used quicklistDelEntry() to delete entries in the iterator loop.