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