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