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"
30 #define TESTDIR "testRock__testRockSearch"
32 CPPUNIT_TEST_SUITE_REGISTRATION( testRock
);
34 extern REMOVALPOLICYCREATE createRemovalPolicy_lru
;
36 static char cwd
[MAXPATHLEN
];
39 addSwapDir(testRock::SwapDirPointer aStore
)
41 allocate_new_swapdir(&Config
.cacheSwap
);
42 Config
.cacheSwap
.swapDirs
[Config
.cacheSwap
.n_configured
] = aStore
.getRaw();
43 ++Config
.cacheSwap
.n_configured
;
49 CPPUNIT_NS::TestFixture::setUp();
51 if (0 > system ("rm -rf " TESTDIR
))
52 throw std::runtime_error("Failed to clean test work directory");
54 // use current directory for shared segments (on path-based OSes)
55 Ipc::Mem::Segment::BasePath
= getcwd(cwd
,MAXPATHLEN
);
56 if (Ipc::Mem::Segment::BasePath
== NULL
)
57 Ipc::Mem::Segment::BasePath
= ".";
59 Store::Root(new StoreController
);
61 store
= new Rock::SwapDir();
67 char *path
=xstrdup(TESTDIR
);
69 char *config_line
=xstrdup("foo 10 max-size=16384");
71 strtok(config_line
, w_space
);
73 store
->parse(0, path
);
77 safe_free(config_line
);
79 /* ok, ready to create */
82 rr
= new Rock::SwapDirRr
;
83 rr
->run(rrAfterConfig
);
89 CPPUNIT_NS::TestFixture::tearDown();
95 free_cachedir(&Config
.cacheSwap
);
99 // TODO: do this once, or each time.
100 // safe_free(Config.replPolicy->type);
101 // delete Config.replPolicy;
103 if (0 > system ("rm -rf " TESTDIR
))
104 throw std::runtime_error("Failed to clean test work directory");
108 testRock::commonInit()
110 static bool inited
= false;
115 StoreFileSystem::SetupAllFs();
117 Config
.Store
.avgObjectSize
= 1024;
119 Config
.Store
.objectsPerBucket
= 20;
121 Config
.Store
.maxObjectSize
= 2048;
123 Config
.store_dir_select_algorithm
= xstrdup("round-robin");
125 Config
.replPolicy
= new RemovalPolicySettings
;
127 Config
.replPolicy
->type
= xstrdup ("lru");
129 Config
.replPolicy
->args
= NULL
;
132 storeReplAdd("lru", createRemovalPolicy_lru
);
134 visible_appname_string
= xstrdup(APP_FULLNAME
);
140 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
142 httpReplyInitModule(); /* must go before accepting replies */
144 mem_policy
= createRemovalPolicy(Config
.replPolicy
);
150 testRock::storeInit()
152 /* ok, ready to use */
153 Store::Root().init();
155 /* rebuild is a scheduled event */
158 /* our swapdir must be scheduled to rebuild */
159 CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding
);
163 /* cannot use loop.run(); as the loop will never idle: the store-dir
164 * clean() scheduled event prevents it
167 /* nothing left to rebuild */
168 CPPUNIT_ASSERT_EQUAL(1, StoreController::store_dirs_rebuilding
);
172 testRock::createEntry(const int i
)
177 snprintf(url
, sizeof(url
), "dummy url %i", i
);
178 url
[sizeof(url
) - 1] = '\0';
179 StoreEntry
*const pe
=
180 storeCreateEntry(url
, "dummy log url", flags
, Http::METHOD_GET
);
181 HttpReply
*const rep
= const_cast<HttpReply
*>(pe
->getReply());
182 rep
->setHeaders(HTTP_OK
, "dummy test object", "x-squid-internal/test",
183 -1, -1, squid_curtime
+ 100000);
191 testRock::addEntry(const int i
)
193 StoreEntry
*const pe
= createEntry(i
);
196 /* TODO: remove this when the metadata is separated */
199 packerToStoreInit(&p
, pe
);
200 pe
->getReply()->packHeadersInto(&p
);
213 testRock::getEntry(const int i
)
215 StoreEntry
*const pe
= createEntry(i
);
216 return store
->get(reinterpret_cast<const cache_key
*>(pe
->key
));
220 testRock::testRockCreate()
224 CPPUNIT_ASSERT(::stat(TESTDIR
, &sb
) == 0);
226 /* TODO: check the size */
228 /* TODO: test rebuild */
232 testRock::testRockSwapOut()
236 // add few entries to prime the database
237 for (int i
= 0; i
< 5; ++i
) {
238 CPPUNIT_ASSERT_EQUAL((uint64_t)i
, store
->currentCount());
240 StoreEntry
*const pe
= addEntry(i
);
242 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
243 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
244 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
246 // Rock::IoState::finishedWriting() schedules an AsyncCall
247 // storeSwapOutFileClosed(). Let it fire.
251 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_DONE
);
256 CPPUNIT_ASSERT_EQUAL((uint64_t)5, store
->currentCount());
258 // try to swap out entry to a used unlocked slot
260 StoreEntry
*const pe
= addEntry(4);
262 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
263 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
264 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
269 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_DONE
);
272 // try to swap out entry to a used locked slot
274 StoreEntry
*const pe
= addEntry(5);
276 CPPUNIT_ASSERT(pe
->swap_status
== SWAPOUT_WRITING
);
277 CPPUNIT_ASSERT(pe
->swap_dirn
== 0);
278 CPPUNIT_ASSERT(pe
->swap_filen
>= 0);
280 // the slot is locked here because the async calls have not run yet
281 StoreEntry
*const pe2
= addEntry(5);
282 CPPUNIT_ASSERT(pe2
->swap_status
== SWAPOUT_NONE
);
283 CPPUNIT_ASSERT(pe2
->mem_obj
->swapout
.decision
==
284 MemObject::SwapOut::swImpossible
);
285 CPPUNIT_ASSERT(pe2
->swap_dirn
== -1);
286 CPPUNIT_ASSERT(pe2
->swap_filen
== -1);
292 CPPUNIT_ASSERT_EQUAL((uint64_t)6, store
->currentCount());
294 // try to get and unlink entries
295 for (int i
= 0; i
< 6; ++i
) {
296 StoreEntry
*const pe
= getEntry(i
);
297 CPPUNIT_ASSERT(pe
!= NULL
);
301 StoreEntry
*const pe2
= getEntry(i
);
302 CPPUNIT_ASSERT(pe2
== NULL
);