From d6d4319e21d2cd2b5dc361e0b70ad570c4669d02 Mon Sep 17 00:00:00 2001 From: James Grogan Date: Tue, 29 Nov 2022 18:00:19 +0000 Subject: [PATCH] Add test fixture. --- src/compression/Lz77Encoder.cpp | 11 -- src/compression/huffman/HuffmanEncoder.cpp | 75 ++++++++---- src/compression/huffman/HuffmanEncoder.h | 14 ++- src/compression/huffman/HuffmanFixedCodes.h | 125 ++++++++++++++++++++ src/image/png/PngWriter.cpp | 1 - test/CMakeLists.txt | 27 ++--- test/audio/TestAudioWriter.cpp | 46 ++----- test/audio/TestMidiReader.cpp | 27 +---- test/compiler/TestLexer.cpp | 5 - test/compiler/TestTemplatingEngine.cpp | 5 +- test/compression/TestHuffmanStream.cpp | 37 +++--- test/compression/TestLz77Encoder.cpp | 8 +- test/compression/TestStreamCompressor.cpp | 27 ++--- test/core/TestBinaryStream.cpp | 4 - test/core/TestBitStream.cpp | 16 +-- test/core/TestByteUtils.cpp | 6 +- test/core/TestDataStructures.cpp | 6 +- test/core/TestTomlReader.cpp | 6 +- test/database/TestDatabase.cpp | 6 +- test/fonts/TestFontReader.cpp | 6 +- test/fonts/TestFreeTypeFontEngine.cpp | 6 +- test/graphics/TestOpenGlRendering.cpp | 27 ++--- test/graphics/TestRasterizer.cpp | 6 +- test/image/TestPngReader.cpp | 14 +-- test/image/TestPngWriter.cpp | 18 +-- test/network/TestNetworkManagerClient.cpp | 11 +- test/network/TestNetworkManagerServer.cpp | 11 +- test/publishing/TestPdfWriter.cpp | 5 +- test/test_runner.cpp | 17 +++ test/test_utils/TestCase.h | 38 +++++- test/test_utils/TestCaseRunner.cpp | 30 ++++- test/test_utils/TestCaseRunner.h | 16 ++- test/test_utils/TestFramework.h | 18 +++ test/video/TestVideoDecoder.cpp | 7 +- test/web/TestMarkdownParser.cpp | 6 +- test/web/TestXmlParser.cpp | 6 +- test/windows/TestWaylandWindow.cpp | 6 +- 37 files changed, 421 insertions(+), 279 deletions(-) delete mode 100644 test/compiler/TestLexer.cpp delete mode 100644 test/core/TestBinaryStream.cpp create mode 100644 test/test_utils/TestFramework.h diff --git a/src/compression/Lz77Encoder.cpp b/src/compression/Lz77Encoder.cpp index 9818a64..b247e45 100644 --- a/src/compression/Lz77Encoder.cpp +++ b/src/compression/Lz77Encoder.cpp @@ -64,11 +64,9 @@ unsigned char Lz77Encoder::getSearchBufferItem(unsigned index) const unsigned Lz77Encoder::lookAheadForMatchingChars(unsigned distance) { unsigned length{0}; - std::cout << "In hit check at distance " << distance << " max buffer index is: " << mMaxLookAheadBufferIndex << std::endl; for(unsigned idx=0; idx(search_offset)); } - unsigned char lookahead_char = mLookaheadBuffer.getItem(idx); - - std::cout << "Checking search char " << static_cast(search_char) << " and lookup char " << static_cast(lookahead_char) << std::endl; if ((lookahead_char != search_char) || (idx == mMaxLookAheadBufferIndex)) { if (idx + 1>= mMinLengthMatchSize) @@ -100,9 +95,7 @@ void Lz77Encoder::lookForMatches(unsigned char searchChar, unsigned& hitLength, { if (mSearchBuffer.getItem(mSearchBuffer.getNumItems() - 1 - idx) == searchChar) { - std::cout << "Looking for hits " << std::endl; auto num_hits = lookAheadForMatchingChars(idx + 1); - if (num_hits > 0 && num_hits >= hitLength) { hitLength = num_hits; @@ -197,14 +190,10 @@ bool Lz77Encoder::encode() } const auto working_byte = mLookaheadBuffer.getItem(0); - std::cout << "Working byte is " << static_cast(working_byte) << std::endl; - unsigned hit_length{0}; unsigned hit_distance{0}; lookForMatches(working_byte, hit_length, hit_distance); - std::cout << "Got hit length " << hit_length << " and distance " << hit_distance << std::endl; - const Hit hit{hit_length, hit_distance, working_byte}; mHitBuffer.push_back(hit); diff --git a/src/compression/huffman/HuffmanEncoder.cpp b/src/compression/huffman/HuffmanEncoder.cpp index 35d56f5..7b7b30c 100644 --- a/src/compression/huffman/HuffmanEncoder.cpp +++ b/src/compression/huffman/HuffmanEncoder.cpp @@ -2,6 +2,8 @@ #include "RawTree.h" +#include "HuffmanFixedCodes.h" + #include #include #include @@ -40,34 +42,22 @@ void HuffmanEncoder::dumpTree(const RawTree& tree) const dumpNode(tree.getRootNode(), 0); } -void HuffmanEncoder::encode(const HuffmanEncoder::DataStream& stream) +void HuffmanEncoder::encode(const std::vector& counts) { - std::unordered_map counts; - for (auto c : stream) - { - counts[c]++; - } - encode(counts); -} - -void HuffmanEncoder::encode(const std::unordered_map& counts) -{ - std::cout << "Counts" << std::endl; - for (const auto& data: counts) - { - std::cout << data.first << " | " << data.second << std::endl; - } - std::cout << "*******" << std::endl; - auto cmp = [](RawNode* left, RawNode* right) { return left->getData().second > right->getData().second; }; std::priority_queue*, std::vector* >, decltype(cmp)> q(cmp); - for (const auto& entry : counts) + unsigned offset{0}; + for (auto count : counts) { - q.push(new RawNode(entry)); + if (count > 0) + { + q.push(new RawNode({offset, count})); + } + offset++; } while(q.size() > 1) @@ -99,6 +89,18 @@ void HuffmanEncoder::encode(const std::unordered_map& c std::cout << "********" << std::endl; } +void HuffmanEncoder::encode(const std::unordered_map& counts) +{ + std::vector just_counts; + for (const auto& data: counts) + { + mSymbolMapping.push_back(data.first); + just_counts.push_back(data.second); + } + + encode(just_counts); +} + void HuffmanEncoder::setUseFixedCode(bool useFixed) { mUseFixedCode = useFixed; @@ -129,16 +131,43 @@ std::optional HuffmanEncoder::getEndOfStreamValue() const return mLiteralLengthTable.getCodeForSymbol(256); } -void HuffmanEncoder::initializeTrees() +void HuffmanEncoder::initializeTrees(const std::vector& hits) { - initializeLiteralLengthTable(); + initializeLiteralLengthTable(hits); } -void HuffmanEncoder::initializeLiteralLengthTable() +void HuffmanEncoder::initializeLiteralLengthTable(const std::vector& hits) { if(mUseFixedCode) { mLiteralLengthTable.setInputLengthSequence(HuffmanFixedCodes::getDeflateFixedHuffmanCodes(), false); mLiteralLengthTable.buildPrefixCodes(); + return; } + + std::vector counts(285, 0); + counts[256] = 1; + for (const auto& hit : hits) + { + const auto& [length, distance, next_char] = hit; + if (length > 0 ) + { + const auto& [code, extra_bits, num_extra_bits] = HuffmanFixedCodes::getCodeForLength(length); + counts[code]++; + } + else + { + counts[next_char]++; + } + } + + for(unsigned idx=0; idx0) + { + std::cout << "Count for " << idx << " is " << counts[idx] << std::endl; + } + } + + encode(counts); } diff --git a/src/compression/huffman/HuffmanEncoder.h b/src/compression/huffman/HuffmanEncoder.h index 87285d4..0b53364 100644 --- a/src/compression/huffman/HuffmanEncoder.h +++ b/src/compression/huffman/HuffmanEncoder.h @@ -6,6 +6,7 @@ #include "HuffmanFixedCodes.h" #include +#include #include class PrefixCodeGenerator @@ -21,11 +22,11 @@ public: class HuffmanEncoder : public PrefixCodeGenerator { -using DataStream = std::vector; -using CountPair = std::pair; + using CountPair = std::pair; + using Hit = std::tuple; public: - void encode(const DataStream& stream); + void encode(const std::vector& counts); void encode(const std::unordered_map& counts); uint32_t getLengthValue(unsigned length); @@ -38,18 +39,19 @@ public: std::optional getEndOfStreamValue() const override; - void initializeTrees(); + void initializeTrees(const std::vector& hits); void setUseFixedCode(bool useFixed); - private: - void initializeLiteralLengthTable(); + void initializeLiteralLengthTable(const std::vector& hits); void dumpTree(const RawTree& tree) const; void dumpNode(RawNode* node, unsigned depth) const; bool mUseFixedCode{false}; bool mTableIsInitialized{false}; + + std::vector mSymbolMapping; HuffmanCodeLengthTable mLiteralLengthTable; HuffmanCodeLengthTable mDistanceTable; }; diff --git a/src/compression/huffman/HuffmanFixedCodes.h b/src/compression/huffman/HuffmanFixedCodes.h index 82ef9db..f3b89fe 100644 --- a/src/compression/huffman/HuffmanFixedCodes.h +++ b/src/compression/huffman/HuffmanFixedCodes.h @@ -1,6 +1,7 @@ #pragma once #include +#include namespace HuffmanFixedCodes { @@ -17,4 +18,128 @@ namespace HuffmanFixedCodes } return sequence; } + + inline std::tuple getCodeForLength(unsigned length) + { + if (length <= 10) + { + return {length - 3, 0, 0}; + } + + unsigned base = 2; + unsigned last_offset = 10; + for (unsigned n = 1; n < 5; n++) + { + const auto diff = length - last_offset; + if (diff <= 4*base) + { + auto extra = diff/base + diff % base; + return {last_offset + diff/base, extra, n}; + } + + last_offset += 4*n; + base = base*2; + } + return {258, 0, 0}; + } + + /* + inline std::pair getCodeForLength(unsigned length) + { + if (length <= 10) + { + return {257 + length - 3, 0}; + } + else if(length <= 18) + { + auto offset = length - 10; + auto extra = offset/2 + offset % 2; + return {265 + offset/2, extra}; + } + else if(length <= 34) + { + auto offset = length - 19; + auto extra = offset/4 + offset % 4; + return {269 + offset/4, extra}; + } + else if(length <= 66) + { + auto offset = length - 35; + auto extra = offset/8 + offset % 8; + return {273 + offset/8, extra}; + } + else if(length <= 114) + { + auto offset = length - 67; + auto extra = offset/16 + offset % 16; + return {277 + offset/16, extra}; + } + else if(length <= 257) + { + auto offset = length - 115; + auto extra = offset/32 + offset % 32; + return {281 + offset/32, extra}; + } + else + { + return {258, 0}; + } + } + + inline unsigned getLengthForCode(unsigned symbol, unsigned extra) + { + if (symbol <= 264) + { + return 3 + symbol - 257; + } + else if (symbol <= 268) + { + return 11 + 2*(symbol - 265) + extra; + const auto valid_dist = readNextDistanceSymbol(distance); + copyFromBuffer(length, distance); + } + else if (symbol <= 272) + { + unsigned char extra{0}; + mInputStream->readNextNBits(2, extra); + + auto length = 19 + 4*(symbol - 269) + extra; + const auto valid_dist = readNextDistanceSymbol(distance); + copyFromBuffer(length, distance); + } + else if (symbol <= 276) + { + unsigned char extra{0}; + mInputStream->readNextNBits(3, extra); + + auto length = 35 + 8*(symbol - 273) + extra; + const auto valid_dist = readNextDistanceSymbol(distance); + copyFromBuffer(length, distance); + } + else if (symbol <= 280) + { + unsigned char extra{0}; + mInputStream->readNextNBits(4, extra); + + auto length = 67 + 16*(symbol - 277) + extra; + const auto valid_dist = readNextDistanceSymbol(distance); + copyFromBuffer(length, distance); + } + else if (symbol <= 284) + { + unsigned char extra{0}; + mInputStream->readNextNBits(5, extra); + + auto length = 131 + 32*(symbol - 281) + extra; + const auto valid_dist = readNextDistanceSymbol(distance); + copyFromBuffer(length, distance); + } + else if (symbol == 285) + { + auto length = 258; + const auto valid_dist = readNextDistanceSymbol(distance); + copyFromBuffer(length, distance); + } + } + */ } diff --git a/src/image/png/PngWriter.cpp b/src/image/png/PngWriter.cpp index 168eb85..d1d73fe 100644 --- a/src/image/png/PngWriter.cpp +++ b/src/image/png/PngWriter.cpp @@ -200,7 +200,6 @@ void PngWriter::write(const std::unique_ptr >& image) { auto huffman_encoder = std::make_unique(); huffman_encoder->setUseFixedCode(true); - huffman_encoder->initializeTrees(); lz77_encoder.setPrefixCodeGenerator(std::move(huffman_encoder)); } lz77_encoder.encode(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3fc9442..184b276 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,16 +10,14 @@ target_include_directories(test_utils PUBLIC list(APPEND TestFiles audio/TestAudioWriter.cpp audio/TestMidiReader.cpp - core/TestByteUtils.cpp - core/TestBinaryStream.cpp - core/TestBitStream.cpp - core/TestTomlReader.cpp - core/TestDataStructures.cpp - compiler/TestLexer.cpp compiler/TestTemplatingEngine.cpp compression/TestStreamCompressor.cpp compression/TestHuffmanStream.cpp compression/TestLz77Encoder.cpp + core/TestByteUtils.cpp + core/TestBitStream.cpp + core/TestTomlReader.cpp + core/TestDataStructures.cpp database/TestDatabase.cpp fonts/TestFontReader.cpp graphics/TestRasterizer.cpp @@ -29,7 +27,8 @@ list(APPEND TestFiles network/TestNetworkManagerServer.cpp publishing/TestPdfWriter.cpp web/TestMarkdownParser.cpp - web/TestXmlParser.cpp) + web/TestXmlParser.cpp + ) if (${HAS_FFMPEG}) list(APPEND TestFiles @@ -71,16 +70,6 @@ if(UNIX) endif() endif() -foreach(TestFile ${TestFiles}) - cmake_path(GET TestFile FILENAME TestFileName) - cmake_path(GET TestFileName STEM TestName) +add_executable(test_runner test_runner.cpp ${TestFiles}) - add_executable(${TestName} ${TestFile}) - - target_link_libraries(${TestName} PUBLIC core compiler compression fonts network image publishing video database geometry audio graphics web client test_utils ${DBUS_LIBRARIES}) - set_property(TARGET ${TestName} PROPERTY FOLDER test) -endforeach() - - -add_executable(test_runner test_runner.cpp) -target_link_libraries(test_runner PUBLIC core fonts network database geometry audio graphics web client) +target_link_libraries(test_runner PUBLIC test_utils publishing core compiler fonts network database geometry audio graphics web client) diff --git a/test/audio/TestAudioWriter.cpp b/test/audio/TestAudioWriter.cpp index 42a8dc5..43c927a 100644 --- a/test/audio/TestAudioWriter.cpp +++ b/test/audio/TestAudioWriter.cpp @@ -3,8 +3,7 @@ #include "AudioWriter.h" #include "WasapiInterface.h" -#include "TestCase.h" -#include "TestCaseRunner.h" +#include "TestFramework.h" #include #include @@ -13,50 +12,23 @@ #endif #include -class TestWriteWav : public TestCase +TEST_CASE(TestWriteWav, "audio") { -public: - bool Run() override - { - AudioWriter writer; - writer.SetPath("test.wav"); + AudioWriter writer; + writer.SetPath("test.wav"); - AudioSynth synth; - auto sample = synth.GetSineWave(240, 5); + AudioSynth synth; + auto sample = synth.GetSineWave(240, 5); - writer.Write(sample); - return true; - } + writer.Write(sample); }; -class TestAudioRender : public TestCase +TEST_CASE(TestAudioRender, "audio") { -public: - bool Run() override - { + #ifdef _WIN32 WasapiInterface audio_interface; auto device = AudioDevice::Create(); audio_interface.Play(device); #endif - return true; - } }; - -//int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) -int main() -{ -#ifdef _WIN32 - CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); -#endif - std::cout << "into entry point" << std::endl; - TestCaseRunner runner; - runner.AddTestCase("TestWriteNav", std::make_unique()); - runner.AddTestCase("TestAudioRender", std::make_unique()); - - const auto testsPassed = runner.Run(); - return testsPassed ? 0 : -1; -#ifdef _WIN32 - CoUninitialize(); -#endif -} diff --git a/test/audio/TestMidiReader.cpp b/test/audio/TestMidiReader.cpp index 86c06a5..9f8ee6a 100644 --- a/test/audio/TestMidiReader.cpp +++ b/test/audio/TestMidiReader.cpp @@ -1,31 +1,16 @@ #include "MidiReader.h" -#include "TestCase.h" -#include "TestCaseRunner.h" +#include "TestFramework.h" #include #include #include -class TestReadMidi : public TestCase +TEST_CASE(TestReadMidi, "audio") { -public: - bool Run() override - { - MidiReader reader; - reader.Read("/home/jmsgrogan/Downloads/test.mid"); + MidiReader reader; + reader.Read("/home/jmsgrogan/Downloads/test.mid"); - auto document = reader.GetDocument(); - std::cout << document->Serialize() << std::endl; - return true; - } + auto document = reader.GetDocument(); + // std::cout << document->Serialize() << std::endl; }; - -int main() -{ - TestCaseRunner runner; - runner.AddTestCase("TestReadMidi", std::make_unique()); - - const auto testsPassed = runner.Run(); - return testsPassed ? 0 : -1; -} diff --git a/test/compiler/TestLexer.cpp b/test/compiler/TestLexer.cpp deleted file mode 100644 index 22ca09c..0000000 --- a/test/compiler/TestLexer.cpp +++ /dev/null @@ -1,5 +0,0 @@ - -int main(int argc, char** argv) -{ - return 0; -} diff --git a/test/compiler/TestTemplatingEngine.cpp b/test/compiler/TestTemplatingEngine.cpp index bcdc028..b0de8be 100644 --- a/test/compiler/TestTemplatingEngine.cpp +++ b/test/compiler/TestTemplatingEngine.cpp @@ -1,11 +1,12 @@ #include "TemplatingEngine.h" #include +#include "TestFramework.h" #include #include -int main() +TEST_CASE(TestTemplatingEngine, "compiler") { const auto data_loc = std::filesystem::path(__FILE__) / "../../data"; @@ -15,4 +16,4 @@ int main() File outfile("index.html"); outfile.WriteText(content); -} \ No newline at end of file +} diff --git a/test/compression/TestHuffmanStream.cpp b/test/compression/TestHuffmanStream.cpp index 2f5ad11..1dffe8c 100644 --- a/test/compression/TestHuffmanStream.cpp +++ b/test/compression/TestHuffmanStream.cpp @@ -1,9 +1,11 @@ #include +#include "TestFramework.h" + #include "HuffmanStream.h" #include "BufferBitStream.h" -void testHuffmanCodeLengthTable() +TEST_CASE(TestHuffmanCodeLengthTable, "compression") { HuffmanCodeLengthTable table; @@ -17,23 +19,23 @@ void testHuffmanCodeLengthTable() } } table.setInputLengthSequence(code_length_sequence, false); - table.buildCompressedLengthSequence(); auto compressed_sequence = table.getCompressedLengthSequence(); for (auto entry : compressed_sequence) { - std::cout << "Count " << entry.first << " extra bits " << entry.second << std::endl; + // std::cout << "Count " << entry.first << " extra bits " << entry.second << std::endl; } auto compressed_lengths = table.getCompressedLengthCounts(); for(unsigned idx = 0; idx lengths = {7,4,4,7,5,5,7,7,6,6,7,6,6,6,8,6,6,8, 6,6,7,6,8,7,7,7,7,7,7,6,6,7,7,6,6,7,7,8,8,7,7,7,6,6,7,7,7,7,6,7,7,7, @@ -53,13 +55,13 @@ void testLiteralsTable() auto compressed_sequence = table.getCompressedLengthSequence(); for (auto entry : compressed_sequence) { - std::cout << "Code " << entry.first << " extra bits " << entry.second << std::endl; + // std::cout << "Code " << entry.first << " extra bits " << entry.second << std::endl; } auto compressed_lengths = table.getCompressedLengthCounts(); for(unsigned idx = 0; idx #include "Lz77Encoder.h" +#include "HuffmanEncoder.h" #include "BufferBitStream.h" -int main() +#include "TestFramework.h" + +TEST_CASE(TestLz77Encoder, "compression") { std::vector values {0, 10, 11, 12, 10, 11, 12, 0, 13, 14, 15, 10, 11, 12}; @@ -28,5 +31,6 @@ int main() std::cout << "Got hit " << length << " | " << distance << " | " << static_cast(next_char) << std::endl; } - return 0; + HuffmanEncoder huffman_encoder; + huffman_encoder.initializeTrees(hit_buffer); } diff --git a/test/compression/TestStreamCompressor.cpp b/test/compression/TestStreamCompressor.cpp index 4f4af7c..3eff02d 100644 --- a/test/compression/TestStreamCompressor.cpp +++ b/test/compression/TestStreamCompressor.cpp @@ -5,21 +5,25 @@ #include "RunLengthEncoder.h" #include "Lz77Encoder.h" -void test_run_length_encoder() +#include "StringUtils.h" + +#include "TestFramework.h" + +TEST_CASE(TestRunLengthEncoder, "compression") { std::string test_data = "BCAAAADDDCCACACAC"; RunLengthEncoder encoder; - auto encoded = encoder.encode(test_data); + auto encoded = encoder.encode(StringUtils::toBytes(test_data)); - std::cout << "Encoded: " << encoded << std::endl; + //std::cout << "Encoded: " << encoded << std::endl; auto decoded = encoder.decode(encoded); - std::cout << "Decoded: " << decoded << std::endl; + //std::cout << "Decoded: " << decoded << std::endl; } -void test_huffman_encoder() +TEST_CASE(TestHuffmanEncoder, "compression") { //std::string testData = "BCAADDDCCACACAC"; //std::vector stream(testData.begin(), testData.end()); @@ -38,7 +42,7 @@ void test_huffman_encoder() encoder.encode(counts); } -void test_lz77_encoder() +TEST_CASE(TestLz77Encoder, "compression") { std::string test_data = "sir sid eastman easily teases sea sick seals"; //std::string test_data = "sir sid eastman"; @@ -56,14 +60,3 @@ void test_lz77_encoder() //std::cout << "Decoded: " << decoded << std::endl; } - - -int main() -{ - //test_huffman_encoder(); - - //test_run_length_encoder(); - - test_lz77_encoder(); - return 0; -} diff --git a/test/core/TestBinaryStream.cpp b/test/core/TestBinaryStream.cpp deleted file mode 100644 index 905869d..0000000 --- a/test/core/TestBinaryStream.cpp +++ /dev/null @@ -1,4 +0,0 @@ -int main() -{ - return 0; -} diff --git a/test/core/TestBitStream.cpp b/test/core/TestBitStream.cpp index 53c7ccc..9dbd976 100644 --- a/test/core/TestBitStream.cpp +++ b/test/core/TestBitStream.cpp @@ -1,9 +1,11 @@ #include "ByteUtils.h" #include "BufferBitStream.h" +#include "TestFramework.h" + #include -void testReading() +TEST_CASE(TestReadBitStream, "core") { std::vector bytes{ "11101101", @@ -37,7 +39,7 @@ void testReading() std::cout << "Slice3 is " << ByteUtils::toString(buffer) << std::endl; } -void testWriting() +TEST_CASE(TestWritingBitStream, "core") { BufferBitStream stream; @@ -72,13 +74,3 @@ void testWriting() std::cout << "Got bytes 3 " << byte3 << std::endl; std::cout << "Got bytes 4 " << byte4 << std::endl; } - - -int main() -{ - //testReading() - - testWriting(); - - return 0; -} diff --git a/test/core/TestByteUtils.cpp b/test/core/TestByteUtils.cpp index 3ea1a73..7dc8f92 100644 --- a/test/core/TestByteUtils.cpp +++ b/test/core/TestByteUtils.cpp @@ -1,8 +1,10 @@ #include "ByteUtils.h" +#include "TestFramework.h" + #include -int main() +TEST_CASE(TestReadByteUtils, "core") { auto byte = ByteUtils::getFromString("00110101"); std::cout << "Value is " << static_cast(byte) << std::endl; @@ -32,6 +34,4 @@ int main() unsigned hold = byte; hold = (hold << 5) + 3; std::cout << "Big val is " << ByteUtils::toString(hold, 16) << std::endl; - - return 0; } diff --git a/test/core/TestDataStructures.cpp b/test/core/TestDataStructures.cpp index c297475..1072594 100644 --- a/test/core/TestDataStructures.cpp +++ b/test/core/TestDataStructures.cpp @@ -1,8 +1,10 @@ #include "CircleBuffer.h" +#include "TestFramework.h" + #include -int main() +TEST_CASE(TestCircleBuffer, "core") { CircleBuffer buffer(3); @@ -29,6 +31,4 @@ int main() auto item = buffer.getItem(idx); std::cout << "Got item: " << idx << " " << item << std::endl; } - - return 0; } diff --git a/test/core/TestTomlReader.cpp b/test/core/TestTomlReader.cpp index 9802cf6..bd16dc9 100644 --- a/test/core/TestTomlReader.cpp +++ b/test/core/TestTomlReader.cpp @@ -1,9 +1,11 @@ #include "TomlReader.h" +#include "TestFramework.h" + #include #include -int main() +TEST_CASE(TestTomlReader, "core") { const auto data_loc = std::filesystem::path(__FILE__) / "../../data"; const auto sample_toml_file = data_loc / "sample_toml.toml"; @@ -16,6 +18,4 @@ int main() { std::cout << "Got entry with key: " << items.first << " and val " << items.second << std::endl; } - - return 0; } diff --git a/test/database/TestDatabase.cpp b/test/database/TestDatabase.cpp index a10be39..bc1392f 100644 --- a/test/database/TestDatabase.cpp +++ b/test/database/TestDatabase.cpp @@ -1,12 +1,12 @@ #include "DatabaseManager.h" -int main() +#include "TestFramework.h" + +TEST_CASE(TestDatabaseManager, "database") { DatabaseManager db_manager; db_manager.CreateDatabase("test.db"); std::string statement = "CREATE TABLE corporation;"; db_manager.Run(statement); - - return 0; } diff --git a/test/fonts/TestFontReader.cpp b/test/fonts/TestFontReader.cpp index 33b612a..d47dd17 100644 --- a/test/fonts/TestFontReader.cpp +++ b/test/fonts/TestFontReader.cpp @@ -3,7 +3,9 @@ #include -int main() +#include "TestFramework.h" + +TEST_CASE(TestFontReader, "fonts") { const auto font_path = "/usr/share/fonts/truetype/tlwg/TlwgTypo-Bold.ttf"; @@ -12,6 +14,4 @@ int main() auto font = reader.read(); font->dumpInfo(); - - return 0; } diff --git a/test/fonts/TestFreeTypeFontEngine.cpp b/test/fonts/TestFreeTypeFontEngine.cpp index b770a0d..93b9b03 100644 --- a/test/fonts/TestFreeTypeFontEngine.cpp +++ b/test/fonts/TestFreeTypeFontEngine.cpp @@ -3,9 +3,11 @@ #include "FontGlyph.h" #include "Image.h" +#include "TestFramework.h" + #include -int main() +TEST_CASE(TestFreeTypeFontEngine, "fonts") { FreeTypeFontEngine engine; engine.initialize(); @@ -14,6 +16,4 @@ int main() engine.loadGlyph('A'); engine.loadGlyph(66); engine.loadGlyph(67); - - return 0; } diff --git a/test/graphics/TestOpenGlRendering.cpp b/test/graphics/TestOpenGlRendering.cpp index aa0e19a..f85392e 100644 --- a/test/graphics/TestOpenGlRendering.cpp +++ b/test/graphics/TestOpenGlRendering.cpp @@ -3,30 +3,17 @@ #include "GuiApplication.h" +#include "TestFramework.h" + #include #include #include -class TestOpenGlRendering : public TestCase +TEST_CASE(TestOpenGlRendering, "graphics") { -public: - bool Run() override - { - auto app = std::make_unique(); + auto app = std::make_unique(); - app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11); - //app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER); - app->run(); - - return true; - } + app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11); + //app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER); + app->run(); }; - -int main() -{ - TestCaseRunner runner; - runner.AddTestCase("TestOpenGlRendering", std::make_unique()); - - const auto testsPassed = runner.Run(); - return testsPassed ? 0 : -1; -} diff --git a/test/graphics/TestRasterizer.cpp b/test/graphics/TestRasterizer.cpp index 2309a25..d6285c2 100644 --- a/test/graphics/TestRasterizer.cpp +++ b/test/graphics/TestRasterizer.cpp @@ -9,7 +9,9 @@ #include "Point.h" #include "TriMesh.h" -int main() +#include "TestFramework.h" + +TEST_CASE(TestRasterizer, "graphics") { /* DrawingManager manager; @@ -18,6 +20,4 @@ int main() auto line = LineSegment::Create(Point(10.0, 10.0), Point(190.0, 190.0)); */ - - return 0; } diff --git a/test/image/TestPngReader.cpp b/test/image/TestPngReader.cpp index d90cecf..f705cc2 100644 --- a/test/image/TestPngReader.cpp +++ b/test/image/TestPngReader.cpp @@ -5,7 +5,9 @@ #include "Image.h" #include -void testThirdParty() +#include "TestFramework.h" + +TEST_CASE(TestThirdPartyPng, "image") { const auto path = "/home/jmsgrogan/Downloads/test.png"; @@ -26,7 +28,7 @@ void testThirdParty() //} } -void testFixedCode() +TEST_CASE(TestFxedCodePng, "image") { const auto path = "/home/jmsgrogan/code/MediaTool-build/bin/test_fixed.png"; @@ -37,11 +39,3 @@ void testFixedCode() reader.setPath(path); auto image = reader.read(); } - -int main() -{ - testThirdParty(); - //testFixedCode(); - - return 0; -} diff --git a/test/image/TestPngWriter.cpp b/test/image/TestPngWriter.cpp index 04e04ab..a189d6d 100644 --- a/test/image/TestPngWriter.cpp +++ b/test/image/TestPngWriter.cpp @@ -6,9 +6,11 @@ #include "ByteUtils.h" #include "ImagePrimitives.h" +#include "TestFramework.h" + #include -void testCompressedPng() +TEST_CASE(TestCompressedPng, "image") { unsigned width = 20; unsigned height = 20; @@ -43,7 +45,7 @@ void testCompressedPng() test_file.Close(); } -void testFixedPng() +TEST_CASE(TestFixedPng, "image") { unsigned width = 10; unsigned height = 10; @@ -73,7 +75,7 @@ void testFixedPng() } -void testDynamicCompressedPng() +TEST_CASE(TestDynamicCompressedPng, "image") { unsigned width = 10; unsigned height = 10; @@ -99,14 +101,4 @@ void testDynamicCompressedPng() //return; File test_file("test_dynamic.png"); std::cout << test_file.dumpBinary(); - -} - -int main() -{ - //testCompressedPng(); - //testFixedPng(); - testDynamicCompressedPng(); - - return 0; } diff --git a/test/network/TestNetworkManagerClient.cpp b/test/network/TestNetworkManagerClient.cpp index d2d0d0f..6943c63 100644 --- a/test/network/TestNetworkManagerClient.cpp +++ b/test/network/TestNetworkManagerClient.cpp @@ -1,12 +1,13 @@ #include "NetworkManager.h" +#include "TestFramework.h" + #include -int main() +TEST_CASE(TestNetworkManagerClient, "network") { - std::cout << "into main" << std::endl; - auto network_manager = NetworkManager::Create(); + std::cout << "into main" << std::endl; + auto network_manager = NetworkManager::Create(); - network_manager->RunHttpClient(); - return 0; + network_manager->RunHttpClient(); } diff --git a/test/network/TestNetworkManagerServer.cpp b/test/network/TestNetworkManagerServer.cpp index 4b33c35..fde0683 100644 --- a/test/network/TestNetworkManagerServer.cpp +++ b/test/network/TestNetworkManagerServer.cpp @@ -1,12 +1,13 @@ #include "NetworkManager.h" +#include "TestFramework.h" + #include -int main() +TEST_CASE(TestNetworkManagerServer, "network") { - std::cout << "into main" << std::endl; - auto network_manager = NetworkManager::Create(); + std::cout << "into main" << std::endl; + auto network_manager = NetworkManager::Create(); - network_manager->RunHttpServer(); - return 0; + network_manager->RunHttpServer(); } diff --git a/test/publishing/TestPdfWriter.cpp b/test/publishing/TestPdfWriter.cpp index 97c6276..dad2d8e 100644 --- a/test/publishing/TestPdfWriter.cpp +++ b/test/publishing/TestPdfWriter.cpp @@ -3,7 +3,9 @@ #include "PdfObject.h" #include "File.h" -int main() +#include "TestFramework.h" + +TEST_CASE(TestPdfWriter, "publishing") { auto document = std::make_unique(); @@ -14,5 +16,4 @@ int main() pdf_file.SetAccessMode(File::AccessMode::Write); pdf_file.Open(); pdf_file.WriteText(output); - return 0; } diff --git a/test/test_runner.cpp b/test/test_runner.cpp index 905869d..7b577ed 100644 --- a/test/test_runner.cpp +++ b/test/test_runner.cpp @@ -1,4 +1,21 @@ +#include "TestFramework.h" + +#ifdef _WIN32 +#include +#endif + +//int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) int main() { +#ifdef _WIN32 + CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); +#endif + + auto test_runner = TestCaseRunner::getInstance(); + test_runner.run(); + +#ifdef _WIN32 + CoUninitialize(); +#endif return 0; } diff --git a/test/test_utils/TestCase.h b/test/test_utils/TestCase.h index 6105350..84ad8be 100644 --- a/test/test_utils/TestCase.h +++ b/test/test_utils/TestCase.h @@ -1,13 +1,45 @@ #pragma once #include +#include +#include class TestCase { public: - TestCase(){}; + using TestCaseFunction = std::function; + + TestCase(const std::string& name, const std::string& tags, TestCaseFunction func) + : mName(name), + mTags(tags), + mTestFunction(func) + { + + }; + virtual ~TestCase() = default; - TestCase(const TestCase&) = delete; - virtual bool Run() {return false;}; + + const std::string& getName() const + { + return mName; + } + + const std::string& getTags() const + { + return mTags; + } + + virtual void run() + { + mTestFunction(); + }; + +public: + TestCaseFunction mTestFunction{nullptr}; + +private: + std::string mName; + std::string mTags; + }; using TestCasePtr = std::unique_ptr; diff --git a/test/test_utils/TestCaseRunner.cpp b/test/test_utils/TestCaseRunner.cpp index f588948..fb71188 100644 --- a/test/test_utils/TestCaseRunner.cpp +++ b/test/test_utils/TestCaseRunner.cpp @@ -3,24 +3,42 @@ #include #include -void TestCaseRunner::AddTestCase(const std::string& label, TestCasePtr testCase) +TestCaseRunner::~TestCaseRunner() { - mCases.push_back({label, std::move(testCase)}); + for (auto testCase : mCases) + { + //delete testCase; + } } -bool TestCaseRunner::Run() +void TestCaseRunner::addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func) { + auto test_case = new TestCase(label, tag, func); + mCases.push_back(test_case); +} + +bool TestCaseRunner::run() +{ + for (auto test_case : mCases) + { + std::cout << "TestFramework: Running Test - " << test_case->getName() << std::endl; + test_case->run(); + } + bool testsPassed = true; + /* for(const auto& test : mCases) { - std::cout << "Running " << test.first << std::endl; - const auto result = test.second->Run(); + std::cout << "Running " << test->getName() << std::endl; + const auto result = test->Run(); if (!result) { - std::cout << test.first << " Failed" << std::endl; + std::cout << test->getName() << " Failed" << std::endl; testsPassed = false; break; } } return testsPassed; + */ + return true; } diff --git a/test/test_utils/TestCaseRunner.h b/test/test_utils/TestCaseRunner.h index 39cfb42..b929cb6 100644 --- a/test/test_utils/TestCaseRunner.h +++ b/test/test_utils/TestCaseRunner.h @@ -8,12 +8,20 @@ class TestCaseRunner { public: + TestCaseRunner() = default; - void AddTestCase(const std::string& label, TestCasePtr testCase); + static TestCaseRunner& getInstance() + { + static TestCaseRunner instance; + return instance; + } - bool Run(); + ~TestCaseRunner(); + + void addTestCase(const std::string& label, const std::string& tag, TestCase::TestCaseFunction func); + + bool run(); private: - using TestInstance = std::pair; - std::vector mCases; + std::vector mCases; }; diff --git a/test/test_utils/TestFramework.h b/test/test_utils/TestFramework.h new file mode 100644 index 0000000..40514d9 --- /dev/null +++ b/test/test_utils/TestFramework.h @@ -0,0 +1,18 @@ +#pragma once + +#include "TestCaseRunner.h" + +struct Holder +{ + Holder(const std::string& name, const std::string& tags, std::function func) + { + TestCaseRunner::getInstance().addTestCase(name, tags, func); + } +}; + +#define TEST_CASE(NAME, TAGS) \ + static void Test##NAME(); \ + namespace{Holder holder##NAME( #NAME, #TAGS, &Test##NAME );} \ + static void Test##NAME() \ + + diff --git a/test/video/TestVideoDecoder.cpp b/test/video/TestVideoDecoder.cpp index 45cbc1a..9ecdd7d 100644 --- a/test/video/TestVideoDecoder.cpp +++ b/test/video/TestVideoDecoder.cpp @@ -2,10 +2,11 @@ #include "Image.h" #include "FfmpegInterface.h" #include "PngWriter.h" -#include "PngWriterImpl.h" #include -int main() +#include "TestFramework.h" + +TEST_CASE(TestVideoDecoder, "video") { auto video = Video::Create(); video->SetPath("/home/jmsgrogan/test.mp4"); @@ -21,6 +22,4 @@ int main() writer.SetPath(filename); writer.Write(images[idx]); } - - return 0; } diff --git a/test/web/TestMarkdownParser.cpp b/test/web/TestMarkdownParser.cpp index 71e84b0..9a2b667 100644 --- a/test/web/TestMarkdownParser.cpp +++ b/test/web/TestMarkdownParser.cpp @@ -2,7 +2,9 @@ #include "File.h" #include "HtmlWriter.h" -int main() +#include "TestFramework.h" + +TEST_CASE(TestMarkdownParser, "web") { File md_file("/home/jmsgrogan/code/MediaTool/test/data/sample_markdown.md"); md_file.Open(); @@ -20,6 +22,4 @@ int main() html_file.SetAccessMode(File::AccessMode::Write); html_file.Open(); html_file.WriteText(html_string); - return 0; - } diff --git a/test/web/TestXmlParser.cpp b/test/web/TestXmlParser.cpp index 14b2cec..79ace09 100644 --- a/test/web/TestXmlParser.cpp +++ b/test/web/TestXmlParser.cpp @@ -5,7 +5,9 @@ #include "XmlWriter.h" #include "File.h" -int main(int argc, char *argv[]) +#include "TestFramework.h" + +TEST_CASE(TestXmlParser, "web") { XmlParser parser; @@ -26,6 +28,4 @@ int main(int argc, char *argv[]) XmlWriter writer; auto content = writer.ToString(parser.GetDocument().get()); outFile->WriteText(content); - - return 0; } diff --git a/test/windows/TestWaylandWindow.cpp b/test/windows/TestWaylandWindow.cpp index ddc3a35..93be811 100644 --- a/test/windows/TestWaylandWindow.cpp +++ b/test/windows/TestWaylandWindow.cpp @@ -5,7 +5,9 @@ #include "GuiApplication.h" -int main() +#include "TestFramework.h" + +TEST_CASE(TestWaylandWindow, "web") { FileLogger::GetInstance().Open(); @@ -15,6 +17,4 @@ int main() app->setUiInterfaceBackend(UiInterfaceFactory::Backend::WAYLAND_RASTER); app->run(); - - return 0; }