|  | @@ -0,0 +1,239 @@
 | 
		
	
		
			
			|  | 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 | +
 | 
		
	
		
			
			|  | 20 | +FILE_LICENCE ( GPL2_OR_LATER );
 | 
		
	
		
			
			|  | 21 | +
 | 
		
	
		
			
			|  | 22 | +/** @file
 | 
		
	
		
			
			|  | 23 | + *
 | 
		
	
		
			
			|  | 24 | + * DEFLATE tests
 | 
		
	
		
			
			|  | 25 | + *
 | 
		
	
		
			
			|  | 26 | + */
 | 
		
	
		
			
			|  | 27 | +
 | 
		
	
		
			
			|  | 28 | +/* Forcibly enable assertions */
 | 
		
	
		
			
			|  | 29 | +#undef NDEBUG
 | 
		
	
		
			
			|  | 30 | +
 | 
		
	
		
			
			|  | 31 | +#include <stdint.h>
 | 
		
	
		
			
			|  | 32 | +#include <stdlib.h>
 | 
		
	
		
			
			|  | 33 | +#include <string.h>
 | 
		
	
		
			
			|  | 34 | +#include <ipxe/deflate.h>
 | 
		
	
		
			
			|  | 35 | +#include <ipxe/test.h>
 | 
		
	
		
			
			|  | 36 | +
 | 
		
	
		
			
			|  | 37 | +/** A DEFLATE test */
 | 
		
	
		
			
			|  | 38 | +struct deflate_test {
 | 
		
	
		
			
			|  | 39 | +	/** Compression format */
 | 
		
	
		
			
			|  | 40 | +	enum deflate_format format;
 | 
		
	
		
			
			|  | 41 | +	/** Compressed data */
 | 
		
	
		
			
			|  | 42 | +	const void *compressed;
 | 
		
	
		
			
			|  | 43 | +	/** Length of compressed data */
 | 
		
	
		
			
			|  | 44 | +	size_t compressed_len;
 | 
		
	
		
			
			|  | 45 | +	/** Expected uncompressed data */
 | 
		
	
		
			
			|  | 46 | +	const void *expected;
 | 
		
	
		
			
			|  | 47 | +	/** Length of expected uncompressed data */
 | 
		
	
		
			
			|  | 48 | +	size_t expected_len;
 | 
		
	
		
			
			|  | 49 | +};
 | 
		
	
		
			
			|  | 50 | +
 | 
		
	
		
			
			|  | 51 | +/** A DEFLATE fragment list */
 | 
		
	
		
			
			|  | 52 | +struct deflate_test_fragments {
 | 
		
	
		
			
			|  | 53 | +	/** Fragment lengths */
 | 
		
	
		
			
			|  | 54 | +	size_t len[8];
 | 
		
	
		
			
			|  | 55 | +};
 | 
		
	
		
			
			|  | 56 | +
 | 
		
	
		
			
			|  | 57 | +/** Define inline data */
 | 
		
	
		
			
			|  | 58 | +#define DATA(...) { __VA_ARGS__ }
 | 
		
	
		
			
			|  | 59 | +
 | 
		
	
		
			
			|  | 60 | +/** Define a DEFLATE test */
 | 
		
	
		
			
			|  | 61 | +#define DEFLATE( name, FORMAT, COMPRESSED, EXPECTED )			\
 | 
		
	
		
			
			|  | 62 | +	static const uint8_t name ## _compressed[] = COMPRESSED;	\
 | 
		
	
		
			
			|  | 63 | +	static const uint8_t name ## _expected[] = EXPECTED;		\
 | 
		
	
		
			
			|  | 64 | +	static struct deflate_test name = {				\
 | 
		
	
		
			
			|  | 65 | +		.format = FORMAT,					\
 | 
		
	
		
			
			|  | 66 | +		.compressed = name ## _compressed,			\
 | 
		
	
		
			
			|  | 67 | +		.compressed_len = sizeof ( name ## _compressed ),	\
 | 
		
	
		
			
			|  | 68 | +		.expected = name ## _expected,				\
 | 
		
	
		
			
			|  | 69 | +		.expected_len = sizeof ( name ## _expected ),		\
 | 
		
	
		
			
			|  | 70 | +	};
 | 
		
	
		
			
			|  | 71 | +
 | 
		
	
		
			
			|  | 72 | +/* Empty file, no compression */
 | 
		
	
		
			
			|  | 73 | +DEFLATE ( empty_literal, DEFLATE_RAW,
 | 
		
	
		
			
			|  | 74 | +	  DATA ( 0x01, 0x00, 0x00, 0xff, 0xff ), DATA() );
 | 
		
	
		
			
			|  | 75 | +
 | 
		
	
		
			
			|  | 76 | +/* "iPXE" string, no compression */
 | 
		
	
		
			
			|  | 77 | +DEFLATE ( literal, DEFLATE_RAW,
 | 
		
	
		
			
			|  | 78 | +	  DATA ( 0x01, 0x04, 0x00, 0xfb, 0xff, 0x69, 0x50, 0x58, 0x45 ),
 | 
		
	
		
			
			|  | 79 | +	  DATA ( 0x69, 0x50, 0x58, 0x45 ) );
 | 
		
	
		
			
			|  | 80 | +
 | 
		
	
		
			
			|  | 81 | +/* Empty file */
 | 
		
	
		
			
			|  | 82 | +DEFLATE ( empty, DEFLATE_RAW, DATA ( 0x03, 0x00 ), DATA() );
 | 
		
	
		
			
			|  | 83 | +
 | 
		
	
		
			
			|  | 84 | +/* "Hello world" */
 | 
		
	
		
			
			|  | 85 | +DEFLATE ( hello_world, DEFLATE_RAW,
 | 
		
	
		
			
			|  | 86 | +	  DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca,
 | 
		
	
		
			
			|  | 87 | +		 0x49, 0x01, 0x00 ),
 | 
		
	
		
			
			|  | 88 | +	  DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
 | 
		
	
		
			
			|  | 89 | +		 0x64 ) );
 | 
		
	
		
			
			|  | 90 | +
 | 
		
	
		
			
			|  | 91 | +/* "Hello hello world" */
 | 
		
	
		
			
			|  | 92 | +DEFLATE ( hello_hello_world, DEFLATE_RAW,
 | 
		
	
		
			
			|  | 93 | +	  DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0xc8, 0x00, 0x93, 0xe5,
 | 
		
	
		
			
			|  | 94 | +		 0xf9, 0x45, 0x39, 0x29, 0x00 ),
 | 
		
	
		
			
			|  | 95 | +	  DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x68, 0x65, 0x6c, 0x6c,
 | 
		
	
		
			
			|  | 96 | +		 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64 ) );
 | 
		
	
		
			
			|  | 97 | +
 | 
		
	
		
			
			|  | 98 | +/* "This specification defines a lossless compressed data format" */
 | 
		
	
		
			
			|  | 99 | +DEFLATE ( rfc_sentence, DEFLATE_RAW,
 | 
		
	
		
			
			|  | 100 | +	  DATA ( 0x0d, 0xc6, 0xdb, 0x09, 0x00, 0x21, 0x0c, 0x04, 0xc0, 0x56,
 | 
		
	
		
			
			|  | 101 | +		 0xb6, 0x28, 0x1b, 0x08, 0x79, 0x70, 0x01, 0x35, 0xe2, 0xa6,
 | 
		
	
		
			
			|  | 102 | +		 0x7f, 0xce, 0xf9, 0x9a, 0xf1, 0x25, 0xc1, 0xe3, 0x9a, 0x91,
 | 
		
	
		
			
			|  | 103 | +		 0x2a, 0x9d, 0xb5, 0x61, 0x1e, 0xb9, 0x9d, 0x10, 0xcc, 0x22,
 | 
		
	
		
			
			|  | 104 | +		 0xa7, 0x93, 0xd0, 0x5a, 0xe7, 0xbe, 0xb8, 0xc1, 0xa4, 0x05,
 | 
		
	
		
			
			|  | 105 | +		 0x51, 0x77, 0x49, 0xff ),
 | 
		
	
		
			
			|  | 106 | +	  DATA ( 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69,
 | 
		
	
		
			
			|  | 107 | +		 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64,
 | 
		
	
		
			
			|  | 108 | +		 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x61, 0x20, 0x6c,
 | 
		
	
		
			
			|  | 109 | +		 0x6f, 0x73, 0x73, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x63, 0x6f,
 | 
		
	
		
			
			|  | 110 | +		 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x64,
 | 
		
	
		
			
			|  | 111 | +		 0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74 ) );
 | 
		
	
		
			
			|  | 112 | +
 | 
		
	
		
			
			|  | 113 | +/* "ZLIB Compressed Data Format Specification" */
 | 
		
	
		
			
			|  | 114 | +DEFLATE ( zlib, DEFLATE_ZLIB,
 | 
		
	
		
			
			|  | 115 | +	  DATA ( 0x78, 0x01, 0x8b, 0xf2, 0xf1, 0x74, 0x52, 0x70, 0xce, 0xcf,
 | 
		
	
		
			
			|  | 116 | +		 0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0x51, 0x70, 0x49,
 | 
		
	
		
			
			|  | 117 | +		 0x2c, 0x49, 0x54, 0x70, 0xcb, 0x2f, 0xca, 0x4d, 0x2c, 0x51,
 | 
		
	
		
			
			|  | 118 | +		 0x08, 0x2e, 0x48, 0x4d, 0xce, 0x4c, 0xcb, 0x4c, 0x4e, 0x2c,
 | 
		
	
		
			
			|  | 119 | +		 0xc9, 0xcc, 0xcf, 0x03, 0x00, 0x2c, 0x0e, 0x0e, 0xeb ),
 | 
		
	
		
			
			|  | 120 | +	  DATA ( 0x5a, 0x4c, 0x49, 0x42, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x72,
 | 
		
	
		
			
			|  | 121 | +		 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x44, 0x61, 0x74, 0x61,
 | 
		
	
		
			
			|  | 122 | +		 0x20, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x53, 0x70,
 | 
		
	
		
			
			|  | 123 | +		 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
 | 
		
	
		
			
			|  | 124 | +		 0x6e ) );
 | 
		
	
		
			
			|  | 125 | +
 | 
		
	
		
			
			|  | 126 | +/* "ZLIB Compressed Data Format Specification" fragment list */
 | 
		
	
		
			
			|  | 127 | +static struct deflate_test_fragments zlib_fragments[] = {
 | 
		
	
		
			
			|  | 128 | +	{ { -1UL, } },
 | 
		
	
		
			
			|  | 129 | +	{ { 0, 1, 5, -1UL, } },
 | 
		
	
		
			
			|  | 130 | +	{ { 0, 0, 1, 0, 0, 1, -1UL } },
 | 
		
	
		
			
			|  | 131 | +	{ { 10, 8, 4, 7, 11, -1UL } },
 | 
		
	
		
			
			|  | 132 | +	{ { 45, -1UL } },
 | 
		
	
		
			
			|  | 133 | +	{ { 48, -1UL } },
 | 
		
	
		
			
			|  | 134 | +};
 | 
		
	
		
			
			|  | 135 | +
 | 
		
	
		
			
			|  | 136 | +/**
 | 
		
	
		
			
			|  | 137 | + * Report DEFLATE test result
 | 
		
	
		
			
			|  | 138 | + *
 | 
		
	
		
			
			|  | 139 | + * @v deflate		Decompressor
 | 
		
	
		
			
			|  | 140 | + * @v test		Deflate test
 | 
		
	
		
			
			|  | 141 | + * @v frags		Fragment list, or NULL
 | 
		
	
		
			
			|  | 142 | + * @v file		Test code file
 | 
		
	
		
			
			|  | 143 | + * @v line		Test code line
 | 
		
	
		
			
			|  | 144 | + */
 | 
		
	
		
			
			|  | 145 | +static void deflate_okx ( struct deflate *deflate,
 | 
		
	
		
			
			|  | 146 | +			  struct deflate_test *test,
 | 
		
	
		
			
			|  | 147 | +			  struct deflate_test_fragments *frags,
 | 
		
	
		
			
			|  | 148 | +			  const char *file, unsigned int line ) {
 | 
		
	
		
			
			|  | 149 | +	uint8_t data[ test->expected_len ];
 | 
		
	
		
			
			|  | 150 | +	struct deflate_chunk in;
 | 
		
	
		
			
			|  | 151 | +	struct deflate_chunk out;
 | 
		
	
		
			
			|  | 152 | +	size_t frag_len = -1UL;
 | 
		
	
		
			
			|  | 153 | +	size_t offset = 0;
 | 
		
	
		
			
			|  | 154 | +	size_t remaining = test->compressed_len;
 | 
		
	
		
			
			|  | 155 | +	unsigned int i;
 | 
		
	
		
			
			|  | 156 | +
 | 
		
	
		
			
			|  | 157 | +	/* Initialise decompressor */
 | 
		
	
		
			
			|  | 158 | +	deflate_init ( deflate, test->format );
 | 
		
	
		
			
			|  | 159 | +
 | 
		
	
		
			
			|  | 160 | +	/* Initialise output chunk */
 | 
		
	
		
			
			|  | 161 | +	deflate_chunk_init ( &out, virt_to_user ( data ), 0, sizeof ( data ) );
 | 
		
	
		
			
			|  | 162 | +
 | 
		
	
		
			
			|  | 163 | +	/* Process input (in fragments, if applicable) */
 | 
		
	
		
			
			|  | 164 | +	for ( i = 0 ; i < ( sizeof ( frags->len ) /
 | 
		
	
		
			
			|  | 165 | +			    sizeof ( frags->len[0] ) ) ; i++ ) {
 | 
		
	
		
			
			|  | 166 | +
 | 
		
	
		
			
			|  | 167 | +		/* Initialise input chunk */
 | 
		
	
		
			
			|  | 168 | +		if ( frags )
 | 
		
	
		
			
			|  | 169 | +			frag_len = frags->len[i];
 | 
		
	
		
			
			|  | 170 | +		if ( frag_len > remaining )
 | 
		
	
		
			
			|  | 171 | +			frag_len = remaining;
 | 
		
	
		
			
			|  | 172 | +		deflate_chunk_init ( &in, virt_to_user ( test->compressed ),
 | 
		
	
		
			
			|  | 173 | +				     offset, ( offset + frag_len ) );
 | 
		
	
		
			
			|  | 174 | +
 | 
		
	
		
			
			|  | 175 | +		/* Decompress this fragment */
 | 
		
	
		
			
			|  | 176 | +		okx ( deflate_inflate ( deflate, &in, &out ) == 0, file, line );
 | 
		
	
		
			
			|  | 177 | +		okx ( in.len == ( offset + frag_len ), file, line );
 | 
		
	
		
			
			|  | 178 | +		okx ( in.offset == in.len, file, line );
 | 
		
	
		
			
			|  | 179 | +
 | 
		
	
		
			
			|  | 180 | +		/* Move to next fragment */
 | 
		
	
		
			
			|  | 181 | +		offset = in.offset;
 | 
		
	
		
			
			|  | 182 | +		remaining -= frag_len;
 | 
		
	
		
			
			|  | 183 | +		if ( ! remaining )
 | 
		
	
		
			
			|  | 184 | +			break;
 | 
		
	
		
			
			|  | 185 | +
 | 
		
	
		
			
			|  | 186 | +		/* Check that decompression has not terminated early */
 | 
		
	
		
			
			|  | 187 | +		okx ( ! deflate_finished ( deflate ), file, line );
 | 
		
	
		
			
			|  | 188 | +	}
 | 
		
	
		
			
			|  | 189 | +
 | 
		
	
		
			
			|  | 190 | +	/* Check decompression has terminated as expected */
 | 
		
	
		
			
			|  | 191 | +	okx ( deflate_finished ( deflate ), file, line );
 | 
		
	
		
			
			|  | 192 | +	okx ( offset == test->compressed_len, file, line );
 | 
		
	
		
			
			|  | 193 | +	okx ( out.offset == test->expected_len, file, line );
 | 
		
	
		
			
			|  | 194 | +	okx ( memcmp ( data, test->expected, test->expected_len ) == 0,
 | 
		
	
		
			
			|  | 195 | +	     file, line );
 | 
		
	
		
			
			|  | 196 | +}
 | 
		
	
		
			
			|  | 197 | +#define deflate_ok( deflate, test, frags ) \
 | 
		
	
		
			
			|  | 198 | +	deflate_okx ( deflate, test, frags, __FILE__, __LINE__ )
 | 
		
	
		
			
			|  | 199 | +
 | 
		
	
		
			
			|  | 200 | +/**
 | 
		
	
		
			
			|  | 201 | + * Perform DEFLATE self-test
 | 
		
	
		
			
			|  | 202 | + *
 | 
		
	
		
			
			|  | 203 | + */
 | 
		
	
		
			
			|  | 204 | +static void deflate_test_exec ( void ) {
 | 
		
	
		
			
			|  | 205 | +	struct deflate *deflate;
 | 
		
	
		
			
			|  | 206 | +	unsigned int i;
 | 
		
	
		
			
			|  | 207 | +
 | 
		
	
		
			
			|  | 208 | +	/* Allocate shared structure */
 | 
		
	
		
			
			|  | 209 | +	deflate = malloc ( sizeof ( *deflate ) );
 | 
		
	
		
			
			|  | 210 | +	ok ( deflate != NULL );
 | 
		
	
		
			
			|  | 211 | +
 | 
		
	
		
			
			|  | 212 | +	/* Perform self-tests */
 | 
		
	
		
			
			|  | 213 | +	if ( deflate ) {
 | 
		
	
		
			
			|  | 214 | +
 | 
		
	
		
			
			|  | 215 | +		/* Test as a single pass */
 | 
		
	
		
			
			|  | 216 | +		deflate_ok ( deflate, &empty_literal, NULL );
 | 
		
	
		
			
			|  | 217 | +		deflate_ok ( deflate, &literal, NULL );
 | 
		
	
		
			
			|  | 218 | +		deflate_ok ( deflate, &empty, NULL );
 | 
		
	
		
			
			|  | 219 | +		deflate_ok ( deflate, &hello_world, NULL );
 | 
		
	
		
			
			|  | 220 | +		deflate_ok ( deflate, &hello_hello_world, NULL );
 | 
		
	
		
			
			|  | 221 | +		deflate_ok ( deflate, &rfc_sentence, NULL );
 | 
		
	
		
			
			|  | 222 | +		deflate_ok ( deflate, &zlib, NULL );
 | 
		
	
		
			
			|  | 223 | +
 | 
		
	
		
			
			|  | 224 | +		/* Test fragmentation */
 | 
		
	
		
			
			|  | 225 | +		for ( i = 0 ; i < ( sizeof ( zlib_fragments ) /
 | 
		
	
		
			
			|  | 226 | +				    sizeof ( zlib_fragments[0] ) ) ; i++ ) {
 | 
		
	
		
			
			|  | 227 | +			deflate_ok ( deflate, &zlib, &zlib_fragments[i] );
 | 
		
	
		
			
			|  | 228 | +		}
 | 
		
	
		
			
			|  | 229 | +	}
 | 
		
	
		
			
			|  | 230 | +
 | 
		
	
		
			
			|  | 231 | +	/* Free shared structure */
 | 
		
	
		
			
			|  | 232 | +	free ( deflate );
 | 
		
	
		
			
			|  | 233 | +}
 | 
		
	
		
			
			|  | 234 | +
 | 
		
	
		
			
			|  | 235 | +/** DEFLATE self-test */
 | 
		
	
		
			
			|  | 236 | +struct self_test deflate_test __self_test = {
 | 
		
	
		
			
			|  | 237 | +	.name = "deflate",
 | 
		
	
		
			
			|  | 238 | +	.exec = deflate_test_exec,
 | 
		
	
		
			
			|  | 239 | +};
 |