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