tunsafe-clang15/Tests/Tests.cpp
2018-10-21 16:54:18 +02:00

126 lines
2.9 KiB
C++

// Tests.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include "stdafx.h"
#include "../ip_to_peer_map.h"
#include "../tunsafe_endian.h"
#include "../bit_ops.h"
#include <assert.h>
class RoutingTrie32Ref {
typedef void *Value;
typedef uint32 NodePtr;
enum {
BITS = 32
};
struct Node {
Value value;
NodePtr nodes[2];
uint8 shift, cidr;
uint32 key;
};
std::vector<Node> nodes_;
NodePtr root_;
#define NEXT_NODE(n, key) n->nodes[(key >> n->shift) & 1]
static int CommonBits(const uint32 a, const uint32 b) {
return 32 - FindHighestSetBit32(a ^ b);
}
NodePtr NewNode(uint32 key, int cidr, Value value) {
nodes_.emplace_back();
Node *n = &nodes_.back();
if (n) {
n->nodes[0] = n->nodes[1] = 0;
n->cidr = cidr;
n->shift = (~cidr & 31);
n->value = value;
n->key = key;
}
return (uint32)nodes_.size();
}
public:
RoutingTrie32Ref() : root_() {}
~RoutingTrie32Ref() {
}
__declspec(noinline) Value Lookup(const uint8 *key_in) {
NodePtr ni = root_;
Node *n;
Value value = NULL;
uint32 key = ReadBE32(key_in);
while (ni != NULL && (n = &nodes_[ni - 1], CommonBits(key, n->key) >= n->cidr)) {
value = n->value ? n->value : value;
ni = n->nodes[(key >> n->shift) & 1];
}
return value;
}
Node *deref(NodePtr x) { return &nodes_[x - 1]; }
bool Insert(const uint8 *key_in, int cidr, Value value) {
NodePtr p = 0, no = root_;
uint32 key = ReadBE32(key_in);
while (no != NULL && (deref(no)->cidr <= cidr && CommonBits(key, deref(no)->key) >= deref(no)->cidr)) {
if (deref(no)->cidr == cidr) {
deref(no)->value = value;
return true;
}
p = no;// &NEXT_NODE(deref(no), key);
no = NEXT_NODE(deref(p), key);
}
NodePtr n = NewNode(key, cidr, value);
if (!n)
return false;
if (no != NULL) {
int cbits = CommonBits(deref(no)->key, key);
if (cbits < cidr) {
NodePtr nn = NewNode(key, cbits, NULL);
if (!nn) {
// delete n;
return false;
}
NEXT_NODE(deref(nn), key) = n;
n = nn;
}
NEXT_NODE(deref(n), deref(no)->key) = no;
}
if (p == NULL)
root_ = n;
else
NEXT_NODE(deref(p), key) = n;
return true;
}
};
int main() {
RoutingTrie32Ref ref;
RoutingTrie32 test;
for (int i = 0; i < 256; i++) {
uint8 ip[4];
uint32 ipv = 0x10200000 + i * 256;
WriteBE32(ip, ipv);
ref.Insert(ip, 24, (void*)(i * 2));
void*x = (void*)(i * 2);
test.Insert(ipv, 24, &x);
}
uint32 iters = 0x800000;
for (uint32 i = 0; i < iters; i++) {
uint32 j = i * 944676833;// (i & 0xF) + (i & ~0xF) * 16 + 0xF0;
uint8 xx[4] = { (uint8)(j >> 24),(uint8)(j >> 16),(uint8)(j >> 8),(uint8)j };
void *ans1 = ref.Lookup(xx);
void *ans2 = test.Lookup(j);
assert(ans1 == ans2);
}
}