iPXE
deflate_test.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
3 *
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.
8 *
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.
13 *
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
17 * 02110-1301, USA.
18 *
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.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26/** @file
27 *
28 * DEFLATE tests
29 *
30 */
31
32/* Forcibly enable assertions */
33#undef NDEBUG
34
35#include <stdint.h>
36#include <stdlib.h>
37#include <string.h>
38#include <ipxe/deflate.h>
39#include <ipxe/test.h>
40
41/** A DEFLATE test */
43 /** Compression format */
45 /** Compressed data */
46 const void *compressed;
47 /** Length of compressed data */
49 /** Expected uncompressed data */
50 const void *expected;
51 /** Length of expected uncompressed data */
53};
54
55/** A DEFLATE fragment list */
57 /** Fragment lengths */
58 size_t len[8];
59};
60
61/** Define inline data */
62#define DATA(...) { __VA_ARGS__ }
63
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 = { \
69 .format = FORMAT, \
70 .compressed = name ## _compressed, \
71 .compressed_len = sizeof ( name ## _compressed ), \
72 .expected = name ## _expected, \
73 .expected_len = sizeof ( name ## _expected ), \
74 };
75
76/* Empty file, no compression */
77DEFLATE ( empty_literal, DEFLATE_RAW,
78 DATA ( 0x01, 0x00, 0x00, 0xff, 0xff ), DATA() );
79
80/* "iPXE" string, no compression */
82 DATA ( 0x01, 0x04, 0x00, 0xfb, 0xff, 0x69, 0x50, 0x58, 0x45 ),
83 DATA ( 0x69, 0x50, 0x58, 0x45 ) );
84
85/* "iPXE" string, no compression, split into two literals */
86DEFLATE ( 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 ) );
90
91/* Empty file */
92DEFLATE ( empty, DEFLATE_RAW, DATA ( 0x03, 0x00 ), DATA() );
93
94/* "Hello world" */
95DEFLATE ( hello_world, DEFLATE_RAW,
96 DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca,
97 0x49, 0x01, 0x00 ),
98 DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
99 0x64 ) );
100
101/* "Hello hello world" */
102DEFLATE ( 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 ) );
107
108/* "This specification defines a lossless compressed data format" */
109DEFLATE ( 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 ) );
122
123/* "ZLIB Compressed Data Format Specification" */
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,
134 0x6e ) );
135
136/* "ZLIB Compressed Data Format Specification" fragment list */
138 { { -1UL, } },
139 { { 0, 1, 5, -1UL, } },
140 { { 0, 0, 1, 0, 0, 1, -1UL } },
141 { { 10, 8, 4, 7, 11, -1UL } },
142 { { 45, -1UL } },
143 { { 48, -1UL } },
144};
145
146/**
147 * Report DEFLATE test result
148 *
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
154 */
155static void deflate_okx ( struct deflate *deflate,
156 struct deflate_test *test,
158 const char *file, unsigned int line ) {
159 uint8_t buf[ test->expected_len ];
160 const void *data = test->compressed;
161 size_t remaining = test->compressed_len;
162 size_t frag_len = -1UL;
163 struct deflate_chunk out;
164 unsigned int i;
165
166 /* Initialise decompressor */
167 deflate_init ( deflate, test->format );
168
169 /* Initialise output chunk */
170 deflate_chunk_init ( &out, buf, 0, sizeof ( buf ) );
171
172 /* Process input (in fragments, if applicable) */
173 for ( i = 0 ; i < ( sizeof ( frags->len ) /
174 sizeof ( frags->len[0] ) ) ; i++ ) {
175
176 /* Initialise input chunk */
177 if ( frags )
178 frag_len = frags->len[i];
179 if ( frag_len > remaining )
180 frag_len = remaining;
181
182 /* Decompress this fragment */
183 okx ( deflate_inflate ( deflate, data, frag_len,
184 &out ) == 0, file, line );
185 okx ( deflate->in == ( data + frag_len ), file, line );
186 okx ( deflate->end == ( data + frag_len ), file, line );
187
188 /* Move to next fragment */
189 data += frag_len;
190 remaining -= frag_len;
191 if ( ! remaining )
192 break;
193
194 /* Check that decompression has not terminated early */
195 okx ( ! deflate_finished ( deflate ), file, line );
196 }
197
198 /* Check decompression has terminated as expected */
199 okx ( deflate_finished ( deflate ), file, line );
200 okx ( deflate->in == ( test->compressed + test->compressed_len ),
201 file, line );
202 okx ( deflate->end == ( test->compressed + test->compressed_len ),
203 file, line );
204 okx ( out.offset == test->expected_len, file, line );
205 okx ( out.data == buf, file, line );
206 okx ( memcmp ( out.data, test->expected, test->expected_len ) == 0,
207 file, line );
208}
209#define deflate_ok( deflate, test, frags ) \
210 deflate_okx ( deflate, test, frags, __FILE__, __LINE__ )
211
212/**
213 * Perform DEFLATE self-test
214 *
215 */
216static void deflate_test_exec ( void ) {
217 struct deflate *deflate;
218 unsigned int i;
219
220 /* Allocate shared structure */
221 deflate = malloc ( sizeof ( *deflate ) );
222 ok ( deflate != NULL );
223
224 /* Perform self-tests */
225 if ( deflate ) {
226
227 /* Test as a single pass */
228 deflate_ok ( deflate, &empty_literal, NULL );
229 deflate_ok ( deflate, &literal, NULL );
230 deflate_ok ( deflate, &split_literal, NULL );
231 deflate_ok ( deflate, &empty, NULL );
232 deflate_ok ( deflate, &hello_world, NULL );
233 deflate_ok ( deflate, &hello_hello_world, NULL );
234 deflate_ok ( deflate, &rfc_sentence, NULL );
235 deflate_ok ( deflate, &zlib, NULL );
236
237 /* Test fragmentation */
238 for ( i = 0 ; i < ( sizeof ( zlib_fragments ) /
239 sizeof ( zlib_fragments[0] ) ) ; i++ ) {
240 deflate_ok ( deflate, &zlib, &zlib_fragments[i] );
241 }
242 }
243
244 /* Free shared structure */
245 free ( deflate );
246}
247
248/** DEFLATE self-test */
250 .name = "deflate",
251 .exec = deflate_test_exec,
252};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
__be32 out[4]
Definition CIB_PRM.h:8
#define DATA(...)
Define inline data.
Definition acpi_test.c:74
unsigned char uint8_t
Definition stdint.h:10
void deflate_init(struct deflate *deflate, enum deflate_format format)
Initialise decompressor.
Definition deflate.c:992
int deflate_inflate(struct deflate *deflate, const void *data, size_t len, struct deflate_chunk *out)
Inflate compressed data.
Definition deflate.c:484
DEFLATE decompression algorithm.
static int deflate_finished(struct deflate *deflate)
Check if decompression has finished.
Definition deflate.h:278
deflate_format
Compression formats.
Definition deflate.h:17
@ DEFLATE_ZLIB
ZLIB header and footer.
Definition deflate.h:21
@ DEFLATE_RAW
Raw DEFLATE data (no header or footer)
Definition deflate.h:19
#define deflate_ok(deflate, test, frags)
#define DEFLATE(name, FORMAT, COMPRESSED, EXPECTED)
Define a DEFLATE test.
static void deflate_test_exec(void)
Perform DEFLATE self-test.
#define DATA(...)
Define inline data.
static struct deflate_test_fragments zlib_fragments[]
static void deflate_okx(struct deflate *deflate, struct deflate_test *test, struct deflate_test_fragments *frags, const char *file, unsigned int line)
Report DEFLATE test result.
uint8_t data[48]
Additional event data.
Definition ena.h:11
static int test
Definition epic100.c:73
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
String functions.
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A chunk of data.
Definition deflate.h:246
A DEFLATE fragment list.
size_t len[8]
Fragment lengths.
A DEFLATE test.
const void * expected
Expected uncompressed data.
size_t expected_len
Length of expected uncompressed data.
size_t compressed_len
Length of compressed data.
const void * compressed
Compressed data.
enum deflate_format format
Compression format.
Decompressor.
Definition deflate.h:156
const uint8_t * end
End of input data pointer.
Definition deflate.h:169
const uint8_t * in
Current input data pointer.
Definition deflate.h:167
A self-test set.
Definition test.h:15
Self-test infrastructure.
#define okx(success, file, line)
Report test result.
Definition test.h:44
#define ok(success)
Definition test.h:46
#define __self_test
Declare a self-test.
Definition test.h:32
struct velocity_frag frags[7]
Definition velocity.h:3