From 4718a1827a8e701c711294f78b2d4384663a82f2 Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Thu, 19 Dec 2019 02:23:45 +0100 Subject: [PATCH] Added tests --- flint.yaml | 24 +++ include/io/write.h | 4 +- test/src/test.cpp | 415 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 381 insertions(+), 62 deletions(-) diff --git a/flint.yaml b/flint.yaml index a536986..48840cc 100644 --- a/flint.yaml +++ b/flint.yaml @@ -7,4 +7,28 @@ test: path: test dependency: - io + - logging + - test_framework + +fmt: + type: lib + git: + url: https://github.com/fmtlib/fmt + revision: 6.1.2 + +logging: + type: lib + git: + url: https://git.mtgames.nl/Dreaded_X/logging + revision: master + dependency: + - fmt + +test_framework: + type: lib + git: + url: https://git.mtgames.nl/Dreaded_X/test_framework + revision: master + dependency: + - logger diff --git a/include/io/write.h b/include/io/write.h index b061c3f..aa96804 100644 --- a/include/io/write.h +++ b/include/io/write.h @@ -62,7 +62,7 @@ namespace io { // @todo Merge this into one function with the proper default automatically template - void write(std::ostream& os, T value, bool store_length = true) { + void write(std::ostream& os, const T& value, bool store_length = true) { if (store_length) { write(os, value.size()); } @@ -72,7 +72,7 @@ namespace io { } template requires requires (T a) { std::tuple_size::value; } - void write(std::ostream& os, T value, bool store_length = false) { + void write(std::ostream& os, const T& value, bool store_length = false) { if (store_length) { write(os, value.size()); } diff --git a/test/src/test.cpp b/test/src/test.cpp index a8f9470..6eb1235 100644 --- a/test/src/test.cpp +++ b/test/src/test.cpp @@ -1,13 +1,19 @@ -#include +#include "io.h" + +#include "test_franework.h" #include #include #include +#include #include -#include struct A { int b; + + bool operator==(const A& other) { + return b == other.b; + } }; namespace io { @@ -23,74 +29,363 @@ namespace io { } int main() { - { - std::ofstream f("test.bin"); - io::write(f, 80085); + Test("Write for bool false", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + io::write(f, false); + + bool succes = 1 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 0x00; + return succes; + }()); + + Test("Read for bool false", [] { + std::ifstream f("test.bin"); + return io::read(f) == false; + }()); + + Test("Write for bool true", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + io::write(f, true); + + bool succes = 1 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 0x01; + return succes; + }()); + + Test("Read for bool true", [] { + std::ifstream f("test.bin"); + return io::read(f) == true; + }()); + + Test("Write for int", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + io::write(f, 80085); + + bool succes = 4 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 0x00; + f.read(&c,1); succes &= (c & 0xff) == 0x01; + f.read(&c,1); succes &= (c & 0xff) == 0x38; + f.read(&c,1); succes &= (c & 0xff) == 0xd5; + return succes; + }()); + + Test("Read for int", [] { + std::ifstream f("test.bin"); + return io::read(f) == 80085; + }()); + + Test("Write for short size_t", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + io::write(f, 12); + + bool succes = 1 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 0x0C; + return succes; + }()); + + Test("Read for short size_t", [] { + std::ifstream f("test.bin"); + return io::read(f) == 12; + }()); + + Test("Write for border size_t", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + io::write(f, 0b10000000); + + bool succes = 2 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 0b10000001; + f.read(&c,1); succes &= (c & 0xff) == 0b10000000; + return succes; + }()); + + Test("Read for border size_t", [] { + std::ifstream f("test.bin"); + return io::read(f) == 0b10000000; + }()); + + Test("Write for medium size_t", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); io::write(f, 123456); - io::write(f, "test"); + bool succes = 4 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == (0b10000000 | 3); + f.read(&c,1); succes &= (c & 0xff) == 0x01; + f.read(&c,1); succes &= (c & 0xff) == 0xe2; + f.read(&c,1); succes &= (c & 0xff) == 0x40; + return succes; + }()); - std::array a = {'a', 'b'}; - // Does not store length by default - io::write(f, a); - - std::array b = {"Hello", "World"}; - // Explicitly store length - io::write(f, b, true); - - std::vector c = {1, 2, 3, 4, 5}; - // Stores length by default - io::write(f, c); - - std::list d = {6, 7, 8, 9}; - // Stores length by default - io::write(f, d); - - io::write(f, A{4}); - - std::array e = {A{1}, A{5}, A{3}}; - io::write(f, e, true); - } - - { + Test("Read for medium size_t", [] { std::ifstream f("test.bin"); - std::cout << io::read(f) << '\n'; - std::cout << io::read(f) << '\n'; - std::cout << io::read(f) << '\n'; + return io::read(f) == 123456; + }()); - // Length is implied by the array - auto a = io::read>(f); - for (auto& v : a) { - std::cout << v << ' '; + Test("Write for long size_t", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + io::write(f, std::numeric_limits::max()); + + bool succes = 9 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == (0b10000000 | 8); + f.read(&c,1); succes &= (c & 0xff) == 0xff; + f.read(&c,1); succes &= (c & 0xff) == 0xff; + f.read(&c,1); succes &= (c & 0xff) == 0xff; + f.read(&c,1); succes &= (c & 0xff) == 0xff; + f.read(&c,1); succes &= (c & 0xff) == 0xff; + f.read(&c,1); succes &= (c & 0xff) == 0xff; + f.read(&c,1); succes &= (c & 0xff) == 0xff; + f.read(&c,1); succes &= (c & 0xff) == 0xff; + return succes; + }()); + + Test("Read for long size_t", [] { + std::ifstream f("test.bin"); + return io::read(f) == std::numeric_limits::max(); + }()); + + Test("Write for short std::string", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + std::string value = "test"; + io::write(f, value); + + bool succes = 5 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 4; + f.read(&c,1); succes &= (c & 0xff) == 't'; + f.read(&c,1); succes &= (c & 0xff) == 'e'; + f.read(&c,1); succes &= (c & 0xff) == 's'; + f.read(&c,1); succes &= (c & 0xff) == 't'; + return succes; + }()); + + Test("Read for short std::string", [] { + std::ifstream f("test.bin"); + std::string value = "test"; + return !value.compare(io::read(f)); + }()); + + Test("Write for short std::string (no length)", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + std::string value = "test"; + io::write(f, value, false); + + bool succes = 4 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 't'; + f.read(&c,1); succes &= (c & 0xff) == 'e'; + f.read(&c,1); succes &= (c & 0xff) == 's'; + f.read(&c,1); succes &= (c & 0xff) == 't'; + return succes; + }()); + + Test("Read for short std::string (no length)", [] { + std::ifstream f("test.bin"); + std::string value = "test"; + return !value.compare(io::read(f,4)); + }()); + + // Test long string seperately since short strings might get optimized + Test("Write for long std::string", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + std::string value = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla rhoncus accumsan mauris, vitae mollis ipsum. Ut in ultrices enim. Aenean ac risus nec nulla porttitor egestas. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer molestie tellus urna, sit amet scelerisque ligula porttitor et. Maecenas efficitur tortor vitae dui tincidunt, sit amet ultricies mi consectetur. Quisque eu pellentesque ex. Morbi nibh dolor, rutrum a tortor et, ornare tempor nisi. Nam ornare quam eget orci volutpat sagittis et eu risus. Cras dignissim felis eu libero interdum, a condimentum elit mollis. Quisque sagittis vel ante eget mattis. Quisque non nibh lectus."; + io::write(f, value); + + bool succes = 667 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == (0b10000000 | 2); + f.read(&c,1); succes &= (c & 0xff) == 0x02; + f.read(&c,1); succes &= (c & 0xff) == 0x98; + for (size_t i = 0; i < 664; ++i) { + f.read(&c,1); succes &= (c & 0xff) == value[i]; } - std::cout << '\n'; + return succes; + }()); - // Length is read from file (optionally can be provided as parameter) - auto b = io::read>(f); - for (auto& v : b) { - std::cout << v << ' '; - } - std::cout << '\n'; + Test("Read for long std::string", [] { + std::ifstream f("test.bin"); + std::string value = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla rhoncus accumsan mauris, vitae mollis ipsum. Ut in ultrices enim. Aenean ac risus nec nulla porttitor egestas. Interdum et malesuada fames ac ante ipsum primis in faucibus. Integer molestie tellus urna, sit amet scelerisque ligula porttitor et. Maecenas efficitur tortor vitae dui tincidunt, sit amet ultricies mi consectetur. Quisque eu pellentesque ex. Morbi nibh dolor, rutrum a tortor et, ornare tempor nisi. Nam ornare quam eget orci volutpat sagittis et eu risus. Cras dignissim felis eu libero interdum, a condimentum elit mollis. Quisque sagittis vel ante eget mattis. Quisque non nibh lectus."; + return !value.compare(io::read(f)); + }()); - auto c = io::read>(f); - for (auto& v : c) { - std::cout << v << ' '; - } - std::cout << '\n'; + // Only do one test with const char* as everything else should behave the same + Test("Write for short const char*", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + const char* value = "test"; + io::write(f, value); - auto d = io::read>(f); - for (auto& v : d) { - std::cout << v << ' '; - } - std::cout << '\n'; + bool succes = 5 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 4; + f.read(&c,1); succes &= (c & 0xff) == 't'; + f.read(&c,1); succes &= (c & 0xff) == 'e'; + f.read(&c,1); succes &= (c & 0xff) == 's'; + f.read(&c,1); succes &= (c & 0xff) == 't'; + return succes; + }()); - std::cout << io::read(f).b << '\n'; + Test("Read for short const char* (as std::string)", [] { + std::ifstream f("test.bin"); + const char* value = "test"; + return !io::read(f).compare(value); + }()); - auto e = io::read>(f); - for (auto& v : e) { - std::cout << v << ' '; - } - std::cout << '\n'; + Test("Write for std::array", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + std::array value = {'a', 'b'}; + io::write>(f, value); - } + bool succes = 2 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 'a'; + f.read(&c,1); succes &= (c & 0xff) == 'b'; + return succes; + }()); + + Test("Read for std::array", [] { + std::ifstream f("test.bin"); + std::array value = io::read>(f); + return value[0] == 'a' && value[1] == 'b'; + }()); + + Test("Read for std::array (as std::vector)", [] { + std::ifstream f("test.bin"); + std::vector value = io::read>(f,2); + return value.size() == 2 && value[0] == 'a' && value[1] == 'b'; + }()); + + Test("Read for std::array (as std::list)", [] { + std::ifstream f("test.bin"); + std::list value = io::read>(f,2); + return value.size() == 2 && value.front() == 'a' && value.back() == 'b'; + }()); + + // Test("Read for std::array (as std::forward_list)", [] { + // std::ifstream f("test.bin"); + // std::forward_list value = io::read>(f,2); + // return *(value.begin()) == 'a' && *(value.begin()++) == 'a'; + // }()); + + Test("Write for std::array (length)", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + std::array value = {'c', 'd'}; + io::write>(f, value, true); + + bool succes = 3 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 2; + f.read(&c,1); succes &= (c & 0xff) == 'c'; + f.read(&c,1); succes &= (c & 0xff) == 'd'; + return succes; + }()); + + Test("Read for std::array (as std::vector, length)", [] { + std::ifstream f("test.bin"); + std::vector value = io::read>(f); + return value.size() == 2 && value[0] == 'c' && value[1] == 'd'; + }()); + + Test("Write for std::vector", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + std::vector value = {'e', 'f'}; + io::write>(f, value); + + bool succes = 3 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 2; + f.read(&c,1); succes &= (c & 0xff) == 'e'; + f.read(&c,1); succes &= (c & 0xff) == 'f'; + return succes; + }()); + + Test("Read for std::vector", [] { + std::ifstream f("test.bin"); + std::vector value = io::read>(f); + return value.size() == 2 && value[0] == 'e' && value[1] == 'f'; + }()); + + Test("Read for std::vector (as std::array)", [] { + std::ifstream f("test.bin"); + bool succes = io::read(f) == 2; + std::array value = io::read>(f); + return succes && value[0] == 'e' && value[1] == 'f'; + }()); + + Test("Read for std::vector (as std::list)", [] { + std::ifstream f("test.bin"); + std::list value = io::read>(f); + return value.size() == 2 && value.front() == 'e' && value.back() == 'f'; + }()); + + // Test("Read for std::vector (as std::forward_list)", [] { + // std::ifstream f("test.bin"); + // std::forward_list value = io::read>(f); + // return value.size() == 2 && value.front() == 'e' && value.back() == 'f'; + // }()); + + Test("Write for std::vector (no length)", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + std::vector value = {'g', 'h'}; + io::write>(f, value, false); + + bool succes = 2 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 'g'; + f.read(&c,1); succes &= (c & 0xff) == 'h'; + return succes; + }()); + + Test("Read for std::vector (no length)", [] { + std::ifstream f("test.bin"); + std::vector value = io::read>(f, 2); + return value.size() == 2 && value[0] == 'g' && value[1] == 'h'; + }()); + + Test("Write for std::list", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + std::list value = {'i', 'j'}; + io::write>(f, value); + + bool succes = 3 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 2; + f.read(&c,1); succes &= (c & 0xff) == 'i'; + f.read(&c,1); succes &= (c & 0xff) == 'j'; + return succes; + }()); + + Test("Read for std::list", [] { + std::ifstream f("test.bin"); + std::list value = io::read>(f); + return value.size() == 2 && value.front() == 'i' && value.back() == 'j'; + }()); + + Test("Read for std::list (as std::vector)", [] { + std::ifstream f("test.bin"); + std::vector value = io::read>(f); + return value.size() == 2 && value[0] == 'i' && value[1] == 'j'; + }()); + + Test("Read for std::list (as std::array)", [] { + std::ifstream f("test.bin"); + bool succes = io::read(f) == 2; + std::array value = io::read>(f); + return succes && value[0] == 'i' && value[1] == 'j'; + }()); + + // Test("Read for std::vector (as std::forward_list)", [] { + // std::ifstream f("test.bin"); + // std::forward_list value = io::read>(f); + // return value.size() == 2 && value.front() == 'e' && value.back() == 'f'; + // }()); + + Test("Write for custom struct", [] { + std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out); + A value = {5}; + io::write(f, value); + + bool succes = 4 == f.tellg(); f.seekg(0); char c; + f.read(&c,1); succes &= (c & 0xff) == 0x00; + f.read(&c,1); succes &= (c & 0xff) == 0x00; + f.read(&c,1); succes &= (c & 0xff) == 0x00; + f.read(&c,1); succes &= (c & 0xff) == 0x05; + return succes; + }()); + + Test("Read for custom struct", [] { + std::ifstream f("test.bin"); + A value = io::read(f); + return value == A{5}; + }()); + + return !Test::evaluate(); }