#include "testing/testing.hpp" #include "coding/huffman.hpp" #include "coding/reader.hpp" #include "coding/writer.hpp" #include "base/string_utils.hpp" #include "std/vector.hpp" namespace { vector MakeUniStringVector(vector const & v) { vector result(v.size()); for (size_t i = 0; i < v.size(); ++i) result[i] = strings::MakeUniString(v[i]); return result; } void TestDecode(coding::HuffmanCoder const & h, uint32_t bits, uint32_t len, uint32_t expected) { coding::HuffmanCoder::Code code(bits, len); uint32_t received; TEST(h.Decode(code, received), ("Could not decode", code.bits, "( length", code.len, ")")); TEST_EQUAL(expected, received, ()); } } // namespace namespace coding { UNIT_TEST(Huffman_Smoke) { HuffmanCoder h; h.Init(MakeUniStringVector(vector{"ab", "ac"})); TestDecode(h, 0, 1, static_cast('a')); // 0 TestDecode(h, 1, 2, static_cast('b')); // 10 TestDecode(h, 3, 2, static_cast('c')); // 11 } UNIT_TEST(Huffman_OneSymbol) { HuffmanCoder h; h.Init(MakeUniStringVector(vector{string(5, 0)})); TestDecode(h, 0, 0, 0); } UNIT_TEST(Huffman_NonAscii) { HuffmanCoder h; string const data = "2πΩ"; strings::UniString const uniData = strings::MakeUniString(data); h.Init(vector{uniData}); TestDecode(h, 0, 2, static_cast(uniData[0])); // 00 TestDecode(h, 1, 1, static_cast(uniData[1])); // 1 TestDecode(h, 2, 2, static_cast(uniData[2])); // 01 } UNIT_TEST(Huffman_Init) { HuffmanCoder h; h.Init(MakeUniStringVector(vector{"ab"})); vector buf; buf.push_back(16); // size buf.push_back(105); // 01101001 buf.push_back(150); // 10010110 MemReader memReader(&buf[0], buf.size()); ReaderSource reader(memReader); strings::UniString received = h.ReadAndDecode(reader); strings::UniString expected = strings::MakeUniString("baababbaabbabaab"); TEST_EQUAL(expected, received, ()); } UNIT_TEST(Huffman_Serialization_Encoding) { HuffmanCoder hW; hW.Init(MakeUniStringVector( vector{"aaaaaaaaaa", "bbbbbbbbbb", "ccccc", "ddddd"})); // 10, 10, 5, 5 vector buf; MemWriter> writer(buf); hW.WriteEncoding(writer); HuffmanCoder hR; MemReader memReader(&buf[0], buf.size()); ReaderSource reader(memReader); hR.ReadEncoding(reader); TEST_EQUAL(reader.Pos(), writer.Pos(), ()); TestDecode(hW, 0, 2, static_cast('a')); // 00 TestDecode(hW, 2, 2, static_cast('b')); // 01 TestDecode(hW, 1, 2, static_cast('c')); // 10 TestDecode(hW, 3, 2, static_cast('d')); // 11 TestDecode(hR, 0, 2, static_cast('a')); TestDecode(hR, 2, 2, static_cast('b')); TestDecode(hR, 1, 2, static_cast('c')); TestDecode(hR, 3, 2, static_cast('d')); } UNIT_TEST(Huffman_Serialization_Data) { HuffmanCoder hW; hW.Init(MakeUniStringVector( vector{"aaaaaaaaaa", "bbbbbbbbbb", "ccccc", "ddddd"})); // 10, 10, 5, 5 vector buf; string const data = "abacabaddddaaabbcabacabadbabd"; strings::UniString expected = strings::UniString(data.begin(), data.end()); MemWriter> writer(buf); hW.WriteEncoding(writer); hW.EncodeAndWrite(writer, expected); HuffmanCoder hR; MemReader memReader(&buf[0], buf.size()); ReaderSource reader(memReader); hR.ReadEncoding(reader); strings::UniString received = hR.ReadAndDecode(reader); TEST_EQUAL(expected, received, ()); } } // namespace coding