1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: expandtab:ts=8:sw=4:softtabstop=4:
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file       test_filter_flags.c
6 /// \brief      Tests Filter Flags coders
7 //
8 //  Author:     Lasse Collin
9 //
10 //  This file has been put into the public domain.
11 //  You can do whatever you want with this file.
12 //
13 ///////////////////////////////////////////////////////////////////////////////
14 
15 #include "tests.h"
16 
17 
18 static uint8_t buffer[4096];
19 static lzma_filter known_flags;
20 static lzma_filter decoded_flags;
21 static lzma_stream strm = LZMA_STREAM_INIT;
22 
23 
24 static bool
encode(uint32_t known_size)25 encode(uint32_t known_size)
26 {
27 	memcrap(buffer, sizeof(buffer));
28 
29 	uint32_t tmp;
30 	if (lzma_filter_flags_size(&tmp, &known_flags) != LZMA_OK)
31 		return true;
32 
33 	if (tmp != known_size)
34 		return true;
35 
36 	size_t out_pos = 0;
37 	if (lzma_filter_flags_encode(&known_flags,
38 			buffer, &out_pos, known_size) != LZMA_OK)
39 		return true;
40 
41 	if (out_pos != known_size)
42 		return true;
43 
44 	return false;
45 }
46 
47 
48 static bool
decode_ret(uint32_t known_size,lzma_ret expected_ret)49 decode_ret(uint32_t known_size, lzma_ret expected_ret)
50 {
51 	memcrap(&decoded_flags, sizeof(decoded_flags));
52 
53 	size_t pos = 0;
54 	if (lzma_filter_flags_decode(&decoded_flags, NULL,
55 				buffer, &pos, known_size) != expected_ret
56 			|| pos != known_size)
57 		return true;
58 
59 	return false;
60 }
61 
62 
63 static bool
decode(uint32_t known_size)64 decode(uint32_t known_size)
65 {
66 	if (decode_ret(known_size, LZMA_OK))
67 		return true;
68 
69 	if (known_flags.id != decoded_flags.id)
70 		return true;
71 
72 	return false;
73 }
74 
75 
76 #if defined(HAVE_ENCODER_SUBBLOCK) && defined(HAVE_DECODER_SUBBLOCK)
77 static void
test_subblock(void)78 test_subblock(void)
79 {
80 	// Test 1
81 	known_flags.id = LZMA_FILTER_SUBBLOCK;
82 	known_flags.options = NULL;
83 	expect(!encode(2));
84 	expect(!decode(2));
85 	expect(decoded_flags.options == NULL);
86 
87 	// Test 2
88 	buffer[0] = LZMA_FILTER_SUBBLOCK;
89 	buffer[1] = 1;
90 	buffer[2] = 0;
91 	expect(!decode_ret(3, LZMA_OPTIONS_ERROR));
92 }
93 #endif
94 
95 
96 #if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86)
97 static void
test_bcj(void)98 test_bcj(void)
99 {
100 	// Test 1
101 	known_flags.id = LZMA_FILTER_X86;
102 	known_flags.options = NULL;
103 
104 	expect(!encode(2));
105 	expect(!decode(2));
106 	expect(decoded_flags.options == NULL);
107 
108 	// Test 2
109 	lzma_options_bcj options;
110 	options.start_offset = 0;
111 	known_flags.options = &options;
112 	expect(!encode(2));
113 	expect(!decode(2));
114 	expect(decoded_flags.options == NULL);
115 
116 	// Test 3
117 	options.start_offset = 123456;
118 	known_flags.options = &options;
119 	expect(!encode(6));
120 	expect(!decode(6));
121 	expect(decoded_flags.options != NULL);
122 
123 	lzma_options_bcj *decoded = decoded_flags.options;
124 	expect(decoded->start_offset == options.start_offset);
125 
126 	free(decoded);
127 }
128 #endif
129 
130 
131 #if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA)
132 static void
test_delta(void)133 test_delta(void)
134 {
135 	// Test 1
136 	known_flags.id = LZMA_FILTER_DELTA;
137 	known_flags.options = NULL;
138 	expect(encode(99));
139 
140 	// Test 2
141 	lzma_options_delta options = {
142 		.type = LZMA_DELTA_TYPE_BYTE,
143 		.dist = 0
144 	};
145 	known_flags.options = &options;
146 	expect(encode(99));
147 
148 	// Test 3
149 	options.dist = LZMA_DELTA_DIST_MIN;
150 	expect(!encode(3));
151 	expect(!decode(3));
152 	expect(((lzma_options_delta *)(decoded_flags.options))->dist
153 			== options.dist);
154 
155 	free(decoded_flags.options);
156 
157 	// Test 4
158 	options.dist = LZMA_DELTA_DIST_MAX;
159 	expect(!encode(3));
160 	expect(!decode(3));
161 	expect(((lzma_options_delta *)(decoded_flags.options))->dist
162 			== options.dist);
163 
164 	free(decoded_flags.options);
165 
166 	// Test 5
167 	options.dist = LZMA_DELTA_DIST_MAX + 1;
168 	expect(encode(99));
169 }
170 #endif
171 
172 /*
173 #ifdef HAVE_FILTER_LZMA
174 static void
175 validate_lzma(void)
176 {
177 	const lzma_options_lzma *known = known_flags.options;
178 	const lzma_options_lzma *decoded = decoded_flags.options;
179 
180 	expect(known->dictionary_size <= decoded->dictionary_size);
181 
182 	if (known->dictionary_size == 1)
183 		expect(decoded->dictionary_size == 1);
184 	else
185 		expect(known->dictionary_size + known->dictionary_size / 2
186 				> decoded->dictionary_size);
187 
188 	expect(known->literal_context_bits == decoded->literal_context_bits);
189 	expect(known->literal_pos_bits == decoded->literal_pos_bits);
190 	expect(known->pos_bits == decoded->pos_bits);
191 }
192 
193 
194 static void
195 test_lzma(void)
196 {
197 	// Test 1
198 	known_flags.id = LZMA_FILTER_LZMA1;
199 	known_flags.options = NULL;
200 	expect(encode(99));
201 
202 	// Test 2
203 	lzma_options_lzma options = {
204 		.dictionary_size = 0,
205 		.literal_context_bits = 0,
206 		.literal_pos_bits = 0,
207 		.pos_bits = 0,
208 		.preset_dictionary = NULL,
209 		.preset_dictionary_size = 0,
210 		.mode = LZMA_MODE_INVALID,
211 		.fast_bytes = 0,
212 		.match_finder = LZMA_MF_INVALID,
213 		.match_finder_cycles = 0,
214 	};
215 
216 	// Test 3 (empty dictionary not allowed)
217 	known_flags.options = &options;
218 	expect(encode(99));
219 
220 	// Test 4 (brute-force test some valid dictionary sizes)
221 	options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN;
222 	while (options.dictionary_size != LZMA_DICTIONARY_SIZE_MAX) {
223 		if (++options.dictionary_size == 5000)
224 			options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX - 5;
225 
226 		expect(!encode(4));
227 		expect(!decode(4));
228 		validate_lzma();
229 
230 		free(decoded_flags.options);
231 	}
232 
233 	// Test 5 (too big dictionary size)
234 	options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX + 1;
235 	expect(encode(99));
236 
237 	// Test 6 (brute-force test lc/lp/pb)
238 	options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN;
239 	for (uint32_t lc = LZMA_LITERAL_CONTEXT_BITS_MIN;
240 			lc <= LZMA_LITERAL_CONTEXT_BITS_MAX; ++lc) {
241 		for (uint32_t lp = LZMA_LITERAL_POS_BITS_MIN;
242 				lp <= LZMA_LITERAL_POS_BITS_MAX; ++lp) {
243 			for (uint32_t pb = LZMA_POS_BITS_MIN;
244 					pb <= LZMA_POS_BITS_MAX; ++pb) {
245 				if (lc + lp > LZMA_LITERAL_BITS_MAX)
246 					continue;
247 
248 				options.literal_context_bits = lc;
249 				options.literal_pos_bits = lp;
250 				options.pos_bits = pb;
251 
252 				expect(!encode(4));
253 				expect(!decode(4));
254 				validate_lzma();
255 
256 				free(decoded_flags.options);
257 			}
258 		}
259 	}
260 }
261 #endif
262 */
263 
264 int
main(void)265 main(void)
266 {
267 #if defined(HAVE_ENCODER_SUBBLOCK) && defined(HAVE_DECODER_SUBBLOCK)
268 	test_subblock();
269 #endif
270 #if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86)
271 	test_bcj();
272 #endif
273 #if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA)
274 	test_delta();
275 #endif
276 // #ifdef HAVE_FILTER_LZMA
277 // 	test_lzma();
278 // #endif
279 
280 	lzma_end(&strm);
281 
282 	return 0;
283 }
284