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