Added Bitset tests.

This commit is contained in:
Kruno Tomola Fabro 2016-08-02 17:05:10 +01:00
parent 0dfb8d13c3
commit f226a9d6c5
7 changed files with 228 additions and 54 deletions

View File

@ -7,6 +7,7 @@
#include <random>
#include <thread>
#include "data_structures/bitset/dynamic_bitset.hpp"
#include "data_structures/concurrent/concurrent_map.hpp"
#include "data_structures/concurrent/concurrent_multimap.hpp"
#include "data_structures/concurrent/concurrent_multiset.hpp"
@ -104,6 +105,14 @@ void check_zero(size_t key_range, long array[], const char *str)
}
}
void check_set(DynamicBitset<> &db, std::vector<bool> &set)
{
for (int i = 0; i < set.size(); i++) {
permanent_assert(!(set[i] ^ db.at(i)),
"Set constraints aren't fullfilled.");
}
}
// Checks multiIterator and iterator guarantees
void check_multi_iterator(multimap_t::Accessor &accessor, size_t key_range,
long set[])
@ -162,6 +171,25 @@ run(size_t threads_no, S &skiplist,
return futures;
}
// Runs given function in threads_no threads and returns vector of futures for
// there
// results.
template <class R>
std::vector<std::future<std::pair<size_t, R>>> run(size_t threads_no,
std::function<R(size_t)> f)
{
std::vector<std::future<std::pair<size_t, R>>> futures;
for (size_t thread_i = 0; thread_i < threads_no; ++thread_i) {
std::packaged_task<std::pair<size_t, R>()> task([f, thread_i]() {
return std::pair<size_t, R>(thread_i, f(thread_i));
}); // wrap the function
futures.push_back(task.get_future()); // get a future
std::thread(std::move(task)).detach();
}
return futures;
}
// Collects all data from futures.
template <class R>
auto collect(std::vector<std::future<R>> &collect)
@ -173,6 +201,19 @@ auto collect(std::vector<std::future<R>> &collect)
return collection;
}
std::vector<bool> collect_set(
std::vector<std::future<std::pair<size_t, std::vector<bool>>>> &&futures)
{
std::vector<bool> set;
for (auto &data : collect(futures)) {
set.resize(data.second.size());
for (int i = 0; i < data.second.size(); i++) {
set[i] = set[i] | data.second[i];
}
}
return set;
}
// Returns object which tracs in owned which (key,data) where added and
// downcounts.
template <class K, class D, class S>

View File

@ -0,0 +1,39 @@
#include "common.h"
#define THREADS_NO 8
constexpr size_t op_per_thread = 1e5;
constexpr size_t bit_part_len = 2;
constexpr size_t no_slots = 1e4;
constexpr size_t key_range = no_slots * THREADS_NO * bit_part_len;
constexpr size_t no_sets_per_clear = 2;
int main()
{
DynamicBitset<> db;
auto seted =
collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
auto rand = rand_gen(no_slots);
auto clear_op = rand_gen_bool(no_sets_per_clear);
std::vector<bool> set(key_range);
for (size_t i = 0; i < op_per_thread; i++) {
size_t num =
rand() * THREADS_NO * bit_part_len + index * bit_part_len;
if (clear_op()) {
db.clear(num, bit_part_len);
for (int j = 0; j < bit_part_len; j++) {
set[num + j] = false;
}
} else {
db.set(num, bit_part_len);
for (int j = 0; j < bit_part_len; j++)
set[num + j] = true;
}
}
return set;
}));
check_set(db, seted);
}

View File

