Browse Source

Issue #15 test cases out

master
Ludovic 'Archivist' Lagouardette 2 years ago
parent
commit
e438445f0f
3 changed files with 246 additions and 1 deletions
  1. +9
    -0
      include/gp/containers/vector.hpp
  2. +1
    -1
      tests.cpp
  3. +236
    -0
      tests/issue15_test.cpp

+ 9
- 0
include/gp/containers/vector.hpp View File

@ -67,6 +67,8 @@ namespace gp{
, cap(oth.cap)
, alloc(oth.alloc)
{
oth.sz = 0;
oth.cap = 0;
oth.ary = nullptr;
}
@ -81,10 +83,12 @@ namespace gp{
gp_config::assertion(reserve(oth.size()), "could not reserve space on assign");
for(size_t i = 0; i < gp::min(sz, oth.sz); ++i)
{
if constexpr (!std::is_trivially_destructible_v<T>) ary[i]->~T();
new(ary+i) T(oth[i]);
}
if(sz < oth.sz) {
for(size_t i = sz; i < oth.sz; ++i) {
if constexpr (!std::is_trivially_destructible_v<T>) ary[i]->~T();
new(ary+i) T(oth[i]);
}
} else if(sz > oth.sz) {
@ -123,10 +127,14 @@ namespace gp{
size_t idx = 0;
for(auto& elem : oth) {
new(ary+idx) T(gp::move(elem));
++idx;
elem.~T();
}
gp_config::assertion(alloc.get().deallocate(oth.ary), "could not deallocate");
sz = idx;
oth.sz = 0;
oth.capacity = 0;
oth.ary = nullptr;
}
return *this;
}
@ -147,6 +155,7 @@ namespace gp{
{
if(ary)
{
if constexpr (!std::is_trivially_destructible_v<T>)
for(auto& elem : *this) {
elem.~T();
}

+ 1
- 1
tests.cpp View File

@ -10,7 +10,7 @@
alignas(2048) gp::array<char, 4096> static_mapper::store;
gp::buddy<> static_mapper::impl = gp::buddy<>{store.begin().data, store.size()};
static_logging_segment<128> logger;
static_logging_segment<1024> logger;
void log_failure(const char* failure) {
log_segment("FAILURE", failure, std::numeric_limits<int16_t>::max());

+ 236
- 0
tests/issue15_test.cpp View File

@ -0,0 +1,236 @@
#include "test_scaffold.h"
#include "gp/containers/array.hpp"
#include "gp/containers/vector.hpp"
#include "gp/ipc/envelope/cbor.hpp"
#include "gp/algorithms/tmp_manip.hpp"
#include "gp/functional/monostates.hpp"
#include "gp/utils/allocators/allocator.hpp"
#include <string>
#include <unordered_map>
extern void print_logs();
struct std_allocator : gp::allocator {
using dbg_map = std::unordered_map<void*, size_t>;
[[no_unique_address]] dbg_map debug_info;
/**
* @brief Allocates memory
*
* @param sz the amount of bytes to allocate
*
* @return the allocated memory as a pointer on success
* @return nullptr if it failed allocating
*/
virtual void* allocate(size_t sz) {
auto v = new char[sz];
log_segment("data allocated", (std::to_string(sz) + " bytes @"+std::to_string((uintptr_t)v)).c_str());
debug_info[v] = sz;
return v;
}
/**
* @brief Deallocates memory
*
* @param ptr the memory to deallocate
*
* @return true if the memory was successfully deallocated
* @return false if the memory was not deallocated
*/
virtual bool deallocate(void* ptr) {
log_segment("data deallocated", "Trying deallocation");
log_segment("data deallocated", ("Target: @" + std::to_string((uintptr_t)ptr)).c_str());
if(!debug_info.contains(ptr))
gp_config::assertion(false, "Double free detected");
print_logs();
delete (char*)ptr;
log_segment("data deallocated", (std::to_string(debug_info[ptr]) + " bytes @"+std::to_string((uintptr_t)ptr)).c_str());
debug_info.erase(ptr);
return true;
}
/**
* @brief Tries to reallocate memory
*
* @param ptr The memory to reallocate
* @param sz The new size we want to give the memory
*
* @return true if reallocation was successful
* @return false if the reallocation failed
*/
virtual bool try_reallocate(void*, size_t) {
return false;
}
virtual ~std_allocator() = default;
};
std_allocator allocator;
enum class co_state {
waiting_receive,
waiting_send,
data_received,
data_sent
};
typedef gp::array<char, 16> identifier_t;
using fd_t = int;
struct packet_info {
uint64_t attempts = 0;
uint64_t sequence = 0;
identifier_t co_id;
gp::vector<char> data{allocator};
};
gp::vector<char>& push_as_cbor(gp::vector<char>& src, identifier_t& value) {
gp::push_as_cbor(src, gp::cbor_tag_initiator{.as_integer = 37});
gp::push_as_cbor(src, value.as_buffer());
return src;
}
gp::vector<char>& push_as_cbor(gp::vector<char>& src, packet_info& value) {
push_as_cbor(src, gp::cbor_tag_initiator{.as_integer = 1994});
push_as_cbor(src, gp::cbor_array_initiator{4});
push_as_cbor(src, value.sequence);
push_as_cbor(src, value.attempts);
push_as_cbor(src, value.co_id);
push_as_cbor(src, value.data.as_buffer());
return src;
}
namespace gp { template<>
gp::pair<gp::optional<packet_info>, parsing_state> read_cbor<packet_info>(parsing_state state, gp::allocator& alloc) {
size_t seq, attempts;
identifier_t uuid;
gp::vector<char> data{alloc};
bool ok = true;
auto array_parser = [&](parsing_state state, allocator& alloc){
for(size_t idx : {0,1,2,3})
switch(idx) {
case 0:{
auto [v ,new_state] = read_cbor<uint64_t>(state, alloc);
if(v.has_value()) {
seq = v.value();
return new_state;
}
}break;
case 1:{
auto [v ,new_state] = read_cbor<uint64_t>(state, alloc);
if(v.has_value()) {
attempts = v.value();
return new_state;
}
}break;
case 2:{
auto [tg ,nc_state] = read_cbor<cbor_tag_initiator>(state, alloc);
if(!tg.has_value()) break;
if(tg.value().as_integer != 37) break;
auto [v ,new_state] = read_cbor<gp::vector<char>>(nc_state, alloc);
if(v.has_value()) {
for(size_t idx : {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}) {
uuid[idx] = v.value()[idx];
}
return new_state;
}
}break;
case 3:{
auto [v ,new_state] = read_cbor<gp::vector<char>>(state, alloc);
if(v.has_value()) {
data = v.value();
return new_state;
}
}break;
}
ok &= false;
log_segment("ok", ok ? "true" : "false");
return state;
};
parsing_state nc_state = state;
{
auto [value, new_state] = read_cbor<cbor_tag_initiator>(nc_state, alloc);
if(!value.has_value()) return {gp::nullopt, state};
nc_state = new_state;
}
{
auto new_state = read_cbor_array(nc_state, alloc, array_parser, [&](size_t sz){
ok &= sz == 4;
log_segment("ok", ok ? "true" : "false");
return ok;
});
if(ok && new_state.size() != nc_state.size()) {
log_segment("INFO", "Parsing terminated successfully");
return {packet_info{.attempts = attempts, .sequence = seq, .data = gp::move(data)}, new_state};
}
else
return {nullopt, state};
}
}}
struct packet_info_serialization_test : public test_scaffold {
packet_info_serialization_test() {
name = __FILE__ "@packet_info_serialization_test";
}
virtual int run() {
packet_info item;
item.sequence = 1;
item.attempts = 2;
for(auto& c : item.co_id) c = 1;
for(auto idx : {0,1,2,3,4,5,6,7,8,9}) item.data.push_back(idx);
gp::vector<char> serialized(allocator);
push_as_cbor(serialized, item);
log_segment("size", std::to_string(serialized.size()).c_str());
gp_config::assertion(serialized.size() == 36, "serialization of the wrong size");
return 0;
}
};
append_test packet_info_serialization_test_impl(new packet_info_serialization_test());
struct packet_info_deserialization_test : public test_scaffold {
packet_info_deserialization_test() {
name = __FILE__ "@packet_info_deserialization_test";
}
virtual int run() {
packet_info item;
item.sequence = 1;
item.attempts = 2;
for(auto& c : item.co_id) c = 1;
for(auto idx : {0,1,2,3,4,5,6,7,8,9}) item.data.push_back(idx);
gp::vector<char> serialized(allocator);
push_as_cbor(serialized, item);
log_segment("size", std::to_string(serialized.size()).c_str());
gp_config::assertion(serialized.size() == 36, "serialization of the wrong size");
auto [value, state] = gp::read_cbor<packet_info>(serialized.as_buffer(), allocator);
gp_config::assertion(value.has_value(), "deserialization failed");
gp_config::assertion(!state.size(), "unprocessed state remains");
gp_config::assertion(value.value().sequence == item.sequence, "comparison failed step 1");
gp_config::assertion(value.value().attempts == item.attempts, "comparison failed step 2");
gp_config::assertion(value.value().co_id == item.co_id, "comparison failed step 3");
gp_config::assertion(value.value().data == item.data, "comparison failed step 4");
return 0;
}
};
append_test packet_info_deserialization_test_impl(new packet_info_deserialization_test());

Loading…
Cancel
Save