]> git.ipfire.org Git - thirdparty/squid.git/blob - src/tests/testRock.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / tests / testRock.cc
1 /*
2 * Copyright (C) 1996-2018 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 "ConfigParser.h"
11 #include "DiskIO/DiskIOModule.h"
12 #include "fs/rock/RockSwapDir.h"
13 #include "globals.h"
14 #include "HttpHeader.h"
15 #include "HttpReply.h"
16 #include "MemObject.h"
17 #include "RequestFlags.h"
18 #include "SquidConfig.h"
19 #include "Store.h"
20 #include "store/Disk.h"
21 #include "store/Disks.h"
22 #include "StoreFileSystem.h"
23 #include "StoreSearch.h"
24 #include "testRock.h"
25 #include "testStoreSupport.h"
26 #include "unitTestMain.h"
27
28 #include <stdexcept>
29 #if HAVE_SYS_STAT_H
30 #include <sys/stat.h>
31 #endif
32 #if HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #define TESTDIR "tr"
37
38 CPPUNIT_TEST_SUITE_REGISTRATION( testRock );
39
40 extern REMOVALPOLICYCREATE createRemovalPolicy_lru;
41
42 static char cwd[MAXPATHLEN];
43
44 static void
45 addSwapDir(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
52 void
53 testRock::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
60 Config.memShared.defaultTo(false);
61 Config.shmLocking.defaultTo(false);
62
63 // use current directory for shared segments (on path-based OSes)
64 Ipc::Mem::Segment::BasePath = getcwd(cwd,MAXPATHLEN);
65 if (Ipc::Mem::Segment::BasePath == NULL)
66 Ipc::Mem::Segment::BasePath = ".";
67
68 Store::Init();
69
70 store = new Rock::SwapDir();
71
72 addSwapDir(store);
73
74 commonInit();
75
76 char *path=xstrdup(TESTDIR);
77
78 char *config_line=xstrdup("10 max-size=16384");
79
80 ConfigParser::SetCfgLine(config_line);
81
82 store->parse(0, path);
83 store_maxobjsize = 1024*1024*2;
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;
93 rr->useConfig();
94 }
95
96 void
97 testRock::tearDown()
98 {
99 CPPUNIT_NS::TestFixture::tearDown();
100
101 Store::FreeMemory();
102
103 store = NULL;
104
105 free_cachedir(&Config.cacheSwap);
106
107 rr->finishShutdown(); // deletes rr
108 rr = NULL;
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
118 void
119 testRock::commonInit()
120 {
121 static bool inited = false;
122
123 if (inited)
124 return;
125
126 StoreFileSystem::SetupAllFs();
127
128 Config.Store.avgObjectSize = 1024;
129 Config.Store.objectsPerBucket = 20;
130 Config.Store.maxObjectSize = 2048;
131
132 Config.store_dir_select_algorithm = xstrdup("round-robin");
133
134 Config.replPolicy = new RemovalPolicySettings;
135 Config.replPolicy->type = xstrdup("lru");
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
147 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
148
149 mem_policy = createRemovalPolicy(Config.replPolicy);
150
151 inited = true;
152 }
153
154 void
155 testRock::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 */
173 CPPUNIT_ASSERT_EQUAL(0, StoreController::store_dirs_rebuilding);
174 }
175
176 static const char *
177 storeId(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;
183 }
184
185 StoreEntry *
186 testRock::createEntry(const int i)
187 {
188 RequestFlags flags;
189 flags.cachable = true;
190 StoreEntry *const pe =
191 storeCreateEntry(storeId(i), "dummy log url", flags, Http::METHOD_GET);
192 HttpReply *const rep = const_cast<HttpReply *>(pe->getReply());
193 rep->setHeaders(Http::scOkay, "dummy test object", "x-squid-internal/test", 0, -1, squid_curtime + 100000);
194
195 pe->setPublicKey();
196
197 return pe;
198 }
199
200 StoreEntry *
201 testRock::addEntry(const int i)
202 {
203 StoreEntry *const pe = createEntry(i);
204
205 pe->buffer();
206 pe->getReply()->packHeadersInto(pe);
207 pe->flush();
208 pe->timestampsSet();
209 pe->complete();
210 pe->swapOut();
211
212 return pe;
213 }
214
215 StoreEntry *
216 testRock::getEntry(const int i)
217 {
218 return storeGetPublic(storeId(i), Http::METHOD_GET);
219 }
220
221 void
222 testRock::testRockCreate()
223 {
224 struct stat sb;
225
226 CPPUNIT_ASSERT_EQUAL(0, ::stat(TESTDIR, &sb));
227
228 /* TODO: check the size */
229
230 /* TODO: test rebuild */
231 }
232
233 void
234 testRock::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
244 CPPUNIT_ASSERT_EQUAL(SWAPOUT_WRITING, pe->swap_status);
245 CPPUNIT_ASSERT_EQUAL(0, pe->swap_dirn);
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
253 CPPUNIT_ASSERT_EQUAL(SWAPOUT_DONE, pe->swap_status);
254
255 pe->unlock("testRock::testRockSwapOut priming");
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
264 CPPUNIT_ASSERT_EQUAL(SWAPOUT_WRITING, pe->swap_status);
265 CPPUNIT_ASSERT_EQUAL(0, pe->swap_dirn);
266 CPPUNIT_ASSERT(pe->swap_filen >= 0);
267
268 StockEventLoop loop;
269 loop.run();
270
271 CPPUNIT_ASSERT_EQUAL(SWAPOUT_DONE, pe->swap_status);
272
273 pe->unlock("testRock::testRockSwapOut e#4");
274 }
275
276 // try to swap out entry to a used locked slot
277 {
278 StoreEntry *const pe = addEntry(5);
279
280 CPPUNIT_ASSERT_EQUAL(SWAPOUT_WRITING, pe->swap_status);
281 CPPUNIT_ASSERT_EQUAL(0, pe->swap_dirn);
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);
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);
290
291 StockEventLoop loop;
292 loop.run();
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");
306 }
307
308 CPPUNIT_ASSERT_EQUAL((uint64_t)6, store->currentCount());
309
310 // try to get and release all entries
311 for (int i = 0; i < 6; ++i) {
312 StoreEntry *const pe = getEntry(i);
313 CPPUNIT_ASSERT(pe != NULL);
314
315 pe->release(); // destroys pe
316
317 StoreEntry *const pe2 = getEntry(i);
318 CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), pe2);
319 }
320 }
321