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