]>
| Commit | Line | Data |
|---|---|---|
| 4e0938ef | 1 | /* |
| 1f7b830e | 2 | * Copyright (C) 1996-2025 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 | ||
| 582c2af2 | 9 | #include "squid.h" |
| 26e65059 | 10 | #include "anyp/Uri.h" |
| 62ee09ca | 11 | #include "CacheManager.h" |
| ae022809 | 12 | #include "compat/cppunit.h" |
| 602d9612 | 13 | #include "mgr/Action.h" |
| 99572608 | 14 | #include "mgr/Registration.h" |
| b707cdeb | 15 | #include "Store.h" |
| 7f861c77 | 16 | #include "unitTestMain.h" |
| 62ee09ca | 17 | |
| 3d41e53a | 18 | #include <cppunit/TestAssert.h> |
| ae022809 FC |
19 | /* |
| 20 | * test the CacheManager implementation | |
| 21 | */ | |
| 22 | ||
| 23 | class TestCacheManager : public CPPUNIT_NS::TestFixture | |
| 24 | { | |
| 25 | CPPUNIT_TEST_SUITE(TestCacheManager); | |
| 26 | CPPUNIT_TEST(testCreate); | |
| 27 | CPPUNIT_TEST(testRegister); | |
| 28 | CPPUNIT_TEST(testParseUrl); | |
| 29 | CPPUNIT_TEST_SUITE_END(); | |
| 30 | ||
| ae022809 FC |
31 | protected: |
| 32 | void testCreate(); | |
| 33 | void testRegister(); | |
| 34 | void testParseUrl(); | |
| 35 | }; | |
| 62ee09ca | 36 | |
| 41e9c9f0 | 37 | CPPUNIT_TEST_SUITE_REGISTRATION( TestCacheManager ); |
| 62ee09ca | 38 | |
| 26e65059 AJ |
39 | /// Provides test code access to CacheManager internal symbols |
| 40 | class CacheManagerInternals : public CacheManager | |
| 41 | { | |
| 42 | public: | |
| 3c383cc3 AR |
43 | /// checks CacheManager parsing of the given valid URL |
| 44 | void testValidUrl(const AnyP::Uri &); | |
| 45 | ||
| 46 | /// checks CacheManager parsing of the given invalid URL | |
| 47 | /// \param problem a bad part of the URL or its description | |
| 48 | void testInvalidUrl(const AnyP::Uri &, const char *problem); | |
| 26e65059 AJ |
49 | }; |
| 50 | ||
| 3c383cc3 AR |
51 | void |
| 52 | CacheManagerInternals::testValidUrl(const AnyP::Uri &url) | |
| 53 | { | |
| eb743f8b | 54 | CPPUNIT_ASSERT_NO_THROW(ParseUrl(url)); |
| 3c383cc3 AR |
55 | } |
| 56 | ||
| 57 | void | |
| 58 | CacheManagerInternals::testInvalidUrl(const AnyP::Uri &url, const char *const problem) | |
| 59 | { | |
| eb743f8b | 60 | CPPUNIT_ASSERT_THROW_MESSAGE(problem, ParseUrl(url), TextException); |
| 3c383cc3 AR |
61 | } |
| 62 | ||
| 53a5a6de AR |
63 | /// customizes our test setup |
| 64 | class MyTestProgram: public TestProgram | |
| 65 | { | |
| 66 | public: | |
| 67 | /* TestProgram API */ | |
| 68 | void startup() override; | |
| 69 | }; | |
| 62ee09ca | 70 | |
| 53a5a6de AR |
71 | void |
| 72 | MyTestProgram::startup() | |
| 62ee09ca | 73 | { |
| 16555581 | 74 | Mem::Init(); |
| 26e65059 | 75 | AnyP::UriScheme::Init(); |
| 16555581 | 76 | } |
| 62ee09ca | 77 | |
| 78 | /* | |
| 79 | * Test creating a CacheManager | |
| 80 | */ | |
| 81 | void | |
| 41e9c9f0 | 82 | TestCacheManager::testCreate() |
| 62ee09ca | 83 | { |
| b707cdeb | 84 | CacheManager::GetInstance(); //it's a singleton.. |
| 62ee09ca | 85 | } |
| 86 | ||
| 87 | /* an action to register */ | |
| 88 | static void | |
| 89 | dummy_action(StoreEntry * sentry) | |
| b707cdeb FC |
90 | { |
| 91 | sentry->flags=1; | |
| 92 | } | |
| 62ee09ca | 93 | |
| 94 | /* | |
| 95 | * registering an action makes it findable. | |
| 96 | */ | |
| 97 | void | |
| 41e9c9f0 | 98 | TestCacheManager::testRegister() |
| 62ee09ca | 99 | { |
| b707cdeb | 100 | CacheManager *manager=CacheManager::GetInstance(); |
| aee3523a | 101 | CPPUNIT_ASSERT(manager != nullptr); |
| b707cdeb | 102 | |
| 99572608 | 103 | Mgr::RegisterAction("sample", "my sample", &dummy_action, Mgr::Protected::no, Mgr::Atomic::no, Mgr::Format::informal); |
| 8822ebee | 104 | Mgr::Action::Pointer action = manager->createNamedAction("sample"); |
| aee3523a | 105 | CPPUNIT_ASSERT(action != nullptr); |
| b707cdeb | 106 | |
| 8822ebee | 107 | const Mgr::ActionProfile::Pointer profile = action->command().profile; |
| aee3523a AR |
108 | CPPUNIT_ASSERT(profile != nullptr); |
| 109 | CPPUNIT_ASSERT(profile->creator != nullptr); | |
| 8822ebee AR |
110 | CPPUNIT_ASSERT_EQUAL(false, profile->isPwReq); |
| 111 | CPPUNIT_ASSERT_EQUAL(false, profile->isAtomic); | |
| 99572608 FC |
112 | CPPUNIT_ASSERT_EQUAL(Mgr::Format::informal, profile->format); |
| 113 | CPPUNIT_ASSERT_EQUAL(Mgr::Format::informal, action->format()); | |
| 8822ebee | 114 | CPPUNIT_ASSERT_EQUAL(String("sample"), String(action->name())); |
| b707cdeb FC |
115 | |
| 116 | StoreEntry *sentry=new StoreEntry(); | |
| 99572608 | 117 | sentry->createMemObject(); |
| b707cdeb | 118 | sentry->flags=0x25; //arbitrary test value |
| 8822ebee | 119 | action->run(sentry, false); |
| b707cdeb | 120 | CPPUNIT_ASSERT_EQUAL(1,(int)sentry->flags); |
| 62ee09ca | 121 | } |
| f53969cc | 122 | |
| 26e65059 | 123 | void |
| 41e9c9f0 | 124 | TestCacheManager::testParseUrl() |
| 26e65059 AJ |
125 | { |
| 126 | auto *mgr = static_cast<CacheManagerInternals *>(CacheManager::GetInstance()); | |
| 127 | CPPUNIT_ASSERT(mgr != nullptr); | |
| 128 | ||
| 129 | std::vector<AnyP::ProtocolType> validSchemes = { | |
| 26e65059 AJ |
130 | AnyP::PROTO_HTTP, |
| 131 | AnyP::PROTO_HTTPS, | |
| 132 | AnyP::PROTO_FTP | |
| 133 | }; | |
| 134 | ||
| 135 | AnyP::Uri mgrUrl; | |
| 136 | mgrUrl.host("localhost"); | |
| 137 | mgrUrl.port(3128); | |
| 138 | ||
| 26e65059 AJ |
139 | const std::vector<const char *> validActions = { |
| 140 | "", | |
| 141 | "menu" | |
| 142 | }; | |
| 143 | ||
| 144 | const std::vector<const char *> invalidActions = { | |
| 145 | "INVALID" // any unregistered name | |
| 146 | }; | |
| 147 | ||
| 148 | const std::vector<const char *> validParams = { | |
| 149 | "", | |
| 150 | "?", | |
| 151 | "?&", | |
| 152 | "?&&&&&&&&&&&&", | |
| 153 | "?foo=bar", | |
| 154 | "?0123456789=bar", | |
| 155 | "?foo=bar&", | |
| 156 | "?foo=bar&&&&", | |
| 157 | "?&foo=bar", | |
| 158 | "?&&&&foo=bar", | |
| 159 | "?&foo=bar&", | |
| 160 | "?&&&&foo=bar&&&&", | |
| 161 | "?foo=?_weird?~`:[]stuff&bar=okay&&&&&&", | |
| 162 | "?intlist=1", | |
| 163 | "?intlist=1,2,3,4,5", | |
| 164 | "?string=1a", | |
| 165 | "?string=1,2,3,4,z", | |
| 166 | "?string=1,2,3,4,[0]", | |
| 167 | "?intlist=1,2,3,4,5&string=1,2,3,4,y" | |
| 168 | }; | |
| 169 | ||
| 170 | const std::vector<const char *> invalidParams = { | |
| 171 | "?/", | |
| 172 | "?foo", | |
| 173 | "?/foo", | |
| 174 | "?foo/", | |
| 175 | "?foo=", | |
| 176 | "?foo=&", | |
| 177 | "?=foo", | |
| 178 | "? foo=bar", | |
| 179 | "? &", | |
| 180 | "?& ", | |
| 181 | "?=&", | |
| 182 | "?&=", | |
| 183 | "? &&&", | |
| 184 | "?& &&", | |
| 185 | "?&& &", | |
| 186 | "?=&&&", | |
| 187 | "?&=&&", | |
| 188 | "?&&=&" | |
| 189 | }; | |
| 190 | ||
| 191 | const std::vector<const char *> validFragments = { | |
| 192 | "", | |
| 193 | "#", | |
| 194 | "##", | |
| 195 | "#?a=b", | |
| 196 | "#fragment" | |
| 197 | }; | |
| 198 | ||
| 3c383cc3 AR |
199 | const auto &prefix = CacheManager::WellKnownUrlPathPrefix(); |
| 200 | ||
| 201 | assert(prefix.length()); | |
| 202 | const auto insufficientPrefix = prefix.substr(0, prefix.length()-1); | |
| 203 | ||
| 26e65059 AJ |
204 | for (const auto &scheme : validSchemes) { |
| 205 | mgrUrl.setScheme(scheme); | |
| 206 | ||
| 3c383cc3 AR |
207 | // Check that the parser rejects URLs that lack the full prefix prefix. |
| 208 | // These negative tests log "Squid BUG: assurance failed" ERRORs because | |
| 209 | // they violate CacheManager::ParseUrl()'s ForSomeCacheManager() | |
| 210 | // precondition. | |
| 211 | for (const auto *action : validActions) { | |
| 212 | for (const auto *param : validParams) { | |
| 213 | for (const auto *frag : validFragments) { | |
| 214 | SBuf bits; | |
| 215 | bits.append(insufficientPrefix); | |
| 216 | bits.append(action); | |
| 217 | bits.append(param); | |
| 218 | bits.append(frag); | |
| 219 | mgrUrl.path(bits); | |
| 220 | mgr->testInvalidUrl(mgrUrl, "insufficient prefix"); | |
| 26e65059 AJ |
221 | } |
| 222 | } | |
| 3c383cc3 AR |
223 | } |
| 224 | ||
| 225 | // Check that the parser accepts valid URLs. | |
| 226 | for (const auto action: validActions) { | |
| 227 | for (const auto param: validParams) { | |
| 228 | for (const auto frag: validFragments) { | |
| 229 | SBuf bits; | |
| 230 | bits.append(prefix); | |
| 231 | bits.append(action); | |
| 232 | bits.append(param); | |
| 233 | bits.append(frag); | |
| 234 | mgrUrl.path(bits); | |
| 235 | mgr->testValidUrl(mgrUrl); | |
| 236 | } | |
| 237 | } | |
| 238 | } | |
| 26e65059 | 239 | |
| 3c383cc3 AR |
240 | // Check that the parser rejects URLs with invalid parameters. |
| 241 | for (const auto action: validActions) { | |
| 242 | for (const auto invalidParam: invalidParams) { | |
| 243 | for (const auto frag: validFragments) { | |
| 244 | SBuf bits; | |
| 245 | bits.append(prefix); | |
| 246 | bits.append(action); | |
| 247 | bits.append(invalidParam); | |
| 248 | bits.append(frag); | |
| 249 | mgrUrl.path(bits); | |
| 250 | mgr->testInvalidUrl(mgrUrl, invalidParam); | |
| 26e65059 AJ |
251 | } |
| 252 | } | |
| 253 | } | |
| 254 | } | |
| 255 | } | |
| 53521734 | 256 | |
| 53a5a6de AR |
257 | int |
| 258 | main(int argc, char *argv[]) | |
| 259 | { | |
| 260 | return MyTestProgram().run(argc, argv); | |
| 261 | } | |
| 262 |