2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
10 #include "DiskIO/DiskIOModule.h"
12 #include "fs/ufs/UFSSwapDir.h"
14 #include "HttpHeader.h"
15 #include "HttpReply.h"
16 #include "MemObject.h"
17 #include "RequestFlags.h"
18 #include "SquidConfig.h"
20 #include "store/Disks.h"
21 #include "testStoreSupport.h"
23 #include "unitTestMain.h"
27 #define TESTDIR "testUfs_Store"
29 CPPUNIT_TEST_SUITE_REGISTRATION( testUfs
);
31 typedef RefCount
<Fs::Ufs::UFSSwapDir
> MySwapDirPointer
;
32 extern REMOVALPOLICYCREATE createRemovalPolicy_lru
; /* XXX fails with --enable-removal-policies=heap */
35 addSwapDir(MySwapDirPointer aStore
)
37 allocate_new_swapdir(Config
.cacheSwap
);
38 Config
.cacheSwap
.swapDirs
[Config
.cacheSwap
.n_configured
] = aStore
.getRaw();
39 ++Config
.cacheSwap
.n_configured
;
45 searchCallback(void *cbdata
)
53 static bool inited
= false;
58 Config
.Store
.avgObjectSize
= 1024;
59 Config
.Store
.objectsPerBucket
= 20;
60 Config
.Store
.maxObjectSize
= 2048;
62 Config
.store_dir_select_algorithm
= xstrdup("round-robin");
64 Config
.replPolicy
= new RemovalPolicySettings
;
65 Config
.replPolicy
->type
= xstrdup("lru");
67 Config
.memShared
.defaultTo(false);
70 storeReplAdd("lru", createRemovalPolicy_lru
);
78 httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */
84 testUfs::testUfsSearch()
87 * make a valid working ufs swapdir
88 * put two entries in it and sync logs
90 * check the entries we find are what we want
93 if (0 > system ("rm -rf " TESTDIR
))
94 throw std::runtime_error("Failed to clean test work directory");
98 MySwapDirPointer
aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
100 aStore
->IO
= new Fs::Ufs::UFSStrategy(DiskIOModule::Find("Blocking")->createStrategy());
105 mem_policy
= createRemovalPolicy(Config
.replPolicy
);
107 char *path
=xstrdup(TESTDIR
);
109 char *config_line
=xstrdup("100 1 1");
111 visible_appname_string
= xstrdup(PACKAGE
"/" VERSION
);
113 ConfigParser::SetCfgLine(config_line
);
115 aStore
->parse(0, path
);
116 store_maxobjsize
= 1024*1024*2;
120 safe_free(config_line
);
122 /* ok, ready to create */
125 /* ok, ready to use - inits store & hash too */
126 Store::Root().init();
128 /* our swapdir must be scheduled to rebuild */
129 CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding
);
131 /* rebuild is a scheduled event */
134 while (StoreController::store_dirs_rebuilding
)
137 /* cannot use loop.run(); as the loop will never idle: the store-dir
138 * clean() scheduled event prevents it
141 /* nothing left to rebuild */
142 CPPUNIT_ASSERT_EQUAL(0, StoreController::store_dirs_rebuilding
);
146 /* Create "vary" base object */
148 flags
.cachable
= true;
149 StoreEntry
*pe
= storeCreateEntry("dummy url", "dummy log url", flags
, Http::METHOD_GET
);
150 auto &reply
= pe
->mem().adjustableBaseReply();
151 reply
.setHeaders(Http::scOkay
, "dummy test object", "x-squid-internal/test", 0, -1, squid_curtime
+ 100000);
156 pe
->mem().freshestReply().packHeadersUsingSlowPacker(*pe
);
161 CPPUNIT_ASSERT_EQUAL(0, pe
->swap_dirn
);
162 CPPUNIT_ASSERT_EQUAL(0, pe
->swap_filen
);
163 pe
->unlock("testUfs::testUfsSearch vary");
166 storeDirWriteCleanLogs(0);
168 /* here we cheat: we know that UFSSwapDirs search off disk. If we did an init call to a new
169 * swapdir instance, we'd not be testing a clean build.
171 StoreSearchPointer search
= Store::Root().search(); /* search for everything in the store */
173 /* nothing should be immediately available */
176 CPPUNIT_ASSERT_EQUAL(false, search
->next());
179 CPPUNIT_ASSERT_EQUAL(false, search
->error());
180 CPPUNIT_ASSERT_EQUAL(false, search
->isDone());
181 CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry
*>(NULL
), search
->currentItem());
183 /* trigger a callback */
185 search
->next(searchCallback
, NULL
);
186 CPPUNIT_ASSERT_EQUAL(true, cbcalled
);
188 /* we should have access to a entry now, that matches the entry we had before */
189 //CPPUNIT_ASSERT_EQUAL(false, search->next());
190 CPPUNIT_ASSERT_EQUAL(false, search
->error());
191 CPPUNIT_ASSERT_EQUAL(false, search
->isDone());
192 CPPUNIT_ASSERT(search
->currentItem() != NULL
);
194 /* trigger another callback */
196 search
->next(searchCallback
, NULL
);
197 CPPUNIT_ASSERT_EQUAL(true, cbcalled
);
199 /* now we should have no error, we should have finished and have no current item */
200 //CPPUNIT_ASSERT_EQUAL(false, search->next());
201 CPPUNIT_ASSERT_EQUAL(false, search
->error());
202 CPPUNIT_ASSERT_EQUAL(true, search
->isDone());
203 CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry
*>(NULL
), search
->currentItem());
207 free_cachedir(&Config
.cacheSwap
);
209 // TODO: here we should test a dirty rebuild
211 safe_free(Config
.replPolicy
->type
);
212 delete Config
.replPolicy
;
214 if (0 > system ("rm -rf " TESTDIR
))
215 throw std::runtime_error("Failed to clean test work directory");
218 /* The UFS store should always configure an IO engine even if none is
219 * supplied on the configuration line.
222 testUfs::testUfsDefaultEngine()
224 /* boring common test boilerplate */
225 if (0 > system ("rm -rf " TESTDIR
))
226 throw std::runtime_error("Failed to clean test work directory");
228 // This assertion may fail if previous test cases fail.
229 // Apparently, CPPUNIT_ASSERT* failure may prevent destructors of local
230 // objects such as "StorePointer aRoot" from being called.
231 CPPUNIT_ASSERT(!store_table
); // or StoreHashIndex ctor will abort below
234 MySwapDirPointer
aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking"));
237 Config
.replPolicy
= new RemovalPolicySettings
;
238 Config
.replPolicy
->type
= xstrdup("lru");
239 mem_policy
= createRemovalPolicy(Config
.replPolicy
);
241 char *path
=xstrdup(TESTDIR
);
242 char *config_line
=xstrdup("100 1 1");
243 ConfigParser::SetCfgLine(config_line
);
244 aStore
->parse(0, path
);
246 safe_free(config_line
);
247 CPPUNIT_ASSERT(aStore
->IO
->io
!= NULL
);
250 free_cachedir(&Config
.cacheSwap
);
251 safe_free(Config
.replPolicy
->type
);
252 delete Config
.replPolicy
;
254 if (0 > system ("rm -rf " TESTDIR
))
255 throw std::runtime_error("Failed to clean test work directory");