-
Notifications
You must be signed in to change notification settings - Fork 0
Add unit tests to estore #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/expire.c
Outdated
|
||
for(int i = 0; i < es->num_buckets && maxCascade > 0; i++) | ||
maxCascade -= ebCascade(es->buckets + i, es->bucket_type, now, maxCascade); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- We will need some "static" context to memorize across calls , at which bucket we stopped as well and not start from the begining (Later on, we might want increase aggressivness if too many times stopped due to maxCascade limit.)
- Need some way to iterate over the non empty buckets, very similar to the way kvstore does. See function
kvstoreGetNextNonEmptyDictIndex()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Static context is added.
src/expire.c
Outdated
TEST("Create estore with pre-allocated buckets") { | ||
int num_bits = 3; // 2^3 = 8 buckets | ||
int num_buckets = 1 << num_bits; | ||
|
||
estore *es = estoreCreate(&testEbType, num_bits); | ||
|
||
for (int i = 0; i < num_buckets; i++) { | ||
ebuckets b = es->buckets[i]; | ||
assert(b == NULL); // ebCreate returns NULL | ||
} | ||
|
||
assert(es->num_buckets == num_buckets); | ||
assert(es->num_buckets_bits == num_bits); | ||
assert(es->bucket_type == &testEbType); | ||
assert(es->count == 0); | ||
|
||
estoreRelease(es); // Clean up | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test covers overly trivial logic and seems redundant.
Please try to use c-style comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Covering even the trivial test cases helps improve code coverage. Good coverage shows that the code works as expected and is designed properly. It also gives us confidence that future changes won’t break existing functionality. Without it, we’re just hoping everything keeps working.
src/expire.c
Outdated
TEST("estoreGetBucket with cluster mode OFF") { | ||
server.cluster_enabled = 0; // Non-cluster mode | ||
|
||
estore *es = estoreCreate(&testEbType, 2); // 2^2 = 4 buckets | ||
ebuckets *expected = &es->buckets[0]; | ||
|
||
for (int i = 0; i < 4; i++) { | ||
ebuckets *b = estoreGetBucket(es, i); | ||
assert(b == expected); // All slots should return the first bucket in non-cluster mode | ||
} | ||
|
||
estoreRelease(es); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Covering even the trivial test cases helps improve code coverage. Good coverage shows that the code works as expected and is designed properly. It also gives us confidence that future changes won’t break existing functionality. Without it, we’re just hoping everything keeps working.
src/expire.c
Outdated
TEST("estoreGetBucket with cluster mode ON") { | ||
server.cluster_enabled = 1; // Cluster mode enabled | ||
|
||
estore *es = estoreCreate(&testEbType, 2); // 4 buckets | ||
|
||
for (int i = 0; i < 4; i++) { | ||
ebuckets *b = estoreGetBucket(es, i); | ||
assert(b == &es->buckets[i]); // Each slot should map to its corresponding bucket | ||
} | ||
|
||
estoreRelease(es); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Better have it covered by TCL test to verify correctness of cluster mode.
- Note that there are cluster tests currently in comment at file expire.tcl - We should strive to make it functional again.
- If coverage is not sufficient, then we better extend it there.
src/expire.c
Outdated
TEST("estoreAdd inserts kvobj at correct address in expected bucket") { | ||
server.cluster_enabled = 0; | ||
|
||
estore *es = estoreCreate(&testEbType, 2); // 4 buckets (slots 0-3) | ||
TestKVObj *kv = zmalloc(sizeof(TestKVObj)); | ||
long long expire_time = 1; | ||
int slot = 1; | ||
|
||
assert(estoreSize(es) == 0); | ||
|
||
estoreAdd(es, (kvobj*)kv, slot, expire_time); | ||
assert(estoreSize(es) == 1); | ||
|
||
// Get the expected bucket | ||
ebuckets *bucket = estoreGetBucket(es, slot); | ||
EbucketsIterator iter; | ||
int found = 0; | ||
|
||
ebStart(&iter, *bucket, es->bucket_type); | ||
while (iter.currItem) { | ||
if (iter.currItem == kv) { | ||
found = 1; | ||
break; | ||
} | ||
ebNext(&iter); | ||
} | ||
ebStop(&iter); | ||
|
||
assert(found == 1); // kvobj was found by pointer | ||
|
||
zfree(kv); | ||
estoreRelease(es); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test should also be covered at TCL level and if needed by DEBUG HTSTATS
(Maybe we should have dedicate DEBUG EXPIRE-STATS
.
src/expire.c
Outdated
TEST("estoreRelease with NULL does nothing") { | ||
// Should not crash or do anything | ||
estoreRelease(NULL); | ||
} | ||
|
||
TEST("estoreRelease frees all resources for valid estore") { | ||
// Setup | ||
estore *es = estoreCreate(&testEbType, 2); // 4 buckets | ||
|
||
// Add an item to ensure some real content exists | ||
TestKVObj *kv = zmalloc(sizeof(TestKVObj)); | ||
estoreAdd(es, (kvobj*)kv, 1, 1); | ||
|
||
// Just ensure it was added (not strictly necessary, but good check) | ||
assert(estoreSize(es) == 1); | ||
|
||
// Release the estore | ||
estoreRelease(es); | ||
|
||
// We can't assert anything post-release (pointer is now invalid), | ||
// but Valgrind or AddressSanitizer will catch use-after-free if any. | ||
zfree(kv); // Caller owns kvobj memory separately | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one should be also tested at TCL level. Add items and then flushdb . Then verify it is empty via statstitcs. Note that i made another commit that fixes flushdb/flushall which takes care to empty estoreRelease() before kvstoreRelease() (This is because ebuckets relies on embedded data in the keys and we should release it before releasing the keyspace)
src/expire.c
Outdated
TEST("estoreRemove removes kvobj and decrements count") { | ||
server.cluster_enabled = 0; | ||
|
||
// Create estore with 1 bucket | ||
estore *es = estoreCreate(&testEbType, 1); | ||
|
||
// Allocate and add a test kvobj | ||
TestKVObj *kv = zmalloc(sizeof(TestKVObj)); | ||
long long expire_time = 1; | ||
|
||
estoreAdd(es, (kvobj*)kv, 0, expire_time); | ||
assert(estoreSize(es) == 1); | ||
|
||
// Remove the kvobj | ||
estoreRemove(es, 0, (kvobj*)kv); | ||
assert(estoreSize(es) == 0); | ||
|
||
// Cleanup | ||
zfree(kv); | ||
estoreRelease(es); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should have here few meaningfull tests. Something iterative like:
- T = current time + 100 seconds
- For precision : P // take care it expands also beyond 1 hour....
- Verify ESTORE stat
- For i:0->100
- Add item with expiration time {T+i * P}
- Verify ESTORE stat
- For i:0->100
- Verify expiration time of item
- Remove item
- Verify ESTORE stat
e44f440
to
c3138e7
Compare
1fcc98e
to
b901c04
Compare
This PR adds unit test for estore functionality.