2
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; either version 2 of the
7
* License, or any later version.
9
* This program is distributed in the hope that it will be useful, but
10
* WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
* You can also choose to distribute this program under the terms of
20
* the Unmodified Binary Distribution Licence (as given in the file
21
* COPYING.UBDL), provided that you have satisfied its requirements.
24
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
32
/* Forcibly enable assertions */
38
#include <ipxe/deflate.h>
39
#include <ipxe/test.h>
43
/** Compression format */
44
enum deflate_format format;
45
/** Compressed data */
46
const void *compressed;
47
/** Length of compressed data */
48
size_t compressed_len;
49
/** Expected uncompressed data */
51
/** Length of expected uncompressed data */
55
/** A DEFLATE fragment list */
56
struct deflate_test_fragments {
57
/** Fragment lengths */
61
/** Define inline data */
62
#define DATA(...) { __VA_ARGS__ }
64
/** Define a DEFLATE test */
65
#define DEFLATE( name, FORMAT, COMPRESSED, EXPECTED ) \
66
static const uint8_t name ## _compressed[] = COMPRESSED; \
67
static const uint8_t name ## _expected[] = EXPECTED; \
68
static struct deflate_test name = { \
70
.compressed = name ## _compressed, \
71
.compressed_len = sizeof ( name ## _compressed ), \
72
.expected = name ## _expected, \
73
.expected_len = sizeof ( name ## _expected ), \
76
/* Empty file, no compression */
77
DEFLATE ( empty_literal, DEFLATE_RAW,
78
DATA ( 0x01, 0x00, 0x00, 0xff, 0xff ), DATA() );
80
/* "iPXE" string, no compression */
81
DEFLATE ( literal, DEFLATE_RAW,
82
DATA ( 0x01, 0x04, 0x00, 0xfb, 0xff, 0x69, 0x50, 0x58, 0x45 ),
83
DATA ( 0x69, 0x50, 0x58, 0x45 ) );
85
/* "iPXE" string, no compression, split into two literals */
86
DEFLATE ( split_literal, DEFLATE_RAW,
87
DATA ( 0x00, 0x02, 0x00, 0xfd, 0xff, 0x69, 0x50, 0x01, 0x02, 0x00,
88
0xfd, 0xff, 0x58, 0x45 ),
89
DATA ( 0x69, 0x50, 0x58, 0x45 ) );
92
DEFLATE ( empty, DEFLATE_RAW, DATA ( 0x03, 0x00 ), DATA() );
95
DEFLATE ( hello_world, DEFLATE_RAW,
96
DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca,
98
DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
101
/* "Hello hello world" */
102
DEFLATE ( hello_hello_world, DEFLATE_RAW,
103
DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0xc8, 0x00, 0x93, 0xe5,
104
0xf9, 0x45, 0x39, 0x29, 0x00 ),
105
DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x68, 0x65, 0x6c, 0x6c,
106
0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64 ) );
108
/* "This specification defines a lossless compressed data format" */
109
DEFLATE ( rfc_sentence, DEFLATE_RAW,
110
DATA ( 0x0d, 0xc6, 0xdb, 0x09, 0x00, 0x21, 0x0c, 0x04, 0xc0, 0x56,
111
0xb6, 0x28, 0x1b, 0x08, 0x79, 0x70, 0x01, 0x35, 0xe2, 0xa6,
112
0x7f, 0xce, 0xf9, 0x9a, 0xf1, 0x25, 0xc1, 0xe3, 0x9a, 0x91,
113
0x2a, 0x9d, 0xb5, 0x61, 0x1e, 0xb9, 0x9d, 0x10, 0xcc, 0x22,
114
0xa7, 0x93, 0xd0, 0x5a, 0xe7, 0xbe, 0xb8, 0xc1, 0xa4, 0x05,
115
0x51, 0x77, 0x49, 0xff ),
116
DATA ( 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69,
117
0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64,
118
0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x61, 0x20, 0x6c,
119
0x6f, 0x73, 0x73, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x63, 0x6f,
120
0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x64,
121
0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74 ) );
123
/* "ZLIB Compressed Data Format Specification" */
124
DEFLATE ( zlib, DEFLATE_ZLIB,
125
DATA ( 0x78, 0x01, 0x8b, 0xf2, 0xf1, 0x74, 0x52, 0x70, 0xce, 0xcf,
126
0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0x51, 0x70, 0x49,
127
0x2c, 0x49, 0x54, 0x70, 0xcb, 0x2f, 0xca, 0x4d, 0x2c, 0x51,
128
0x08, 0x2e, 0x48, 0x4d, 0xce, 0x4c, 0xcb, 0x4c, 0x4e, 0x2c,
129
0xc9, 0xcc, 0xcf, 0x03, 0x00, 0x2c, 0x0e, 0x0e, 0xeb ),
130
DATA ( 0x5a, 0x4c, 0x49, 0x42, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x72,
131
0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x44, 0x61, 0x74, 0x61,
132
0x20, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x53, 0x70,
133
0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
136
/* "ZLIB Compressed Data Format Specification" fragment list */
137
static struct deflate_test_fragments zlib_fragments[] = {
139
{ { 0, 1, 5, -1UL, } },
140
{ { 0, 0, 1, 0, 0, 1, -1UL } },
141
{ { 10, 8, 4, 7, 11, -1UL } },
147
* Report DEFLATE test result
149
* @v deflate Decompressor
150
* @v test Deflate test
151
* @v frags Fragment list, or NULL
152
* @v file Test code file
153
* @v line Test code line
155
static void deflate_okx ( struct deflate *deflate,
156
struct deflate_test *test,
157
struct deflate_test_fragments *frags,
158
const char *file, unsigned int line ) {
159
uint8_t data[ test->expected_len ];
160
struct deflate_chunk in;
161
struct deflate_chunk out;
162
size_t frag_len = -1UL;
164
size_t remaining = test->compressed_len;
167
/* Initialise decompressor */
168
deflate_init ( deflate, test->format );
170
/* Initialise output chunk */
171
deflate_chunk_init ( &out, virt_to_user ( data ), 0, sizeof ( data ) );
173
/* Process input (in fragments, if applicable) */
174
for ( i = 0 ; i < ( sizeof ( frags->len ) /
175
sizeof ( frags->len[0] ) ) ; i++ ) {
177
/* Initialise input chunk */
179
frag_len = frags->len[i];
180
if ( frag_len > remaining )
181
frag_len = remaining;
182
deflate_chunk_init ( &in, virt_to_user ( test->compressed ),
183
offset, ( offset + frag_len ) );
185
/* Decompress this fragment */
186
okx ( deflate_inflate ( deflate, &in, &out ) == 0, file, line );
187
okx ( in.len == ( offset + frag_len ), file, line );
188
okx ( in.offset == in.len, file, line );
190
/* Move to next fragment */
192
remaining -= frag_len;
196
/* Check that decompression has not terminated early */
197
okx ( ! deflate_finished ( deflate ), file, line );
200
/* Check decompression has terminated as expected */
201
okx ( deflate_finished ( deflate ), file, line );
202
okx ( offset == test->compressed_len, file, line );
203
okx ( out.offset == test->expected_len, file, line );
204
okx ( memcmp ( data, test->expected, test->expected_len ) == 0,
207
#define deflate_ok( deflate, test, frags ) \
208
deflate_okx ( deflate, test, frags, __FILE__, __LINE__ )
211
* Perform DEFLATE self-test
214
static void deflate_test_exec ( void ) {
215
struct deflate *deflate;
218
/* Allocate shared structure */
219
deflate = malloc ( sizeof ( *deflate ) );
220
ok ( deflate != NULL );
222
/* Perform self-tests */
225
/* Test as a single pass */
226
deflate_ok ( deflate, &empty_literal, NULL );
227
deflate_ok ( deflate, &literal, NULL );
228
deflate_ok ( deflate, &split_literal, NULL );
229
deflate_ok ( deflate, &empty, NULL );
230
deflate_ok ( deflate, &hello_world, NULL );
231
deflate_ok ( deflate, &hello_hello_world, NULL );
232
deflate_ok ( deflate, &rfc_sentence, NULL );
233
deflate_ok ( deflate, &zlib, NULL );
235
/* Test fragmentation */
236
for ( i = 0 ; i < ( sizeof ( zlib_fragments ) /
237
sizeof ( zlib_fragments[0] ) ) ; i++ ) {
238
deflate_ok ( deflate, &zlib, &zlib_fragments[i] );
242
/* Free shared structure */
246
/** DEFLATE self-test */
247
struct self_test deflate_test __self_test = {
249
.exec = deflate_test_exec,