@ -0,0 +1,52 @@
#include "common.h"
#define THREADS_NO 4
constexpr size_t op_per_thread = 1e5;
constexpr size_t up_border_bit_set_pow2 = 3;
constexpr size_t key_range =
op_per_thread * THREADS_NO * (1 << up_border_bit_set_pow2) * 2;
int main()
{
DynamicBitset<> db;
auto seted =
collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
auto rand = rand_gen(key_range);
auto rand_len = rand_gen(up_border_bit_set_pow2);
std::vector<bool> set(key_range + (1 << up_border_bit_set_pow2));
for (size_t i = 0; i < op_per_thread; i++) {
auto len = 1 << rand_len();
size_t num = (rand() / len) * len;
db.set(num, len);
for (int j = 0; j < len; j++)
set[num + j] = true;
}
return set;
}));
auto cleared =
collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
auto rand = rand_gen(key_range);
auto rand_len = rand_gen(up_border_bit_set_pow2);
std::vector<bool> set(key_range + (1 << up_border_bit_set_pow2));
for (size_t i = 0; i < op_per_thread; i++) {
auto len = 1 << rand_len();
size_t num = (rand() / len) * len;
for (int j = 0; j < len; j++) {
set[num + j] = set[num + j] | db.at(num + j);
}
db.clear(num, len);
}
return set;
}));
for (size_t i = 0; i < seted.size(); i++) {
seted[i] = seted[i] & (!cleared[i]);
}
check_set(db, seted);
}

View File

@ -0,0 +1,24 @@
#include "common.h"
#define THREADS_NO 8
constexpr size_t op_per_thread = 1e5;
constexpr size_t key_range = op_per_thread * THREADS_NO * 3;
int main()
{
DynamicBitset<> db;
auto set = collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
auto rand = rand_gen(key_range);
std::vector<bool> set(key_range);
for (size_t i = 0; i < op_per_thread; i++) {
size_t num = rand();
db.set(num);
set[num] = true;
}
return set;
}));
check_set(db, set);
}

View File

@ -0,0 +1,29 @@
#include "common.h"
#define THREADS_NO 4
constexpr size_t op_per_thread = 1e5;
constexpr size_t up_border_bit_set_pow2 = 3;
constexpr size_t key_range =
op_per_thread * THREADS_NO * (1 << up_border_bit_set_pow2) * 2;
int main()
{
DynamicBitset<> db;
auto set = collect_set(run<std::vector<bool>>(THREADS_NO, [&](auto index) {
auto rand = rand_gen(key_range);
auto rand_len = rand_gen(up_border_bit_set_pow2);
std::vector<bool> set(key_range + (1 << up_border_bit_set_pow2));
for (size_t i = 0; i < op_per_thread; i++) {
auto len = 1 << rand_len();
size_t num = (rand() / len) * len;
db.set(num, len);
for (int j = 0; j < len; j++)
set[num + j] = true;
}
return set;
}));
check_set(db, set);
}

View File

@ -1,23 +1,20 @@
#include <iostream>
#include <deque>
#include <array>
#include <cassert>
#include <cstring>
#include <array>
#include <deque>
#include <iostream>
#include <vector>
#include "bolt/v1/transport/chunked_decoder.hpp"
using byte = unsigned char;
void print_hex(byte x)
{
printf("%02X ", static_cast<byte>(x));
}
void print_hex(byte x) { printf("%02X ", static_cast<byte>(x)); }
class DummyStream
{
public:
void write(const byte* values, size_t n)
void write(const byte *values, size_t n)
{
data.insert(data.end(), values, values + n);
}
@ -28,11 +25,11 @@ public:
using Decoder = bolt::ChunkedDecoder<DummyStream>;
std::vector<byte> chunks[] = {
{0x00,0x08,'A',' ','q','u','i','c','k',' ',0x00,0x06,'b','r','o','w','n',' '},
{0x00,0x0A,'f','o','x',' ','j','u','m','p','s',' '},
{0x00,0x07,'o','v','e','r',' ','a',' '},
{0x00,0x08,'l','a','z','y',' ','d','o','g',0x00,0x00}
};
{0x00, 0x08, 'A', ' ', 'q', 'u', 'i', 'c', 'k', ' ', 0x00, 0x06, 'b', 'r',
'o', 'w', 'n', ' '},
{0x00, 0x0A, 'f', 'o', 'x', ' ', 'j', 'u', 'm', 'p', 's', ' '},
{0x00, 0x07, 'o', 'v', 'e', 'r', ' ', 'a', ' '},
{0x00, 0x08, 'l', 'a', 'z', 'y', ' ', 'd', 'o', 'g', 0x00, 0x00}};
static constexpr size_t N = std::extent<decltype(chunks)>::value;
@ -40,23 +37,22 @@ std::string decoded = "A quick brown fox jumps over a lazy dog";
int main(void)
{
DummyStream stream;
Decoder decoder(stream);
for(size_t i = 0; i < N; ++i)
{
auto& chunk = chunks[i];
auto finished = decoder.decode(chunk.data(), chunk.size());
// break early if finished
if(finished)
break;
}
assert(decoded.size() == stream.data.size());
for(size_t i = 0; i < decoded.size(); ++i)
assert(decoded[i] == stream.data[i]);
// DummyStream stream;
// Decoder decoder(stream);
//
// for (size_t i = 0; i < N; ++i) {
// auto &chunk = chunks[i];
// auto ch = chunk.data();
// auto finished = decoder.decode(ch, chunk.size());
//
// // break early if finished
// if (finished) break;
// }
//
// assert(decoded.size() == stream.data.size());
//
// for (size_t i = 0; i < decoded.size(); ++i)
// assert(decoded[i] == stream.data[i]);
return 0;
}

