From 2a472af7b842edb6647a832bdf2581d304fa5364 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Mon, 30 Jan 2017 12:59:01 -0800 Subject: [PATCH] Add sanity checking to LRU cache --- src/fish_tests.cpp | 2 ++ src/lru.h | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 8a0040fc0..f06a2997a 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -1170,9 +1170,11 @@ static void test_lru(void) { while (expected_values.size() > test_lru_t::test_capacity) { expected_values.erase(expected_values.begin()); } + cache.check_sanity(); } do_test(cache.evicted == expected_evicted); do_test(cache.values() == expected_values); + cache.check_sanity(); // Stable-sort ints in reverse order // This a/2 check ensures that some different ints compare the same diff --git a/src/lru.h b/src/lru.h index 83b770f50..4dcc1f314 100644 --- a/src/lru.h +++ b/src/lru.h @@ -242,7 +242,9 @@ class lru_cache_t { } // Number of entries - size_t size() { return this->node_map.size(); } + size_t size() const { + return this->node_map.size(); + } // Sorting support // Given a binary function F implementing less-than on the contents, place the nodes in sorted order @@ -296,6 +298,41 @@ class lru_cache_t { iterator begin() const { return iterator(mouth.prev); }; iterator end() const { return iterator(&mouth); }; + + void check_sanity() const { + // Check linked list sanity + size_t expected_count = this->size(); + const lru_link_t *prev = &mouth; + const lru_link_t *cursor = mouth.next; + + size_t max = 1024 * 1024 * 64; + size_t count = 0; + while (cursor != &mouth) { + if (cursor->prev != prev) { + assert(0 && "Node busted previous link"); + } + prev = cursor; + cursor = cursor->next; + if (count++ > max) { + assert(0 && "LRU cache unable to re-reach the mouth - not circularly linked?"); + } + } + if (mouth.prev != prev) { + assert(0 && "mouth.prev does not connect to last node"); + } + if (count != expected_count) { + assert(0 && "Linked list count mismatch from map count"); + } + + // Count iterators + size_t iter_dist = 0; + for (const auto &p : *this) { + iter_dist++; + } + if (iter_dist != count) { + assert(0 && "Linked list iterator mismatch from map count"); + } + } }; #endif