| 1 | // ========================================================= // |
|---|
| 2 | // // |
|---|
| 3 | // File : cache.cxx // |
|---|
| 4 | // Purpose : test header-only class cache::Cache // |
|---|
| 5 | // // |
|---|
| 6 | // Coded by Ralf Westram (coder@reallysoft.de) in Jan 22 // |
|---|
| 7 | // http://www.arb-home.de/ // |
|---|
| 8 | // // |
|---|
| 9 | // ========================================================= // |
|---|
| 10 | |
|---|
| 11 | // -------------------------------------------------------------------------------- |
|---|
| 12 | |
|---|
| 13 | #ifdef UNIT_TESTS |
|---|
| 14 | #ifndef TEST_UNIT_H |
|---|
| 15 | #include <test_unit.h> |
|---|
| 16 | #endif |
|---|
| 17 | |
|---|
| 18 | #include <cache.h> |
|---|
| 19 | #include <arb_string.h> |
|---|
| 20 | |
|---|
| 21 | inline int *intcopy(int i) { int *ip = new int; *ip = i; return ip; } |
|---|
| 22 | |
|---|
| 23 | #define CACHED(p,t) that(p.is_cached()).is_equal_to(t) |
|---|
| 24 | #define CACHED_p123(t1,t2,t3) all().of(CACHED(p1, t1), CACHED(p2, t2), CACHED(p3, t3)) |
|---|
| 25 | |
|---|
| 26 | void TEST_CachedPtr() { |
|---|
| 27 | using namespace cache; |
|---|
| 28 | { |
|---|
| 29 | typedef SmartPtr<int> IntPtr; |
|---|
| 30 | |
|---|
| 31 | CacheHandle<IntPtr> p1; |
|---|
| 32 | CacheHandle<IntPtr> p2; |
|---|
| 33 | CacheHandle<IntPtr> p3; |
|---|
| 34 | |
|---|
| 35 | { |
|---|
| 36 | Cache<IntPtr> cache(2); |
|---|
| 37 | TEST_EXPECT_ZERO(cache.entries()); // nothing cached yet |
|---|
| 38 | |
|---|
| 39 | p1.assign(intcopy(1), cache); |
|---|
| 40 | TEST_EXPECT_EQUAL(*p1.access(cache), 1); |
|---|
| 41 | TEST_EXPECT_EQUAL(cache.entries(), 1); |
|---|
| 42 | TEST_EXPECTATION(CACHED_p123(true, false, false)); |
|---|
| 43 | |
|---|
| 44 | p2.assign(intcopy(2), cache); |
|---|
| 45 | TEST_EXPECT_EQUAL(*p2.access(cache), 2); |
|---|
| 46 | TEST_EXPECT_EQUAL(cache.entries(), 2); |
|---|
| 47 | TEST_EXPECTATION(CACHED_p123(true, true, false)); |
|---|
| 48 | |
|---|
| 49 | p3.assign(intcopy(3), cache); |
|---|
| 50 | TEST_EXPECT_EQUAL(*p3.access(cache), 3); |
|---|
| 51 | TEST_EXPECT_EQUAL(cache.entries(), 2); |
|---|
| 52 | TEST_EXPECTATION(CACHED_p123(false, true, true)); // p1 has been invalidated by caching p3 |
|---|
| 53 | |
|---|
| 54 | p3.assign(intcopy(33), cache); // test re-assignment |
|---|
| 55 | TEST_EXPECT_EQUAL(*p3.access(cache), 33); |
|---|
| 56 | TEST_EXPECT_EQUAL(cache.entries(), 2); |
|---|
| 57 | TEST_EXPECTATION(CACHED_p123(false, true, true)); // p2 still cached |
|---|
| 58 | |
|---|
| 59 | TEST_EXPECT_EQUAL(*p2.access(cache), 2); // should make p2 the LRU cache entry |
|---|
| 60 | TEST_EXPECT_EQUAL(cache.entries(), 2); |
|---|
| 61 | TEST_EXPECTATION(CACHED_p123(false, true, true)); // p2 still cached |
|---|
| 62 | |
|---|
| 63 | IntPtr s4; |
|---|
| 64 | { |
|---|
| 65 | CacheHandle<IntPtr> p4; |
|---|
| 66 | p4.assign(intcopy(4), cache); |
|---|
| 67 | TEST_EXPECT_EQUAL(*p4.access(cache), 4); |
|---|
| 68 | TEST_EXPECT_EQUAL(cache.entries(), 2); |
|---|
| 69 | |
|---|
| 70 | s4 = p4.access(cache); // keep data of p4 in s4 |
|---|
| 71 | TEST_EXPECT_EQUAL(s4.references(), 2); // ref'd by s4 and p4 |
|---|
| 72 | |
|---|
| 73 | p4.release(cache); // need to release p4 before destruction (otherwise assertion fails) |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | TEST_EXPECT_EQUAL(*s4, 4); // check kept value of deleted CacheHandle |
|---|
| 77 | TEST_EXPECT_EQUAL(s4.references(), 1); // only ref'd by s4 |
|---|
| 78 | |
|---|
| 79 | TEST_EXPECT_EQUAL(cache.entries(), 1); // contains only p2 (p4 has been released) |
|---|
| 80 | TEST_EXPECTATION(CACHED_p123(false, true, false)); // p3 has been invalidated by caching p4 |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | TEST_EXPECTATION(CACHED_p123(false, false, false)); // Cache was destroyed = > all CacheHandle will be invalid |
|---|
| 84 | // no need to release p1..p3 (due cache was destroyed) |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | // test cache of SmartCharPtr |
|---|
| 88 | { |
|---|
| 89 | Cache<SmartCharPtr> cache(3); |
|---|
| 90 | |
|---|
| 91 | { |
|---|
| 92 | const int P = 4; |
|---|
| 93 | CacheHandle<SmartCharPtr> p[P]; |
|---|
| 94 | const char *word[] = { "apple", "orange", "pie", "juice" }; |
|---|
| 95 | |
|---|
| 96 | for (int i = 0; i<P; ++i) p[i].assign(ARB_strdup(word[i]), cache); |
|---|
| 97 | TEST_REJECT(p[0].is_cached()); |
|---|
| 98 | for (int i = 1; i<P; ++i) TEST_EXPECT_EQUAL(&*p[i].access(cache), word[i]); |
|---|
| 99 | |
|---|
| 100 | TEST_REJECT(p[0].is_cached()); |
|---|
| 101 | TEST_EXPECT(p[1].is_cached()); // oldest entry |
|---|
| 102 | |
|---|
| 103 | cache.resize(cache.size()-1); |
|---|
| 104 | TEST_REJECT(p[1].is_cached()); // invalidated by resize |
|---|
| 105 | |
|---|
| 106 | for (int i = P-1; i >= 0; --i) p[i].assign(ARB_strdup(word[P-1-i]), cache); |
|---|
| 107 | |
|---|
| 108 | for (int i = 0; i<2; ++i) TEST_EXPECT_EQUAL(&*p[i].access(cache), word[P-1-i]); |
|---|
| 109 | for (int i = 2; i<P; ++i) TEST_REJECT(p[i].is_cached()); |
|---|
| 110 | |
|---|
| 111 | cache.flush(); |
|---|
| 112 | } |
|---|
| 113 | } |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | #endif // UNIT_TESTS |
|---|
| 117 | |
|---|
| 118 | // -------------------------------------------------------------------------------- |
|---|