Add extended tests with no new line at eof

This commit is contained in:
ado 2024-02-22 00:30:05 +01:00
parent 57ba23c574
commit 3ea8adedfd
4 changed files with 43 additions and 41 deletions

View File

@ -12,7 +12,7 @@ using string_range = std::pair<const char*, const char*>;
using split_data = std::vector<string_range>; using split_data = std::vector<string_range>;
constexpr inline auto default_delimiter = ","; constexpr inline auto default_delimiter = ",";
constexpr static auto get_line_initial_buffer_size = 128; constexpr inline auto get_line_initial_buffer_size = 128;
template <bool StringError> template <bool StringError>
inline void assert_string_error_defined() { inline void assert_string_error_defined() {
@ -31,7 +31,7 @@ inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) {
return getline(lineptr, n, stream); return getline(lineptr, n, stream);
} }
#else #else
// TODO set ERRNO ?
using ssize_t = int64_t; using ssize_t = int64_t;
inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) { inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) {
size_t pos; size_t pos;

View File

@ -5,6 +5,7 @@
#include "exception.hpp" #include "exception.hpp"
#include "extract.hpp" #include "extract.hpp"
#include "restrictions.hpp" #include "restrictions.hpp"
#include <cerrno>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <optional> #include <optional>
@ -742,7 +743,6 @@ private:
reader(const reader& other) = delete; reader(const reader& other) = delete;
reader& operator=(const reader& other) = delete; reader& operator=(const reader& other) = delete;
// TODO set error numbers on error
ssize_t get_line_buffer(char** lineptr, size_t* n, ssize_t get_line_buffer(char** lineptr, size_t* n,
const char* const buffer, size_t csv_data_size, const char* const buffer, size_t csv_data_size,
size_t& curr_char) { size_t& curr_char) {
@ -812,6 +812,9 @@ private:
} }
if (ssize == -1) { if (ssize == -1) {
if (errno == ENOMEM) {
throw std::bad_alloc{};
}
return false; return false;
} }

37
ssp.hpp
View File

@ -1,5 +1,6 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cerrno>
#include <charconv> #include <charconv>
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
@ -625,7 +626,7 @@ using string_range = std::pair<const char*, const char*>;
using split_data = std::vector<string_range>; using split_data = std::vector<string_range>;
constexpr inline auto default_delimiter = ","; constexpr inline auto default_delimiter = ",";
constexpr static auto get_line_initial_buffer_size = 128; constexpr inline auto get_line_initial_buffer_size = 128;
template <bool StringError> template <bool StringError>
inline void assert_string_error_defined() { inline void assert_string_error_defined() {
@ -644,6 +645,7 @@ inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) {
return getline(lineptr, n, stream); return getline(lineptr, n, stream);
} }
#else #else
using ssize_t = int64_t; using ssize_t = int64_t;
inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) { inline ssize_t get_line_file(char** lineptr, size_t* n, FILE* stream) {
size_t pos; size_t pos;
@ -2495,20 +2497,22 @@ public:
template <typename U, typename... Us, typename Fun = none> template <typename U, typename... Us, typename Fun = none>
void try_convert_and_invoke(std::optional<U>& value, Fun&& fun) { void try_convert_and_invoke(std::optional<U>& value, Fun&& fun) {
if (!parser_.valid()) { if (parser_.valid()) {
auto tuple_output = try_same<Us...>(); return;
if (!parser_.valid()) {
return;
}
if constexpr (!std::is_same_v<U, decltype(tuple_output)>) {
value = to_object<U>(std::move(tuple_output));
} else {
value = std::move(tuple_output);
}
parser_.try_invoke(*value, std::forward<Fun>(fun));
} }
auto tuple_output = try_same<Us...>();
if (!parser_.valid()) {
return;
}
if constexpr (!std::is_same_v<U, decltype(tuple_output)>) {
value = to_object<U>(std::move(tuple_output));
} else {
value = std::move(tuple_output);
}
parser_.try_invoke(*value, std::forward<Fun>(fun));
} }
template <typename U, typename... Us> template <typename U, typename... Us>
@ -2936,6 +2940,9 @@ private:
} }
if (ssize == -1) { if (ssize == -1) {
if (errno == ENOMEM) {
throw std::bad_alloc{};
}
return false; return false;
} }
@ -3067,7 +3074,7 @@ private:
buffer_size = first_size + second_size + 3; buffer_size = first_size + second_size + 3;
auto new_first = static_cast<char*>( auto new_first = static_cast<char*>(
realloc(static_cast<void*>(first), buffer_size)); realloc(static_cast<void*>(first), buffer_size));
if (!first) { if (!new_first) {
throw std::bad_alloc{}; throw std::bad_alloc{};
} }

View File

