mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-03-10 22:44:21 +00:00
Cleanup, multicast fingerprint, benchmark asymmetric crypto
This commit is contained in:
parent
199b3345a0
commit
6e730cfad1
@ -43,15 +43,11 @@ class MulticastGroup
|
|||||||
public:
|
public:
|
||||||
ZT_ALWAYS_INLINE MulticastGroup() :
|
ZT_ALWAYS_INLINE MulticastGroup() :
|
||||||
_mac(),
|
_mac(),
|
||||||
_adi(0)
|
_adi(0) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE MulticastGroup(const MAC &m,uint32_t a) :
|
ZT_ALWAYS_INLINE MulticastGroup(const MAC &m,uint32_t a) :
|
||||||
_mac(m),
|
_mac(m),
|
||||||
_adi(a)
|
_adi(a) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive the multicast group used for address resolution (ARP/NDP) for an IP
|
* Derive the multicast group used for address resolution (ARP/NDP) for an IP
|
||||||
@ -97,6 +93,42 @@ public:
|
|||||||
ZT_ALWAYS_INLINE bool operator<=(const MulticastGroup &g) const { return !(g < *this); }
|
ZT_ALWAYS_INLINE bool operator<=(const MulticastGroup &g) const { return !(g < *this); }
|
||||||
ZT_ALWAYS_INLINE bool operator>=(const MulticastGroup &g) const { return !(*this < g); }
|
ZT_ALWAYS_INLINE bool operator>=(const MulticastGroup &g) const { return !(*this < g); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a 32-bit fnv1a hash of a multicast group and a network ID
|
||||||
|
*
|
||||||
|
* @param mg Multicast group
|
||||||
|
* @param nwid Network ID
|
||||||
|
* @return 32-bit relatively-unique ID
|
||||||
|
*/
|
||||||
|
static ZT_ALWAYS_INLINE uint32_t id(const MulticastGroup &mg,const uint64_t nwid)
|
||||||
|
{
|
||||||
|
const uint32_t fnv1aPrime = 0x01000193;
|
||||||
|
uint32_t i = 0x811c9dc5;
|
||||||
|
i = (((uint32_t)(nwid >> 56) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(nwid >> 48) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(nwid >> 40) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(nwid >> 32) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(nwid >> 24) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(nwid >> 16) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(nwid >> 8) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)nwid & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
const uint64_t mac = mg._mac.toInt();
|
||||||
|
i = (((uint32_t)(mac >> 56) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(mac >> 48) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(mac >> 40) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(mac >> 32) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(mac >> 24) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(mac >> 16) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)(mac >> 8) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((uint32_t)mac & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
const uint32_t adi = mg._adi;
|
||||||
|
i = (((adi >> 24) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((adi >> 16) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = (((adi >> 8) & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
i = ((adi & 0xff) ^ i) * fnv1aPrime;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MAC _mac;
|
MAC _mac;
|
||||||
uint32_t _adi;
|
uint32_t _adi;
|
||||||
|
109
node/Mutex.hpp
109
node/Mutex.hpp
@ -26,15 +26,11 @@ namespace ZeroTier {
|
|||||||
|
|
||||||
#if defined(__GNUC__) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
#if defined(__GNUC__) && (defined(__amd64) || defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || defined(__AMD64) || defined(__AMD64__) || defined(_M_X64))
|
||||||
|
|
||||||
// Inline ticket lock on x64 systems with GCC and CLANG (Mac, Linux) -- this is really fast as long as locking durations are very short
|
// Inline ticket lock on x64 systems with GCC and CLANG (Mac, Linux) -- this is really fast as long as contention is LOW
|
||||||
class Mutex
|
class Mutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ZT_ALWAYS_INLINE Mutex() :
|
ZT_ALWAYS_INLINE Mutex() : nextTicket(0),nowServing(0) {}
|
||||||
nextTicket(0),
|
|
||||||
nowServing(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE void lock() const
|
ZT_ALWAYS_INLINE void lock() const
|
||||||
{
|
{
|
||||||
@ -47,9 +43,6 @@ public:
|
|||||||
|
|
||||||
ZT_ALWAYS_INLINE void unlock() const { ++(const_cast<Mutex *>(this)->nowServing); }
|
ZT_ALWAYS_INLINE void unlock() const { ++(const_cast<Mutex *>(this)->nowServing); }
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses C++ contexts and constructor/destructor to lock/unlock automatically
|
|
||||||
*/
|
|
||||||
class Lock
|
class Lock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -74,46 +67,17 @@ private:
|
|||||||
class Mutex
|
class Mutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ZT_ALWAYS_INLINE Mutex()
|
ZT_ALWAYS_INLINE Mutex() { pthread_mutex_init(&_mh,(const pthread_mutexattr_t *)0); }
|
||||||
{
|
ZT_ALWAYS_INLINE ~Mutex() { pthread_mutex_destroy(&_mh); }
|
||||||
pthread_mutex_init(&_mh,(const pthread_mutexattr_t *)0);
|
ZT_ALWAYS_INLINE void lock() const { pthread_mutex_lock(&((const_cast <Mutex *> (this))->_mh)); }
|
||||||
}
|
ZT_ALWAYS_INLINE void unlock() const { pthread_mutex_unlock(&((const_cast <Mutex *> (this))->_mh)); }
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE ~Mutex()
|
|
||||||
{
|
|
||||||
pthread_mutex_destroy(&_mh);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE void lock() const
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&((const_cast <Mutex *> (this))->_mh));
|
|
||||||
}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE void unlock() const
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&((const_cast <Mutex *> (this))->_mh));
|
|
||||||
}
|
|
||||||
|
|
||||||
class Lock
|
class Lock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ZT_ALWAYS_INLINE Lock(Mutex &m) :
|
ZT_ALWAYS_INLINE Lock(Mutex &m) : _m(&m) { m.lock(); }
|
||||||
_m(&m)
|
ZT_ALWAYS_INLINE Lock(const Mutex &m) : _m(const_cast<Mutex *>(&m)) { _m->lock(); }
|
||||||
{
|
ZT_ALWAYS_INLINE ~Lock() { _m->unlock(); }
|
||||||
m.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE Lock(const Mutex &m) :
|
|
||||||
_m(const_cast<Mutex *>(&m))
|
|
||||||
{
|
|
||||||
_m->lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
ZT_ALWAYS_INLINE ~Lock()
|
|
||||||
{
|
|
||||||
_m->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex *const _m;
|
Mutex *const _m;
|
||||||
};
|
};
|
||||||
@ -142,56 +106,19 @@ namespace ZeroTier {
|
|||||||
class Mutex
|
class Mutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline Mutex()
|
ZT_ALWAYS_INLINE Mutex() { InitializeCriticalSection(&_cs); }
|
||||||
{
|
ZT_ALWAYS_INLINE ~Mutex() { DeleteCriticalSection(&_cs); }
|
||||||
InitializeCriticalSection(&_cs);
|
ZT_ALWAYS_INLINE void lock() { EnterCriticalSection(&_cs); }
|
||||||
}
|
ZT_ALWAYS_INLINE void unlock() { LeaveCriticalSection(&_cs); }
|
||||||
|
ZT_ALWAYS_INLINE void lock() const { (const_cast <Mutex *> (this))->lock(); }
|
||||||
inline ~Mutex()
|
ZT_ALWAYS_INLINE void unlock() const { (const_cast <Mutex *> (this))->unlock(); }
|
||||||
{
|
|
||||||
DeleteCriticalSection(&_cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void lock()
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&_cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void unlock()
|
|
||||||
{
|
|
||||||
LeaveCriticalSection(&_cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void lock() const
|
|
||||||
{
|
|
||||||
(const_cast <Mutex *> (this))->lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void unlock() const
|
|
||||||
{
|
|
||||||
(const_cast <Mutex *> (this))->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
class Lock
|
class Lock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline Lock(Mutex &m) :
|
ZT_ALWAYS_INLINE Lock(Mutex &m) : _m(&m) { m.lock(); }
|
||||||
_m(&m)
|
ZT_ALWAYS_INLINE Lock(const Mutex &m) : _m(const_cast<Mutex *>(&m)) { _m->lock(); }
|
||||||
{
|
ZT_ALWAYS_INLINE ~Lock() { _m->unlock(); }
|
||||||
m.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Lock(const Mutex &m) :
|
|
||||||
_m(const_cast<Mutex *>(&m))
|
|
||||||
{
|
|
||||||
_m->lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ~Lock()
|
|
||||||
{
|
|
||||||
_m->unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex *const _m;
|
Mutex *const _m;
|
||||||
};
|
};
|
||||||
|
222
selftest.cpp
222
selftest.cpp
@ -178,7 +178,7 @@ static int testCrypto()
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::cout << "[crypto] Testing and benchmarking AES-256 and GCM..." ZT_EOL_S << " AES-256 (test vectors): "; std::cout.flush();
|
std::cout << "[crypto] Testing and benchmarking AES-256..." ZT_EOL_S << " AES-256 (test vectors): "; std::cout.flush();
|
||||||
AES tv(AES_TEST_VECTOR_0_KEY);
|
AES tv(AES_TEST_VECTOR_0_KEY);
|
||||||
tv.encrypt(AES_TEST_VECTOR_0_IN,(uint8_t *)buf1);
|
tv.encrypt(AES_TEST_VECTOR_0_IN,(uint8_t *)buf1);
|
||||||
if (memcmp(buf1,AES_TEST_VECTOR_0_OUT,16) != 0) {
|
if (memcmp(buf1,AES_TEST_VECTOR_0_OUT,16) != 0) {
|
||||||
@ -458,6 +458,60 @@ static int testCrypto()
|
|||||||
std::cout << "[crypto] ECDSA Test Vector: PASS" ZT_EOL_S;
|
std::cout << "[crypto] ECDSA Test Vector: PASS" ZT_EOL_S;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "[crypto] Benchmarking asymmetric crypto..." ZT_EOL_S;
|
||||||
|
{
|
||||||
|
uint8_t pub[128],priv[128],hash[128],sig[128];
|
||||||
|
volatile uint8_t foo = 0;
|
||||||
|
Utils::getSecureRandom(hash,sizeof(hash));
|
||||||
|
|
||||||
|
C25519::generate(pub,priv);
|
||||||
|
int64_t start = OSUtils::now();
|
||||||
|
for(int k=0;k<1500;++k) {
|
||||||
|
++hash[0];
|
||||||
|
C25519::sign(priv,pub,hash,sizeof(hash),sig);
|
||||||
|
foo = sig[0];
|
||||||
|
}
|
||||||
|
int64_t end = OSUtils::now();
|
||||||
|
std::cout << " Ed25519 sign: " << (1500.0 / ((double)(end - start) / 1000.0)) << " signatures/second" ZT_EOL_S;
|
||||||
|
start = OSUtils::now();
|
||||||
|
for(int k=0;k<1000;++k) {
|
||||||
|
++sig[0];
|
||||||
|
foo = (uint8_t)C25519::verify(pub,hash,sizeof(hash),sig,ZT_C25519_SIGNATURE_LEN);
|
||||||
|
}
|
||||||
|
end = OSUtils::now();
|
||||||
|
std::cout << " Ed25519 verify: " << (1000.0 / ((double)(end - start) / 1000.0)) << " verifications/second" ZT_EOL_S;
|
||||||
|
start = OSUtils::now();
|
||||||
|
for(int k=0;k<1000;++k) {
|
||||||
|
C25519::agree(priv,pub,hash);
|
||||||
|
foo = hash[0];
|
||||||
|
}
|
||||||
|
end = OSUtils::now();
|
||||||
|
std::cout << " C25519 ECDH: " << (1000.0 / ((double)(end - start) / 1000.0)) << " agreements/second" ZT_EOL_S;
|
||||||
|
|
||||||
|
ECC384GenerateKey(pub,priv);
|
||||||
|
start = OSUtils::now();
|
||||||
|
for(int k=0;k<1000;++k) {
|
||||||
|
++hash[0];
|
||||||
|
ECC384ECDSASign(priv,hash,sig);
|
||||||
|
foo = sig[0];
|
||||||
|
}
|
||||||
|
end = OSUtils::now();
|
||||||
|
std::cout << " ECC P-384 sign: " << (1000.0 / ((double)(end - start) / 1000.0)) << " signatures/second" ZT_EOL_S;
|
||||||
|
start = OSUtils::now();
|
||||||
|
for(int k=0;k<1000;++k) {
|
||||||
|
foo = ECC384ECDSAVerify(pub,hash,sig);
|
||||||
|
}
|
||||||
|
end = OSUtils::now();
|
||||||
|
std::cout << " ECC P-384 verify: " << (1000.0 / ((double)(end - start) / 1000.0)) << " verifications/second" ZT_EOL_S;
|
||||||
|
start = OSUtils::now();
|
||||||
|
for(int k=0;k<1000;++k) {
|
||||||
|
ECC384ECDH(pub,priv,hash);
|
||||||
|
foo = hash[0];
|
||||||
|
}
|
||||||
|
end = OSUtils::now();
|
||||||
|
std::cout << " ECC P-384 ECDH: " << (1000.0 / ((double)(end - start) / 1000.0)) << " agreements/second" ZT_EOL_S;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,172 +840,6 @@ static int testOther()
|
|||||||
std::cout << " " << InetAddress("").toString(buf);
|
std::cout << " " << InetAddress("").toString(buf);
|
||||||
std::cout << ZT_EOL_S;
|
std::cout << ZT_EOL_S;
|
||||||
|
|
||||||
#if 0
|
|
||||||
std::cout << "[other] Testing Hashtable... "; std::cout.flush();
|
|
||||||
{
|
|
||||||
Hashtable<uint64_t,std::string> ht;
|
|
||||||
std::map<uint64_t,std::string> ref; // assume std::map works correctly :)
|
|
||||||
for(int x=0;x<2;++x) {
|
|
||||||
for(int i=0;i<77777;++i) {
|
|
||||||
uint64_t k = rand();
|
|
||||||
while ((k == 0)||(ref.count(k) > 0))
|
|
||||||
++k;
|
|
||||||
std::string v("!");
|
|
||||||
for(int j=0;j<(int)(k % 64);++j)
|
|
||||||
v.push_back("0123456789"[rand() % 10]);
|
|
||||||
ref[k] = v;
|
|
||||||
ht.set(0xffffffffffffffffULL,v);
|
|
||||||
std::string &vref = ht[k];
|
|
||||||
vref = v;
|
|
||||||
ht.erase(0xffffffffffffffffULL);
|
|
||||||
}
|
|
||||||
if (ht.size() != ref.size()) {
|
|
||||||
std::cout << "FAILED! (size mismatch, original)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Hashtable<uint64_t,std::string>::Iterator i(ht);
|
|
||||||
uint64_t *k = (uint64_t *)0;
|
|
||||||
std::string *v = (std::string *)0;
|
|
||||||
while(i.next(k,v)) {
|
|
||||||
if (ref.find(*k)->second != *v) {
|
|
||||||
std::cout << "FAILED! (data mismatch!)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(std::map<uint64_t,std::string>::const_iterator i(ref.begin());i!=ref.end();++i) {
|
|
||||||
if (ht[i->first] != i->second) {
|
|
||||||
std::cout << "FAILED! (data mismatch!)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Hashtable<uint64_t,std::string> ht2;
|
|
||||||
ht2 = ht;
|
|
||||||
Hashtable<uint64_t,std::string> ht3(ht2);
|
|
||||||
if (ht2.size() != ref.size()) {
|
|
||||||
std::cout << "FAILED! (size mismatch, assigned)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (ht3.size() != ref.size()) {
|
|
||||||
std::cout << "FAILED! (size mismatch, copied)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::map<uint64_t,std::string>::iterator i(ref.begin());i!=ref.end();++i) {
|
|
||||||
std::string *v = ht.get(i->first);
|
|
||||||
if (!v) {
|
|
||||||
std::cout << "FAILED! (key " << i->first << " not found, original)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (*v != i->second) {
|
|
||||||
std::cout << "FAILED! (key " << i->first << " not equal, original)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
v = ht2.get(i->first);
|
|
||||||
if (!v) {
|
|
||||||
std::cout << "FAILED! (key " << i->first << " not found, assigned)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (*v != i->second) {
|
|
||||||
std::cout << "FAILED! (key " << i->first << " not equal, assigned)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
v = ht3.get(i->first);
|
|
||||||
if (!v) {
|
|
||||||
std::cout << "FAILED! (key " << i->first << " not found, copied)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (*v != i->second) {
|
|
||||||
std::cout << "FAILED! (key " << i->first << " not equal, copied)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
uint64_t *k;
|
|
||||||
std::string *v;
|
|
||||||
Hashtable<uint64_t,std::string>::Iterator i(ht);
|
|
||||||
unsigned long ic = 0;
|
|
||||||
while (i.next(k,v)) {
|
|
||||||
if (ref[*k] != *v) {
|
|
||||||
std::cout << "FAILED! (iterate)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
++ic;
|
|
||||||
}
|
|
||||||
if (ic != ht.size()) {
|
|
||||||
std::cout << "FAILED! (iterate coverage)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(std::map<uint64_t,std::string>::iterator i(ref.begin());i!=ref.end();) {
|
|
||||||
if (!ht.get(i->first)) {
|
|
||||||
std::cout << "FAILED! (erase, check if exists)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ht.erase(i->first);
|
|
||||||
if (ht.get(i->first)) {
|
|
||||||
std::cout << "FAILED! (erase, check if erased)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ref.erase(i++);
|
|
||||||
if (ht.size() != ref.size()) {
|
|
||||||
std::cout << "FAILED! (erase, size)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ht.empty()) {
|
|
||||||
std::cout << "FAILED! (erase, empty)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
for(int i=0;i<10000;++i) {
|
|
||||||
uint64_t k = rand();
|
|
||||||
while ((k == 0)||(ref.count(k) > 0))
|
|
||||||
++k;
|
|
||||||
std::string v;
|
|
||||||
for(int j=0;j<(int)(k % 64);++j)
|
|
||||||
v.push_back("0123456789"[rand() % 10]);
|
|
||||||
ht.set(k,v);
|
|
||||||
ref[k] = v;
|
|
||||||
}
|
|
||||||
if (ht.size() != ref.size()) {
|
|
||||||
std::cout << "FAILED! (second populate)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ht.clear();
|
|
||||||
ref.clear();
|
|
||||||
if (ht.size() != ref.size()) {
|
|
||||||
std::cout << "FAILED! (clear)" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
for(int i=0;i<10000;++i) {
|
|
||||||
uint64_t k = rand();
|
|
||||||
while ((k == 0)||(ref.count(k) > 0))
|
|
||||||
++k;
|
|
||||||
std::string v;
|
|
||||||
for(int j=0;j<(int)(k % 64);++j)
|
|
||||||
v.push_back("0123456789"[rand() % 10]);
|
|
||||||
ht.set(k,v);
|
|
||||||
ref[k] = v;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Hashtable<uint64_t,std::string>::Iterator i(ht);
|
|
||||||
uint64_t *k;
|
|
||||||
std::string *v;
|
|
||||||
while (i.next(k,v))
|
|
||||||
ht.erase(*k);
|
|
||||||
}
|
|
||||||
ref.clear();
|
|
||||||
if (ht.size() != ref.size()) {
|
|
||||||
std::cout << "FAILED! (clear by iterate, " << ht.size() << ")" ZT_EOL_S;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "PASS" ZT_EOL_S;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
{
|
{
|
||||||
std::cout << "[other] Testing/fuzzing Dictionary... "; std::cout.flush();
|
std::cout << "[other] Testing/fuzzing Dictionary... "; std::cout.flush();
|
||||||
for(int k=0;k<250;++k) {
|
for(int k=0;k<250;++k) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user