]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tests/testRock.cc
SourceLayout: shuffle StatusCode.h to http/StatusCode.h
[thirdparty/squid.git] / src / tests / testRock.cc
CommitLineData
9bb01611 1#define SQUID_UNIT_TEST 1
f7f3304a 2#include "squid.h"
9bb01611
AR
3
4#include "DiskIO/DiskIOModule.h"
582c2af2
FC
5#include "fs/rock/RockSwapDir.h"
6#include "globals.h"
9bb01611
AR
7#include "HttpHeader.h"
8#include "HttpReply.h"
9#include "Mem.h"
10#include "MemObject.h"
f206b652 11#include "RequestFlags.h"
4d5904f7 12#include "SquidConfig.h"
9bb01611
AR
13#include "Store.h"
14#include "StoreFileSystem.h"
15#include "StoreSearch.h"
16#include "SwapDir.h"
9bb01611
AR
17#include "testRock.h"
18#include "testStoreSupport.h"
19
582c2af2
FC
20#if HAVE_SYS_STAT_H
21#include <sys/stat.h>
22#endif
9bb01611
AR
23#if HAVE_STDEXCEPT
24#include <stdexcept>
25#endif
1dccf1c6
FC
26#if HAVE_UNISTD_H
27#include <unistd.h>
28#endif
9bb01611 29
6bf39e49 30#define TESTDIR "testRock_Store"
9bb01611
AR
31
32CPPUNIT_TEST_SUITE_REGISTRATION( testRock );
33
34extern REMOVALPOLICYCREATE createRemovalPolicy_lru;
35
1dccf1c6
FC
36static char cwd[MAXPATHLEN];
37
9bb01611
AR
38static void
39addSwapDir(testRock::SwapDirPointer aStore)
40{
41 allocate_new_swapdir(&Config.cacheSwap);
42 Config.cacheSwap.swapDirs[Config.cacheSwap.n_configured] = aStore.getRaw();
43 ++Config.cacheSwap.n_configured;
44}
45
46void
47testRock::setUp()
48{
49 CPPUNIT_NS::TestFixture::setUp();
50
51 if (0 > system ("rm -rf " TESTDIR))
52 throw std::runtime_error("Failed to clean test work directory");
53
ef8de464 54 // use current directory for shared segments (on path-based OSes)
1dccf1c6
FC
55 Ipc::Mem::Segment::BasePath = getcwd(cwd,MAXPATHLEN);
56 if (Ipc::Mem::Segment::BasePath == NULL)
57 Ipc::Mem::Segment::BasePath = ".";
ef8de464 58
9bb01611
AR
59 Store::Root(new StoreController);
60
61 store = new Rock::SwapDir();
62
63 addSwapDir(store);
64
65 commonInit();
66
67 char *path=xstrdup(TESTDIR);
68
fda15c05 69 char *config_line=xstrdup("foo 10 max-size=16384");
9bb01611
AR
70
71 strtok(config_line, w_space);
72
73 store->parse(0, path);
b51ec8c8 74 store_maxobjsize = 1024*1024*2;
9bb01611
AR
75
76 safe_free(path);
77
78 safe_free(config_line);
79
80 /* ok, ready to create */
81 store->create();
82
83 rr = new Rock::SwapDirRr;
84 rr->run(rrAfterConfig);
85}
86
87void
88testRock::tearDown()
89{
90 CPPUNIT_NS::TestFixture::tearDown();
91
92 Store::Root(NULL);
93
94 store = NULL;
95
96 free_cachedir(&Config.cacheSwap);
97
98 delete rr;
99
100 // TODO: do this once, or each time.
101 // safe_free(Config.replPolicy->type);
102 // delete Config.replPolicy;
103
104 if (0 > system ("rm -rf " TESTDIR))
105 throw std::runtime_error("Failed to clean test work directory");
106}
107
108void
109testRock::commonInit()
110{
111 static bool inited = false;
112
113 if (inited)
114 return;
115
116 StoreFileSystem::SetupAllFs();
117
118 Config.Store.avgObjectSize = 1024;
119
120 Config.Store.objectsPerBucket = 20;
121
122 Config.Store.maxObjectSize = 2048;
123
124 Config.store_dir_select_algorithm = xstrdup("round-robin");
125
126 Config.replPolicy = new RemovalPolicySettings;
127
128 Config.replPolicy->type = xstrdup ("lru");
129
130 Config.replPolicy->args = NULL;
131
132 /* garh garh */
133 storeReplAdd("lru", createRemovalPolicy_lru);
134
135 visible_appname_string = xstrdup(APP_FULLNAME);
136
137 Mem::Init();
138
139 comm_init();
140
141 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
142
143 httpReplyInitModule(); /* must go before accepting replies */
144
145 mem_policy = createRemovalPolicy(Config.replPolicy);
146
147 inited = true;
148}
149
150void
151testRock::storeInit()
152{
153 /* ok, ready to use */
154 Store::Root().init();
155
156 /* rebuild is a scheduled event */
157 StockEventLoop loop;
158
159 /* our swapdir must be scheduled to rebuild */
160 CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding);
161
162 loop.run();
163
164 /* cannot use loop.run(); as the loop will never idle: the store-dir
165 * clean() scheduled event prevents it
166 */
167
168 /* nothing left to rebuild */
169 CPPUNIT_ASSERT_EQUAL(1, StoreController::store_dirs_rebuilding);
170}
171
172StoreEntry *
173testRock::createEntry(const int i)
174{
f206b652 175 RequestFlags flags;
e857372a 176 flags.cachable = true;
9bb01611
AR
177 char url[64];
178 snprintf(url, sizeof(url), "dummy url %i", i);
179 url[sizeof(url) - 1] = '\0';
180 StoreEntry *const pe =
c2a7cefd 181 storeCreateEntry(url, "dummy log url", flags, Http::METHOD_GET);
9bb01611 182 HttpReply *const rep = const_cast<HttpReply *>(pe->getReply());
955394ce 183 rep->setHeaders(Http::scOkay, "dummy test object", "x-squid-internal/test", 0, -1, squid_curtime + 100000);
9bb01611
AR
184
185 pe->setPublicKey();
186
187 return pe;
188}
189
190StoreEntry *
191testRock::addEntry(const int i)
192{
193 StoreEntry *const pe = createEntry(i);
194
195 pe->buffer();
196 /* TODO: remove this when the metadata is separated */
197 {
198 Packer p;
199 packerToStoreInit(&p, pe);
200 pe->getReply()->packHeadersInto(&p);
201 packerClean(&p);
202 }
203
204 pe->flush();
205 pe->timestampsSet();
206 pe->complete();
207 pe->swapOut();
208
209 return pe;
210}
211
212StoreEntry *
213testRock::getEntry(const int i)
214{
215 StoreEntry *const pe = createEntry(i);
216 return store->get(reinterpret_cast<const cache_key *>(pe->key));
217}
218
219void
220testRock::testRockCreate()
221{
222 struct stat sb;
223
224 CPPUNIT_ASSERT(::stat(TESTDIR, &sb) == 0);
225
226 /* TODO: check the size */
227
228 /* TODO: test rebuild */
229}
230
231void
232testRock::testRockSwapOut()
233{
234 storeInit();
235
236 // add few entries to prime the database
237 for (int i = 0; i < 5; ++i) {
238 CPPUNIT_ASSERT_EQUAL((uint64_t)i, store->currentCount());
239
240 StoreEntry *const pe = addEntry(i);
241
242 CPPUNIT_ASSERT(pe->swap_status == SWAPOUT_WRITING);
243 CPPUNIT_ASSERT(pe->swap_dirn == 0);
244 CPPUNIT_ASSERT(pe->swap_filen >= 0);
245
246 // Rock::IoState::finishedWriting() schedules an AsyncCall
247 // storeSwapOutFileClosed(). Let it fire.
248 StockEventLoop loop;
249 loop.run();
250
251 CPPUNIT_ASSERT(pe->swap_status == SWAPOUT_DONE);
252
253 pe->unlock();
254 }
255
256 CPPUNIT_ASSERT_EQUAL((uint64_t)5, store->currentCount());
257
258 // try to swap out entry to a used unlocked slot
259 {
260 StoreEntry *const pe = addEntry(4);
261
262 CPPUNIT_ASSERT(pe->swap_status == SWAPOUT_WRITING);
263 CPPUNIT_ASSERT(pe->swap_dirn == 0);
264 CPPUNIT_ASSERT(pe->swap_filen >= 0);
265
266 StockEventLoop loop;
267 loop.run();
268
269 CPPUNIT_ASSERT(pe->swap_status == SWAPOUT_DONE);
270 }
271
272 // try to swap out entry to a used locked slot
273 {
274 StoreEntry *const pe = addEntry(5);
275
276 CPPUNIT_ASSERT(pe->swap_status == SWAPOUT_WRITING);
277 CPPUNIT_ASSERT(pe->swap_dirn == 0);
278 CPPUNIT_ASSERT(pe->swap_filen >= 0);
279
280 // the slot is locked here because the async calls have not run yet
281 StoreEntry *const pe2 = addEntry(5);
282 CPPUNIT_ASSERT(pe2->swap_status == SWAPOUT_NONE);
283 CPPUNIT_ASSERT(pe2->mem_obj->swapout.decision ==
284 MemObject::SwapOut::swImpossible);
285 CPPUNIT_ASSERT(pe2->swap_dirn == -1);
286 CPPUNIT_ASSERT(pe2->swap_filen == -1);
287
288 StockEventLoop loop;
289 loop.run();
290 }
291
292 CPPUNIT_ASSERT_EQUAL((uint64_t)6, store->currentCount());
293
294 // try to get and unlink entries
295 for (int i = 0; i < 6; ++i) {
296 StoreEntry *const pe = getEntry(i);
297 CPPUNIT_ASSERT(pe != NULL);
298
299 pe->unlink();
300
301 StoreEntry *const pe2 = getEntry(i);
302 CPPUNIT_ASSERT(pe2 == NULL);
303 }
304}