1 #define SQUID_UNIT_TEST 1
4 #include "DiskIO/DiskIOModule.h"
5 #include "fs/ufs/UFSSwapDir.h"
7 #include "HttpHeader.h"
10 #include "MemObject.h"
11 #include "RequestFlags.h"
12 #include "SquidConfig.h"
15 #include "testStoreSupport.h"
22 #define TESTDIR "testUfs__testUfsSearch"
24 CPPUNIT_TEST_SUITE_REGISTRATION( testUfs
);
26 typedef RefCount
<Fs::Ufs::UFSSwapDir
> SwapDirPointer
;
27 extern REMOVALPOLICYCREATE createRemovalPolicy_lru
; /* XXX fails with --enable-removal-policies=heap */
30 addSwapDir(SwapDirPointer aStore
)
32 allocate_new_swapdir(&Config
.cacheSwap
);
33 Config
.cacheSwap
.swapDirs
[Config
.cacheSwap
.n_configured
] = aStore
.getRaw();
34 ++Config
.cacheSwap
.n_configured
;
37 /* TODO make this a cbdata class */
42 searchCallback(void *cbdata
)
50 static bool inited
= false;
55 Config
.Store
.avgObjectSize
= 1024;
57 Config
.Store
.objectsPerBucket
= 20;
59 Config
.Store
.maxObjectSize
= 2048;
61 Config
.store_dir_select_algorithm
= xstrdup("round-robin");
63 Config
.replPolicy
= new RemovalPolicySettings
;
65 Config
.replPolicy
->type
= xstrdup ("lru");
68 storeReplAdd("lru", createRemovalPolicy_lru
);
74 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
76 httpReplyInitModule(); /* must go before accepting replies */
82 testUfs::testUfsSearch()
85 * make a valid working ufs swapdir
86 * put two entries in it and sync logs
88 * check the entries we find are what we want
91 if (0 > system ("rm -rf " TESTDIR
))
92 throw std::runtime_error("Failed to clean test work directory");
94 Store::Root(new StoreController
);
96 SwapDirPointer
aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
98 aStore
->IO
= new Fs::Ufs::UFSStrategy(DiskIOModule::Find("Blocking")->createStrategy());
103 mem_policy
= createRemovalPolicy(Config
.replPolicy
);
105 char *path
=xstrdup(TESTDIR
);
107 char *config_line
=xstrdup("foo 100 1 1");
109 visible_appname_string
= xstrdup(PACKAGE
"/" VERSION
);
111 strtok(config_line
, w_space
);
113 aStore
->parse(0, path
);
114 store_maxobjsize
= 1024*1024*2;
118 safe_free(config_line
);
120 /* ok, ready to create */
123 /* ok, ready to use - inits store & hash too */
124 Store::Root().init();
126 /* our swapdir must be scheduled to rebuild */
127 CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding
);
129 /* rebuild is a scheduled event */
132 while (StoreController::store_dirs_rebuilding
> 1)
135 /* cannot use loop.run(); as the loop will never idle: the store-dir
136 * clean() scheduled event prevents it
139 /* nothing left to rebuild */
140 CPPUNIT_ASSERT_EQUAL(1, StoreController::store_dirs_rebuilding
);
144 /* Create "vary" base object */
146 flags
.cachable
= true;
147 StoreEntry
*pe
= storeCreateEntry("dummy url", "dummy log url", flags
, Http::METHOD_GET
);
148 HttpReply
*rep
= (HttpReply
*) pe
->getReply(); // bypass const
149 rep
->setHeaders(HTTP_OK
, "dummy test object", "x-squid-internal/test", 0, -1, squid_curtime
+ 100000);
154 /* TODO: remove this when the metadata is separated */
157 packerToStoreInit(&p
, pe
);
158 pe
->getReply()->packHeadersInto(&p
);
166 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
167 CPPUNIT_ASSERT(pe
->swap_filen
== 0);
171 storeDirWriteCleanLogs(0);
173 /* here we cheat: we know that UFSSwapDirs search off disk. If we did an init call to a new
174 * swapdir instance, we'd not be testing a clean build.
176 StoreSearchPointer search
= aStore
->search (NULL
, NULL
); /* search for everything in the store */
178 /* nothing should be immediately available */
181 CPPUNIT_ASSERT(search
->next() == false);
184 CPPUNIT_ASSERT(search
->error() == false);
185 CPPUNIT_ASSERT(search
->isDone() == false);
186 CPPUNIT_ASSERT(search
->currentItem() == NULL
);
188 /* trigger a callback */
190 search
->next(searchCallback
, NULL
);
191 CPPUNIT_ASSERT(cbcalled
== true);
193 /* we should have access to a entry now, that matches the entry we had before */
194 //CPPUNIT_ASSERT(search->next() == false);
195 CPPUNIT_ASSERT(search
->error() == false);
196 CPPUNIT_ASSERT(search
->isDone() == false);
197 CPPUNIT_ASSERT(search
->currentItem() != NULL
);
199 /* trigger another callback */
201 search
->next(searchCallback
, NULL
);
202 CPPUNIT_ASSERT(cbcalled
== true);
204 /* now we should have no error, we should have finished and have no current item */
205 //CPPUNIT_ASSERT(search->next() == false);
206 CPPUNIT_ASSERT(search
->error() == false);
207 CPPUNIT_ASSERT(search
->isDone() == true);
208 CPPUNIT_ASSERT(search
->currentItem() == NULL
);
212 free_cachedir(&Config
.cacheSwap
);
214 /* todo: here we should test a dirty rebuild */
216 safe_free(Config
.replPolicy
->type
);
217 delete Config
.replPolicy
;
219 if (0 > system ("rm -rf " TESTDIR
))
220 throw std::runtime_error("Failed to clean test work directory");
223 /* The UFS store should always configure an IO engine even if none is
224 * supplied on the configuration line.
227 testUfs::testUfsDefaultEngine()
229 /* boring common test boilerplate */
230 if (0 > system ("rm -rf " TESTDIR
))
231 throw std::runtime_error("Failed to clean test work directory");
233 // This assertion may fail if previous test cases fail.
234 // Apparently, CPPUNIT_ASSERT* failure may prevent destructors of local
235 // objects such as "StorePointer aRoot" from being called.
236 CPPUNIT_ASSERT(!store_table
); // or StoreHashIndex ctor will abort below
238 Store::Root(new StoreController
);
239 SwapDirPointer
aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
242 Config
.replPolicy
= new RemovalPolicySettings
;
243 Config
.replPolicy
->type
= xstrdup ("lru");
244 mem_policy
= createRemovalPolicy(Config
.replPolicy
);
246 char *path
=xstrdup(TESTDIR
);
247 char *config_line
=xstrdup("foo 100 1 1");
248 strtok(config_line
, w_space
);
249 aStore
->parse(0, path
);
251 safe_free(config_line
);
252 CPPUNIT_ASSERT(aStore
->IO
->io
!= NULL
);
255 free_cachedir(&Config
.cacheSwap
);
256 safe_free(Config
.replPolicy
->type
);
257 delete Config
.replPolicy
;
259 if (0 > system ("rm -rf " TESTDIR
))
260 throw std::runtime_error("Failed to clean test work directory");