2008-01-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

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}
pull/1/head
Tatsuhiro Tsujikawa 2008-01-11 13:32:00 +00:00
parent 5b8358b4d5
commit 83c82f3ec2
6 changed files with 605 additions and 120 deletions

View File

@ -1,3 +1,17 @@
2008-01-11 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
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 <tujikawa at rednoah dot com>
Fixed the bug that EX_TOO_LONG_PAYLOAD exception is thrown if just

View File

@ -34,6 +34,7 @@
/* copyright --> */
#include "BitfieldMan.h"
#include "Util.h"
#include "array_fun.h"
#include <string.h>
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<typename Array>
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<unsigned char> 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<unsigned char> 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<typename Array>
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<unsigned char> 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<unsigned char> 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<unsigned char> 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<unsigned char> 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<typename Array>
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<unsigned char> 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<unsigned char> 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();

View File

@ -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<typename Array>
int32_t
getMissingIndexRandomly(const Array& bitfield,
int32_t bitfieldLength) const;
template<typename Array>
int32_t getFirstMissingIndex(const Array& bitfield, int32_t bitfieldLength) const;
template<typename Array>
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

198
src/array_fun.h Normal file
View File

@ -0,0 +1,198 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef _D_ARRAY_FUN_H_
#define _D_ARRAY_FUN_H_
#include <functional>
template<typename T>
class bit_negate:public std::unary_function<T, T> {
public:
T operator()(const T& t) const
{
return ~t;
}
};
template<typename T>
class bit_and:public std::binary_function<T, T, T> {
public:
T operator()(const T& t1, const T& t2) const
{
return t1&t2;
}
};
template<typename R>
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<typename A, typename F>
class array_unary_function:public array_function_base<typename F::result_type> {
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<typename F::result_type>* clone() const
{
return new array_unary_function(*this);
}
};
template<typename A, typename B, typename F>
class array_binary_function:public array_function_base<typename F::result_type>{
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<typename F::result_type>* clone() const
{
return new array_binary_function(*this);
}
};
template<typename R>
class array_fun {
private:
array_function_base<R>* _p;
public:
template<typename A, typename F>
array_fun(A a, F f):_p(new array_unary_function<A, F>(a, f)) {}
template<typename A, typename B, typename F>
array_fun(A a, B b, F f):_p(new array_binary_function<A, B, F>(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<typename R, typename A>
array_fun<R>
array_negate(A a)
{
return array_fun<R>(a, bit_negate<R>());
}
template<typename T>
array_fun<T>
array_negate(T* a)
{
return array_fun<T>(a, bit_negate<T>());
}
template<typename A>
array_fun<typename A::result_type>
array_negate(A a)
{
return array_fun<typename A::result_type>(a, bit_negate<typename A::result_type>());
}
template<typename R, typename A, typename B>
array_fun<R>
array_and(A a, B b)
{
return array_fun<R>(a, b, bit_and<R>());
}
template<typename T>
array_fun<T>
array_and(T* a, T* b)
{
return array_fun<T>(a, b, bit_and<T>());
}
template<typename T>
array_fun<typename T::result_type>
array_and(T a, T b)
{
return array_fun<typename T::result_type>(a, b, bit_and<typename T::result_type>());
}
template<typename A, typename B>
array_fun<typename A::result_type>
array_and(A a, B b)
{
return array_fun<typename A::result_type>(a, b, bit_and<typename A::result_type>());
}
template<typename A, typename B>
array_fun<typename B::result_type>
array_and(A a, B b)
{
return array_fun<typename B::result_type>(a, b, bit_and<typename B::result_type>());
}
#endif // _D_ARRAY_FUN_H_

View File

@ -1,16 +1,13 @@
#include "BitfieldMan.h"
#include "FixedNumberRandomizer.h"
#include "BitfieldManFactory.h"
#include <string>
#include <cppunit/extensions/HelperMacros.h>
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());
}

67
test/array_funTest.cc Normal file
View File

@ -0,0 +1,67 @@
#include "array_fun.h"
#include <cppunit/extensions/HelperMacros.h>
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<unsigned char>()(b));
}
void array_funTest::testBit_and()
{
unsigned char b = 0xaa;
CPPUNIT_ASSERT_EQUAL((unsigned char)0x0a, bit_and<unsigned char>()(b, 0x0a));
}
void array_funTest::testArray_negate()
{
unsigned char a[] = { 0xaa, 0x55 };
array_fun<unsigned char> f = array_negate((unsigned char*)a);
CPPUNIT_ASSERT_EQUAL((unsigned char)0x55, f[0]);
CPPUNIT_ASSERT_EQUAL((unsigned char)0xaa, f[1]);
array_fun<unsigned char> 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<unsigned char> 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<unsigned char> 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<unsigned char> 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<unsigned char> 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]);
}