]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tests/testRock.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / tests / testRock.cc
CommitLineData
4e0938ef 1/*
f70aedc4 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
4e0938ef
AJ
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
f7f3304a 9#include "squid.h"
2eceb328 10#include "ConfigParser.h"
9bb01611 11#include "DiskIO/DiskIOModule.h"
d7ca82e6 12#include "fde.h"
582c2af2
FC
13#include "fs/rock/RockSwapDir.h"
14#include "globals.h"
9bb01611
AR
15#include "HttpHeader.h"
16#include "HttpReply.h"
9bb01611 17#include "MemObject.h"
f206b652 18#include "RequestFlags.h"
4d5904f7 19#include "SquidConfig.h"
9bb01611 20#include "Store.h"
2745fea5
AR
21#include "store/Disk.h"
22#include "store/Disks.h"
9bb01611
AR
23#include "StoreFileSystem.h"
24#include "StoreSearch.h"
9bb01611
AR
25#include "testRock.h"
26#include "testStoreSupport.h"
7f861c77
AJ
27#include "unitTestMain.h"
28
074d6a40 29#include <stdexcept>
582c2af2
FC
30#if HAVE_SYS_STAT_H
31#include <sys/stat.h>
32#endif
1dccf1c6
FC
33#if HAVE_UNISTD_H
34#include <unistd.h>
35#endif
9bb01611 36
e852298f 37#define TESTDIR "tr"
9bb01611
AR
38
39CPPUNIT_TEST_SUITE_REGISTRATION( testRock );
40
41extern REMOVALPOLICYCREATE createRemovalPolicy_lru;
42
1dccf1c6
FC
43static char cwd[MAXPATHLEN];
44
9bb01611
AR
45static void
46addSwapDir(testRock::SwapDirPointer aStore)
47{
5d84beb5 48 allocate_new_swapdir(Config.cacheSwap);
9bb01611
AR
49 Config.cacheSwap.swapDirs[Config.cacheSwap.n_configured] = aStore.getRaw();
50 ++Config.cacheSwap.n_configured;
51}
52
53void
54testRock::setUp()
55{
56 CPPUNIT_NS::TestFixture::setUp();
57
58 if (0 > system ("rm -rf " TESTDIR))
59 throw std::runtime_error("Failed to clean test work directory");
60
c50b35b5 61 Config.memShared.defaultTo(false);
c756d517 62 Config.shmLocking.defaultTo(false);
c50b35b5 63
ef8de464 64 // use current directory for shared segments (on path-based OSes)
1dccf1c6
FC
65 Ipc::Mem::Segment::BasePath = getcwd(cwd,MAXPATHLEN);
66 if (Ipc::Mem::Segment::BasePath == NULL)
67 Ipc::Mem::Segment::BasePath = ".";
ef8de464 68
2745fea5 69 Store::Init();
9bb01611
AR
70
71 store = new Rock::SwapDir();
72
73 addSwapDir(store);
74
75 commonInit();
76
77 char *path=xstrdup(TESTDIR);
78
2eceb328 79 char *config_line=xstrdup("10 max-size=16384");
9bb01611 80
2eceb328 81 ConfigParser::SetCfgLine(config_line);
9bb01611
AR
82
83 store->parse(0, path);
b51ec8c8 84 store_maxobjsize = 1024*1024*2;
9bb01611
AR
85
86 safe_free(path);
87
88 safe_free(config_line);
89
90 /* ok, ready to create */
91 store->create();
92
93 rr = new Rock::SwapDirRr;
21b7990f 94 rr->useConfig();
9bb01611
AR
95}
96
97void
98testRock::tearDown()
99{
100 CPPUNIT_NS::TestFixture::tearDown();
101
2745fea5 102 Store::FreeMemory();
9bb01611
AR
103
104 store = NULL;
105
106 free_cachedir(&Config.cacheSwap);
107
21b7990f
AR
108 rr->finishShutdown(); // deletes rr
109 rr = NULL;
9bb01611
AR
110
111 // TODO: do this once, or each time.
112 // safe_free(Config.replPolicy->type);
113 // delete Config.replPolicy;
114
115 if (0 > system ("rm -rf " TESTDIR))
116 throw std::runtime_error("Failed to clean test work directory");
117}
118
119void
120testRock::commonInit()
121{
122 static bool inited = false;
123
124 if (inited)
125 return;
126
127 StoreFileSystem::SetupAllFs();
128
129 Config.Store.avgObjectSize = 1024;
9bb01611 130 Config.Store.objectsPerBucket = 20;
9bb01611
AR
131 Config.Store.maxObjectSize = 2048;
132
133 Config.store_dir_select_algorithm = xstrdup("round-robin");
134
135 Config.replPolicy = new RemovalPolicySettings;
86c63190 136 Config.replPolicy->type = xstrdup("lru");
9bb01611
AR
137 Config.replPolicy->args = NULL;
138
139 /* garh garh */
140 storeReplAdd("lru", createRemovalPolicy_lru);
141
142 visible_appname_string = xstrdup(APP_FULLNAME);
143
144 Mem::Init();
145
d7ca82e6
EB
146 fde::Init();
147
9bb01611
AR
148 comm_init();
149
f53969cc 150 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
9bb01611 151
9bb01611
AR
152 mem_policy = createRemovalPolicy(Config.replPolicy);
153
154 inited = true;
155}
156
157void
158testRock::storeInit()
159{
160 /* ok, ready to use */
161 Store::Root().init();
162
163 /* rebuild is a scheduled event */
164 StockEventLoop loop;
165
166 /* our swapdir must be scheduled to rebuild */
167 CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding);
168
169 loop.run();
170
171 /* cannot use loop.run(); as the loop will never idle: the store-dir
172 * clean() scheduled event prevents it
173 */
174
175 /* nothing left to rebuild */
02c267b0
AR
176 CPPUNIT_ASSERT_EQUAL(0, StoreController::store_dirs_rebuilding);
177}
178
179static const char *
180storeId(const int i)
181{
182 static char buf[64];
183 snprintf(buf, sizeof(buf), "dummy url %i", i);
184 buf[sizeof(buf) - 1] = '\0';
185 return buf;
9bb01611
AR
186}
187
188StoreEntry *
189testRock::createEntry(const int i)
190{
f206b652 191 RequestFlags flags;
e857372a 192 flags.cachable = true;
9bb01611 193 StoreEntry *const pe =
02c267b0 194 storeCreateEntry(storeId(i), "dummy log url", flags, Http::METHOD_GET);
66d51f4f
AR
195 auto &rep = pe->mem().adjustableBaseReply();
196 rep.setHeaders(Http::scOkay, "dummy test object", "x-squid-internal/test", 0, -1, squid_curtime + 100000);
9bb01611
AR
197
198 pe->setPublicKey();
199
200 return pe;
201}
202
203StoreEntry *
204testRock::addEntry(const int i)
205{
206 StoreEntry *const pe = createEntry(i);
207
208 pe->buffer();
66d51f4f 209 pe->mem().freshestReply().packHeadersUsingSlowPacker(*pe);
9bb01611
AR
210 pe->flush();
211 pe->timestampsSet();
212 pe->complete();
213 pe->swapOut();
214
215 return pe;
216}
217
218StoreEntry *
219testRock::getEntry(const int i)
220{
02c267b0 221 return storeGetPublic(storeId(i), Http::METHOD_GET);
9bb01611
AR
222}
223
224void
225testRock::testRockCreate()
226{
227 struct stat sb;
228
5d1dff27 229 CPPUNIT_ASSERT_EQUAL(0, ::stat(TESTDIR, &sb));
9bb01611
AR
230
231 /* TODO: check the size */
232
233 /* TODO: test rebuild */
234}
235
236void
237testRock::testRockSwapOut()
238{
239 storeInit();
240
241 // add few entries to prime the database
242 for (int i = 0; i < 5; ++i) {
243 CPPUNIT_ASSERT_EQUAL((uint64_t)i, store->currentCount());
244
245 StoreEntry *const pe = addEntry(i);
246
5d1dff27
FC
247 CPPUNIT_ASSERT_EQUAL(SWAPOUT_WRITING, pe->swap_status);
248 CPPUNIT_ASSERT_EQUAL(0, pe->swap_dirn);
9bb01611
AR
249 CPPUNIT_ASSERT(pe->swap_filen >= 0);
250
251 // Rock::IoState::finishedWriting() schedules an AsyncCall
252 // storeSwapOutFileClosed(). Let it fire.
253 StockEventLoop loop;
254 loop.run();
255
5d1dff27 256 CPPUNIT_ASSERT_EQUAL(SWAPOUT_DONE, pe->swap_status);
9bb01611 257
02c267b0 258 pe->unlock("testRock::testRockSwapOut priming");
9bb01611
AR
259 }
260
261 CPPUNIT_ASSERT_EQUAL((uint64_t)5, store->currentCount());
262
263 // try to swap out entry to a used unlocked slot
264 {
4310f8b0
EB
265 // without marking the old entry as deleted
266 StoreEntry *const pe = addEntry(3);
9bb01611 267
4310f8b0
EB
268 CPPUNIT_ASSERT_EQUAL(SWAPOUT_NONE, pe->swap_status);
269 CPPUNIT_ASSERT_EQUAL(-1, pe->swap_dirn);
270 CPPUNIT_ASSERT_EQUAL(-1, pe->swap_filen);
271 pe->unlock("testRock::testRockSwapOut e#3");
272
273 // after marking the old entry as deleted
274 StoreEntry *const pe2 = getEntry(4);
275 CPPUNIT_ASSERT(pe2 != nullptr);
276 pe2->release();
277
278 StoreEntry *const pe3 = addEntry(4);
279 CPPUNIT_ASSERT_EQUAL(SWAPOUT_WRITING, pe3->swap_status);
280 CPPUNIT_ASSERT_EQUAL(0, pe3->swap_dirn);
281 CPPUNIT_ASSERT(pe3->swap_filen >= 0);
9bb01611
AR
282
283 StockEventLoop loop;
284 loop.run();
285
4310f8b0 286 CPPUNIT_ASSERT_EQUAL(SWAPOUT_DONE, pe3->swap_status);
02c267b0
AR
287
288 pe->unlock("testRock::testRockSwapOut e#4");
9bb01611
AR
289 }
290
291 // try to swap out entry to a used locked slot
292 {
293 StoreEntry *const pe = addEntry(5);
294
5d1dff27
FC
295 CPPUNIT_ASSERT_EQUAL(SWAPOUT_WRITING, pe->swap_status);
296 CPPUNIT_ASSERT_EQUAL(0, pe->swap_dirn);
9bb01611
AR
297 CPPUNIT_ASSERT(pe->swap_filen >= 0);
298
299 // the slot is locked here because the async calls have not run yet
300 StoreEntry *const pe2 = addEntry(5);
5d1dff27
FC
301 CPPUNIT_ASSERT_EQUAL(SWAPOUT_NONE, pe2->swap_status);
302 CPPUNIT_ASSERT_EQUAL(MemObject::SwapOut::swImpossible, pe2->mem_obj->swapout.decision);
303 CPPUNIT_ASSERT_EQUAL(-1, pe2->swap_dirn);
304 CPPUNIT_ASSERT_EQUAL(-1, pe2->swap_filen);
9bb01611
AR
305
306 StockEventLoop loop;
307 loop.run();
02c267b0
AR
308
309 pe->unlock("testRock::testRockSwapOut e#5.1");
310 pe2->unlock("testRock::testRockSwapOut e#5.2");
311
312 // pe2 has the same public key as pe so it marks old pe for release
313 // here, we add another entry #5 into the now-available slot
314 StoreEntry *const pe3 = addEntry(5);
315 CPPUNIT_ASSERT_EQUAL(SWAPOUT_WRITING, pe3->swap_status);
316 CPPUNIT_ASSERT_EQUAL(0, pe3->swap_dirn);
317 CPPUNIT_ASSERT(pe3->swap_filen >= 0);
318 loop.run();
319 CPPUNIT_ASSERT_EQUAL(SWAPOUT_DONE, pe3->swap_status);
320 pe3->unlock("testRock::testRockSwapOut e#5.3");
9bb01611
AR
321 }
322
323 CPPUNIT_ASSERT_EQUAL((uint64_t)6, store->currentCount());
324
02c267b0 325 // try to get and release all entries
9bb01611
AR
326 for (int i = 0; i < 6; ++i) {
327 StoreEntry *const pe = getEntry(i);
328 CPPUNIT_ASSERT(pe != NULL);
329
02c267b0 330 pe->release(); // destroys pe
9bb01611
AR
331
332 StoreEntry *const pe2 = getEntry(i);
5d1dff27 333 CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), pe2);
9bb01611
AR
334 }
335}
f53969cc 336