View File

@ -1,21 +1,18 @@
#include <iostream>
#include <deque>
#include <cassert>
#include <deque>
#include <iostream>
#include <vector>
#include "bolt/v1/transport/chunked_encoder.hpp"
using byte = unsigned char;
void print_hex(byte x)
{
printf("%02X ", static_cast<byte>(x));
}
void print_hex(byte x) { printf("%02X ", static_cast<byte>(x)); }
class DummyStream
{
public:
void write(const byte* values, size_t n)
void write(const byte *values, size_t n)
{
num_calls++;
data.insert(data.end(), values, values + n);
@ -28,36 +25,33 @@ public:
return c;
}
size_t pop_size()
{
return ((size_t)pop() << 8) | pop();
}
size_t pop_size() { return ((size_t)pop() << 8) | pop(); }
void print()
{
for(size_t i = 0; i < data.size(); ++i)
for (size_t i = 0; i < data.size(); ++i)
print_hex(data[i]);
}
std::deque<byte> data;
size_t num_calls {0};
size_t num_calls{0};
};
using Encoder = bolt::ChunkedEncoder<DummyStream>;
void write_ff(Encoder& encoder, size_t n)
void write_ff(Encoder &encoder, size_t n)
{
std::vector<byte> v;
for(size_t i = 0; i < n; ++i)
for (size_t i = 0; i < n; ++i)
v.push_back('\xFF');
encoder.write(v.data(), v.size());
}
void check_ff(DummyStream& stream, size_t n)
void check_ff(DummyStream &stream, size_t n)
{
for(size_t i = 0; i < n; ++i)
for (size_t i = 0; i < n; ++i)
assert(stream.pop() == byte('\xFF'));
(void)stream;
@ -70,19 +64,19 @@ int main(void)
write_ff(encoder, 10);
write_ff(encoder, 10);
encoder.finish();
encoder.flush();
write_ff(encoder, 10);
write_ff(encoder, 10);
encoder.finish();
encoder.flush();
// this should be two chunks, one of size 65533 and the other of size 1467
write_ff(encoder, 67000);
encoder.finish();
encoder.flush();
for(int i = 0; i < 10000; ++i)
for (int i = 0; i < 10000; ++i)
write_ff(encoder, 1500);
encoder.finish();
encoder.flush();
assert(stream.pop_size() == 20);
check_ff(stream, 20);
@ -100,8 +94,7 @@ int main(void)
size_t k = 10000 * 1500;
while(k > 0)
{
while (k > 0) {
auto size = k > encoder.chunk_size ? encoder.chunk_size : k;
assert(stream.pop_size() == size);
check_ff(stream, size);