Added tests

This commit is contained in:
Dreaded_X 2019-12-19 02:23:45 +01:00
parent 42ca9fefff
commit 4718a1827a
3 changed files with 381 additions and 62 deletions

View File

@ -7,4 +7,28 @@ test:
path: test path: test
dependency: dependency:
- io - 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

View File

@ -62,7 +62,7 @@ namespace io {
// @todo Merge this into one function with the proper default automatically // @todo Merge this into one function with the proper default automatically
template <Container T> template <Container T>
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) { if (store_length) {
write<size_t>(os, value.size()); write<size_t>(os, value.size());
} }
@ -72,7 +72,7 @@ namespace io {
} }
template <Container T> requires requires (T a) { std::tuple_size<T>::value; } template <Container T> requires requires (T a) { std::tuple_size<T>::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) { if (store_length) {
write<size_t>(os, value.size()); write<size_t>(os, value.size());
} }

View File

@ -1,13 +1,19 @@
#include <io.h> #include "io.h"
#include "test_franework.h"
#include <vector> #include <vector>
#include <array> #include <array>
#include <list> #include <list>
#include <forward_list>
#include <fstream> #include <fstream>
#include <experimental/source_location>
struct A { struct A {
int b; int b;
bool operator==(const A& other) {
return b == other.b;
}
}; };
namespace io { namespace io {
@ -23,74 +29,363 @@ namespace io {
} }
int main() { int main() {
{ Test("Write for bool false", [] {
std::ofstream f("test.bin"); std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
io::write(f, 80085); io::write<bool>(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<bool>(f) == false;
}());
Test("Write for bool true", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
io::write<bool>(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<bool>(f) == true;
}());
Test("Write for int", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
io::write<int>(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<int>(f) == 80085;
}());
Test("Write for short size_t", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
io::write<size_t>(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<size_t>(f) == 12;
}());
Test("Write for border size_t", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
io::write<size_t>(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<size_t>(f) == 0b10000000;
}());
Test("Write for medium size_t", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
io::write<size_t>(f, 123456); io::write<size_t>(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<char, 2> a = {'a', 'b'}; Test("Read for medium size_t", [] {
// 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<int> 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);
}
{
std::ifstream f("test.bin"); std::ifstream f("test.bin");
std::cout << io::read<int>(f) << '\n'; return io::read<size_t>(f) == 123456;
std::cout << io::read<size_t>(f) << '\n'; }());
std::cout << io::read<std::string>(f) << '\n';
// Length is implied by the array Test("Write for long size_t", [] {
auto a = io::read<std::array<char,2>>(f); std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
for (auto& v : a) { io::write<size_t>(f, std::numeric_limits<size_t>::max());
std::cout << v << ' ';
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<size_t>(f) == std::numeric_limits<size_t>::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<std::string>(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<std::string>(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<std::string>(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<std::string>(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<std::string>(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) Test("Read for long std::string", [] {
auto b = io::read<std::vector<std::string>>(f); std::ifstream f("test.bin");
for (auto& v : b) { 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.";
std::cout << v << ' '; return !value.compare(io::read<std::string>(f));
} }());
std::cout << '\n';
auto c = io::read<std::vector<int>>(f); // Only do one test with const char* as everything else should behave the same
for (auto& v : c) { Test("Write for short const char*", [] {
std::cout << v << ' '; std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
} const char* value = "test";
std::cout << '\n'; io::write<const char*>(f, value);
auto d = io::read<std::list<int>>(f); bool succes = 5 == f.tellg(); f.seekg(0); char c;
for (auto& v : d) { f.read(&c,1); succes &= (c & 0xff) == 4;
std::cout << v << ' '; f.read(&c,1); succes &= (c & 0xff) == 't';
} f.read(&c,1); succes &= (c & 0xff) == 'e';
std::cout << '\n'; f.read(&c,1); succes &= (c & 0xff) == 's';
f.read(&c,1); succes &= (c & 0xff) == 't';
return succes;
}());
std::cout << io::read<A>(f).b << '\n'; Test("Read for short const char* (as std::string)", [] {
std::ifstream f("test.bin");
const char* value = "test";
return !io::read<std::string>(f).compare(value);
}());
auto e = io::read<std::list<int>>(f); Test("Write for std::array<char>", [] {
for (auto& v : e) { std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
std::cout << v << ' '; std::array<char, 2> value = {'a', 'b'};
} io::write<std::array<char, 2>>(f, value);
std::cout << '\n';
} 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<char>", [] {
std::ifstream f("test.bin");
std::array<char, 2> value = io::read<std::array<char, 2>>(f);
return value[0] == 'a' && value[1] == 'b';
}());
Test("Read for std::array<char> (as std::vector<char>)", [] {
std::ifstream f("test.bin");
std::vector<char> value = io::read<std::vector<char>>(f,2);
return value.size() == 2 && value[0] == 'a' && value[1] == 'b';
}());
Test("Read for std::array<char> (as std::list<char>)", [] {
std::ifstream f("test.bin");
std::list<char> value = io::read<std::list<char>>(f,2);
return value.size() == 2 && value.front() == 'a' && value.back() == 'b';
}());
// Test("Read for std::array<char> (as std::forward_list<char>)", [] {
// std::ifstream f("test.bin");
// std::forward_list<char> value = io::read<std::forward_list<char>>(f,2);
// return *(value.begin()) == 'a' && *(value.begin()++) == 'a';
// }());
Test("Write for std::array<char> (length)", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
std::array<char, 2> value = {'c', 'd'};
io::write<std::array<char, 2>>(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<char> (as std::vector<char>, length)", [] {
std::ifstream f("test.bin");
std::vector<char> value = io::read<std::vector<char>>(f);
return value.size() == 2 && value[0] == 'c' && value[1] == 'd';
}());
Test("Write for std::vector<char>", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
std::vector<char> value = {'e', 'f'};
io::write<std::vector<char>>(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<char>", [] {
std::ifstream f("test.bin");
std::vector<char> value = io::read<std::vector<char>>(f);
return value.size() == 2 && value[0] == 'e' && value[1] == 'f';
}());
Test("Read for std::vector<char> (as std::array<char>)", [] {
std::ifstream f("test.bin");
bool succes = io::read<size_t>(f) == 2;
std::array<char, 2> value = io::read<std::array<char, 2>>(f);
return succes && value[0] == 'e' && value[1] == 'f';
}());
Test("Read for std::vector<char> (as std::list<char>)", [] {
std::ifstream f("test.bin");
std::list<char> value = io::read<std::list<char>>(f);
return value.size() == 2 && value.front() == 'e' && value.back() == 'f';
}());
// Test("Read for std::vector<char> (as std::forward_list<char>)", [] {
// std::ifstream f("test.bin");
// std::forward_list<char> value = io::read<std::forward_list<char>>(f);
// return value.size() == 2 && value.front() == 'e' && value.back() == 'f';
// }());
Test("Write for std::vector<char> (no length)", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
std::vector<char> value = {'g', 'h'};
io::write<std::vector<char>>(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<char> (no length)", [] {
std::ifstream f("test.bin");
std::vector<char> value = io::read<std::vector<char>>(f, 2);
return value.size() == 2 && value[0] == 'g' && value[1] == 'h';
}());
Test("Write for std::list<char>", [] {
std::fstream f("test.bin", std::ios::trunc | std::ios::in | std::ios::out);
std::list<char> value = {'i', 'j'};
io::write<std::list<char>>(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<char>", [] {
std::ifstream f("test.bin");
std::list<char> value = io::read<std::list<char>>(f);
return value.size() == 2 && value.front() == 'i' && value.back() == 'j';
}());
Test("Read for std::list<char> (as std::vector<char>)", [] {
std::ifstream f("test.bin");
std::vector<char> value = io::read<std::vector<char>>(f);
return value.size() == 2 && value[0] == 'i' && value[1] == 'j';
}());
Test("Read for std::list<char> (as std::array<char>)", [] {
std::ifstream f("test.bin");
bool succes = io::read<size_t>(f) == 2;
std::array<char, 2> value = io::read<std::array<char, 2>>(f);
return succes && value[0] == 'i' && value[1] == 'j';
}());
// Test("Read for std::vector<char> (as std::forward_list<char>)", [] {
// std::ifstream f("test.bin");
// std::forward_list<char> value = io::read<std::forward_list<char>>(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<A>(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<A>(f);
return value == A{5};
}());
return !Test::evaluate();
} }