@ -258,20 +258,22 @@ std::vector<std::string> generate_csv_data(const std::vector<field>& data,
[[maybe_unused]] void write_to_file(const std::vector<std::string>& data, [[maybe_unused]] void write_to_file(const std::vector<std::string>& data,
const std::string& delim, const std::string& delim,
const std::string& file_name) { const std::string& file_name,
bool add_new_line = true) {
std::ofstream out{file_name, std::ios_base::app}; std::ofstream out{file_name, std::ios_base::app};
std::string line; std::string line;
// TODO remove new line at eof randomly
for (size_t i = 0; i < data.size(); ++i) { for (size_t i = 0; i < data.size(); ++i) {
line += data[i]; line += data[i];
if (i != data.size() - 1) { if (i != data.size() - 1) {
line += delim; line += delim;
} }
} }
out << line << std::endl; out << line;
if (add_new_line) {
out << std::endl;
}
} }
#define CHECK_EQ_CRLF(V1, V2) \ #define CHECK_EQ_CRLF(V1, V2) \
@ -333,7 +335,11 @@ void test_data_combinations(const std::vector<column>& input_data,
if (include_header) { if (include_header) {
auto header_data = generate_csv_data<Ts...>(field_header, delim); auto header_data = generate_csv_data<Ts...>(field_header, delim);
write_to_file(header_data, delim, f.name); if (input_data.size() == 0 && rand() % 10 == 0) {
write_to_file(header_data, delim, f.name, false);
} else {
write_to_file(header_data, delim, f.name);
}
} }
std::vector<int> layout; std::vector<int> layout;
@ -358,15 +364,12 @@ void test_data_combinations(const std::vector<column>& input_data,
expected_data.push_back(raw_data); expected_data.push_back(raw_data);
auto data = generate_csv_data<Ts...>(raw_data, delim); auto data = generate_csv_data<Ts...>(raw_data, delim);
write_to_file(data, delim, f.name);
/* if (i + 1 == n && rand() % 10 == 0) {
std::cout << "[."; write_to_file(data, delim, f.name, false);
for (const auto& el : data) { } else {
std::cout << el << '.'; write_to_file(data, delim, f.name);
} }
std::cout << "]" << std::endl;
*/
} }
auto layout_combinations = include_header && !setup::ignore_header auto layout_combinations = include_header && !setup::ignore_header
@ -430,7 +433,6 @@ void test_data_combinations(const std::vector<column>& input_data,
auto s0 = p.template get_next<std::string>(); auto s0 = p.template get_next<std::string>();
if (i < n) { if (i < n) {
check_error(); check_error();
// std::cout << s0 << std::endl;
CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value); CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value);
} else { } else {
CHECK(p.eof()); CHECK(p.eof());
@ -443,7 +445,6 @@ void test_data_combinations(const std::vector<column>& input_data,
p.template get_next<std::string, std::string>(); p.template get_next<std::string, std::string>();
if (i < n) { if (i < n) {
check_error(); check_error();
// std::cout << s0 << ' ' << s1 << std::endl;
CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value); CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value);
CHECK_EQ_CRLF(s1, expected_data[i][layout[1]].value); CHECK_EQ_CRLF(s1, expected_data[i][layout[1]].value);
} else { } else {
@ -458,8 +459,6 @@ void test_data_combinations(const std::vector<column>& input_data,
std::string>(); std::string>();
if (i < n) { if (i < n) {
check_error(); check_error();
// std::cout << s0 << ' ' << s1 << ' ' << s2 <<
// std::endl;
CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value); CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value);
CHECK_EQ_CRLF(s1, expected_data[i][layout[1]].value); CHECK_EQ_CRLF(s1, expected_data[i][layout[1]].value);
CHECK_EQ_CRLF(s2, expected_data[i][layout[2]].value); CHECK_EQ_CRLF(s2, expected_data[i][layout[2]].value);
@ -475,10 +474,6 @@ void test_data_combinations(const std::vector<column>& input_data,
std::string, std::string>(); std::string, std::string>();
if (i < n) { if (i < n) {
check_error(); check_error();
/*
std::cout << s0 << ' ' << s1 << ' ' << s2 << ' ' << s3
<< std::endl;
*/
CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value); CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value);
CHECK_EQ_CRLF(s1, expected_data[i][layout[1]].value); CHECK_EQ_CRLF(s1, expected_data[i][layout[1]].value);
CHECK_EQ_CRLF(s2, expected_data[i][layout[2]].value); CHECK_EQ_CRLF(s2, expected_data[i][layout[2]].value);
@ -496,9 +491,6 @@ void test_data_combinations(const std::vector<column>& input_data,
std::string>(); std::string>();
if (i < n) { if (i < n) {
check_error(); check_error();
// std::cout << s0 << ' ' << s1 << ' ' << s2 << ' ' <<
// s3
// << ' ' << s4 << std::endl;
CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value); CHECK_EQ_CRLF(s0, expected_data[i][layout[0]].value);
CHECK_EQ_CRLF(s1, expected_data[i][layout[1]].value); CHECK_EQ_CRLF(s1, expected_data[i][layout[1]].value);
CHECK_EQ_CRLF(s2, expected_data[i][layout[2]].value); CHECK_EQ_CRLF(s2, expected_data[i][layout[2]].value);