]> git.ipfire.org Git - thirdparty/squid.git/blob - src/tests/testUfs.cc
Merge from trunk rev.14061
[thirdparty/squid.git] / src / tests / testUfs.cc
1 /*
2 * Copyright (C) 1996-2015 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 "DiskIO/DiskIOModule.h"
11 #include "fs/ufs/UFSSwapDir.h"
12 #include "globals.h"
13 #include "HttpHeader.h"
14 #include "HttpReply.h"
15 #include "MemObject.h"
16 #include "Packer.h"
17 #include "RequestFlags.h"
18 #include "SquidConfig.h"
19 #include "Store.h"
20 #include "SwapDir.h"
21 #include "testStoreSupport.h"
22 #include "testUfs.h"
23 #include "unitTestMain.h"
24
25 #include <stdexcept>
26
27 #define TESTDIR "testUfs_Store"
28
29 CPPUNIT_TEST_SUITE_REGISTRATION( testUfs );
30
31 typedef RefCount<Fs::Ufs::UFSSwapDir> SwapDirPointer;
32 extern REMOVALPOLICYCREATE createRemovalPolicy_lru; /* XXX fails with --enable-removal-policies=heap */
33
34 static void
35 addSwapDir(SwapDirPointer aStore)
36 {
37 allocate_new_swapdir(&Config.cacheSwap);
38 Config.cacheSwap.swapDirs[Config.cacheSwap.n_configured] = aStore.getRaw();
39 ++Config.cacheSwap.n_configured;
40 }
41
42 /* TODO make this a cbdata class */
43
44 static bool cbcalled;
45
46 static void
47 searchCallback(void *cbdata)
48 {
49 cbcalled = true;
50 }
51
52 void
53 testUfs::commonInit()
54 {
55 static bool inited = false;
56
57 if (inited)
58 return;
59
60 Config.Store.avgObjectSize = 1024;
61 Config.Store.objectsPerBucket = 20;
62 Config.Store.maxObjectSize = 2048;
63
64 Config.store_dir_select_algorithm = xstrdup("round-robin");
65
66 Config.replPolicy = new RemovalPolicySettings;
67 Config.replPolicy->type = xstrdup("lru");
68
69 /* garh garh */
70 storeReplAdd("lru", createRemovalPolicy_lru);
71
72 Mem::Init();
73
74 comm_init();
75
76 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
77
78 httpReplyInitModule(); /* must go before accepting replies */
79
80 inited = true;
81 }
82
83 void
84 testUfs::testUfsSearch()
85 {
86 /* test sequence
87 * make a valid working ufs swapdir
88 * put two entries in it and sync logs
89 * search the ufs dir
90 * check the entries we find are what we want
91 */
92
93 if (0 > system ("rm -rf " TESTDIR))
94 throw std::runtime_error("Failed to clean test work directory");
95
96 Store::Root(new StoreController);
97
98 SwapDirPointer aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
99
100 aStore->IO = new Fs::Ufs::UFSStrategy(DiskIOModule::Find("Blocking")->createStrategy());
101
102 addSwapDir(aStore);
103
104 commonInit();
105 mem_policy = createRemovalPolicy(Config.replPolicy);
106
107 char *path=xstrdup(TESTDIR);
108
109 char *config_line=xstrdup("100 1 1");
110
111 visible_appname_string = xstrdup(PACKAGE "/" VERSION);
112
113 ConfigParser::SetCfgLine(config_line);
114
115 aStore->parse(0, path);
116 store_maxobjsize = 1024*1024*2;
117
118 safe_free(path);
119
120 safe_free(config_line);
121
122 /* ok, ready to create */
123 aStore->create();
124
125 /* ok, ready to use - inits store & hash too */
126 Store::Root().init();
127
128 /* our swapdir must be scheduled to rebuild */
129 CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding);
130
131 /* rebuild is a scheduled event */
132 StockEventLoop loop;
133
134 while (StoreController::store_dirs_rebuilding)
135 loop.runOnce();
136
137 /* cannot use loop.run(); as the loop will never idle: the store-dir
138 * clean() scheduled event prevents it
139 */
140
141 /* nothing left to rebuild */
142 CPPUNIT_ASSERT_EQUAL(0, StoreController::store_dirs_rebuilding);
143
144 /* add an entry */
145 {
146 /* Create "vary" base object */
147 RequestFlags flags;
148 flags.cachable = true;
149 StoreEntry *pe = storeCreateEntry("dummy url", "dummy log url", flags, Http::METHOD_GET);
150 HttpReply *rep = (HttpReply *) pe->getReply(); // bypass const
151 rep->setHeaders(Http::scOkay, "dummy test object", "x-squid-internal/test", 0, -1, squid_curtime + 100000);
152
153 pe->setPublicKey();
154
155 pe->buffer();
156 /* TODO: remove this when the metadata is separated */
157 {
158 Packer p;
159 packerToStoreInit(&p, pe);
160 pe->getReply()->packHeadersInto(&p);
161 }
162
163 pe->flush();
164 pe->timestampsSet();
165 pe->complete();
166 pe->swapOut();
167 CPPUNIT_ASSERT_EQUAL(0, pe->swap_dirn);
168 CPPUNIT_ASSERT_EQUAL(0, pe->swap_filen);
169 pe->unlock("testUfs::testUfsSearch vary");
170 }
171
172 storeDirWriteCleanLogs(0);
173
174 /* here we cheat: we know that UFSSwapDirs search off disk. If we did an init call to a new
175 * swapdir instance, we'd not be testing a clean build.
176 */
177 StoreSearchPointer search = aStore->search (NULL, NULL); /* search for everything in the store */
178
179 /* nothing should be immediately available */
180 #if 0
181
182 CPPUNIT_ASSERT_EQUAL(false, search->next());
183 #endif
184
185 CPPUNIT_ASSERT_EQUAL(false, search->error());
186 CPPUNIT_ASSERT_EQUAL(false, search->isDone());
187 CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
188
189 /* trigger a callback */
190 cbcalled = false;
191 search->next(searchCallback, NULL);
192 CPPUNIT_ASSERT_EQUAL(true, cbcalled);
193
194 /* we should have access to a entry now, that matches the entry we had before */
195 //CPPUNIT_ASSERT_EQUAL(false, search->next());
196 CPPUNIT_ASSERT_EQUAL(false, search->error());
197 CPPUNIT_ASSERT_EQUAL(false, search->isDone());
198 CPPUNIT_ASSERT(search->currentItem() != NULL);
199
200 /* trigger another callback */
201 cbcalled = false;
202 search->next(searchCallback, NULL);
203 CPPUNIT_ASSERT_EQUAL(true, cbcalled);
204
205 /* now we should have no error, we should have finished and have no current item */
206 //CPPUNIT_ASSERT_EQUAL(false, search->next());
207 CPPUNIT_ASSERT_EQUAL(false, search->error());
208 CPPUNIT_ASSERT_EQUAL(true, search->isDone());
209 CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(NULL), search->currentItem());
210
211 Store::Root(NULL);
212
213 free_cachedir(&Config.cacheSwap);
214
215 /* todo: here we should test a dirty rebuild */
216
217 safe_free(Config.replPolicy->type);
218 delete Config.replPolicy;
219
220 if (0 > system ("rm -rf " TESTDIR))
221 throw std::runtime_error("Failed to clean test work directory");
222 }
223
224 /* The UFS store should always configure an IO engine even if none is
225 * supplied on the configuration line.
226 */
227 void
228 testUfs::testUfsDefaultEngine()
229 {
230 /* boring common test boilerplate */
231 if (0 > system ("rm -rf " TESTDIR))
232 throw std::runtime_error("Failed to clean test work directory");
233
234 // This assertion may fail if previous test cases fail.
235 // Apparently, CPPUNIT_ASSERT* failure may prevent destructors of local
236 // objects such as "StorePointer aRoot" from being called.
237 CPPUNIT_ASSERT(!store_table); // or StoreHashIndex ctor will abort below
238
239 Store::Root(new StoreController);
240 SwapDirPointer aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
241 addSwapDir(aStore);
242 commonInit();
243 Config.replPolicy = new RemovalPolicySettings;
244 Config.replPolicy->type = xstrdup("lru");
245 mem_policy = createRemovalPolicy(Config.replPolicy);
246
247 char *path=xstrdup(TESTDIR);
248 char *config_line=xstrdup("100 1 1");
249 ConfigParser::SetCfgLine(config_line);
250 aStore->parse(0, path);
251 safe_free(path);
252 safe_free(config_line);
253 CPPUNIT_ASSERT(aStore->IO->io != NULL);
254
255 Store::Root(NULL);
256 free_cachedir(&Config.cacheSwap);
257 safe_free(Config.replPolicy->type);
258 delete Config.replPolicy;
259
260 if (0 > system ("rm -rf " TESTDIR))
261 throw std::runtime_error("Failed to clean test work directory");
262 }
263