/* * Copyright (C) 1996-2023 The Squid Software Foundation and contributors * * Squid software is distributed under GPLv2+ license and includes * contributions from numerous individuals and organizations. * Please see the COPYING and CONTRIBUTORS files for details. */ #include "squid.h" #include "compat/cppunit.h" #include "MemObject.h" #include "SquidConfig.h" #include "Store.h" #include "store/Disks.h" #include "StoreSearch.h" #include "TestSwapDir.h" /* * test the store framework */ class TestStoreController : public CPPUNIT_NS::TestFixture { CPPUNIT_TEST_SUITE(TestStoreController); CPPUNIT_TEST(testStats); CPPUNIT_TEST(testMaxSize); CPPUNIT_TEST(testSearch); CPPUNIT_TEST_SUITE_END(); public: protected: void testStats(); void testMaxSize(); void testSearch(); }; CPPUNIT_TEST_SUITE_REGISTRATION(TestStoreController); static void addSwapDir(TestSwapDirPointer aStore) { allocate_new_swapdir(Config.cacheSwap); Config.cacheSwap.swapDirs[Config.cacheSwap.n_configured] = aStore.getRaw(); ++Config.cacheSwap.n_configured; } void TestStoreController::testStats() { StoreEntry *logEntry = new StoreEntry; logEntry->createMemObject("dummy_storeId", nullptr, HttpRequestMethod()); logEntry->store_status = STORE_PENDING; TestSwapDirPointer aStore (new TestSwapDir); TestSwapDirPointer aStore2 (new TestSwapDir); addSwapDir(aStore); addSwapDir(aStore2); CPPUNIT_ASSERT_EQUAL(false, aStore->statsCalled); CPPUNIT_ASSERT_EQUAL(false, aStore2->statsCalled); Store::Stats(logEntry); free_cachedir(&Config.cacheSwap); CPPUNIT_ASSERT_EQUAL(true, aStore->statsCalled); CPPUNIT_ASSERT_EQUAL(true, aStore2->statsCalled); } static void commonInit() { static bool inited = false; if (inited) return; Config.memShared.defaultTo(false); Mem::Init(); Config.Store.avgObjectSize = 1024; Config.Store.objectsPerBucket = 20; Config.Store.maxObjectSize = 2048; Config.store_dir_select_algorithm = xstrdup("round-robin"); } void TestStoreController::testMaxSize() { commonInit(); StoreEntry *logEntry = new StoreEntry; logEntry->createMemObject("dummy_storeId", nullptr, HttpRequestMethod()); logEntry->store_status = STORE_PENDING; TestSwapDirPointer aStore (new TestSwapDir); TestSwapDirPointer aStore2 (new TestSwapDir); addSwapDir(aStore); addSwapDir(aStore2); CPPUNIT_ASSERT_EQUAL(static_cast(6), Store::Root().maxSize()); free_cachedir(&Config.cacheSwap); } static StoreEntry * addedEntry(Store::Disk *aStore, String name, String, String ) { StoreEntry *e = new StoreEntry(); e->store_status = STORE_OK; e->setMemStatus(NOT_IN_MEMORY); e->swap_status = SWAPOUT_DONE; /* bogus haha */ e->swap_filen = 0; /* garh - lower level*/ e->swap_dirn = -1; for (int i=0; i < Config.cacheSwap.n_configured; ++i) { if (INDEXSD(i) == aStore) e->swap_dirn = i; } CPPUNIT_ASSERT (e->swap_dirn != -1); e->swap_file_sz = 0; /* garh lower level */ e->lastref = squid_curtime; e->timestamp = squid_curtime; e->expires = squid_curtime; e->lastModified(squid_curtime); e->refcount = 1; e->ping_status = PING_NONE; EBIT_CLR(e->flags, ENTRY_VALIDATED); e->hashInsert((const cache_key *)name.termedBuf()); /* do it after we clear KEY_PRIVATE */ return e; } /* TODO make this a cbdata class */ static bool cbcalled; static void searchCallback(void *) { cbcalled = true; } void TestStoreController::testSearch() { commonInit(); TestSwapDirPointer aStore (new TestSwapDir); TestSwapDirPointer aStore2 (new TestSwapDir); addSwapDir(aStore); addSwapDir(aStore2); Store::Root().init(); StoreEntry * entry1 = addedEntry(aStore.getRaw(), "name", nullptr, nullptr); StoreEntry * entry2 = addedEntry(aStore2.getRaw(), "name2", nullptr, nullptr); StoreSearchPointer search = Store::Root().search(); /* search for everything in the store */ /* nothing should be immediately available */ CPPUNIT_ASSERT_EQUAL(false, search->error()); CPPUNIT_ASSERT_EQUAL(false, search->isDone()); CPPUNIT_ASSERT_EQUAL(static_cast(nullptr), search->currentItem()); /* trigger a callback */ cbcalled = false; search->next(searchCallback, nullptr); CPPUNIT_ASSERT_EQUAL(true, cbcalled); /* we should have access to a entry now, that matches the entry we had before */ CPPUNIT_ASSERT_EQUAL(false, search->error()); CPPUNIT_ASSERT_EQUAL(false, search->isDone()); /* note the hash order is random - the test happens to be in a nice order */ CPPUNIT_ASSERT_EQUAL(entry1, search->currentItem()); //CPPUNIT_ASSERT_EQUAL(false, search->next()); /* trigger another callback */ cbcalled = false; search->next(searchCallback, nullptr); CPPUNIT_ASSERT_EQUAL(true, cbcalled); /* we should have access to a entry now, that matches the entry we had before */ CPPUNIT_ASSERT_EQUAL(false, search->error()); CPPUNIT_ASSERT_EQUAL(false, search->isDone()); CPPUNIT_ASSERT_EQUAL(entry2, search->currentItem()); //CPPUNIT_ASSERT_EQUAL(false, search->next()); /* trigger another callback */ cbcalled = false; search->next(searchCallback, nullptr); CPPUNIT_ASSERT_EQUAL(true, cbcalled); /* now we should have no error, we should have finished and have no current item */ CPPUNIT_ASSERT_EQUAL(false, search->error()); CPPUNIT_ASSERT_EQUAL(true, search->isDone()); CPPUNIT_ASSERT_EQUAL(static_cast(nullptr), search->currentItem()); //CPPUNIT_ASSERT_EQUAL(false, search->next()); } // This test uses main() from ./testStore.cc.