diff --git a/src/tests/kits/support/Jamfile b/src/tests/kits/support/Jamfile index c41a264189..19fcd03d9c 100644 --- a/src/tests/kits/support/Jamfile +++ b/src/tests/kits/support/Jamfile @@ -6,6 +6,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) bautolock ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) blocker ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) bmemoryio ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) bstring ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) bblockcache ] ; CommonTestLib libsupporttest.so : SupportKitTestAddon.cpp @@ -66,6 +67,11 @@ CommonTestLib libsupporttest.so StringSearchTest.cpp StringReplaceTest.cpp + #BBlockCache + BlockCacheTest.cpp + BlockCacheExerciseTest.cpp + BlockCacheConcurrencyTest.cpp + : libopenbeos.so be stdc++.r4 : be stdc++.r4 diff --git a/src/tests/kits/support/SupportKitTestAddon.cpp b/src/tests/kits/support/SupportKitTestAddon.cpp index 1c059e5cde..1c42d57ec7 100644 --- a/src/tests/kits/support/SupportKitTestAddon.cpp +++ b/src/tests/kits/support/SupportKitTestAddon.cpp @@ -8,6 +8,7 @@ #include "bmemoryio/MemoryIOTest.h" #include "bmemoryio/MallocIOTest.h" #include "bstring/StringTest.h" +#include "bblockcache/BlockCacheTest.h" BTestSuite* getTestSuite() { BTestSuite *suite = new BTestSuite("Support"); @@ -19,6 +20,7 @@ BTestSuite* getTestSuite() { suite->addTest("BMemoryIO", MemoryIOTestSuite()); suite->addTest("BMallocIO", MallocIOTestSuite()); suite->addTest("BString", StringTestSuite()); + suite->addTest("BBlockCache", BlockCacheTestSuite()); return suite; } diff --git a/src/tests/kits/support/bblockcache/BlockCacheConcurrencyTest.cpp b/src/tests/kits/support/bblockcache/BlockCacheConcurrencyTest.cpp new file mode 100644 index 0000000000..8a801d9be3 --- /dev/null +++ b/src/tests/kits/support/bblockcache/BlockCacheConcurrencyTest.cpp @@ -0,0 +1,301 @@ +/* + $Id: BlockCacheConcurrencyTest.cpp,v 1.1 2003/09/07 11:53:03 bonefish Exp $ + + This file tests BBlockCache from multiple threads to ensure there are + no concurrency problems. + + */ + + +#include "BlockCacheConcurrencyTest.h" +#include "ThreadedTestCaller.h" +#include +#include + + +/* + * Method: BlockCacheConcurrencyTest::BlockCacheConcurrencyTest() + * Descr: This method is the only constructor for the BlockCacheConcurrencyTest + * class. + */ + + + BlockCacheConcurrencyTest::BlockCacheConcurrencyTest(std::string name) : + BThreadedTestCase(name), + theObjCache(NULL), + theMallocCache(NULL), + numBlocksInCache(128), + sizeOfBlocksInCache(23), + sizeOfNonCacheBlocks(29) +{ + } + + +/* + * Method: BlockCacheConcurrencyTest::~BlockCacheConcurrencyTest() + * Descr: This method is the destructor for the BlockCacheConcurrencyTest class. + */ + + + BlockCacheConcurrencyTest::~BlockCacheConcurrencyTest() +{ +} + + +/* + * Method: BlockCacheConcurrencyTest::setUp() + * Descr: This method creates a couple of BBlockCache instances to perform + * tests on. One uses new/delete and the other uses malloc/free + * on its blocks. + */ + + + void BlockCacheConcurrencyTest::setUp(void) +{ + theObjCache = new BBlockCache(numBlocksInCache, sizeOfBlocksInCache, + B_OBJECT_CACHE); + theMallocCache = new BBlockCache(numBlocksInCache, sizeOfBlocksInCache, + B_MALLOC_CACHE); +} + + +/* + * Method: BlockCacheConcurrencyTest::tearDown() + * Descr: This method cleans up the BBlockCache instances which were tested. + */ + + + void BlockCacheConcurrencyTest::tearDown(void) +{ + delete theObjCache; + delete theMallocCache; +} + + +/* + * Method: BlockCacheConcurrencyTest::GetBlock() + * Descr: This method returns a pointer from the BBlockCache, checking + * the value before passing it to the caller. + */ + + + void *BlockCacheConcurrencyTest::GetBlock(BBlockCache *theCache, + size_t blockSize, + thread_id theThread, + BList *cacheList, + BList *nonCacheList) +{ + void *thePtr = theCache->Get(blockSize); + + // The new block should not already be used by this thread. + assert(!cacheList->HasItem(thePtr)); + assert(!nonCacheList->HasItem(thePtr)); + + // Add the block to the list of blocks used by this thread. + if (blockSize == sizeOfBlocksInCache) { + assert(cacheList->AddItem(thePtr)); + } else { + assert(nonCacheList->AddItem(thePtr)); + } + + // Store the thread id at the start of the block for future + // reference. + *((thread_id *)thePtr) = theThread; + return(thePtr); +} + + +/* + * Method: BlockCacheConcurrencyTest::SavedCacheBlock() + * Descr: This method passes the pointer back to the BBlockCache + * and checks the sanity of the lists. + */ + + + void BlockCacheConcurrencyTest::SaveBlock(BBlockCache *theCache, + void *thePtr, + size_t blockSize, + thread_id theThread, + BList *cacheList, + BList *nonCacheList) +{ + // The block being returned to the cache should still have + // the thread id of this thread in it, or some other thread has + // perhaps manipulated this block which would indicate a + // concurrency problem. + assert(*((thread_id *)thePtr) == theThread); + + // Remove the item from the appropriate list and confirm it isn't + // on the other list for some reason. + if (blockSize == sizeOfBlocksInCache) { + assert(cacheList->RemoveItem(thePtr)); + assert(!nonCacheList->HasItem(thePtr)); + } else { + assert(!cacheList->HasItem(thePtr)); + assert(nonCacheList->RemoveItem(thePtr)); + } + theCache->Save(thePtr, blockSize); +} + + +/* + * Method: BlockCacheConcurrencyTest::FreeBlock() + * Descr: This method frees the block directly using delete[] or free(), + * checking the sanity of the lists as it does the operation. + */ + + + void BlockCacheConcurrencyTest::FreeBlock(void *thePtr, + size_t blockSize, + bool isMallocTest, + thread_id theThread, + BList *cacheList, + BList *nonCacheList) +{ + // The block being returned to the cache should still have + // the thread id of this thread in it, or some other thread has + // perhaps manipulated this block which would indicate a + // concurrency problem. + assert(*((thread_id *)thePtr) == theThread); + + // Remove the item from the appropriate list and confirm it isn't + // on the other list for some reason. + if (blockSize == sizeOfBlocksInCache) { + assert(cacheList->RemoveItem(thePtr)); + assert(!nonCacheList->HasItem(thePtr)); + } else { + assert(!cacheList->HasItem(thePtr)); + assert(nonCacheList->RemoveItem(thePtr)); + } + if (isMallocTest) { + free(thePtr); + } else { + delete[] thePtr; + } +} + + +/* + * Method: BlockCacheConcurrencyTest::TestBlockCache() + * Descr: This method performs the tests on BBlockCache. It is + * called by 6 threads concurrently. Three of them are + * operating on the B_OBJECT_CACHE instance of BBlockCache + * and the other three are operating on the B_MALLOC_CACHE + * instance. + * + * The goal of this method is to perform a series of get, + * save and free operations on block from the cache using + * "cache size" and "non-cache size" blocks. Also, at the + * end of this method, all blocks unfreed by this method are + * freed to avoid a memory leak. + */ + + + void BlockCacheConcurrencyTest::TestBlockCache(BBlockCache *theCache, + bool isMallocTest) +{ + BList cacheList; + BList nonCacheList; + thread_id theThread = find_thread(NULL); + + // Do everything eight times to ensure the test runs long + // enough to check for concurrency problems. + for (int j = 0; j < 8; j++) { + // Perform a series of gets, saves and frees + for (int i = 0; i < numBlocksInCache / 2; i++) { + GetBlock(theCache, sizeOfBlocksInCache, theThread, &cacheList, &nonCacheList); + GetBlock(theCache, sizeOfBlocksInCache, theThread, &cacheList, &nonCacheList); + GetBlock(theCache, sizeOfNonCacheBlocks, theThread, &cacheList, &nonCacheList); + GetBlock(theCache, sizeOfNonCacheBlocks, theThread, &cacheList, &nonCacheList); + + SaveBlock(theCache, cacheList.ItemAt(cacheList.CountItems() / 2), + sizeOfBlocksInCache, theThread, &cacheList, &nonCacheList); + SaveBlock(theCache, nonCacheList.ItemAt(nonCacheList.CountItems() / 2), + sizeOfNonCacheBlocks, theThread, &cacheList, &nonCacheList); + + GetBlock(theCache, sizeOfBlocksInCache, theThread, &cacheList, &nonCacheList); + GetBlock(theCache, sizeOfBlocksInCache, theThread, &cacheList, &nonCacheList); + GetBlock(theCache, sizeOfNonCacheBlocks, theThread, &cacheList, &nonCacheList); + GetBlock(theCache, sizeOfNonCacheBlocks, theThread, &cacheList, &nonCacheList); + + FreeBlock(cacheList.ItemAt(cacheList.CountItems() / 2), + sizeOfBlocksInCache, isMallocTest, theThread, &cacheList, &nonCacheList); + FreeBlock(nonCacheList.ItemAt(nonCacheList.CountItems() / 2), + sizeOfNonCacheBlocks, isMallocTest, theThread, &cacheList, &nonCacheList); + } + bool performFree = false; + // Free or save (every other block) for all "cache sized" blocks. + while (!cacheList.IsEmpty()) { + if (performFree) { + FreeBlock(cacheList.LastItem(), sizeOfBlocksInCache, isMallocTest, theThread, &cacheList, + &nonCacheList); + } else { + SaveBlock(theCache, cacheList.LastItem(), sizeOfBlocksInCache, theThread, &cacheList, + &nonCacheList); + } + performFree = !performFree; + } + // Free or save (every other block) for all "non-cache sized" blocks. + while (!nonCacheList.IsEmpty()) { + if (performFree) { + FreeBlock(nonCacheList.LastItem(), sizeOfNonCacheBlocks, isMallocTest, theThread, &cacheList, + &nonCacheList); + } else { + SaveBlock(theCache, nonCacheList.LastItem(), sizeOfNonCacheBlocks, theThread, &cacheList, + &nonCacheList); + } + performFree = !performFree; + } + } +} + + +/* + * Method: BlockCacheConcurrencyTest::TestThreadMalloc() + * Descr: This method passes the BBlockCache instance to TestBlockCache() + * where the instance will be tested. + */ + + + void BlockCacheConcurrencyTest::TestThreadMalloc(void) +{ + TestBlockCache(theMallocCache, true); +} + + +/* + * Method: BlockCacheConcurrencyTest::TestThreadObj() + * Descr: This method passes the BBlockCache instance to TestBlockCache() + * where the instance will be tested. + */ + + + void BlockCacheConcurrencyTest::TestThreadObj(void) +{ + TestBlockCache(theObjCache, false); +} + + +/* + * Method: BlockCacheConcurrencyTest::suite() + * Descr: This static member function returns a test caller for performing + * the "BlockCacheConcurrencyTest" test. The test caller + * is created as a ThreadedTestCaller with six independent threads. + */ + + +CppUnit::Test *BlockCacheConcurrencyTest::suite(void) +{ + typedef BThreadedTestCaller + BlockCacheConcurrencyTestCaller; + + BlockCacheConcurrencyTest *theTest = new BlockCacheConcurrencyTest(""); + BlockCacheConcurrencyTestCaller *threadedTest = new BlockCacheConcurrencyTestCaller("BBlockCache::Concurrency Test", theTest); + threadedTest->addThread("A", &BlockCacheConcurrencyTest::TestThreadObj); + threadedTest->addThread("B", &BlockCacheConcurrencyTest::TestThreadObj); + threadedTest->addThread("C", &BlockCacheConcurrencyTest::TestThreadObj); + threadedTest->addThread("D", &BlockCacheConcurrencyTest::TestThreadMalloc); + threadedTest->addThread("E", &BlockCacheConcurrencyTest::TestThreadMalloc); + threadedTest->addThread("F", &BlockCacheConcurrencyTest::TestThreadMalloc); + return(threadedTest); +} diff --git a/src/tests/kits/support/bblockcache/BlockCacheConcurrencyTest.h b/src/tests/kits/support/bblockcache/BlockCacheConcurrencyTest.h new file mode 100644 index 0000000000..8798f56700 --- /dev/null +++ b/src/tests/kits/support/bblockcache/BlockCacheConcurrencyTest.h @@ -0,0 +1,50 @@ +/* + $Id: BlockCacheConcurrencyTest.h,v 1.1 2003/09/07 11:53:03 bonefish Exp $ + + This file defines a class for testing BBlockCache + + */ + + +#ifndef BlockCacheConcurrencyTest_H +#define BlockCacheConcurrencyTest_H + + +#include "ThreadedTestCase.h" +#include +#include + + +class BBlockCache; +class BList; + + +class BlockCacheConcurrencyTest : public BThreadedTestCase { + +private: + BBlockCache *theObjCache; + BBlockCache *theMallocCache; + int numBlocksInCache; + size_t sizeOfBlocksInCache; + size_t sizeOfNonCacheBlocks; + + void *GetBlock(BBlockCache *theCache, size_t blockSize, + thread_id theThread, BList *cacheList, BList *nonCacheList); + void SaveBlock(BBlockCache *theCache, void *, size_t blockSize, + thread_id theThread, BList *cacheList, BList *nonCacheList); + void FreeBlock(void *, size_t blockSize, bool isMallocTest, + thread_id theThread, BList *cacheList, + BList *nonCacheList); + void TestBlockCache(BBlockCache *theCache, bool isMallocTest); + +public: + static Test *suite(void); + void TestThreadObj(void); + void TestThreadMalloc(void); + virtual void setUp(void); + virtual void tearDown(void); + BlockCacheConcurrencyTest(std::string); + virtual ~BlockCacheConcurrencyTest(); +}; + +#endif diff --git a/src/tests/kits/support/bblockcache/BlockCacheExerciseTest.cpp b/src/tests/kits/support/bblockcache/BlockCacheExerciseTest.cpp new file mode 100644 index 0000000000..666908357d --- /dev/null +++ b/src/tests/kits/support/bblockcache/BlockCacheExerciseTest.cpp @@ -0,0 +1,361 @@ +/* + $Id: BlockCacheExerciseTest.cpp,v 1.1 2003/09/07 11:53:03 bonefish Exp $ + + This file tests basic functionality of BBlockCache. + + */ + + +#include "BlockCacheExerciseTest.h" +#include "cppunit/TestCaller.h" +#include + + +/* + * Method: BlockCacheExerciseTest::BlockCacheExerciseTest() + * Descr: This method is the only constructor for the BlockCacheExerciseTest + * class. + */ + + + BlockCacheExerciseTest::BlockCacheExerciseTest(std::string name) : + TestCase(name), + theCache(NULL), + numBlocksInCache(0), + sizeOfBlocksInCache(0), + sizeOfNonCacheBlocks(0), + isMallocTest(false) +{ + } + + +/* + * Method: BlockCacheExerciseTest::~BlockCacheExerciseTest() + * Descr: This method is the destructor for the BlockCacheExerciseTest class. + */ + + + BlockCacheExerciseTest::~BlockCacheExerciseTest() +{ + } + + +/* + * Method: BlockCacheExerciseTest::TestBlockCache() + * Descr: This method performs the tests on a particular BBlockCache. + * The goal of the method is to perform the following basic + * sequence: + * 1. Get (numBlocksInCache + 10) blocks of "cache size" from the + * BBlockCache. By doing this, we can guarantee that the cache + * has been exhausted and some elements are allocated to + * satisfy the caller. Then, they are all returned to the + * cache in most recent block to oldest block order. This + * confirms that regardless whether the block was initially + * part of the cache or created because the cache was empty, + * once it is returned to the cache, it is just placed on the + * cache. Imagine a cache of 4 blocks. Initally, the cache + * has the following blocks: + * A, B, C, D + * If five blocks are gotten from the cache, the caller will get + * A, B, C, D, E + * However, E wasn't initially part of the cache. It was allocated + * dynamically to satisfy the caller's request because the cache + * was empty. Now, if they are returned in the order E, D, C, B, A + * the cache will have the following blocks available in it: + * B, C, D, E + * When A is returned, the cache will find there is no more room + * for more free blocks and it will be freed. This is the + * behaviour which is confirmed initially. + * + * 2. After this is done, the cache is just "exercised". The following + * is done "numBlocksInCache" times: + * - 4 "cache sized" blocks are gotten from the cache + * - 4 "non-cache sized" blocks are gotten from the cache + * - 1 "cache sized" block is returned back to the cache + * - 1 "non-cache sized" block is returned back to the cache + * - 1 "cache sized" block is freed and not returned to the cache + * - 1 "non-cache sized" block is freed and not returned to the + * cache (but even if given to the BBlockCache, it would just + * be freed anyhow) + * What this means is that everytime through the loop, 2 "cache sized" + * and 2 "non-cache sized" blocks are kept in memory. At the end, + * 2 * numBlocksInCache items of size "cache size" and "non cache size" + * will exist. + * + * Then, numBlocksInCache / 4 items are returned to the cache and + * numBlocksInCache / 4 are freed. This ensures at the end of the + * test that there are some available blocks in the cache. + * + * The sum total of these actions test the BBlockCache. + */ + + + void BlockCacheExerciseTest::TestBlockCache(void) +{ + + // First get all items from the cache plus ten more + for (int i = 0; i < numBlocksInCache + 10; i++) { + GetBlock(sizeOfBlocksInCache); + } + + // Put them all back in reverse order to confirm 1 from above + while (!usedList.IsEmpty()) { + SaveBlock(usedList.LastItem(), sizeOfBlocksInCache); + } + + // Get a bunch of blocks and send some back to the cache + // to confirm 2 from above. + for (int i = 0; i < numBlocksInCache; i++) { + GetBlock(sizeOfBlocksInCache); + GetBlock(sizeOfBlocksInCache); + GetBlock(sizeOfNonCacheBlocks); + GetBlock(sizeOfNonCacheBlocks); + + // We send one back from the middle of the lists so + // the most recent block is not the one returned. + SaveBlock(usedList.ItemAt(usedList.CountItems() / 2), + sizeOfBlocksInCache); + SaveBlock(nonCacheList.ItemAt(nonCacheList.CountItems() / 2), + sizeOfNonCacheBlocks); + + GetBlock(sizeOfBlocksInCache); + GetBlock(sizeOfBlocksInCache); + GetBlock(sizeOfNonCacheBlocks); + GetBlock(sizeOfNonCacheBlocks); + + // We free one from the middle of the lists so the + // most recent block is not the one freed. + FreeBlock(usedList.ItemAt(usedList.CountItems() / 2), + sizeOfBlocksInCache); + FreeBlock(nonCacheList.ItemAt(nonCacheList.CountItems() / 2), + sizeOfNonCacheBlocks); + } + + // Now, send some blocks back to the cache and free some blocks + // so the cache is not empty at the end of the test. + for (int i = 0; i < numBlocksInCache / 4; i++) { + // Return the blocks which are 2/3s of the way through the + // lists. + SaveBlock(usedList.ItemAt(usedList.CountItems() * 2 / 3), + sizeOfBlocksInCache); + SaveBlock(nonCacheList.ItemAt(nonCacheList.CountItems() * 2 / 3), + sizeOfNonCacheBlocks); + + // Free the blocks which are 1/3 of the way through the lists. + FreeBlock(usedList.ItemAt(usedList.CountItems() / 3), + sizeOfBlocksInCache); + FreeBlock(nonCacheList.ItemAt(nonCacheList.CountItems() / 3), + sizeOfNonCacheBlocks); + } + } + + +/* + * Method: BlockCacheExerciseTest::BuildLists() + * Descr: This method gets all of the blocks from the cache in order to + * track them for future tests. The assumption here is that the + * blocks are not deallocated and reallocated in the implementation + * of BBlockCache. Given the purpose is to provide a cheap way to + * access allocated memory without resorting to malloc()'s or new's, + * this should be a fair assumption. + */ + + + void BlockCacheExerciseTest::BuildLists(void) +{ + freeList.MakeEmpty(); + usedList.MakeEmpty(); + nonCacheList.MakeEmpty(); + + for(int i = 0; i < numBlocksInCache; i++) { + freeList.AddItem(theCache->Get(sizeOfBlocksInCache)); + } + for(int i = 0; i < numBlocksInCache; i++) { + theCache->Save(freeList.ItemAt(i), sizeOfBlocksInCache); + } +} + + +/* + * Method: BlockCacheExerciseTest::GetBlock() + * Descr: This method returns a pointer from the BBlockCache, checking + * the value before passing it to the caller. + */ + + + void *BlockCacheExerciseTest::GetBlock(size_t blockSize) +{ + void *thePtr = theCache->Get(blockSize); + + // This new pointer should not be one which we already + // have from the BBlockCache which we haven't given back + // yet. + assert(!usedList.HasItem(thePtr)); + assert(!nonCacheList.HasItem(thePtr)); + + if (blockSize == sizeOfBlocksInCache) { + // If this block was one which could have come from the + // cache and there are free items on the cache, it + // should be one of those free blocks. + if (freeList.CountItems() > 0) { + assert(freeList.RemoveItem(thePtr)); + } + assert(usedList.AddItem(thePtr)); + } else { + // A "non-cache sized" block should never come from the + // free list. + assert(!freeList.HasItem(thePtr)); + assert(nonCacheList.AddItem(thePtr)); + } + return(thePtr); +} + + +/* + * Method: BlockCacheExerciseTest::SavedCacheBlock() + * Descr: This method passes the pointer back to the BBlockCache + * and checks the sanity of the lists. + */ + + + void BlockCacheExerciseTest::SaveBlock(void *thePtr, size_t blockSize) +{ + // The memory block being returned to the cache should + // not already be free. + assert(!freeList.HasItem(thePtr)); + + if (blockSize == sizeOfBlocksInCache) { + // If there is room on the free list, when this block + // is returned to the cache, it will be put on the + // free list. Therefore we will also track it as + // a free block on the cache. + if (freeList.CountItems() < numBlocksInCache) { + assert(freeList.AddItem(thePtr)); + } + + // This block should not be on the non-cache list but it + // should be on the used list. + assert(!nonCacheList.HasItem(thePtr)); + assert(usedList.RemoveItem(thePtr)); + } else { + // This block should not be on the used list but it should + // be on the non-cache list. + assert(!usedList.HasItem(thePtr)); + assert(nonCacheList.RemoveItem(thePtr)); + } + theCache->Save(thePtr, blockSize); +} + + +/* + * Method: BlockCacheExerciseTest::FreeBlock() + * Descr: This method frees the block directly using delete[] or free(), + * checking the sanity of the lists as it does the operation. + */ + + + void BlockCacheExerciseTest::FreeBlock(void *thePtr, size_t blockSize) +{ + // The block being freed should not already have been + // returned to the cache. + assert(!freeList.HasItem(thePtr)); + + if (blockSize == sizeOfBlocksInCache) { + // This block should not be on the non-cache list but it + // should be on the used list. + assert(!nonCacheList.HasItem(thePtr)); + assert(usedList.RemoveItem(thePtr)); + } else { + // This block should not be on the used list but it should + // be on the non-cache list. + assert(!usedList.HasItem(thePtr)); + assert(nonCacheList.RemoveItem(thePtr)); + } + if (isMallocTest) { + free(thePtr); + } else { + delete[] thePtr; + } +} + + +/* + * Method: BlockCacheExerciseTest::PerformTest() + * Descr: This method performs the tests on a series of BBlockCache + * instances. It performs the tests with a series of + * block sizes and numbers of blocks. Also, it does the + * test using a B_OBJECT_CACHE and B_MALLOC_CACHE type + * cache. For each individual BBlockCache to be tested, it: + * 1. Queries the cache to find out the blocks which are + * on it. + * 2. Performs the test. + * 3. Frees all blocks left after the test to prevent + * memory leaks. + */ + + + void BlockCacheExerciseTest::PerformTest(void) +{ + for (numBlocksInCache = 8; numBlocksInCache < 513; numBlocksInCache *= 2) { + for (sizeOfBlocksInCache = 13; sizeOfBlocksInCache < 9478; sizeOfBlocksInCache *= 3) { + + // To test getting blocks which are not from the cache, + // we will get blocks of 6 bytes less than the size of + // the blocks on the cache. + sizeOfNonCacheBlocks = sizeOfBlocksInCache - 6; + + isMallocTest = false; + theCache = new BBlockCache(numBlocksInCache, sizeOfBlocksInCache, B_OBJECT_CACHE); + assert(theCache != NULL); + + // Query the cache and determine the blocks in it. + BuildLists(); + // Perform the test on this instance. + TestBlockCache(); + delete theCache; + // Clean up remaining memory. + while (!usedList.IsEmpty()) { + FreeBlock(usedList.LastItem(), sizeOfBlocksInCache); + } + while (!nonCacheList.IsEmpty()) { + FreeBlock(nonCacheList.LastItem(), sizeOfNonCacheBlocks); + } + + isMallocTest = true; + theCache = new BBlockCache(numBlocksInCache, sizeOfBlocksInCache, B_MALLOC_CACHE); + assert(theCache != NULL); + + // Query the cache and determine the blocks in it. + BuildLists(); + // Perform the test on this instance. + TestBlockCache(); + delete theCache; + // Clean up remaining memory. + while (!usedList.IsEmpty()) { + FreeBlock(usedList.LastItem(), sizeOfBlocksInCache); + } + while (!nonCacheList.IsEmpty()) { + FreeBlock(nonCacheList.LastItem(), sizeOfNonCacheBlocks); + } + } + } +} + + +/* + * Method: BlockCacheExerciseTest::suite() + * Descr: This static member function returns a test caller for performing + * the "BlockCacheExerciseTest" test. + */ + + +CppUnit::Test *BlockCacheExerciseTest::suite(void) +{ + typedef CppUnit::TestCaller + BlockCacheExerciseTestCaller; + + return(new BlockCacheExerciseTestCaller("BBlockCache::Exercise Test", &BlockCacheExerciseTest::PerformTest)); +} + + + diff --git a/src/tests/kits/support/bblockcache/BlockCacheExerciseTest.h b/src/tests/kits/support/bblockcache/BlockCacheExerciseTest.h new file mode 100644 index 0000000000..245e80e988 --- /dev/null +++ b/src/tests/kits/support/bblockcache/BlockCacheExerciseTest.h @@ -0,0 +1,49 @@ +/* + $Id: BlockCacheExerciseTest.h,v 1.1 2003/09/07 11:53:03 bonefish Exp $ + + This file defines a class for performing tests on the BBlockCache class. + + */ + + +#ifndef BlockCacheExerciseTest_H +#define BlockCacheExerciseTest_H + + +#include "cppunit/TestCase.h" +#include + + +class BBlockCache; + + +class BlockCacheExerciseTest : public CppUnit::TestCase { + +private: + BBlockCache *theCache; + int numBlocksInCache; + size_t sizeOfBlocksInCache; + size_t sizeOfNonCacheBlocks; + + bool isMallocTest; + + BList freeList; + BList usedList; + BList nonCacheList; + + void BuildLists(void); + void *GetBlock(size_t blockSize); + void SaveBlock(void *, size_t blockSize); + void FreeBlock(void *, size_t blockSize); + void TestBlockCache(void); + +protected: + +public: + static CppUnit::Test *suite(void); + BlockCacheExerciseTest(std::string = ""); + virtual ~BlockCacheExerciseTest(); + virtual void PerformTest(void); +}; + +#endif diff --git a/src/tests/kits/support/bblockcache/BlockCacheTest.cpp b/src/tests/kits/support/bblockcache/BlockCacheTest.cpp new file mode 100644 index 0000000000..7144fa0b8d --- /dev/null +++ b/src/tests/kits/support/bblockcache/BlockCacheTest.cpp @@ -0,0 +1,21 @@ +/* + $Id: BlockCacheTest.cpp,v 1.1 2003/09/07 11:53:03 bonefish Exp $ +*/ + + +#include "cppunit/Test.h" +#include "cppunit/TestSuite.h" +#include "BlockCacheExerciseTest.h" +#include "BlockCacheConcurrencyTest.h" + + +CppUnit::Test* BlockCacheTestSuite() +{ + CppUnit::TestSuite *testSuite = new CppUnit::TestSuite(); + + testSuite->addTest(BlockCacheExerciseTest::suite()); + testSuite->addTest(BlockCacheConcurrencyTest::suite()); + + return testSuite; +} + diff --git a/src/tests/kits/support/bblockcache/BlockCacheTest.h b/src/tests/kits/support/bblockcache/BlockCacheTest.h new file mode 100644 index 0000000000..e6ec33f111 --- /dev/null +++ b/src/tests/kits/support/bblockcache/BlockCacheTest.h @@ -0,0 +1,8 @@ +#ifndef _blockcache_test_h_ +#define _blockcache_test_h_ + +class CppUnit::Test; + +CppUnit::Test* BlockCacheTestSuite(); + +#endif // _blockcache_test_h_