|
|
- #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)) {
- print_logs();
- gp_config::assertion(false, "Double free detected");
- }
-
- 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};
- log_segment("INFO", "Init stage");
- bool ok = true;
-
- auto array_parser = [&](parsing_state state, allocator& alloc){
- for(size_t idx : {0,1,2,3})
- switch(idx) {
- case 0:{
- log_segment("INFO", "Array stage 0");
- auto [v ,new_state] = read_cbor<uint64_t>(state, alloc);
- if(v.has_value()) {
- seq = v.value();
- return new_state;
- }
- }break;
- case 1:{
- log_segment("INFO", "Array stage 1");
- auto [v ,new_state] = read_cbor<uint64_t>(state, alloc);
- if(v.has_value()) {
- attempts = v.value();
- return new_state;
- }
- }break;
- case 2:{
- log_segment("INFO", "Array stage 2");
- auto [tg ,nc_state] = read_cbor<cbor_tag_initiator>(state, alloc);
- if(!tg.has_value()) break;
- if(tg.value().as_integer != 37) break;
-
- log_segment("INFO", "\tGet UUID");
- auto [v ,new_state] = read_cbor<gp::vector<char>>(nc_state, alloc);
- if(v.has_value()) {
- log_segment("INFO", "\tUUID obtained");
- 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;
- }
- log_segment("INFO", "\tUUID not found");
- }break;
- case 3:{
- log_segment("INFO", "Array stage 3");
- auto [v ,new_state] = read_cbor<gp::vector<char>>(state, alloc);
- if(v.has_value()) {
- log_segment("INFO", "Data copy");
- data = v.value();
- log_segment("INFO", "ready to return last stale");
- return new_state;
- }
- }break;
- }
- ok &= false;
- log_segment("ok", ok ? "true" : "false");
- return state;
- };
-
- parsing_state nc_state = state;
- {
- log_segment("INFO", "Tag stage");
- auto [value, new_state] = read_cbor<cbor_tag_initiator>(nc_state, alloc);
- if(!value.has_value()) return {gp::nullopt, state};
- nc_state = new_state;
- }
- {
- log_segment("INFO", "Array info stage");
- 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;
- });
- log_segment("INFO", "Parser returned... Testing");
- 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{
- log_segment("INFO", ("Parsing failed with ok=" + std::string(ok ? "true" : "false")).c_str());
- 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);
- log_segment("INFO", "Serialization init");
-
- push_as_cbor(serialized, item);
- log_segment("INFO", "Item serialized");
-
- log_segment("size", std::to_string(serialized.size()).c_str());
-
- gp_config::assertion(serialized.size() == 36, "serialization of the wrong size");
- log_segment("INFO", "Item controlled");
-
- 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());
|