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