1 #define SQUID_UNIT_TEST 1
4 #include "DiskIO/DiskIOModule.h"
5 #include "fs/rock/RockSwapDir.h"
7 #include "HttpHeader.h"
10 #include "MemObject.h"
11 #include "RequestFlags.h"
12 #include "SquidConfig.h"
14 #include "StoreFileSystem.h"
15 #include "StoreSearch.h"
18 #include "testStoreSupport.h"
27 #define TESTDIR "testRock__testRockSearch"
29 CPPUNIT_TEST_SUITE_REGISTRATION( testRock
);
31 extern REMOVALPOLICYCREATE createRemovalPolicy_lru
;
34 addSwapDir(testRock::SwapDirPointer aStore
)
36 allocate_new_swapdir(&Config
.cacheSwap
);
37 Config
.cacheSwap
.swapDirs
[Config
.cacheSwap
.n_configured
] = aStore
.getRaw();
38 ++Config
.cacheSwap
.n_configured
;
44 CPPUNIT_NS::TestFixture::setUp();
46 if (0 > system ("rm -rf " TESTDIR
))
47 throw std::runtime_error("Failed to clean test work directory");
49 // use current directory for shared segments (on path-based OSes)
50 Ipc::Mem::Segment::BasePath
= ".";
52 Store::Root(new StoreController
);
54 store
= new Rock::SwapDir();
60 char *path
=xstrdup(TESTDIR
);
62 char *config_line
=xstrdup("foo 10 max-size=16384");
64 strtok(config_line
, w_space
);
66 store
->parse(0, path
);
70 safe_free(config_line
);
72 /* ok, ready to create */
75 rr
= new Rock::SwapDirRr
;
76 rr
->run(rrAfterConfig
);
82 CPPUNIT_NS::TestFixture::tearDown();
88 free_cachedir(&Config
.cacheSwap
);
92 // TODO: do this once, or each time.
93 // safe_free(Config.replPolicy->type);
94 // delete Config.replPolicy;
96 if (0 > system ("rm -rf " TESTDIR
))
97 throw std::runtime_error("Failed to clean test work directory");
101 testRock::commonInit()
103 static bool inited
= false;
108 StoreFileSystem::SetupAllFs();
110 Config
.Store
.avgObjectSize
= 1024;
112 Config
.Store
.objectsPerBucket
= 20;
114 Config
.Store
.maxObjectSize
= 2048;
116 Config
.store_dir_select_algorithm
= xstrdup("round-robin");
118 Config
.replPolicy
= new RemovalPolicySettings
;
120 Config
.replPolicy
->type
= xstrdup ("lru");
122 Config
.replPolicy
->args
= NULL
;
125 storeReplAdd("lru", createRemovalPolicy_lru
);
127 visible_appname_string
= xstrdup(APP_FULLNAME
);
133 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
135 httpReplyInitModule(); /* must go before accepting replies */
137 mem_policy
= createRemovalPolicy(Config
.replPolicy
);
143 testRock::storeInit()
145 /* ok, ready to use */
146 Store::Root().init();
148 /* rebuild is a scheduled event */
151 /* our swapdir must be scheduled to rebuild */
152 CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding
);
156 /* cannot use loop.run(); as the loop will never idle: the store-dir
157 * clean() scheduled event prevents it
160 /* nothing left to rebuild */
161 CPPUNIT_ASSERT_EQUAL(1, StoreController::store_dirs_rebuilding
);
165 testRock::createEntry(const int i
)
170 snprintf(url
, sizeof(url
), "dummy url %i", i
);
171 url
[sizeof(url
) - 1] = '\0';
172 StoreEntry
*const pe
=
173 storeCreateEntry(url
, "dummy log url", flags
, METHOD_GET
);
174 HttpReply
*const rep
= const_cast<HttpReply
*>(pe
->getReply());
175 rep
->setHeaders(HTTP_OK
, "dummy test object", "x-squid-internal/test",
176 -1, -1, squid_curtime
+ 100000);
184 testRock::addEntry(const int i
)
186 StoreEntry
*const pe
= createEntry(i
);
189 /* TODO: remove this when the metadata is separated */
192 packerToStoreInit(&p
, pe
);
193 pe
->getReply()->packHeadersInto(&p
);
206 testRock::getEntry(const int i
)
208 StoreEntry
*const pe
= createEntry(i
);
209 return store
->get(reinterpret_cast<const cache_key
*>(pe
->key
));
213 testRock::testRockCreate()
217 CPPUNIT_ASSERT(::stat(TESTDIR
, &sb
) == 0);
219 /* TODO: check the size */
221 /* TODO: test rebuild */
225 testRock::testRockSwapOut()
229 // add few entries to prime the database
230 for (int i
= 0; i
< 5; ++i
) {
231 CPPUNIT_ASSERT_EQUAL((uint64_t)i
, store
->currentCount());
233 StoreEntry
*const pe
= addEntry(i
);
235 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
236 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
237 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
239 // Rock::IoState::finishedWriting() schedules an AsyncCall
240 // storeSwapOutFileClosed(). Let it fire.
244 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_DONE
);
249 CPPUNIT_ASSERT_EQUAL((uint64_t)5, store
->currentCount());
251 // try to swap out entry to a used unlocked slot
253 StoreEntry
*const pe
= addEntry(4);
255 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
256 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
257 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
262 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_DONE
);
265 // try to swap out entry to a used locked slot
267 StoreEntry
*const pe
= addEntry(5);
269 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
270 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
271 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
273 // the slot is locked here because the async calls have not run yet
274 StoreEntry
*const pe2
= addEntry(5);
275 CPPUNIT_ASSERT(pe2
->swap_status
== SWAPOUT_NONE
);
276 CPPUNIT_ASSERT(pe2
->mem_obj
->swapout
.decision
==
277 MemObject::SwapOut::swImpossible
);
278 CPPUNIT_ASSERT(pe2
->swap_dirn
== -1);
279 CPPUNIT_ASSERT(pe2
->swap_filen
== -1);
285 CPPUNIT_ASSERT_EQUAL((uint64_t)6, store
->currentCount());
287 // try to get and unlink entries
288 for (int i
= 0; i
< 6; ++i
) {
289 StoreEntry
*const pe
= getEntry(i
);
290 CPPUNIT_ASSERT(pe
!= NULL
);
294 StoreEntry
*const pe2
= getEntry(i
);
295 CPPUNIT_ASSERT(pe2
== NULL
);