]>
Commit | Line | Data |
---|---|---|
4e0938ef | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
4e0938ef AJ |
3 | * |
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. | |
7 | */ | |
8 | ||
f7f3304a | 9 | #include "squid.h" |
ae022809 | 10 | #include "compat/cppunit.h" |
c8f4eac4 | 11 | #include "DiskIO/DiskIOModule.h" |
d7ca82e6 | 12 | #include "fde.h" |
582c2af2 FC |
13 | #include "fs/ufs/UFSSwapDir.h" |
14 | #include "globals.h" | |
c8f4eac4 | 15 | #include "HttpHeader.h" |
16 | #include "HttpReply.h" | |
58373ff8 | 17 | #include "MemObject.h" |
f206b652 | 18 | #include "RequestFlags.h" |
4d5904f7 | 19 | #include "SquidConfig.h" |
58373ff8 | 20 | #include "Store.h" |
2745fea5 | 21 | #include "store/Disks.h" |
582c2af2 | 22 | #include "testStoreSupport.h" |
7f861c77 AJ |
23 | #include "unitTestMain.h" |
24 | ||
27e059d4 | 25 | #include <stdexcept> |
27e059d4 | 26 | |
41e9c9f0 | 27 | #define TESTDIR "TestUfs_Store" |
2e050051 | 28 | |
ae022809 FC |
29 | /* |
30 | * test the store framework | |
31 | */ | |
32 | ||
33 | class TestUfs : public CPPUNIT_NS::TestFixture | |
34 | { | |
35 | CPPUNIT_TEST_SUITE(TestUfs); | |
36 | CPPUNIT_TEST(testUfsSearch); | |
37 | CPPUNIT_TEST(testUfsDefaultEngine); | |
38 | CPPUNIT_TEST_SUITE_END(); | |
39 | ||
40 | public: | |
41 | protected: | |
42 | void commonInit(); | |
43 | void testUfsSearch(); | |
44 | void testUfsDefaultEngine(); | |
45 | }; | |
46 | CPPUNIT_TEST_SUITE_REGISTRATION(TestUfs); | |
c8f4eac4 | 47 | |
2745fea5 | 48 | typedef RefCount<Fs::Ufs::UFSSwapDir> MySwapDirPointer; |
f53969cc | 49 | extern REMOVALPOLICYCREATE createRemovalPolicy_lru; /* XXX fails with --enable-removal-policies=heap */ |
c8f4eac4 | 50 | |
51 | static void | |
2745fea5 | 52 | addSwapDir(MySwapDirPointer aStore) |
c8f4eac4 | 53 | { |
5d84beb5 | 54 | allocate_new_swapdir(Config.cacheSwap); |
c8f4eac4 | 55 | Config.cacheSwap.swapDirs[Config.cacheSwap.n_configured] = aStore.getRaw(); |
56 | ++Config.cacheSwap.n_configured; | |
57 | } | |
58 | ||
c8f4eac4 | 59 | static bool cbcalled; |
60 | ||
61 | static void | |
8b082ed9 | 62 | searchCallback(void *) |
c8f4eac4 | 63 | { |
64 | cbcalled = true; | |
65 | } | |
66 | ||
67 | void | |
41e9c9f0 | 68 | TestUfs::commonInit() |
c8f4eac4 | 69 | { |
b7717b61 | 70 | static bool inited = false; |
c8f4eac4 | 71 | |
b7717b61 | 72 | if (inited) |
73 | return; | |
c8f4eac4 | 74 | |
75 | Config.Store.avgObjectSize = 1024; | |
c8f4eac4 | 76 | Config.Store.objectsPerBucket = 20; |
c8f4eac4 | 77 | Config.Store.maxObjectSize = 2048; |
78 | ||
79 | Config.store_dir_select_algorithm = xstrdup("round-robin"); | |
80 | ||
81 | Config.replPolicy = new RemovalPolicySettings; | |
86c63190 | 82 | Config.replPolicy->type = xstrdup("lru"); |
c8f4eac4 | 83 | |
c50b35b5 AJ |
84 | Config.memShared.defaultTo(false); |
85 | ||
c8f4eac4 | 86 | /* garh garh */ |
87 | storeReplAdd("lru", createRemovalPolicy_lru); | |
88 | ||
89 | Mem::Init(); | |
90 | ||
d7ca82e6 EB |
91 | fde::Init(); |
92 | ||
c8f4eac4 | 93 | comm_init(); |
94 | ||
f53969cc | 95 | httpHeaderInitModule(); /* must go before any header processing (e.g. the one in errorInitialize) */ |
c8f4eac4 | 96 | |
b7717b61 | 97 | inited = true; |
98 | } | |
99 | ||
100 | void | |
41e9c9f0 | 101 | TestUfs::testUfsSearch() |
b7717b61 | 102 | { |
103 | /* test sequence | |
104 | * make a valid working ufs swapdir | |
105 | * put two entries in it and sync logs | |
106 | * search the ufs dir | |
107 | * check the entries we find are what we want | |
108 | */ | |
109 | ||
110 | if (0 > system ("rm -rf " TESTDIR)) | |
111 | throw std::runtime_error("Failed to clean test work directory"); | |
112 | ||
2745fea5 | 113 | MySwapDirPointer aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking")); |
b7717b61 | 114 | |
58373ff8 | 115 | aStore->IO = new Fs::Ufs::UFSStrategy(DiskIOModule::Find("Blocking")->createStrategy()); |
b7717b61 | 116 | |
117 | addSwapDir(aStore); | |
118 | ||
119 | commonInit(); | |
c8f4eac4 | 120 | mem_policy = createRemovalPolicy(Config.replPolicy); |
121 | ||
2e050051 | 122 | char *path=xstrdup(TESTDIR); |
c8f4eac4 | 123 | |
2eceb328 | 124 | char *config_line=xstrdup("100 1 1"); |
c8f4eac4 | 125 | |
474dfa84 | 126 | visible_appname_string = xstrdup(PACKAGE "/" VERSION); |
127 | ||
2eceb328 | 128 | ConfigParser::SetCfgLine(config_line); |
c8f4eac4 | 129 | |
130 | aStore->parse(0, path); | |
b51ec8c8 | 131 | store_maxobjsize = 1024*1024*2; |
c8f4eac4 | 132 | |
133 | safe_free(path); | |
134 | ||
135 | safe_free(config_line); | |
136 | ||
137 | /* ok, ready to create */ | |
138 | aStore->create(); | |
139 | ||
8ff3fa2e | 140 | /* ok, ready to use - inits store & hash too */ |
c8f4eac4 | 141 | Store::Root().init(); |
142 | ||
bef81ea5 | 143 | /* our swapdir must be scheduled to rebuild */ |
1f8dc0fb | 144 | CPPUNIT_ASSERT_EQUAL(2, StoreController::store_dirs_rebuilding); |
bef81ea5 | 145 | |
8ff3fa2e | 146 | /* rebuild is a scheduled event */ |
147 | StockEventLoop loop; | |
148 | ||
02c267b0 | 149 | while (StoreController::store_dirs_rebuilding) |
bef81ea5 | 150 | loop.runOnce(); |
c8f4eac4 | 151 | |
bef81ea5 | 152 | /* cannot use loop.run(); as the loop will never idle: the store-dir |
26ac0430 | 153 | * clean() scheduled event prevents it |
bef81ea5 | 154 | */ |
c8f4eac4 | 155 | |
bef81ea5 | 156 | /* nothing left to rebuild */ |
02c267b0 | 157 | CPPUNIT_ASSERT_EQUAL(0, StoreController::store_dirs_rebuilding); |
c8f4eac4 | 158 | |
159 | /* add an entry */ | |
160 | { | |
161 | /* Create "vary" base object */ | |
f206b652 | 162 | RequestFlags flags; |
aeeff7fd | 163 | flags.cachable.support(); |
c2a7cefd | 164 | StoreEntry *pe = storeCreateEntry("dummy url", "dummy log url", flags, Http::METHOD_GET); |
66d51f4f AR |
165 | auto &reply = pe->mem().adjustableBaseReply(); |
166 | reply.setHeaders(Http::scOkay, "dummy test object", "x-squid-internal/test", 0, -1, squid_curtime + 100000); | |
c8f4eac4 | 167 | |
d88e3c49 | 168 | pe->setPublicKey(); |
c8f4eac4 | 169 | |
3900307b | 170 | pe->buffer(); |
66d51f4f | 171 | pe->mem().freshestReply().packHeadersUsingSlowPacker(*pe); |
3900307b | 172 | pe->flush(); |
173 | pe->timestampsSet(); | |
c8f4eac4 | 174 | pe->complete(); |
c07cbbf4 | 175 | pe->swapOut(); |
5d1dff27 FC |
176 | CPPUNIT_ASSERT_EQUAL(0, pe->swap_dirn); |
177 | CPPUNIT_ASSERT_EQUAL(0, pe->swap_filen); | |
41e9c9f0 | 178 | pe->unlock("TestUfs::testUfsSearch vary"); |
c8f4eac4 | 179 | } |
180 | ||
181 | storeDirWriteCleanLogs(0); | |
182 | ||
183 | /* here we cheat: we know that UFSSwapDirs search off disk. If we did an init call to a new | |
184 | * swapdir instance, we'd not be testing a clean build. | |
185 | */ | |
2745fea5 | 186 | StoreSearchPointer search = Store::Root().search(); /* search for everything in the store */ |
c8f4eac4 | 187 | |
5d1dff27 FC |
188 | CPPUNIT_ASSERT_EQUAL(false, search->error()); |
189 | CPPUNIT_ASSERT_EQUAL(false, search->isDone()); | |
aee3523a | 190 | CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(nullptr), search->currentItem()); |
c8f4eac4 | 191 | |
192 | /* trigger a callback */ | |
193 | cbcalled = false; | |
aee3523a | 194 | search->next(searchCallback, nullptr); |
5d1dff27 | 195 | CPPUNIT_ASSERT_EQUAL(true, cbcalled); |
c8f4eac4 | 196 | |
197 | /* we should have access to a entry now, that matches the entry we had before */ | |
5d1dff27 FC |
198 | //CPPUNIT_ASSERT_EQUAL(false, search->next()); |
199 | CPPUNIT_ASSERT_EQUAL(false, search->error()); | |
200 | CPPUNIT_ASSERT_EQUAL(false, search->isDone()); | |
aee3523a | 201 | CPPUNIT_ASSERT(search->currentItem() != nullptr); |
c8f4eac4 | 202 | |
203 | /* trigger another callback */ | |
204 | cbcalled = false; | |
aee3523a | 205 | search->next(searchCallback, nullptr); |
5d1dff27 | 206 | CPPUNIT_ASSERT_EQUAL(true, cbcalled); |
c8f4eac4 | 207 | |
208 | /* now we should have no error, we should have finished and have no current item */ | |
5d1dff27 FC |
209 | //CPPUNIT_ASSERT_EQUAL(false, search->next()); |
210 | CPPUNIT_ASSERT_EQUAL(false, search->error()); | |
211 | CPPUNIT_ASSERT_EQUAL(true, search->isDone()); | |
aee3523a | 212 | CPPUNIT_ASSERT_EQUAL(static_cast<StoreEntry *>(nullptr), search->currentItem()); |
c8f4eac4 | 213 | |
214 | free_cachedir(&Config.cacheSwap); | |
215 | ||
9837567d | 216 | // TODO: here we should test a dirty rebuild |
c8f4eac4 | 217 | |
b7717b61 | 218 | safe_free(Config.replPolicy->type); |
219 | delete Config.replPolicy; | |
220 | ||
221 | if (0 > system ("rm -rf " TESTDIR)) | |
222 | throw std::runtime_error("Failed to clean test work directory"); | |
223 | } | |
224 | ||
26ac0430 | 225 | /* The UFS store should always configure an IO engine even if none is |
b7717b61 | 226 | * supplied on the configuration line. |
227 | */ | |
228 | void | |
41e9c9f0 | 229 | TestUfs::testUfsDefaultEngine() |
b7717b61 | 230 | { |
231 | /* boring common test boilerplate */ | |
232 | if (0 > system ("rm -rf " TESTDIR)) | |
233 | throw std::runtime_error("Failed to clean test work directory"); | |
234 | ||
2745fea5 | 235 | MySwapDirPointer aStore (new Fs::Ufs::UFSSwapDir("ufs", "Blocking")); |
b7717b61 | 236 | addSwapDir(aStore); |
237 | commonInit(); | |
238 | Config.replPolicy = new RemovalPolicySettings; | |
86c63190 | 239 | Config.replPolicy->type = xstrdup("lru"); |
b7717b61 | 240 | mem_policy = createRemovalPolicy(Config.replPolicy); |
241 | ||
242 | char *path=xstrdup(TESTDIR); | |
2eceb328 CT |
243 | char *config_line=xstrdup("100 1 1"); |
244 | ConfigParser::SetCfgLine(config_line); | |
b7717b61 | 245 | aStore->parse(0, path); |
246 | safe_free(path); | |
247 | safe_free(config_line); | |
aee3523a | 248 | CPPUNIT_ASSERT(aStore->IO->io != nullptr); |
b7717b61 | 249 | |
d5d5493b | 250 | free_cachedir(&Config.cacheSwap); |
c8f4eac4 | 251 | safe_free(Config.replPolicy->type); |
252 | delete Config.replPolicy; | |
253 | ||
2e050051 | 254 | if (0 > system ("rm -rf " TESTDIR)) |
c8f4eac4 | 255 | throw std::runtime_error("Failed to clean test work directory"); |
256 | } | |
f53969cc | 257 | |
53a5a6de AR |
258 | int |
259 | main(int argc, char *argv[]) | |
260 | { | |
261 | return TestProgram().run(argc, argv); | |
262 | } | |
263 |