1///////////////////////////////////////////////////////////////////////////////
2//
3/// \file       test_stream_flags.c
4/// \brief      Tests Stream Header and Stream Footer coders
5//
6//  Author:     Lasse Collin
7//
8//  This file has been put into the public domain.
9//  You can do whatever you want with this file.
10//
11///////////////////////////////////////////////////////////////////////////////
12
13#include "tests.h"
14
15
16static lzma_stream_flags known_flags;
17static lzma_stream_flags decoded_flags;
18static uint8_t buffer[LZMA_STREAM_HEADER_SIZE];
19
20
21static bool
22validate(void)
23{
24	// TODO: This could require the specific error type as an argument.
25	// We could also test that lzma_stream_flags_compare() gives
26	// the correct return values in different situations.
27	return lzma_stream_flags_compare(&known_flags, &decoded_flags)
28			!= LZMA_OK;
29}
30
31
32static bool
33test_header_decoder(lzma_ret expected_ret)
34{
35	memcrap(&decoded_flags, sizeof(decoded_flags));
36
37	if (lzma_stream_header_decode(&decoded_flags, buffer) != expected_ret)
38		return true;
39
40	if (expected_ret != LZMA_OK)
41		return false;
42
43	// Header doesn't have Backward Size, so make
44	// lzma_stream_flags_compare() ignore it.
45	decoded_flags.backward_size = LZMA_VLI_UNKNOWN;
46	return validate();
47}
48
49
50static void
51test_header(void)
52{
53	memcrap(buffer, sizeof(buffer));
54	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
55	succeed(test_header_decoder(LZMA_OK));
56}
57
58
59static bool
60test_footer_decoder(lzma_ret expected_ret)
61{
62	memcrap(&decoded_flags, sizeof(decoded_flags));
63
64	if (lzma_stream_footer_decode(&decoded_flags, buffer) != expected_ret)
65		return true;
66
67	if (expected_ret != LZMA_OK)
68		return false;
69
70	return validate();
71}
72
73
74static void
75test_footer(void)
76{
77	memcrap(buffer, sizeof(buffer));
78	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
79	succeed(test_footer_decoder(LZMA_OK));
80}
81
82
83static void
84test_encode_invalid(void)
85{
86	known_flags.check = LZMA_CHECK_ID_MAX + 1;
87	known_flags.backward_size = 1024;
88
89	expect(lzma_stream_header_encode(&known_flags, buffer)
90			== LZMA_PROG_ERROR);
91
92	expect(lzma_stream_footer_encode(&known_flags, buffer)
93			== LZMA_PROG_ERROR);
94
95	known_flags.check = (lzma_check)(-1);
96
97	expect(lzma_stream_header_encode(&known_flags, buffer)
98			== LZMA_PROG_ERROR);
99
100	expect(lzma_stream_footer_encode(&known_flags, buffer)
101			== LZMA_PROG_ERROR);
102
103	known_flags.check = LZMA_CHECK_NONE;
104	known_flags.backward_size = 0;
105
106	// Header encoder ignores backward_size.
107	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
108
109	expect(lzma_stream_footer_encode(&known_flags, buffer)
110			== LZMA_PROG_ERROR);
111
112	known_flags.backward_size = LZMA_VLI_MAX;
113
114	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
115
116	expect(lzma_stream_footer_encode(&known_flags, buffer)
117			== LZMA_PROG_ERROR);
118}
119
120
121static void
122test_decode_invalid(void)
123{
124	known_flags.check = LZMA_CHECK_NONE;
125	known_flags.backward_size = 1024;
126
127	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
128
129	// Test 1 (invalid Magic Bytes)
130	buffer[5] ^= 1;
131	succeed(test_header_decoder(LZMA_FORMAT_ERROR));
132	buffer[5] ^= 1;
133
134	// Test 2a (valid CRC32)
135	uint32_t crc = lzma_crc32(buffer + 6, 2, 0);
136	unaligned_write32le(buffer + 8, crc);
137	succeed(test_header_decoder(LZMA_OK));
138
139	// Test 2b (invalid Stream Flags with valid CRC32)
140	buffer[6] ^= 0x20;
141	crc = lzma_crc32(buffer + 6, 2, 0);
142	unaligned_write32le(buffer + 8, crc);
143	succeed(test_header_decoder(LZMA_OPTIONS_ERROR));
144
145	// Test 3 (invalid CRC32)
146	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
147	buffer[9] ^= 1;
148	succeed(test_header_decoder(LZMA_DATA_ERROR));
149
150	// Test 4 (invalid Stream Flags with valid CRC32)
151	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
152	buffer[9] ^= 0x40;
153	crc = lzma_crc32(buffer + 4, 6, 0);
154	unaligned_write32le(buffer, crc);
155	succeed(test_footer_decoder(LZMA_OPTIONS_ERROR));
156
157	// Test 5 (invalid Magic Bytes)
158	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
159	buffer[11] ^= 1;
160	succeed(test_footer_decoder(LZMA_FORMAT_ERROR));
161}
162
163
164int
165main(void)
166{
167	// Valid headers
168	known_flags.backward_size = 1024;
169	for (lzma_check check = LZMA_CHECK_NONE;
170			check <= LZMA_CHECK_ID_MAX; ++check) {
171		test_header();
172		test_footer();
173	}
174
175	// Invalid headers
176	test_encode_invalid();
177	test_decode_invalid();
178
179	return 0;
180}
181