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"
12 #include "StoreFileSystem.h"
13 #include "StoreSearch.h"
16 #include "testStoreSupport.h"
25 #define TESTDIR "testRock__testRockSearch"
27 CPPUNIT_TEST_SUITE_REGISTRATION( testRock
);
29 extern REMOVALPOLICYCREATE createRemovalPolicy_lru
;
32 addSwapDir(testRock::SwapDirPointer aStore
)
34 allocate_new_swapdir(&Config
.cacheSwap
);
35 Config
.cacheSwap
.swapDirs
[Config
.cacheSwap
.n_configured
] = aStore
.getRaw();
36 ++Config
.cacheSwap
.n_configured
;
42 CPPUNIT_NS::TestFixture::setUp();
44 if (0 > system ("rm -rf " TESTDIR
))
45 throw std::runtime_error("Failed to clean test work directory");
47 // use current directory for shared segments (on path-based OSes)
48 Ipc::Mem::Segment::BasePath
= ".";
50 Store::Root(new StoreController
);
52 store
= new Rock::SwapDir();
58 char *path
=xstrdup(TESTDIR
);
60 char *config_line
=xstrdup("foo 10 max-size=16384");
62 strtok(config_line
, w_space
);
64 store
->parse(0, path
);
68 safe_free(config_line
);
70 /* ok, ready to create */
73 rr
= new Rock::SwapDirRr
;
74 rr
->run(rrAfterConfig
);
80 CPPUNIT_NS::TestFixture::tearDown();
86 free_cachedir(&Config
.cacheSwap
);
90 // TODO: do this once, or each time.
91 // safe_free(Config.replPolicy->type);
92 // delete Config.replPolicy;
94 if (0 > system ("rm -rf " TESTDIR
))
95 throw std::runtime_error("Failed to clean test work directory");
99 testRock::commonInit()
101 static bool inited
= false;
106 StoreFileSystem::SetupAllFs();
108 Config
.Store
.avgObjectSize
= 1024;
110 Config
.Store
.objectsPerBucket
= 20;
112 Config
.Store
.maxObjectSize
= 2048;
114 Config
.store_dir_select_algorithm
= xstrdup("round-robin");
116 Config
.replPolicy
= new RemovalPolicySettings
;
118 Config
.replPolicy
->type
= xstrdup ("lru");
120 Config
.replPolicy
->args
= NULL
;
123 storeReplAdd("lru", createRemovalPolicy_lru
);
125 visible_appname_string
= xstrdup(APP_FULLNAME
);
131 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
133 httpReplyInitModule(); /* must go before accepting replies */
135 mem_policy
= createRemovalPolicy(Config
.replPolicy
);
141 testRock::storeInit()
143 /* ok, ready to use */
144 Store::Root().init();
146 /* rebuild is a scheduled event */
149 /* our swapdir must be scheduled to rebuild */
150 CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding
);
154 /* cannot use loop.run(); as the loop will never idle: the store-dir
155 * clean() scheduled event prevents it
158 /* nothing left to rebuild */
159 CPPUNIT_ASSERT_EQUAL(1, StoreController::store_dirs_rebuilding
);
163 testRock::createEntry(const int i
)
168 snprintf(url
, sizeof(url
), "dummy url %i", i
);
169 url
[sizeof(url
) - 1] = '\0';
170 StoreEntry
*const pe
=
171 storeCreateEntry(url
, "dummy log url", flags
, METHOD_GET
);
172 HttpReply
*const rep
= const_cast<HttpReply
*>(pe
->getReply());
173 rep
->setHeaders(HTTP_OK
, "dummy test object", "x-squid-internal/test",
174 -1, -1, squid_curtime
+ 100000);
182 testRock::addEntry(const int i
)
184 StoreEntry
*const pe
= createEntry(i
);
187 /* TODO: remove this when the metadata is separated */
190 packerToStoreInit(&p
, pe
);
191 pe
->getReply()->packHeadersInto(&p
);
204 testRock::getEntry(const int i
)
206 StoreEntry
*const pe
= createEntry(i
);
207 return store
->get(reinterpret_cast<const cache_key
*>(pe
->key
));
211 testRock::testRockCreate()
215 CPPUNIT_ASSERT(::stat(TESTDIR
, &sb
) == 0);
217 /* TODO: check the size */
219 /* TODO: test rebuild */
223 testRock::testRockSwapOut()
227 // add few entries to prime the database
228 for (int i
= 0; i
< 5; ++i
) {
229 CPPUNIT_ASSERT_EQUAL((uint64_t)i
, store
->currentCount());
231 StoreEntry
*const pe
= addEntry(i
);
233 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
234 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
235 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
237 // Rock::IoState::finishedWriting() schedules an AsyncCall
238 // storeSwapOutFileClosed(). Let it fire.
242 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_DONE
);
247 CPPUNIT_ASSERT_EQUAL((uint64_t)5, store
->currentCount());
249 // try to swap out entry to a used unlocked slot
251 StoreEntry
*const pe
= addEntry(4);
253 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
254 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
255 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
260 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_DONE
);
263 // try to swap out entry to a used locked slot
265 StoreEntry
*const pe
= addEntry(5);
267 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
268 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
269 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
271 // the slot is locked here because the async calls have not run yet
272 StoreEntry
*const pe2
= addEntry(5);
273 CPPUNIT_ASSERT(pe2
->swap_status
== SWAPOUT_NONE
);
274 CPPUNIT_ASSERT(pe2
->mem_obj
->swapout
.decision
==
275 MemObject::SwapOut::swImpossible
);
276 CPPUNIT_ASSERT(pe2
->swap_dirn
== -1);
277 CPPUNIT_ASSERT(pe2
->swap_filen
== -1);
283 CPPUNIT_ASSERT_EQUAL((uint64_t)6, store
->currentCount());
285 // try to get and unlink entries
286 for (int i
= 0; i
< 6; ++i
) {
287 StoreEntry
*const pe
= getEntry(i
);
288 CPPUNIT_ASSERT(pe
!= NULL
);
292 StoreEntry
*const pe2
= getEntry(i
);
293 CPPUNIT_ASSERT(pe2
== NULL
);