diff --git a/ChangeLog b/ChangeLog index 3f99f190..31526336 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-01-11 Tatsuhiro Tsujikawa + + Rewritten get*Missing*Index functions. Now no need to allocate memory + each time these functions are called. + * src/BitfieldMan.{h, cc} + * test/BitfieldManTest.cc + * src/array_fun.h + * test/array_funTest.cc + + Now BitfieldMan::countBlock() returns BitfieldMan::blocks. + Added new BitfieldMan::countFilteredBlock() to get the number of blocks + filtered. Removed unnecessary cast to int32_t. + * src/BitfieldMan.{h, cc} + 2008-01-10 Tatsuhiro Tsujikawa Fixed the bug that EX_TOO_LONG_PAYLOAD exception is thrown if just diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index 32f3a99c..2a4a04d2 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -34,6 +34,7 @@ /* copyright --> */ #include "BitfieldMan.h" #include "Util.h" +#include "array_fun.h" #include BitfieldMan::BitfieldMan(int32_t blockLength, int64_t totalLength) @@ -131,8 +132,9 @@ int32_t BitfieldMan::getNthBitIndex(const unsigned char bitfield, int32_t nth) c return index; } +template int32_t -BitfieldMan::getMissingIndexRandomly(const unsigned char* bitfield, +BitfieldMan::getMissingIndexRandomly(const Array& bitfield, int32_t bitfieldLength) const { /* @@ -192,47 +194,35 @@ int32_t BitfieldMan::getMissingIndex(const unsigned char* peerBitfield, int32_t if(bitfieldLength != length) { return -1; } - unsigned char* tempBitfield = new unsigned char[bitfieldLength]; - for(int32_t i = 0; i < bitfieldLength; ++i) { - tempBitfield[i] = peerBitfield[i] & ~bitfield[i]; - if(filterEnabled) { - tempBitfield[i] &= filterBitfield[i]; - } + array_fun bf = array_and(array_negate(bitfield), peerBitfield); + if(filterEnabled) { + bf = array_and(bf, filterBitfield); } - int32_t index = getMissingIndexRandomly(tempBitfield, bitfieldLength); - delete [] tempBitfield; - return index; + return getMissingIndexRandomly(bf, bitfieldLength); } int32_t BitfieldMan::getMissingUnusedIndex(const unsigned char* peerBitfield, int32_t length) const { if(bitfieldLength != length) { return -1; } - unsigned char* tempBitfield = new unsigned char[bitfieldLength]; - for(int32_t i = 0; i < bitfieldLength; ++i) { - tempBitfield[i] = peerBitfield[i] & ~bitfield[i] & ~useBitfield[i]; - if(filterEnabled) { - tempBitfield[i] &= filterBitfield[i]; - } + array_fun bf = array_and(array_and(array_negate(bitfield), + array_negate(useBitfield)), + peerBitfield); + if(filterEnabled) { + bf = array_and(bf, filterBitfield); } - int32_t index = getMissingIndexRandomly(tempBitfield, bitfieldLength); - delete [] tempBitfield; - return index; + return getMissingIndexRandomly(bf, bitfieldLength); } -int32_t BitfieldMan::getFirstMissingUnusedIndex(const unsigned char* peerBitfield, int32_t length) const { - if(bitfieldLength != length) { - return -1; - } +template +int32_t BitfieldMan::getFirstMissingIndex(const Array& bitfield, int32_t bitfieldLength) const +{ for(int32_t i = 0; i < bitfieldLength; ++i) { - unsigned char bit = peerBitfield[i] & ~bitfield[i] & ~useBitfield[i]; - if(filterEnabled) { - bit &= filterBitfield[i]; - } - for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) { - unsigned char mask = 1 << bs; - if(bit & mask) { - return i*8+7-bs; + int32_t base = i*8; + for(int32_t bi = 0; bi < 8 && base+bi < blocks; ++bi) { + unsigned char mask = 128 >> bi; + if(bitfield[i] & mask) { + return base+bi; } } } @@ -240,40 +230,38 @@ int32_t BitfieldMan::getFirstMissingUnusedIndex(const unsigned char* peerBitfiel } int32_t BitfieldMan::getFirstMissingUnusedIndex() const { - for(int32_t i = 0; i < bitfieldLength; ++i) { - unsigned char bit = ~bitfield[i] & ~useBitfield[i]; - if(filterEnabled) { - bit &= filterBitfield[i]; - } - for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) { - unsigned char mask = 1 << bs; - if(bit & mask) { - return i*8+7-bs; - } - } + array_fun bf = array_and(array_negate(bitfield), + array_negate(useBitfield)); + if(filterEnabled) { + bf = array_and(bf, filterBitfield); } - return -1; + return getFirstMissingIndex(bf, bitfieldLength); +} + +int32_t BitfieldMan::getFirstMissingIndex() const +{ + array_fun bf = array_negate(bitfield); + if(filterEnabled) { + bf = array_and(bf, filterBitfield); + } + return getFirstMissingIndex(bf, bitfieldLength); } int32_t BitfieldMan::getMissingIndex() const { - unsigned char* tempBitfield = new unsigned char[bitfieldLength]; - for(int32_t i = 0; i < bitfieldLength; ++i) { - tempBitfield[i] = ~bitfield[i]; - if(filterEnabled) { - tempBitfield[i] &= filterBitfield[i]; - } + array_fun bf = array_negate(bitfield); + if(filterEnabled) { + bf = array_and(bf, filterBitfield); } - int32_t index = getMissingIndexRandomly(tempBitfield, bitfieldLength); - delete [] tempBitfield; - return index; + return getMissingIndexRandomly(bf, bitfieldLength); } int32_t BitfieldMan::getMissingUnusedIndex() const { - unsigned char* tempBitfield = new unsigned char[bitfieldLength]; - memset(tempBitfield, 0xff, bitfieldLength); - int32_t index = getMissingUnusedIndex(tempBitfield, bitfieldLength); - delete [] tempBitfield; - return index; + array_fun bf = array_and(array_negate(bitfield), + array_negate(useBitfield)); + if(filterEnabled) { + bf = array_and(bf, filterBitfield); + } + return getMissingIndexRandomly(bf, bitfieldLength); } // [startIndex, endIndex) @@ -298,8 +286,7 @@ public: }; int32_t BitfieldMan::getStartIndex(int32_t index) const { - while(index < (int32_t)blocks && - (isUseBitSet(index) || isBitSet(index))) { + while(index < blocks && (isUseBitSet(index) || isBitSet(index))) { index++; } if((int32_t)blocks <= index) { @@ -310,8 +297,7 @@ int32_t BitfieldMan::getStartIndex(int32_t index) const { } int32_t BitfieldMan::getEndIndex(int32_t index) const { - while(index < (int32_t)blocks && - (!isUseBitSet(index) && !isBitSet(index))) { + while(index < blocks && (!isUseBitSet(index) && !isBitSet(index))) { index++; } return index; @@ -320,9 +306,8 @@ int32_t BitfieldMan::getEndIndex(int32_t index) const { int32_t BitfieldMan::getSparseMissingUnusedIndex() const { Range maxRange; int32_t index = 0; - int32_t blocks = countBlock(); Range currentRange; - while(index < (int32_t)blocks) { + while(index < blocks) { currentRange.startIndex = getStartIndex(index); if(currentRange.startIndex == -1) { break; @@ -346,41 +331,40 @@ int32_t BitfieldMan::getSparseMissingUnusedIndex() const { } } -BlockIndexes BitfieldMan::getAllMissingIndexes() const { +template +BlockIndexes BitfieldMan::getAllMissingIndexes(const Array& bitfield, int32_t bitfieldLength) const +{ BlockIndexes missingIndexes; for(int32_t i = 0; i < bitfieldLength; ++i) { - unsigned char bit = ~bitfield[i]; - if(filterEnabled) { - bit &= filterBitfield[i]; - } - for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) { - unsigned char mask = 1 << bs; - if(bit & mask) { - missingIndexes.push_back(i*8+7-bs); + int32_t base = i*8; + for(int32_t bi = 0; bi < 8 && base+bi < blocks; ++bi) { + unsigned char mask = 128 >> bi; + if(bitfield[i] & mask) { + missingIndexes.push_back(base+bi); } } } return missingIndexes; } +BlockIndexes BitfieldMan::getAllMissingIndexes() const { + array_fun bf = array_negate(bitfield); + if(filterEnabled) { + bf = array_and(bf, filterBitfield); + } + return getAllMissingIndexes(bf, bitfieldLength); +} + BlockIndexes BitfieldMan::getAllMissingIndexes(const unsigned char* peerBitfield, int32_t peerBitfieldLength) const { - BlockIndexes missingIndexes; if(bitfieldLength != peerBitfieldLength) { - return missingIndexes; + return BlockIndexes(); } - for(int32_t i = 0; i < bitfieldLength; ++i) { - unsigned char bit = peerBitfield[i] & ~bitfield[i]; - if(filterEnabled) { - bit &= filterBitfield[i]; - } - for(int bs = 7; bs >= 0 && i*8+7-bs < blocks; bs--) { - unsigned char mask = 1 << bs; - if(bit & mask) { - missingIndexes.push_back(i*8+7-bs); - } - } + array_fun bf = array_and(array_negate(bitfield), + peerBitfield); + if(filterEnabled) { + bf = array_and(bf, filterBitfield); } - return missingIndexes; + return getAllMissingIndexes(bf, bitfieldLength); } int32_t BitfieldMan::countMissingBlock() const { @@ -402,12 +386,12 @@ int32_t BitfieldMan::countMissingBlockNow() const { } } +int32_t BitfieldMan::countFilteredBlock() const { + return cachedNumFilteredBlock; +} + int32_t BitfieldMan::countBlock() const { - if(filterEnabled) { - return cachedNumFilteredBlock; - } else { - return blocks; - } + return blocks; } int32_t BitfieldMan::countFilteredBlockNow() const { @@ -419,7 +403,7 @@ int32_t BitfieldMan::countFilteredBlockNow() const { } bool BitfieldMan::setBitInternal(unsigned char* bitfield, int32_t index, bool on) { - if((int32_t)blocks <= index) { return false; } + if(blocks <= index) { return false; } unsigned char mask = 128 >> index%8; if(on) { bitfield[index/8] |= mask; @@ -479,7 +463,7 @@ bool BitfieldMan::isAllBitSet() const { } bool BitfieldMan::isBitSetInternal(const unsigned char* bitfield, int32_t index) const { - if(index < 0 || (int32_t)blocks <= index) { return false; } + if(index < 0 || blocks <= index) { return false; } unsigned char mask = 128 >> index%8; return (bitfield[index/8] & mask) != 0; } @@ -535,7 +519,7 @@ void BitfieldMan::addFilter(int64_t offset, int64_t length) { } int32_t startBlock = offset/blockLength; int32_t endBlock = (offset+length-1)/blockLength; - for(int i = startBlock; i <= endBlock && i < (int32_t)blocks; i++) { + for(int i = startBlock; i <= endBlock && i < blocks; i++) { setFilterBit(i); } updateCache(); diff --git a/src/BitfieldMan.h b/src/BitfieldMan.h index fbbf60ae..8e976413 100644 --- a/src/BitfieldMan.h +++ b/src/BitfieldMan.h @@ -63,6 +63,17 @@ private: int32_t countSetBit(const unsigned char* bitfield, int32_t len) const; int32_t getNthBitIndex(const unsigned char bit, int32_t nth) const; int32_t getMissingIndexRandomly(const unsigned char* bitfield, int32_t len) const; + + template + int32_t + getMissingIndexRandomly(const Array& bitfield, + int32_t bitfieldLength) const; + template + int32_t getFirstMissingIndex(const Array& bitfield, int32_t bitfieldLength) const; + + template + BlockIndexes getAllMissingIndexes(const Array& bitfield, int32_t bitfieldLength) const; + bool isBitSetInternal(const unsigned char* bitfield, int32_t index) const; bool setBitInternal(unsigned char* bitfield, int32_t index, bool on); bool setFilterBit(int32_t index); @@ -112,9 +123,9 @@ public: } int32_t getBlockLength(int32_t index) const { - if(index == (int32_t)(blocks-1)) { + if(index == blocks-1) { return getLastBlockLength(); - } else if(0 <= index && index < (int32_t)(blocks-1)) { + } else if(0 <= index && index < blocks-1) { return getBlockLength(); } else { return 0; @@ -143,6 +154,10 @@ public: * affected by filter */ int32_t getFirstMissingUnusedIndex() const; + /** + * affected by filter + */ + int32_t getFirstMissingIndex() const; /** * affected by filter */ @@ -194,6 +209,8 @@ public: /** * affected by filter */ + int32_t countFilteredBlock() const; + int32_t countBlock() const; /** * affected by filter diff --git a/src/array_fun.h b/src/array_fun.h new file mode 100644 index 00000000..d9ac1c26 --- /dev/null +++ b/src/array_fun.h @@ -0,0 +1,198 @@ +/* */ +#ifndef _D_ARRAY_FUN_H_ +#define _D_ARRAY_FUN_H_ + +#include + +template +class bit_negate:public std::unary_function { +public: + T operator()(const T& t) const + { + return ~t; + } +}; + +template +class bit_and:public std::binary_function { +public: + T operator()(const T& t1, const T& t2) const + { + return t1&t2; + } +}; + +template +class array_function_base { +public: + virtual ~array_function_base() {} + + virtual R operator[](std::size_t index) const = 0; + + virtual array_function_base* clone() const = 0; +}; + +template +class array_unary_function:public array_function_base { +private: + A _a; + F _f; +public: + array_unary_function(A a, F f):_a(a), _f(f) {} + + virtual typename F::result_type operator[](std::size_t index) const + { + return _f(_a[index]); + } + + virtual array_function_base* clone() const + { + return new array_unary_function(*this); + } +}; + +template +class array_binary_function:public array_function_base{ +private: + A _a; + B _b; + F _f; +public: + array_binary_function(A a, B b, F f):_a(a), _b(b), _f(f) {} + + virtual typename F::result_type operator[](std::size_t index) const + { + return _f(_a[index], _b[index]); + } + + virtual array_function_base* clone() const + { + return new array_binary_function(*this); + } +}; + +template +class array_fun { +private: + array_function_base* _p; +public: + template + array_fun(A a, F f):_p(new array_unary_function(a, f)) {} + + template + array_fun(A a, B b, F f):_p(new array_binary_function(a, b, f)) {} + + array_fun(const array_fun& af):_p(af._p->clone()) {} + + ~array_fun() + { + delete _p; + } + + array_fun& operator=(const array_fun& af) + { + if(this != &af) { + delete _p; + _p = af._p->clone(); + } + return *this; + } + + R operator[](std::size_t index) const + { + return (*_p)[index]; + } + + typedef R result_type; +}; + +template +array_fun +array_negate(A a) +{ + return array_fun(a, bit_negate()); +} + +template +array_fun +array_negate(T* a) +{ + return array_fun(a, bit_negate()); +} + +template +array_fun +array_negate(A a) +{ + return array_fun(a, bit_negate()); +} + +template +array_fun +array_and(A a, B b) +{ + return array_fun(a, b, bit_and()); +} + +template +array_fun +array_and(T* a, T* b) +{ + return array_fun(a, b, bit_and()); +} + +template +array_fun +array_and(T a, T b) +{ + return array_fun(a, b, bit_and()); +} + +template +array_fun +array_and(A a, B b) +{ + return array_fun(a, b, bit_and()); +} + +template +array_fun +array_and(A a, B b) +{ + return array_fun(a, b, bit_and()); +} + +#endif // _D_ARRAY_FUN_H_ diff --git a/test/BitfieldManTest.cc b/test/BitfieldManTest.cc index 2418ed34..2ab69298 100644 --- a/test/BitfieldManTest.cc +++ b/test/BitfieldManTest.cc @@ -1,16 +1,13 @@ #include "BitfieldMan.h" #include "FixedNumberRandomizer.h" -#include "BitfieldManFactory.h" -#include #include -using namespace std; - class BitfieldManTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(BitfieldManTest); CPPUNIT_TEST(testGetBlockSize); CPPUNIT_TEST(testGetFirstMissingUnusedIndex); + CPPUNIT_TEST(testGetFirstMissingIndex); CPPUNIT_TEST(testIsAllBitSet); CPPUNIT_TEST(testFilter); CPPUNIT_TEST(testGetMissingIndex); @@ -19,6 +16,12 @@ class BitfieldManTest:public CppUnit::TestFixture { CPPUNIT_TEST(testIsBitSetOffsetRange); CPPUNIT_TEST(testGetMissingUnusedLength); CPPUNIT_TEST(testSetBitRange); + CPPUNIT_TEST(testGetAllMissingIndexes); + CPPUNIT_TEST(testGetAllMissingIndexes_noarg); + CPPUNIT_TEST(testGetMissingUnusedIndex); + CPPUNIT_TEST(testGetMissingIndex_noarg); + CPPUNIT_TEST(testGetMissingUnusedIndex_noarg); + CPPUNIT_TEST(testCountFilteredBlock); CPPUNIT_TEST_SUITE_END(); private: RandomizerHandle fixedNumberRandomizer; @@ -35,14 +38,22 @@ public: void testGetBlockSize(); void testGetFirstMissingUnusedIndex(); + void testGetFirstMissingIndex(); + void testGetMissingIndex(); + void testGetMissingIndex_noarg(); + void testGetMissingUnusedIndex(); + void testGetMissingUnusedIndex_noarg(); + void testGetAllMissingIndexes(); + void testGetAllMissingIndexes_noarg(); + void testIsAllBitSet(); void testFilter(); - void testGetMissingIndex(); void testGetSparceMissingUnusedIndex(); void testGetSparceMissingUnusedIndex_setBit(); void testIsBitSetOffsetRange(); void testGetMissingUnusedLength(); void testSetBitRange(); + void testCountFilteredBlock(); }; @@ -58,27 +69,116 @@ void BitfieldManTest::testGetBlockSize() { CPPUNIT_ASSERT_EQUAL((int32_t)0, bt2.getBlockLength(11)); } -void BitfieldManTest::testGetFirstMissingUnusedIndex() { - BitfieldMan bt1(1024, 1024*10); - unsigned char bitfield[2]; - memset(bitfield, 0xff, sizeof(bitfield)); - - CPPUNIT_ASSERT_EQUAL((int32_t)0, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield))); - CPPUNIT_ASSERT(bt1.setUseBit(0)); - CPPUNIT_ASSERT_EQUAL((int32_t)1, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield))); - CPPUNIT_ASSERT(bt1.unsetUseBit(0)); - CPPUNIT_ASSERT_EQUAL((int32_t)0, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield))); - CPPUNIT_ASSERT(bt1.setBit(0)); - CPPUNIT_ASSERT_EQUAL((int32_t)1, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield))); - - for(int i = 0; i < 8; i++) { - CPPUNIT_ASSERT(bt1.setBit(i)); +void BitfieldManTest::testGetFirstMissingUnusedIndex() +{ + { + BitfieldMan bt1(1024, 1024*10); + + CPPUNIT_ASSERT_EQUAL(0, bt1.getFirstMissingUnusedIndex()); + bt1.setUseBit(0); + CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingUnusedIndex()); + bt1.unsetUseBit(0); + bt1.setBit(0); + CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingUnusedIndex()); + bt1.setAllBit(); + CPPUNIT_ASSERT_EQUAL(-1, bt1.getFirstMissingUnusedIndex()); } - CPPUNIT_ASSERT_EQUAL((int32_t)8, bt1.getFirstMissingUnusedIndex(bitfield, sizeof(bitfield))); + { + BitfieldMan bt1(1024, 1024*10); - CPPUNIT_ASSERT_EQUAL((int32_t)8, bt1.getFirstMissingUnusedIndex()); - CPPUNIT_ASSERT(bt1.setUseBit(8)); - CPPUNIT_ASSERT_EQUAL((int32_t)9, bt1.getFirstMissingUnusedIndex()); + bt1.addFilter(1024, 1024*10); + bt1.enableFilter(); + CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingUnusedIndex()); + bt1.setUseBit(1); + CPPUNIT_ASSERT_EQUAL(2, bt1.getFirstMissingUnusedIndex()); + bt1.setBit(2); + CPPUNIT_ASSERT_EQUAL(3, bt1.getFirstMissingUnusedIndex()); + } +} + +void BitfieldManTest::testGetFirstMissingIndex() +{ + { + BitfieldMan bt1(1024, 1024*10); + + CPPUNIT_ASSERT_EQUAL(0, bt1.getFirstMissingIndex()); + bt1.setUseBit(0); + CPPUNIT_ASSERT_EQUAL(0, bt1.getFirstMissingIndex()); + bt1.unsetUseBit(0); + bt1.setBit(0); + CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingIndex()); + bt1.setAllBit(); + CPPUNIT_ASSERT_EQUAL(-1, bt1.getFirstMissingIndex()); + } + { + BitfieldMan bt1(1024, 1024*10); + + bt1.addFilter(1024, 1024*10); + bt1.enableFilter(); + CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingIndex()); + bt1.setUseBit(1); + CPPUNIT_ASSERT_EQUAL(1, bt1.getFirstMissingIndex()); + bt1.setBit(1); + CPPUNIT_ASSERT_EQUAL(2, bt1.getFirstMissingIndex()); + } +} + +void BitfieldManTest::testGetMissingUnusedIndex_noarg() +{ + { + BitfieldMan bt1(1024, 1024*10); + bt1.setRandomizer(fixedNumberRandomizer); + + CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingUnusedIndex()); + bt1.setUseBit(0); + CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingUnusedIndex()); + bt1.unsetUseBit(0); + bt1.setBit(0); + CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingUnusedIndex()); + bt1.setAllBit(); + CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingUnusedIndex()); + } + { + BitfieldMan bt1(1024, 1024*10); + bt1.setRandomizer(fixedNumberRandomizer); + + bt1.addFilter(1024, 1024*10); + bt1.enableFilter(); + CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingUnusedIndex()); + bt1.setUseBit(1); + CPPUNIT_ASSERT_EQUAL(2, bt1.getMissingUnusedIndex()); + bt1.setBit(2); + CPPUNIT_ASSERT_EQUAL(3, bt1.getMissingUnusedIndex()); + } +} + +void BitfieldManTest::testGetMissingIndex_noarg() +{ + { + BitfieldMan bt1(1024, 1024*10); + bt1.setRandomizer(fixedNumberRandomizer); + + CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingIndex()); + bt1.setUseBit(0); + CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingIndex()); + bt1.unsetUseBit(0); + bt1.setBit(0); + CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingIndex()); + bt1.setAllBit(); + CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingIndex()); + } + { + BitfieldMan bt1(1024, 1024*10); + bt1.setRandomizer(fixedNumberRandomizer); + + bt1.addFilter(1024, 1024*10); + bt1.enableFilter(); + CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingIndex()); + bt1.setUseBit(1); + CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingIndex()); + bt1.setBit(1); + CPPUNIT_ASSERT_EQUAL(2, bt1.getMissingIndex()); + } } void BitfieldManTest::testIsAllBitSet() { @@ -178,6 +278,11 @@ void BitfieldManTest::testGetMissingIndex() { }; CPPUNIT_ASSERT_EQUAL((int32_t)0, bt1.getMissingIndex(bitArray, 32)); + bt1.addFilter(1024, 1024*256); + bt1.enableFilter(); + CPPUNIT_ASSERT_EQUAL((int32_t)1, bt1.getMissingIndex(bitArray, 32)); + bt1.disableFilter(); + unsigned char bitArray2[] = { 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -354,3 +459,103 @@ void BitfieldManTest::testSetBitRange() } CPPUNIT_ASSERT_EQUAL(int64_t(5*blockLength), bf.getCompletedLength()); } + +void BitfieldManTest::testGetAllMissingIndexes_noarg() +{ + int32_t blockLength = 16*1024; + int64_t totalLength = 1024*1024; + BitfieldMan bf(blockLength, totalLength); + + CPPUNIT_ASSERT_EQUAL((size_t)64, bf.getAllMissingIndexes().size()); + for(int32_t i = 0; i < 63; ++i) { + bf.setBit(i); + } + CPPUNIT_ASSERT_EQUAL((size_t)1, bf.getAllMissingIndexes().size()); + CPPUNIT_ASSERT_EQUAL(63, bf.getAllMissingIndexes().front()); +} + +void BitfieldManTest::testGetAllMissingIndexes() +{ + int32_t blockLength = 16*1024; + int64_t totalLength = 1024*1024; + BitfieldMan bf(blockLength, totalLength); + BitfieldMan peerBf(blockLength, totalLength); + peerBf.setAllBit(); + + CPPUNIT_ASSERT_EQUAL((size_t)64, bf.getAllMissingIndexes(peerBf.getBitfield(), + peerBf.getBitfieldLength()).size()); + for(int32_t i = 0; i < 62; ++i) { + bf.setBit(i); + } + peerBf.unsetBit(62); + + { + Integers indexes = bf.getAllMissingIndexes(peerBf.getBitfield(), + peerBf.getBitfieldLength()); + + CPPUNIT_ASSERT_EQUAL((size_t)1, indexes.size()); + CPPUNIT_ASSERT_EQUAL(63, indexes.front()); + } +} + +void BitfieldManTest::testGetMissingUnusedIndex() +{ + BitfieldMan bt1(1024, 1024*256); + bt1.setRandomizer(fixedNumberRandomizer); + + unsigned char bitArray[] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + }; + CPPUNIT_ASSERT_EQUAL(0, bt1.getMissingUnusedIndex(bitArray, 32)); + + bt1.addFilter(1024, 1024*256); + bt1.enableFilter(); + CPPUNIT_ASSERT_EQUAL(1, bt1.getMissingUnusedIndex(bitArray, 32)); + bt1.setUseBit(1); + CPPUNIT_ASSERT_EQUAL(2, bt1.getMissingUnusedIndex(bitArray, 32)); + bt1.disableFilter(); + + bt1.setBit(0); + CPPUNIT_ASSERT_EQUAL(2, bt1.getMissingUnusedIndex(bitArray, 32)); + + bt1.setAllBit(); + CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingUnusedIndex(bitArray, 32)); + + bt1.clearAllBit(); + bt1.setAllUseBit(); + CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingUnusedIndex(bitArray, 32)); + + unsigned char bitArray4[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }; + + CPPUNIT_ASSERT_EQUAL(-1, bt1.getMissingUnusedIndex(bitArray4, 32)); +} + +void BitfieldManTest::testCountFilteredBlock() +{ + BitfieldMan bt(1024, 1024*256); + CPPUNIT_ASSERT_EQUAL(256, bt.countBlock()); + CPPUNIT_ASSERT_EQUAL(0, bt.countFilteredBlock()); + bt.addFilter(1024, 1024*256); + bt.enableFilter(); + CPPUNIT_ASSERT_EQUAL(256, bt.countBlock()); + CPPUNIT_ASSERT_EQUAL(255, bt.countFilteredBlock()); + bt.disableFilter(); + CPPUNIT_ASSERT_EQUAL(256, bt.countBlock()); + CPPUNIT_ASSERT_EQUAL(0, bt.countFilteredBlock()); +} diff --git a/test/array_funTest.cc b/test/array_funTest.cc new file mode 100644 index 00000000..32fe0b6f --- /dev/null +++ b/test/array_funTest.cc @@ -0,0 +1,67 @@ +#include "array_fun.h" +#include + +using namespace std; + +class array_funTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(array_funTest); + CPPUNIT_TEST(testBit_negate); + CPPUNIT_TEST(testBit_and); + CPPUNIT_TEST(testArray_negate); + CPPUNIT_TEST(testArray_and); + CPPUNIT_TEST_SUITE_END(); +public: + void testBit_negate(); + void testBit_and(); + void testArray_negate(); + void testArray_and(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(array_funTest); + +void array_funTest::testBit_negate() +{ + unsigned char b = 0xaa; + CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, bit_negate()(b)); +} + +void array_funTest::testBit_and() +{ + unsigned char b = 0xaa; + CPPUNIT_ASSERT_EQUAL((unsigned char)0x0a, bit_and()(b, 0x0a)); +} + +void array_funTest::testArray_negate() +{ + unsigned char a[] = { 0xaa, 0x55 }; + array_fun f = array_negate((unsigned char*)a); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, f[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, f[1]); + + array_fun ff = array_negate(f); + CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, ff[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, ff[1]); +} + +void array_funTest::testArray_and() +{ + unsigned char a1[] = { 0xaa, 0x55 }; + unsigned char a2[] = { 0x1a, 0x25 }; + array_fun f = array_and((unsigned char*)a1, (unsigned char*)a2); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x0a, f[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x05, f[1]); + + array_fun f2 = array_and((unsigned char*)a1, array_negate(a2)); + CPPUNIT_ASSERT_EQUAL((unsigned char)0xa0, f2[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x50, f2[1]); + + array_fun f3 = array_and(array_negate(a2), (unsigned char*)a1); + CPPUNIT_ASSERT_EQUAL((unsigned char)0xa0, f3[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x50, f3[1]); + + array_fun f4 = array_and(array_negate(a1), array_negate(a2)); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x45, f4[0]); + CPPUNIT_ASSERT_EQUAL((unsigned char)0x8a, f4[1]); +}