Added Bitset tests.
This commit is contained in:
parent
0dfb8d13c3
commit
f226a9d6c5
@ -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>
|
||||
|
39
tests/concurrent/dynamic_bitset.cpp
Normal file
39
tests/concurrent/dynamic_bitset.cpp
Normal 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);
|
||||
}
|
52
tests/concurrent/dynamic_bitset_clear_n.cpp
Normal file
52
tests/concurrent/dynamic_bitset_clear_n.cpp
Normal 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);
|
||||
}
|
24
tests/concurrent/dynamic_bitset_set.cpp
Normal file
24
tests/concurrent/dynamic_bitset_set.cpp
Normal 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);
|
||||
}
|
29
tests/concurrent/dynamic_bitset_set_n.cpp
Normal file
29
tests/concurrent/dynamic_bitset_set_n.cpp
Normal 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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user