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 
24 FILE_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 */
42 struct 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 */
52  size_t expected_len;
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 */
77 DEFLATE ( empty_literal, DEFLATE_RAW,
78  DATA ( 0x01, 0x00, 0x00, 0xff, 0xff ), DATA() );
79 
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 ) );
84 
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 ) );
90 
91 /* Empty file */
92 DEFLATE ( empty, DEFLATE_RAW, DATA ( 0x03, 0x00 ), DATA() );
93 
94 /* "Hello world" */
95 DEFLATE ( 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" */
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 ) );
107 
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 ) );
122 
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,
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  */
155 static 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  */
216 static 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 };
Self-test infrastructure.
const char * name
Test set name.
Definition: test.h:17
A self-test set.
Definition: test.h:15
__be32 out[4]
Definition: CIB_PRM.h:36
#define DEFLATE(name, FORMAT, COMPRESSED, EXPECTED)
Define a DEFLATE test.
Definition: deflate_test.c:65
struct velocity_frag frags[7]
Definition: velocity.h:14
A chunk of data.
Definition: deflate.h:245
void deflate_init(struct deflate *deflate, enum deflate_format format)
Initialise decompressor.
Definition: deflate.c:991
#define okx(success, file, line)
Report test result.
Definition: test.h:44
static int deflate_finished(struct deflate *deflate)
Check if decompression has finished.
Definition: deflate.h:277
ZLIB header and footer.
Definition: deflate.h:20
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
deflate_format
Compression formats.
Definition: deflate.h:16
unsigned char uint8_t
Definition: stdint.h:10
int deflate_inflate(struct deflate *deflate, const void *data, size_t len, struct deflate_chunk *out)
Inflate compressed data.
Definition: deflate.c:483
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:620
const void * expected
Expected uncompressed data.
Definition: deflate_test.c:50
#define DATA(...)
Define inline data.
Definition: deflate_test.c:62
const uint8_t * in
Current input data pointer.
Definition: deflate.h:166
#define deflate_ok(deflate, test, frags)
Definition: deflate_test.c:209
const void * compressed
Compressed data.
Definition: deflate_test.c:46
Raw DEFLATE data (no header or footer)
Definition: deflate.h:18
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.
Definition: deflate_test.c:155
const uint8_t * end
End of input data pointer.
Definition: deflate.h:168
enum deflate_format format
Compression format.
Definition: deflate_test.c:44
uint8_t data[48]
Additional event data.
Definition: ena.h:22
size_t len[8]
Fragment lengths.
Definition: deflate_test.c:58
A DEFLATE fragment list.
Definition: deflate_test.c:56
DEFLATE decompression algorithm.
static struct deflate_test_fragments zlib_fragments[]
Definition: deflate_test.c:137
A DEFLATE test.
Definition: deflate_test.c:42
static void deflate_test_exec(void)
Perform DEFLATE self-test.
Definition: deflate_test.c:216
struct self_test deflate_test __self_test
DEFLATE self-test.
Definition: deflate_test.c:249
#define ok(success)
Definition: test.h:46
size_t expected_len
Length of expected uncompressed data.
Definition: deflate_test.c:52
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
size_t compressed_len
Length of compressed data.
Definition: deflate_test.c:48
String functions.
static int test
Definition: epic100.c:73
Decompressor.
Definition: deflate.h:155