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 "testStoreController.h"
17 #include "TestSwapDir.h"
18 
19 CPPUNIT_TEST_SUITE_REGISTRATION( testStoreController );
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 testStoreController::testStats()
31 {
32     Store::Init();
33     StoreEntry *logEntry = new StoreEntry;
34     logEntry->createMemObject("dummy_storeId", NULL, HttpRequestMethod());
35     logEntry->store_status = STORE_PENDING;
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 static void
commonInit()50 commonInit()
51 {
52     static bool inited = false;
53 
54     if (inited)
55         return;
56 
57     Config.memShared.defaultTo(false);
58 
59     Mem::Init();
60 
61     Config.Store.avgObjectSize = 1024;
62 
63     Config.Store.objectsPerBucket = 20;
64 
65     Config.Store.maxObjectSize = 2048;
66 
67     Config.store_dir_select_algorithm = xstrdup("round-robin");
68 }
69 
70 void
testMaxSize()71 testStoreController::testMaxSize()
72 {
73     commonInit();
74     StoreEntry *logEntry = new StoreEntry;
75     logEntry->createMemObject("dummy_storeId", NULL, HttpRequestMethod());
76     logEntry->store_status = STORE_PENDING;
77     Store::Init();
78     TestSwapDirPointer aStore (new TestSwapDir);
79     TestSwapDirPointer aStore2 (new TestSwapDir);
80     addSwapDir(aStore);
81     addSwapDir(aStore2);
82     CPPUNIT_ASSERT_EQUAL(static_cast<uint64_t>(6), Store::Root().maxSize());
83     free_cachedir(&Config.cacheSwap);
84     Store::FreeMemory();
85 }
86 
87 static StoreEntry *
addedEntry(Store::Disk * aStore,String name,String varySpec,String varyKey)88 addedEntry(Store::Disk *aStore,
89            String name,
90            String varySpec,
91            String varyKey
92 
93           )
94 {
95     StoreEntry *e = new StoreEntry();
96     e->store_status = STORE_OK;
97     e->setMemStatus(NOT_IN_MEMORY);
98     e->swap_status = SWAPOUT_DONE; /* bogus haha */
99     e->swap_filen = 0; /* garh - lower level*/
100     e->swap_dirn = -1;
101 
102     for (int i=0; i < Config.cacheSwap.n_configured; ++i) {
103         if (INDEXSD(i) == aStore)
104             e->swap_dirn = i;
105     }
106 
107     CPPUNIT_ASSERT (e->swap_dirn != -1);
108     e->swap_file_sz = 0; /* garh lower level */
109     e->lastref = squid_curtime;
110     e->timestamp = squid_curtime;
111     e->expires = squid_curtime;
112     e->lastModified(squid_curtime);
113     e->refcount = 1;
114     e->ping_status = PING_NONE;
115     EBIT_CLR(e->flags, ENTRY_VALIDATED);
116     e->hashInsert((const cache_key *)name.termedBuf()); /* do it after we clear KEY_PRIVATE */
117     return e;
118 }
119 
120 /* TODO make this a cbdata class */
121 
122 static bool cbcalled;
123 
124 static void
searchCallback(void * cbdata)125 searchCallback(void *cbdata)
126 {
127     cbcalled = true;
128 }
129 
130 void
testSearch()131 testStoreController::testSearch()
132 {
133     commonInit();
134     Store::Init();
135     TestSwapDirPointer aStore (new TestSwapDir);
136     TestSwapDirPointer aStore2 (new TestSwapDir);
137     addSwapDir(aStore);
138     addSwapDir(aStore2);
139     Store::Root().init();
140     StoreEntry * entry1 = addedEntry(aStore.getRaw(), "name", NULL, NULL);
141     StoreEntry * entry2 = addedEntry(aStore2.getRaw(), "name2", NULL, NULL);
142     StoreSearchPointer search = Store::Root().search(); /* search for everything in the store */
143 
144     /* nothing should be immediately available */
145     CPPUNIT_ASSERT_EQUAL(false, search->error());
146     CPPUNIT_ASSERT_EQUAL(false, search->isDone());
147     CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
148 #if 0
149 
150     CPPUNIT_ASSERT_EQUAL(false, search->next());
151 #endif
152 
153     /* trigger a callback */
154     cbcalled = false;
155     search->next(searchCallback, NULL);
156     CPPUNIT_ASSERT_EQUAL(true, cbcalled);
157 
158     /* we should have access to a entry now, that matches the entry we had before */
159     CPPUNIT_ASSERT_EQUAL(false, search->error());
160     CPPUNIT_ASSERT_EQUAL(false, search->isDone());
161     /* note the hash order is random - the test happens to be in a nice order */
162     CPPUNIT_ASSERT_EQUAL(entry1, search->currentItem());
163     //CPPUNIT_ASSERT_EQUAL(false, search->next());
164 
165     /* trigger another callback */
166     cbcalled = false;
167     search->next(searchCallback, NULL);
168     CPPUNIT_ASSERT_EQUAL(true, cbcalled);
169 
170     /* we should have access to a entry now, that matches the entry we had before */
171     CPPUNIT_ASSERT_EQUAL(false, search->error());
172     CPPUNIT_ASSERT_EQUAL(false, search->isDone());
173     CPPUNIT_ASSERT_EQUAL(entry2, search->currentItem());
174     //CPPUNIT_ASSERT_EQUAL(false, search->next());
175 
176     /* trigger another callback */
177     cbcalled = false;
178     search->next(searchCallback, NULL);
179     CPPUNIT_ASSERT_EQUAL(true, cbcalled);
180 
181     /* now we should have no error, we should have finished and have no current item */
182     CPPUNIT_ASSERT_EQUAL(false, search->error());
183     CPPUNIT_ASSERT_EQUAL(true, search->isDone());
184     CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
185     //CPPUNIT_ASSERT_EQUAL(false, search->next());
186 
187     Store::FreeMemory();
188 }
189 
190