Initial vibecoded proof of concept
This commit is contained in:
parent
74812459af
commit
461318a656
61 changed files with 13306 additions and 0 deletions
324
tests/unit/utils/test_cache.lua
Normal file
324
tests/unit/utils/test_cache.lua
Normal file
|
@ -0,0 +1,324 @@
|
|||
-- Unit tests for caching utilities
|
||||
local cache = require('notex.utils.cache')
|
||||
|
||||
describe("cache utilities", function()
|
||||
|
||||
before_each(function()
|
||||
-- Reset cache before each test
|
||||
cache.init({
|
||||
memory = {enabled = true, max_size = 10},
|
||||
lru = {enabled = true, max_size = 5},
|
||||
timed = {enabled = true, default_ttl = 1}
|
||||
})
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
cache.cleanup()
|
||||
end)
|
||||
|
||||
describe("memory cache", function()
|
||||
it("should store and retrieve values", function()
|
||||
local ok = cache.memory_set("test_key", "test_value")
|
||||
assert.is_true(ok)
|
||||
|
||||
local value = cache.memory_get("test_key")
|
||||
assert.equals("test_value", value)
|
||||
end)
|
||||
|
||||
it("should return nil for non-existent keys", function()
|
||||
local value = cache.memory_get("non_existent")
|
||||
assert.is_nil(value)
|
||||
end)
|
||||
|
||||
it("should handle cache size limits", function()
|
||||
-- Fill cache beyond max size
|
||||
for i = 1, 15 do
|
||||
cache.memory_set("key_" .. i, "value_" .. i)
|
||||
end
|
||||
|
||||
-- Should still be able to set new values (eviction happens)
|
||||
local ok = cache.memory_set("new_key", "new_value")
|
||||
assert.is_true(ok)
|
||||
|
||||
-- Should still be able to get some values
|
||||
local value = cache.memory_get("new_key")
|
||||
assert.equals("new_value", value)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("LRU cache", function()
|
||||
it("should store and retrieve values with LRU eviction", function()
|
||||
cache.lru_set("key1", "value1")
|
||||
cache.lru_set("key2", "value2")
|
||||
cache.lru_set("key3", "value3")
|
||||
|
||||
-- Access key1 to make it most recently used
|
||||
local value = cache.lru_get("key1")
|
||||
assert.equals("value1", value)
|
||||
|
||||
-- Add more items to trigger eviction
|
||||
cache.lru_set("key4", "value4")
|
||||
cache.lru_set("key5", "value5")
|
||||
cache.lru_set("key6", "value6") -- Should evict key2 (least recently used)
|
||||
|
||||
-- key2 should be evicted, key1 should still exist
|
||||
assert.is_nil(cache.lru_get("key2"))
|
||||
assert.equals("value1", cache.lru_get("key1"))
|
||||
end)
|
||||
|
||||
it("should update access order on get", function()
|
||||
cache.lru_set("key1", "value1")
|
||||
cache.lru_set("key2", "value2")
|
||||
|
||||
-- Get key1 to make it most recently used
|
||||
cache.lru_get("key1")
|
||||
|
||||
-- Fill cache to evict
|
||||
cache.lru_set("key3", "value3")
|
||||
cache.lru_set("key4", "value4")
|
||||
cache.lru_set("key5", "value4")
|
||||
cache.lru_set("key6", "value4") -- Should evict key2
|
||||
|
||||
assert.is_not_nil(cache.lru_get("key1")) -- Should still exist
|
||||
assert.is_nil(cache.lru_get("key2")) -- Should be evicted
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("timed cache", function()
|
||||
it("should store values with TTL", function()
|
||||
cache.timed_set("test_key", "test_value", 2) -- 2 second TTL
|
||||
|
||||
local value = cache.timed_get("test_key")
|
||||
assert.equals("test_value", value)
|
||||
end)
|
||||
|
||||
it("should expire values after TTL", function()
|
||||
cache.timed_set("test_key", "test_value", 1) -- 1 second TTL
|
||||
|
||||
-- Should be available immediately
|
||||
local value = cache.timed_get("test_key")
|
||||
assert.equals("test_value", value)
|
||||
|
||||
-- Wait for expiration
|
||||
vim.defer_fn(function()
|
||||
value = cache.timed_get("test_key")
|
||||
assert.is_nil(value)
|
||||
end, 1100)
|
||||
end)
|
||||
|
||||
it("should use default TTL when not specified", function()
|
||||
cache.timed_set("test_key", "test_value")
|
||||
|
||||
local value = cache.timed_get("test_key")
|
||||
assert.equals("test_value", value)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("generic cache operations", function()
|
||||
it("should set and get with specified cache type", function()
|
||||
local ok = cache.set("test_key", "test_value", "memory")
|
||||
assert.is_true(ok)
|
||||
|
||||
local value = cache.get("test_key", "memory")
|
||||
assert.equals("test_value", value)
|
||||
end)
|
||||
|
||||
it("should default to memory cache", function()
|
||||
local ok = cache.set("test_key", "test_value")
|
||||
assert.is_true(ok)
|
||||
|
||||
local value = cache.get("test_key")
|
||||
assert.equals("test_value", value)
|
||||
end)
|
||||
|
||||
it("should handle unknown cache types", function()
|
||||
local ok = cache.set("test_key", "test_value", "unknown")
|
||||
assert.is_false(ok)
|
||||
|
||||
local value = cache.get("test_key", "unknown")
|
||||
assert.is_nil(value)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("get_or_set", function()
|
||||
it("should return cached value when exists", function()
|
||||
cache.set("test_key", "cached_value")
|
||||
|
||||
local value = cache.get_or_set("test_key", function()
|
||||
return "computed_value"
|
||||
end)
|
||||
|
||||
assert.equals("cached_value", value)
|
||||
end)
|
||||
|
||||
it("should compute and cache value when not exists", function()
|
||||
local call_count = 0
|
||||
local value = cache.get_or_set("test_key", function()
|
||||
call_count = call_count + 1
|
||||
return "computed_value"
|
||||
end)
|
||||
|
||||
assert.equals("computed_value", value)
|
||||
assert.equals(1, call_count)
|
||||
|
||||
-- Second call should use cached value
|
||||
value = cache.get_or_set("test_key", function()
|
||||
call_count = call_count + 1
|
||||
return "new_value"
|
||||
end)
|
||||
|
||||
assert.equals("computed_value", value)
|
||||
assert.equals(1, call_count) -- Should not be called again
|
||||
end)
|
||||
|
||||
it("should handle computation errors", function()
|
||||
assert.has_error(function()
|
||||
cache.get_or_set("test_key", function()
|
||||
error("Computation failed")
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("multi_get", function()
|
||||
it("should try multiple cache types in order", function()
|
||||
cache.set("test_key", "memory_value", "memory")
|
||||
cache.set("test_key", "lru_value", "lru")
|
||||
|
||||
local value, cache_type = cache.multi_get("test_key", {"lru", "memory"})
|
||||
assert.equals("lru_value", value)
|
||||
assert.equals("lru", cache_type)
|
||||
|
||||
-- Should try memory if lru doesn't have it
|
||||
cache.invalidate("test_key", "lru")
|
||||
value, cache_type = cache.multi_get("test_key", {"lru", "memory"})
|
||||
assert.equals("memory_value", value)
|
||||
assert.equals("memory", cache_type)
|
||||
end)
|
||||
|
||||
it("should return nil when not found in any cache", function()
|
||||
local value = cache.multi_get("non_existent", {"memory", "lru", "timed"})
|
||||
assert.is_nil(value)
|
||||
end)
|
||||
|
||||
it("should use default cache types when not specified", function()
|
||||
cache.set("test_key", "memory_value", "memory")
|
||||
|
||||
local value = cache.multi_get("test_key")
|
||||
assert.equals("memory_value", value)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("invalidate", function()
|
||||
it("should invalidate from specific cache type", function()
|
||||
cache.set("test_key", "test_value", "memory")
|
||||
cache.set("test_key", "test_value", "lru")
|
||||
|
||||
cache.invalidate("test_key", "memory")
|
||||
|
||||
assert.is_nil(cache.get("test_key", "memory"))
|
||||
assert.equals("test_value", cache.get("test_key", "lru"))
|
||||
end)
|
||||
|
||||
it("should invalidate from all caches when type not specified", function()
|
||||
cache.set("test_key", "test_value", "memory")
|
||||
cache.set("test_key", "test_value", "lru")
|
||||
cache.set("test_key", "test_value", "timed")
|
||||
|
||||
cache.invalidate("test_key")
|
||||
|
||||
assert.is_nil(cache.get("test_key", "memory"))
|
||||
assert.is_nil(cache.get("test_key", "lru"))
|
||||
assert.is_nil(cache.get("test_key", "timed"))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("clear_all", function()
|
||||
it("should clear all caches", function()
|
||||
cache.set("key1", "value1", "memory")
|
||||
cache.set("key2", "value2", "lru")
|
||||
cache.set("key3", "value3", "timed")
|
||||
|
||||
cache.clear_all()
|
||||
|
||||
assert.is_nil(cache.get("key1", "memory"))
|
||||
assert.is_nil(cache.get("key2", "lru"))
|
||||
assert.is_nil(cache.get("key3", "timed"))
|
||||
end)
|
||||
|
||||
it("should reset metrics", function()
|
||||
-- Generate some metrics
|
||||
cache.set("test", "value")
|
||||
cache.get("test")
|
||||
cache.get("non_existent")
|
||||
|
||||
local stats_before = cache.get_stats()
|
||||
assert.is_true(stats_before.metrics.hits > 0)
|
||||
assert.is_true(stats_before.metrics.misses > 0)
|
||||
|
||||
cache.clear_all()
|
||||
|
||||
local stats_after = cache.get_stats()
|
||||
assert.equals(0, stats_after.metrics.hits)
|
||||
assert.equals(0, stats_after.metrics.misses)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("get_stats", function()
|
||||
it("should return comprehensive statistics", function()
|
||||
-- Generate some activity
|
||||
cache.set("test1", "value1")
|
||||
cache.set("test2", "value2")
|
||||
cache.get("test1")
|
||||
cache.get("non_existent")
|
||||
|
||||
local stats = cache.get_stats()
|
||||
|
||||
assert.is_not_nil(stats.metrics)
|
||||
assert.is_not_nil(stats.sizes)
|
||||
assert.is_not_nil(stats.config)
|
||||
|
||||
assert.is_true(stats.metrics.sets >= 2)
|
||||
assert.is_true(stats.metrics.hits >= 1)
|
||||
assert.is_true(stats.metrics.misses >= 1)
|
||||
assert.is_not_nil(stats.metrics.hit_ratio)
|
||||
end)
|
||||
|
||||
it("should calculate hit ratio correctly", function()
|
||||
-- Generate known metrics
|
||||
cache.set("test", "value")
|
||||
cache.get("test") -- hit
|
||||
cache.get("test") -- hit
|
||||
cache.get("non_existent") -- miss
|
||||
|
||||
local stats = cache.get_stats()
|
||||
-- Should be 2 hits out of 3 total requests = ~0.67
|
||||
assert.is_true(stats.metrics.hit_ratio > 0.6)
|
||||
assert.is_true(stats.metrics.hit_ratio < 0.7)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("configuration", function()
|
||||
it("should initialize with custom configuration", function()
|
||||
cache.init({
|
||||
memory = {enabled = false},
|
||||
lru = {enabled = true, max_size = 20},
|
||||
timed = {enabled = true, default_ttl = 10}
|
||||
})
|
||||
|
||||
-- Memory cache should be disabled
|
||||
local ok = cache.memory_set("test", "value")
|
||||
assert.is_false(ok)
|
||||
|
||||
-- LRU cache should work with new size
|
||||
ok = cache.lru_set("test", "value")
|
||||
assert.is_true(ok)
|
||||
|
||||
-- Timed cache should work with new TTL
|
||||
cache.timed_set("test2", "value")
|
||||
local value = cache.timed_get("test2")
|
||||
assert.equals("value", value)
|
||||
end)
|
||||
end)
|
||||
|
||||
end)
|
Loading…
Add table
Add a link
Reference in a new issue