1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #include "squid.h"
10 #include "MemObject.h"
11 #include "SquidConfig.h"
12 #include "SquidTime.h"
13 #include "Store.h"
14 #include "store/Disks.h"
15 #include "StoreSearch.h"
16 #include "testStoreHashIndex.h"
17 #include "TestSwapDir.h"
18 
19 CPPUNIT_TEST_SUITE_REGISTRATION( testStoreHashIndex );
20 
21 static void
addSwapDir(TestSwapDirPointer aStore)22 addSwapDir(TestSwapDirPointer aStore)
23 {
24     allocate_new_swapdir(&Config.cacheSwap);
25     Config.cacheSwap.swapDirs[Config.cacheSwap.n_configured] = aStore.getRaw();
26     ++Config.cacheSwap.n_configured;
27 }
28 
29 void
testStats()30 testStoreHashIndex::testStats()
31 {
32     StoreEntry *logEntry = new StoreEntry;
33     logEntry->createMemObject("dummy_storeId", NULL, HttpRequestMethod());
34     logEntry->store_status = STORE_PENDING;
35     Store::Init();
36     TestSwapDirPointer aStore (new TestSwapDir);
37     TestSwapDirPointer aStore2 (new TestSwapDir);
38     addSwapDir(aStore);
39     addSwapDir(aStore2);
40     CPPUNIT_ASSERT_EQUAL(false, aStore->statsCalled);
41     CPPUNIT_ASSERT_EQUAL(false, aStore2->statsCalled);
42     Store::Stats(logEntry);
43     free_cachedir(&Config.cacheSwap);
44     CPPUNIT_ASSERT_EQUAL(true, aStore->statsCalled);
45     CPPUNIT_ASSERT_EQUAL(true, aStore2->statsCalled);
46     Store::FreeMemory();
47 }
48 
49 void
testMaxSize()50 testStoreHashIndex::testMaxSize()
51 {
52     StoreEntry *logEntry = new StoreEntry;
53     logEntry->createMemObject("dummy_storeId", NULL, HttpRequestMethod());
54     logEntry->store_status = STORE_PENDING;
55     Store::Init();
56     TestSwapDirPointer aStore (new TestSwapDir);
57     TestSwapDirPointer aStore2 (new TestSwapDir);
58     addSwapDir(aStore);
59     addSwapDir(aStore2);
60     CPPUNIT_ASSERT_EQUAL(static_cast<uint64_t>(6), Store::Root().maxSize());
61     free_cachedir(&Config.cacheSwap);
62     Store::FreeMemory();
63 }
64 
65 StoreEntry *
addedEntry(Store::Disk * aStore,String name,String varySpec,String varyKey)66 addedEntry(Store::Disk *aStore,
67            String name,
68            String varySpec,
69            String varyKey
70 
71           )
72 {
73     StoreEntry *e = new StoreEntry();
74     e->store_status = STORE_OK;
75     e->setMemStatus(NOT_IN_MEMORY);
76     e->swap_status = SWAPOUT_DONE; /* bogus haha */
77     e->swap_filen = 0; /* garh - lower level*/
78     e->swap_dirn = -1;
79 
80     for (int i=0; i < Config.cacheSwap.n_configured; ++i) {
81         if (INDEXSD(i) == aStore)
82             e->swap_dirn = i;
83     }
84 
85     CPPUNIT_ASSERT (e->swap_dirn != -1);
86     e->swap_file_sz = 0; /* garh lower level */
87     e->lastref = squid_curtime;
88     e->timestamp = squid_curtime;
89     e->expires = squid_curtime;
90     e->lastModified(squid_curtime);
91     e->refcount = 1;
92     e->ping_status = PING_NONE;
93     EBIT_CLR(e->flags, ENTRY_VALIDATED);
94     e->hashInsert((const cache_key *)name.termedBuf()); /* do it after we clear KEY_PRIVATE */
95     return e;
96 }
97 
commonInit()98 void commonInit()
99 {
100     static bool inited = false;
101 
102     if (inited)
103         return;
104 
105     Mem::Init();
106 
107     Config.Store.avgObjectSize = 1024;
108 
109     Config.Store.objectsPerBucket = 20;
110 
111     Config.Store.maxObjectSize = 2048;
112 }
113 
114 /* TODO make this a cbdata class */
115 
116 static bool cbcalled;
117 
118 static void
searchCallback(void * cbdata)119 searchCallback(void *cbdata)
120 {
121     cbcalled = true;
122 }
123 
124 void
testSearch()125 testStoreHashIndex::testSearch()
126 {
127     commonInit();
128     Store::Init();
129     TestSwapDirPointer aStore (new TestSwapDir);
130     TestSwapDirPointer aStore2 (new TestSwapDir);
131     addSwapDir(aStore);
132     addSwapDir(aStore2);
133     Store::Root().init();
134     StoreEntry * entry1 = addedEntry(aStore.getRaw(), "name", NULL, NULL);
135     StoreEntry * entry2 = addedEntry(aStore2.getRaw(), "name2", NULL, NULL);
136     StoreSearchPointer search = Store::Root().search(); /* search for everything in the store */
137 
138     /* nothing should be immediately available */
139     CPPUNIT_ASSERT_EQUAL(false, search->error());
140     CPPUNIT_ASSERT_EQUAL(false, search->isDone());
141     CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
142 #if 0
143 
144     CPPUNIT_ASSERT_EQUAL(false, search->next());
145 #endif
146 
147     /* trigger a callback */
148     cbcalled = false;
149     search->next(searchCallback, NULL);
150     CPPUNIT_ASSERT_EQUAL(true, cbcalled);
151 
152     /* we should have access to a entry now, that matches the entry we had before */
153     CPPUNIT_ASSERT_EQUAL(false, search->error());
154     CPPUNIT_ASSERT_EQUAL(false, search->isDone());
155     /* note the hash order is random - the test happens to be in a nice order */
156     CPPUNIT_ASSERT_EQUAL(entry1, search->currentItem());
157     //CPPUNIT_ASSERT_EQUAL(false, search->next());
158 
159     /* trigger another callback */
160     cbcalled = false;
161     search->next(searchCallback, NULL);
162     CPPUNIT_ASSERT_EQUAL(true, cbcalled);
163 
164     /* we should have access to a entry now, that matches the entry we had before */
165     CPPUNIT_ASSERT_EQUAL(false, search->error());
166     CPPUNIT_ASSERT_EQUAL(false, search->isDone());
167     CPPUNIT_ASSERT_EQUAL(entry2, search->currentItem());
168     //CPPUNIT_ASSERT_EQUAL(false, search->next());
169 
170     /* trigger another callback */
171     cbcalled = false;
172     search->next(searchCallback, NULL);
173     CPPUNIT_ASSERT_EQUAL(true, cbcalled);
174 
175     /* now we should have no error, we should have finished and have no current item */
176     CPPUNIT_ASSERT_EQUAL(false, search->error());
177     CPPUNIT_ASSERT_EQUAL(true, search->isDone());
178     CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
179     //CPPUNIT_ASSERT_EQUAL(false, search->next());
180 
181     Store::FreeMemory();
182 }
183 
184