aboutsummaryrefslogtreecommitdiff
path: root/tests/tlzsshuffman.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tlzsshuffman.nim')
-rw-r--r--tests/tlzsshuffman.nim144
1 files changed, 144 insertions, 0 deletions
diff --git a/tests/tlzsshuffman.nim b/tests/tlzsshuffman.nim
new file mode 100644
index 0000000..f771f31
--- /dev/null
+++ b/tests/tlzsshuffman.nim
@@ -0,0 +1,144 @@
1# gzip-like LZSS compressor
2# Copyright (C) 2018 Pacien TRAN-GIRARD
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as
6# published by the Free Software Foundation, either version 3 of the
7# License, or (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17import unittest, tables, lists, sequtils, streams
18import bitio/bitwriter, bitio/bitreader
19import lzss/listpolyfill, lzss/lzssnode, lzss/lzsschain
20import huffman/huffmantree, huffman/huffmantreebuilder, huffman/huffmanencoder, huffman/huffmandecoder
21import lzsshuffman/lzsshuffmansymbol, lzsshuffman/lzsshuffmanstats, lzsshuffman/lzsshuffmanencoder, lzsshuffman/lzsshuffmandecoder
22
23suite "lzsshuffmansymbol":
24 test "isEndMarker":
25 check 'a'.Symbol.isEndMarker() == false
26 check endSymbol.isEndMarker()
27
28 test "isCharacter":
29 check 'a'.Symbol.isCharacter()
30 check endSymbol.isCharacter() == false
31 check 300.Symbol.isCharacter() == false
32
33 test "unpackLzssReference":
34 check unpackLzssReference(257.Symbol, 10) == lzssReference(3, 10)
35 check unpackLzssReference(300.Symbol, 10) == lzssReference(46, 10)
36
37 test "shiftLzssLength":
38 check shiftLzssLength(3) == 257'u16
39 check shiftLzssLength(10) == 264'u16
40
41suite "lzsshuffmanstats":
42 test "aggretateStats":
43 let chain = lzssChain([
44 lzssCharacter(0), lzssCharacter(1), lzssCharacter(2),
45 lzssCharacter(3), lzssCharacter(4), lzssCharacter(5),
46 lzssReference(4, 6), lzssCharacter(0), lzssCharacter(1),
47 lzssReference(3, 8), lzssCharacter(5),
48 lzssReference(3, 3), lzssCharacter(5)])
49 let (symbolTable, positionTable) = chain.aggregateStats()
50 check symbolTable == newCountTable(concat(
51 repeat(0'u16, 2), repeat(1'u16, 2), repeat(2'u16, 1), repeat(3'u16, 1), repeat(4'u16, 1), repeat(5'u16, 3),
52 repeat(endSymbol.uint16, 1),
53 repeat(257'u16, 2), repeat(258'u16, 1)))
54 check positionTable == newCountTable(concat(
55 repeat(3'u16, 1), repeat(6'u16, 1), repeat(8'u16, 1)))
56
57suite "lzsshuffmanencoder":
58 test "writeChain (empty)":
59 let chain = lzssChain(newSeq[LzssNode]())
60 let symbolTree = huffmanLeaf(endSymbol.uint16)
61 let positionTree = huffmanLeaf(0'u16)
62 let stream = newStringStream()
63 defer: stream.close()
64 let bitWriter = stream.bitWriter()
65 writeChain(chain, symbolTree.encoder(uint16), positionTree.encoder(uint16), bitWriter)
66 bitWriter.flush()
67 stream.setPosition(0)
68 check stream.atEnd()
69
70 test "writeChain (minimal)":
71 let chain = lzssChain([
72 lzssCharacter(0), lzssCharacter(1), lzssCharacter(2),
73 lzssReference(3, 3), lzssReference(3, 4)])
74 let symbolTree = huffmanBranch(
75 huffmanBranch(
76 huffmanLeaf(0'u16),
77 huffmanLeaf(1'u16)),
78 huffmanBranch(
79 huffmanLeaf(257'u16),
80 huffmanBranch(
81 huffmanLeaf(2'u16),
82 huffmanLeaf(256'u16))))
83 let positionTree = huffmanBranch(
84 huffmanLeaf(3'u16),
85 huffmanLeaf(4'u16))
86 let stream = newStringStream()
87 defer: stream.close()
88 let bitWriter = stream.bitWriter()
89 writeChain(chain, symbolTree.encoder(uint16), positionTree.encoder(uint16), bitWriter)
90 bitWriter.flush()
91 stream.setPosition(0)
92 let bitReader = stream.bitReader()
93 check bitReader.readBits(2, uint8) == 0b00'u8 # char 0
94 check bitReader.readBits(2, uint8) == 0b10'u8 # char 1
95 check bitReader.readBits(3, uint8) == 0b011'u8 # char 2
96 check bitReader.readBits(2, uint8) == 0b01'u8 # ref len 3
97 check bitReader.readBits(1, uint8) == 0b0'u8 # ref pos 3
98 check bitReader.readBits(2, uint8) == 0b01'u8 # ref len 3
99 check bitReader.readBits(1, uint8) == 0b1'u8 # ref pos 4
100 check bitReader.readBits(3, uint8) == 0b111'u8 # eof
101
102suite "lzsshuffmandecoder":
103 test "readChain (empty)":
104 let symbolTree = huffmanLeaf(endSymbol.uint16)
105 let positionTree = huffmanLeaf(0'u16)
106 let stream = newStringStream()
107 defer: stream.close()
108 stream.write(0'u8) # eof
109 stream.setPosition(0)
110 let bitReader = stream.bitReader()
111 let result = readChain(bitReader, symbolTree.decoder(), positionTree.decoder(), 32_000)
112 check toSeq(result.items).len == 0
113
114 test "readChain (minimal)":
115 let symbolTree = huffmanBranch(
116 huffmanBranch(
117 huffmanLeaf(0'u16),
118 huffmanLeaf(1'u16)),
119 huffmanBranch(
120 huffmanLeaf(257'u16),
121 huffmanBranch(
122 huffmanLeaf(2'u16),
123 huffmanLeaf(256'u16))))
124 let positionTree = huffmanBranch(
125 huffmanLeaf(3'u16),
126 huffmanLeaf(4'u16))
127 let stream = newStringStream()
128 defer: stream.close()
129 let bitWriter = stream.bitWriter()
130 bitWriter.writeBits(2, 0b00'u8)
131 bitWriter.writeBits(2, 0b10'u8)
132 bitWriter.writeBits(3, 0b011'u8)
133 bitWriter.writeBits(2, 0b01'u8)
134 bitWriter.writeBits(1, 0b0'u8)
135 bitWriter.writeBits(2, 0b01'u8)
136 bitWriter.writeBits(1, 0b1'u8)
137 bitWriter.writeBits(3, 0b111'u8)
138 bitWriter.flush()
139 stream.setPosition(0)
140 let bitReader = stream.bitReader()
141 let result = readChain(bitReader, symbolTree.decoder(), positionTree.decoder(), 32_000)
142 check toSeq(result.items) == [
143 lzssCharacter(0), lzssCharacter(1), lzssCharacter(2),
144 lzssReference(3, 3), lzssReference(3, 4)]