diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2025-01-02 18:49:56 -0600 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2025-01-02 18:49:56 -0600 |
commit | d5a174a6d4f8be5e7cffe7c2adbb8db23b578f56 (patch) | |
tree | 536a10802f418e3e71f3828597439537d9e62f21 | |
parent | 908fdf06b41f9084d719a4b517c868b1ad29a9ac (diff) |
Fixing errors in Vector.
-rw-r--r-- | .clang-tidy | 2 | ||||
-rw-r--r-- | include/fud_csv.hpp | 2 | ||||
-rw-r--r-- | include/fud_file.hpp | 10 | ||||
-rw-r--r-- | include/fud_span.hpp | 1 | ||||
-rw-r--r-- | include/fud_string_view.hpp | 34 | ||||
-rw-r--r-- | include/fud_vector.hpp | 35 | ||||
-rw-r--r-- | source/fud_csv.cpp | 50 | ||||
-rw-r--r-- | test/test_common.cpp | 16 | ||||
-rw-r--r-- | test/test_common.hpp | 7 | ||||
-rw-r--r-- | test/test_csv.cpp | 77 | ||||
-rw-r--r-- | test/test_file.cpp | 11 |
11 files changed, 184 insertions, 61 deletions
diff --git a/.clang-tidy b/.clang-tidy index abd3f89..d6fa925 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*,readability*,-readability-use-anyofallof,bugprone*,-bugprone-easily-swappable-parameters,deadcode,cppcoreguidelines*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-avoid-do-while,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-owning-memory,-cppcoreguidelines-non-private-member-variables-in-classes,modernize-*,-modernize-pass-by-value,-modernize-use-trailing-return-type,-modernize-avoid-c-arrays,performance*,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-type-union-access,-clang-diagnostic-unknown-warning-option,-clang-analyzer-valist*,-modernize-use-designated-initializers' +Checks: 'clang-diagnostic-*,clang-analyzer-*,readability*,-readability-use-anyofallof,bugprone*,-bugprone-easily-swappable-parameters,deadcode,cppcoreguidelines*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-avoid-do-while,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-owning-memory,-cppcoreguidelines-non-private-member-variables-in-classes,modernize-*,-modernize-pass-by-value,-modernize-use-trailing-return-type,-modernize-avoid-c-arrays,performance*,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-type-union-access,-clang-diagnostic-unknown-warning-option,-clang-analyzer-valist*,-modernize-use-designated-initializers,-readability-redundant-member-init' WarningsAsErrors: '' HeaderFileExtensions: - '' diff --git a/include/fud_csv.hpp b/include/fud_csv.hpp index 237c56f..2e0b6dd 100644 --- a/include/fud_csv.hpp +++ b/include/fud_csv.hpp @@ -88,6 +88,8 @@ struct Csv { // assumes file is at start static FudStatus parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t maxExtraAttempts); + + [[nodiscard]] Result<Option<StringView>, FudStatus> entry(size_t line, size_t column) const; }; } // namespace fud diff --git a/include/fud_file.hpp b/include/fud_file.hpp index 6f1acbf..66719e4 100644 --- a/include/fud_file.hpp +++ b/include/fud_file.hpp @@ -38,7 +38,7 @@ enum class FileAccessMode : uint8_t ReadWrite = Read | Write }; -enum class OpenFlagEnum : uint16_t +enum class OpenFlagEnum : uint8_t { Append = 0x01, Truncate = Append << 1, @@ -91,7 +91,7 @@ class OpenFlags { return mode; } - constexpr uint32_t flags() const noexcept + [[nodiscard]] constexpr uint32_t flags() const noexcept { uint32_t openFlags = 0; openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::Append)) * O_APPEND; @@ -105,7 +105,7 @@ class OpenFlags { return openFlags; } - constexpr bool hasFlag(OpenFlagEnum flag) const noexcept + [[nodiscard]] constexpr bool hasFlag(OpenFlagEnum flag) const noexcept { return (m_mask & static_cast<FlagType>(flag)) != 0; } @@ -142,7 +142,7 @@ class RegularFile { Result<size_t, FudStatus> size() const; - constexpr int fileDescriptor() const + [[nodiscard]] constexpr int fileDescriptor() const { return m_fd; } @@ -225,7 +225,7 @@ class BufferedRegularFile { Result<size_t, FudStatus> searchSubstring(StringView subString); - constexpr const RegularFile& file() const + [[nodiscard]] constexpr const RegularFile& file() const { return m_file; } diff --git a/include/fud_span.hpp b/include/fud_span.hpp index ed4bcc7..b274d6f 100644 --- a/include/fud_span.hpp +++ b/include/fud_span.hpp @@ -35,6 +35,7 @@ struct Span { using ValueType = T; T* m_data; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members) const size_t m_size; static Span make(Array<T, Size>& array) diff --git a/include/fud_string_view.hpp b/include/fud_string_view.hpp index 327bf20..c3bc0a1 100644 --- a/include/fud_string_view.hpp +++ b/include/fud_string_view.hpp @@ -18,10 +18,10 @@ #ifndef FUD_STRING_VIEW_HPP #define FUD_STRING_VIEW_HPP +#include "fud_assert.hpp" +#include "fud_config.hpp" #include "fud_status.hpp" #include "fud_utf8.hpp" -#include "fud_config.hpp" -#include "fud_assert.hpp" #include <string_view> @@ -31,6 +31,7 @@ class String; struct StringView { template <size_t N> + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) consteval StringView(const utf8 (&input)[N]) : m_length{N - 1}, m_data{input} { static_assert(N > 0); @@ -52,28 +53,42 @@ struct StringView { } template <size_t N> - StringView(const char (&input)[N]) : m_length{N - 1}, m_data{reinterpret_cast<const utf8*>(input)} + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) + StringView(const char (&input)[N]) : + m_length{N - 1}, + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + m_data{reinterpret_cast<const utf8*>(input)} { static_assert(N > 0); } StringView(size_t strLen, const char* strData) : - m_length(strLen), // line break - m_data{reinterpret_cast<const utf8*>(strData)} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + m_length(strLen), + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + m_data{reinterpret_cast<const utf8*>(strData)} { } - StringView(std::string_view rhs) noexcept : StringView(rhs.length(), rhs.data()) {} + StringView(std::string_view rhs) noexcept : StringView(rhs.length(), rhs.data()) + { + } explicit StringView(const String& fudString) noexcept; template <size_t N> + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays) constexpr static StringView makeFromCString(const char (&input)[N]) { static_assert(N > 0); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return StringView{N - 1, reinterpret_cast<const utf8*>(input)}; } + [[nodiscard]] constexpr Span<const utf8> asSpan() const + { + return Span<const utf8>{m_data, m_length}; + } + [[nodiscard]] constexpr size_t length() const { return m_length; @@ -84,8 +99,9 @@ struct StringView { return m_data; } - [[nodiscard]] inline const char* c_str() const + [[nodiscard]] const char* c_str() const { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) return reinterpret_cast<const char*>(m_data); } @@ -98,12 +114,12 @@ struct StringView { return m_data[index]; } - constexpr const utf8* begin() const noexcept + [[nodiscard]] constexpr const utf8* begin() const noexcept { return m_data; } - constexpr const utf8* end() const noexcept + [[nodiscard]] constexpr const utf8* end() const noexcept { return m_data + m_length; } diff --git a/include/fud_vector.hpp b/include/fud_vector.hpp index 2942e71..760587b 100644 --- a/include/fud_vector.hpp +++ b/include/fud_vector.hpp @@ -116,6 +116,7 @@ class Vector { } output.m_allocator = allocator; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) output.m_data = reinterpret_cast<T*>(dataPtrResult.getOkay()); output.m_length = 0; output.m_capacity = capacity; @@ -354,6 +355,7 @@ class Vector { return dataPtrResult.takeError(); } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto* dataPtr = reinterpret_cast<T*>(dataPtrResult.takeOkay()); for (size_t index = 0; index < m_length; ++index) { const auto* ptr = new (dataPtr + index) T(std::move(m_data[index])); @@ -363,6 +365,7 @@ class Vector { auto status = FudStatus::Success; if (m_capacity > 0) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity); } @@ -645,7 +648,9 @@ class Vector { } if (m_length + Size > m_capacity) { - auto status = grow(); + size_t currentLength = m_length; + auto status = resize(m_length + Size); + m_length = currentLength; if (status != FudStatus::Success) { return status; } @@ -660,6 +665,33 @@ class Vector { return FudStatus::Success; } + FudStatus extend(Span<const T> span) + { + if (span.data() == nullptr) { + return FudStatus::NullPointer; + } + if (std::numeric_limits<size_t>::max() - span.size() < m_length) { + return FudStatus::Failure; + } + if (m_length + span.size() > m_capacity) + { + size_t currentLength = m_length; + auto status = resize(m_length + span.size()); + m_length = currentLength; + if (status != FudStatus::Success) { + return status; + } + } + + for (size_t spanIndex = 0; spanIndex < span.size(); ++spanIndex) { + const auto* ptr = new (m_data + m_length) T(span[spanIndex]); + fudAssert(ptr != nullptr); + m_length++; + } + + return FudStatus::Success; + } + FudStatus erase(size_t index) { if (index >= m_length) { @@ -709,6 +741,7 @@ class Vector { auto status = clear(); if (m_data != nullptr && m_allocator != nullptr) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity); } diff --git a/source/fud_csv.cpp b/source/fud_csv.cpp index e1ecf72..bcef925 100644 --- a/source/fud_csv.cpp +++ b/source/fud_csv.cpp @@ -17,8 +17,6 @@ #include "fud_csv.hpp" -#include "fud_print.hpp" - namespace fud { } // namespace fud @@ -50,11 +48,9 @@ FudStatus Csv::parseFromFilenameUnbuffered( Option<int> dirFdOption, size_t maxExtraAttempts) { - debugPrint(u8"Enter parse from filename\n"); auto fileResult{RegularFile::open(filename, FileAccessMode::Read, flags, std::move(dirFdOption))}; if (fileResult.isError()) { - debugPrint(u8"Error opening file: {}\n", FudStatusToString(fileResult.getError())); return fileResult.takeError(); } @@ -70,11 +66,9 @@ FudStatus Csv::parseFromFilenameBuffered( Option<int> dirFdOption, size_t maxExtraAttempts) { - debugPrint(u8"Enter parse from filename\n"); auto fileResult{RegularFile::open(filename, FileAccessMode::Read, flags, std::move(dirFdOption))}; if (fileResult.isError()) { - debugPrint(u8"Error opening file: {}\n", FudStatusToString(fileResult.getError())); return fileResult.takeError(); } @@ -104,8 +98,6 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t return readResult.status; } - debugPrint(u8"Working with {} columns\n", csv.numColumns); - csv.numLines = 1; while (readResult.status == FudStatus::Success) { auto lineResult = scanLine(csv, file, maxExtraAttempts, rawSize); @@ -113,7 +105,6 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t readResult.bytesDrained += lineResult.bytesDrained; if (readResult.status == FudStatus::Success || readResult.status == FudStatus::Partial) { csv.numLines++; - debugPrint(u8"Read additional line - total of {}\n", csv.numLines); } } @@ -126,12 +117,9 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t } if (std::numeric_limits<size_t>::max() / csv.numLines < csv.numColumns) { - debugPrint(u8"Fail: csv.numlines = {}, csv.numColumns = {}\n", csv.numLines, csv.numColumns); return FudStatus::Failure; } - debugPrint(u8"Working with {} lines\n", csv.numLines); - auto reserveStatus = csv.entries.reserve(csv.numLines * csv.numColumns); if (reserveStatus != FudStatus::Success) { return reserveStatus; @@ -142,8 +130,6 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t return reserveStatus; } - debugPrint(u8"Reserved space - {}\n", rawSize + 1); - auto fillStatus = fillBuffer(csv, file, maxExtraAttempts, rawSize); if (fillStatus != FudStatus::Success) { @@ -166,8 +152,6 @@ FudStatus Csv::parseFromUnbufferedFile(Csv& csv, RegularFile&& file, size_t maxE template <typename File> DrainResult readHeader(Csv& csv, File& file, size_t maxExtraAttempts, size_t& rawSize) { - debugPrint(u8"Entered read header\n"); - DrainResult readResult{}; auto lineEnding{newlineText(csv.newlineDelimiter)}; @@ -183,12 +167,10 @@ DrainResult readHeader(Csv& csv, File& file, size_t maxExtraAttempts, size_t& ra readResult.status = drainResult.status; readResult.bytesDrained += drainResult.bytesDrained; if (readResult.status != FudStatus::Success) { - debugPrint(u8"Failed to read: {}", FudStatusToString(readResult.status)); return readResult; } if (csv.strictUtf8 && not utf8Char.valid()) { - debugPrint(u8"UTF8 invalid\n"); readResult.status = FudStatus::Utf8Invalid; return readResult; } @@ -231,7 +213,6 @@ DrainResult readHeader(Csv& csv, File& file, size_t maxExtraAttempts, size_t& ra template <typename File> DrainResult scanLine(const Csv& csv, File& file, size_t maxExtraAttempts, size_t& rawSize) { - debugPrint(u8"Entered scanLine\n"); DrainResult readResult{}; auto lineEnding{newlineText(csv.newlineDelimiter)}; @@ -257,8 +238,6 @@ DrainResult scanLine(const Csv& csv, File& file, size_t maxExtraAttempts, size_t break; } - debugPrint(u8"{}", utf8Char.data()); - if (maybeNewline and utf8Char != Utf8{Ascii{lineEnding[1]}}) { rawSize += 2; maybeNewline = false; @@ -300,12 +279,7 @@ DrainResult scanLine(const Csv& csv, File& file, size_t maxExtraAttempts, size_t } } - if (numColumns > 0) { - debugPrint(u8"\n - Read line above with {} columns \n", numColumns); - } - if (numColumns == 0) { - debugPrint(u8"Read no additional columns\n"); readResult.status = FudStatus::Empty; return readResult; } @@ -343,7 +317,6 @@ FudStatus fillBuffer(Csv& csv, File& file, size_t maxExtraAttempts, size_t rawSi currentEntry.m_data = csv.buffer.data() + sizeCounter; size_t numEntries = csv.numLines * csv.numColumns; - debugPrint(u8"Working over {} entries\n", numEntries); for (size_t entryIndex = 0; entryIndex < numEntries;) { addToSize = false; Utf8 utf8Char{}; @@ -421,7 +394,6 @@ FudStatus fillBuffer(Csv& csv, File& file, size_t maxExtraAttempts, size_t rawSi break; case 0: default: - debugPrint(u8"Char size is ??? {}\n", charSize); charSize = 0; break; } @@ -433,21 +405,13 @@ FudStatus fillBuffer(Csv& csv, File& file, size_t maxExtraAttempts, size_t rawSi } } - debugPrint( - u8"Buffer, with current size = {} and sizeCounter, = {}:\n-----\n{}\n-----\n", - csv.buffer.size(), - sizeCounter, - StringView{csv.buffer.size(), csv.buffer.data()}); - const auto* data = csv.buffer.data(); for (auto& entry : csv.entries) { entry.m_data = data; data += entry.m_length; - debugPrint(u8"Entry = {}\n", entry); } if (rawSize != sizeCounter) { - debugPrint(u8"Invalid: rawSize == {}, sizeCounter == {}"); return FudStatus::Failure; } @@ -455,4 +419,18 @@ FudStatus fillBuffer(Csv& csv, File& file, size_t maxExtraAttempts, size_t rawSi } // NOLINTEND(readability-function-cognitive-complexity) +[[nodiscard]] Result<Option<StringView>, FudStatus> Csv::entry(size_t line, size_t column) const +{ + if (line > numLines || column > numColumns) { + return Error{FudStatus::IndexInvalid}; + } + + StringView entry = entries[(line * numColumns) + column]; + if (entry.length() == 0) { + return Okay{Option<StringView>{NullOpt}}; + } + + return Okay{Option<StringView>{entry}}; +} + } // namespace fud diff --git a/test/test_common.cpp b/test/test_common.cpp index f272dad..03c5dff 100644 --- a/test/test_common.cpp +++ b/test/test_common.cpp @@ -27,28 +27,35 @@ namespace fud { std::byte* MockFudAlloc::operator()(size_t size) { + // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) return static_cast<std::byte*>(malloc(size)); } void MockFudDealloc::operator()(std::byte* pointer) { + // NOLINTNEXTLINE(cppcoreguidelines-no-malloc) free(pointer); } +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) MockFudAlloc globalDefaultMockAlloc{}; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) MockFudDealloc globalDefaultMockDealloc{}; +// NOLINTNEXTLINE(readability-make-member-function-const) std::byte* MockFudAllocator::allocate(size_t size) { return (*m_allocator)(size); } +// NOLINTNEXTLINE(readability-make-member-function-const) void MockFudAllocator::deallocate(std::byte* pointer) { - return (*m_deallocator)(pointer); + (*m_deallocator)(pointer); } +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) MockFudAllocator globalMockFudAlloc{}; std::byte* fudAlloc(size_t size) @@ -58,7 +65,7 @@ std::byte* fudAlloc(size_t size) void fudFree(std::byte* ptr) { - return globalMockFudAlloc.deallocate(ptr); + globalMockFudAlloc.deallocate(ptr); } int unlink_cb(const char* fpath, const struct stat* sb_unused, int typeflag, struct FTW* ftwbuf) @@ -79,7 +86,9 @@ FudStatus removeRecursive(StringView path) if (!path.utf8Valid()) { return FudStatus::Utf8Invalid; } - if (path.length() < 5) { + + constexpr const size_t minPathLength = 5; + if (path.length() < minPathLength) { return FudStatus::ArgumentInvalid; } if (not path.nullTerminated()) { @@ -96,6 +105,7 @@ FudStatus removeRecursive(StringView path) } constexpr int maxOpenFd = 64; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto status = nftw(reinterpret_cast<const char*>(path.data()), unlink_cb, maxOpenFd, FTW_DEPTH | FTW_PHYS); if (status == 0) { return FudStatus::Success; diff --git a/test/test_common.hpp b/test/test_common.hpp index 5f6828f..3be26f0 100644 --- a/test/test_common.hpp +++ b/test/test_common.hpp @@ -58,16 +58,22 @@ static_assert(sizeof(FOUR_BYTE) == 4 + 1); // NOLINTEND(cppcoreguidelines-macro-usage) +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) struct MockFudAlloc { + virtual ~MockFudAlloc() = default; virtual std::byte* operator()(size_t size); }; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern MockFudAlloc globalDefaultMockAlloc; +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) struct MockFudDealloc { + virtual ~MockFudDealloc() = default; virtual void operator()(std::byte* pointer); }; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern MockFudDealloc globalDefaultMockDealloc; struct MockFudAllocator { @@ -78,6 +84,7 @@ struct MockFudAllocator { MockFudDealloc* m_deallocator{&globalDefaultMockDealloc}; }; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern MockFudAllocator globalMockFudAlloc; class String; diff --git a/test/test_csv.cpp b/test/test_csv.cpp index 90e7ef0..cb93a32 100644 --- a/test/test_csv.cpp +++ b/test/test_csv.cpp @@ -20,14 +20,49 @@ #include "gtest/gtest.h" +//NOLINTBEGIN(readability-magic-numbers) + namespace fud { const StringView happyCsvFilename{u8"fud-happy-test.csv"}; const StringView happyData{ u8"foo,bar,baz\n" - u8"1,Unquoted Text,\"Quoted Text with embedded \"\" quote and embedded newline \n" - u8"see\"\n,,\"Prior two fields are empty\"\n"}; + u8"1,Unquoted Text,\"Quoted Text with embedded \"\" quote and embedded newline \nsee\"\n" + u8",,\"Prior two fields are empty\"\n"}; + +Csv expectedHappyCsv() { + Csv csv{Csv::makeDefault()}; + csv.numLines = 3; + csv.numColumns = 3; + + auto resizeStatus = csv.entries.resize(csv.numLines * csv.numColumns); + fudAssert(resizeStatus == FudStatus::Success); + csv.entries[0] = StringView{u8"foo"}; + csv.entries[1] = StringView{u8"bar"}; + csv.entries[2] = StringView{u8"baz"}; + csv.entries[3] = StringView{u8"1"}; + csv.entries[4] = StringView{u8"Unquoted Text"}; + csv.entries[5] = StringView{u8"Quoted Text with embedded \" quote and embedded newline \nsee"}; + csv.entries[6] = StringView{}; + csv.entries[7] = StringView{}; + csv.entries[8] = StringView{u8"Prior two fields are empty"}; + + for (const auto& entry : csv.entries) { + if (entry.length() > 0) { + auto extendStatus = csv.buffer.extend(entry.asSpan()); + fudAssert(extendStatus == FudStatus::Success); + } + } + + size_t totalSize = 0; + for (auto& entry : csv.entries) { + entry.m_data = csv.buffer.data() + totalSize; + totalSize += entry.length(); + } + + return csv; +} auto writeHappyCsv() -> FudStatus { @@ -44,6 +79,7 @@ auto writeHappyCsv() -> FudStatus } auto file{fileResult.takeOkay()}; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto writeResult = file.write(reinterpret_cast<const std::byte*>(happyData.data()), happyData.length()); if (writeResult.status != FudStatus::Success) { return writeResult.status; @@ -62,13 +98,46 @@ TEST(FudCsv, ParseCsvFromFilename) ASSERT_EQ(writeHappyCsv(), FudStatus::Success); - debugPrint(u8"Wrote happy data:\n-----\n{}\n-----\n", happyData); - auto parseStatus = Csv::parseFromFilenameUnbuffered(csv, happyCsvFilename); if (parseStatus != FudStatus::Success) { debugPrint(u8"Error parsing file: {}\n", FudStatusToString(parseStatus)); } ASSERT_EQ(parseStatus, FudStatus::Success); + + auto expectedCsv{expectedHappyCsv()}; + ASSERT_EQ(expectedCsv.numLines, csv.numLines); + ASSERT_EQ(expectedCsv.numColumns, csv.numColumns); + ASSERT_EQ(expectedCsv.buffer.size(), csv.buffer.size()); + ASSERT_EQ(expectedCsv.entries.size(), csv.entries.size()); + EXPECT_EQ(0, compareMem(expectedCsv.buffer.data(), expectedCsv.buffer.size(), csv.buffer.data(), csv.buffer.size()).takeOkayOr(-1)); + for (size_t line = 0; line < csv.numLines; ++line) + { + for (size_t column = 0; column < csv.numColumns; ++column) + { + auto expectedEntryResult = expectedCsv.entry(line, column); + ASSERT_TRUE(expectedEntryResult.isOkay()); + auto expectedEntryOpt{expectedEntryResult.takeOkay()}; + + auto csvEntryResult = csv.entry(line, column); + EXPECT_TRUE(csvEntryResult.isOkay()); + if (csvEntryResult.isError()) { + continue; + } + auto csvEntryOpt{csvEntryResult.takeOkay()}; + + EXPECT_EQ(expectedEntryOpt.hasValue(), csvEntryOpt.hasValue()); + if (expectedEntryOpt.isNone()) { + continue; + } + auto expectedEntry{expectedEntryOpt.value()}; + auto csvEntry{csvEntryOpt.value()}; + + EXPECT_EQ(expectedEntry.length(), csvEntry.length()); + EXPECT_EQ(0, compareMem(expectedEntry.data(), expectedEntry.length(), csvEntry.data(), csvEntry.length()).takeOkayOr(-1)); + } + } } } // namespace fud + +//NOLINTEND(readability-magic-numbers) diff --git a/test/test_file.cpp b/test/test_file.cpp index 12cfb98..c1ce4f1 100644 --- a/test/test_file.cpp +++ b/test/test_file.cpp @@ -21,11 +21,11 @@ #include "test_common.hpp" #include "gtest/gtest.h" -#include <algorithm> #include <cerrno> #include <fcntl.h> #include <ftw.h> -#include <ranges> + +// NOLINTBEGIN(readability-magic-numbers) namespace fud { @@ -121,6 +121,7 @@ TEST(FudBufferedFile, OpenReadWrite) ASSERT_EQ(bufferedFile.file().size().getOkayOr(std::numeric_limits<size_t>::max()), 0); auto writeResult = bufferedFile.write( + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret_cast<const std::byte*>(testName.data()), testName.size(), NullOpt); @@ -132,6 +133,7 @@ TEST(FudBufferedFile, OpenReadWrite) ASSERT_EQ(bufferedFile.seekStart(), FudStatus::Success); Vector<utf8> output{Vector<utf8>::withSize(testName.size()).takeOkay()}; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) auto readResult = bufferedFile.read(reinterpret_cast<std::byte*>(output.data()), testName.size(), NullOpt); ASSERT_EQ(readResult, expected); @@ -142,11 +144,13 @@ TEST(FudBufferedFile, OpenReadWrite) ASSERT_EQ(bufferedFile.seekStart(), FudStatus::Success); expected.bytesDrained = 1; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) readResult = bufferedFile.read(reinterpret_cast<std::byte*>(output.data()), 1, NullOpt); ASSERT_EQ(readResult, expected); EXPECT_EQ(output[0], testName.data()[0]); expected.bytesDrained = testName.size() - 2; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) readResult = bufferedFile.read(reinterpret_cast<std::byte*>(output.data()) + 1, testName.size() - 2, NullOpt); ASSERT_EQ(readResult, expected); EXPECT_EQ( @@ -154,6 +158,7 @@ TEST(FudBufferedFile, OpenReadWrite) compareMem(output.data() + 1, output.size() - 1, testName.data() + 1, testName.size() - 2).takeOkayOr(-1)); expected.bytesDrained = 1; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) readResult = bufferedFile.read(reinterpret_cast<std::byte*>(output.data()), 1, NullOpt); EXPECT_TRUE(readResult.status == FudStatus::Success || readResult.status == FudStatus::Partial); @@ -164,3 +169,5 @@ TEST(FudBufferedFile, OpenReadWrite) } } // namespace fud + +// NOLINTEND(readability-magic-numbers) |