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