iPXE
deflate_test.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 /** @file
00027  *
00028  * DEFLATE tests
00029  *
00030  */
00031 
00032 /* Forcibly enable assertions */
00033 #undef NDEBUG
00034 
00035 #include <stdint.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <ipxe/deflate.h>
00039 #include <ipxe/test.h>
00040 
00041 /** A DEFLATE test */
00042 struct deflate_test {
00043         /** Compression format */
00044         enum deflate_format format;
00045         /** Compressed data */
00046         const void *compressed;
00047         /** Length of compressed data */
00048         size_t compressed_len;
00049         /** Expected uncompressed data */
00050         const void *expected;
00051         /** Length of expected uncompressed data */
00052         size_t expected_len;
00053 };
00054 
00055 /** A DEFLATE fragment list */
00056 struct deflate_test_fragments {
00057         /** Fragment lengths */
00058         size_t len[8];
00059 };
00060 
00061 /** Define inline data */
00062 #define DATA(...) { __VA_ARGS__ }
00063 
00064 /** Define a DEFLATE test */
00065 #define DEFLATE( name, FORMAT, COMPRESSED, EXPECTED )                   \
00066         static const uint8_t name ## _compressed[] = COMPRESSED;        \
00067         static const uint8_t name ## _expected[] = EXPECTED;            \
00068         static struct deflate_test name = {                             \
00069                 .format = FORMAT,                                       \
00070                 .compressed = name ## _compressed,                      \
00071                 .compressed_len = sizeof ( name ## _compressed ),       \
00072                 .expected = name ## _expected,                          \
00073                 .expected_len = sizeof ( name ## _expected ),           \
00074         };
00075 
00076 /* Empty file, no compression */
00077 DEFLATE ( empty_literal, DEFLATE_RAW,
00078           DATA ( 0x01, 0x00, 0x00, 0xff, 0xff ), DATA() );
00079 
00080 /* "iPXE" string, no compression */
00081 DEFLATE ( literal, DEFLATE_RAW,
00082           DATA ( 0x01, 0x04, 0x00, 0xfb, 0xff, 0x69, 0x50, 0x58, 0x45 ),
00083           DATA ( 0x69, 0x50, 0x58, 0x45 ) );
00084 
00085 /* "iPXE" string, no compression, split into two literals */
00086 DEFLATE ( split_literal, DEFLATE_RAW,
00087           DATA ( 0x00, 0x02, 0x00, 0xfd, 0xff, 0x69, 0x50, 0x01, 0x02, 0x00,
00088                  0xfd, 0xff, 0x58, 0x45 ),
00089           DATA ( 0x69, 0x50, 0x58, 0x45 ) );
00090 
00091 /* Empty file */
00092 DEFLATE ( empty, DEFLATE_RAW, DATA ( 0x03, 0x00 ), DATA() );
00093 
00094 /* "Hello world" */
00095 DEFLATE ( hello_world, DEFLATE_RAW,
00096           DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0x28, 0xcf, 0x2f, 0xca,
00097                  0x49, 0x01, 0x00 ),
00098           DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c,
00099                  0x64 ) );
00100 
00101 /* "Hello hello world" */
00102 DEFLATE ( hello_hello_world, DEFLATE_RAW,
00103           DATA ( 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0xc8, 0x00, 0x93, 0xe5,
00104                  0xf9, 0x45, 0x39, 0x29, 0x00 ),
00105           DATA ( 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x68, 0x65, 0x6c, 0x6c,
00106                  0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64 ) );
00107 
00108 /* "This specification defines a lossless compressed data format" */
00109 DEFLATE ( rfc_sentence, DEFLATE_RAW,
00110           DATA ( 0x0d, 0xc6, 0xdb, 0x09, 0x00, 0x21, 0x0c, 0x04, 0xc0, 0x56,
00111                  0xb6, 0x28, 0x1b, 0x08, 0x79, 0x70, 0x01, 0x35, 0xe2, 0xa6,
00112                  0x7f, 0xce, 0xf9, 0x9a, 0xf1, 0x25, 0xc1, 0xe3, 0x9a, 0x91,
00113                  0x2a, 0x9d, 0xb5, 0x61, 0x1e, 0xb9, 0x9d, 0x10, 0xcc, 0x22,
00114                  0xa7, 0x93, 0xd0, 0x5a, 0xe7, 0xbe, 0xb8, 0xc1, 0xa4, 0x05,
00115                  0x51, 0x77, 0x49, 0xff ),
00116           DATA ( 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69,
00117                  0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64,
00118                  0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x61, 0x20, 0x6c,
00119                  0x6f, 0x73, 0x73, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x63, 0x6f,
00120                  0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x64,
00121                  0x61, 0x74, 0x61, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74 ) );
00122 
00123 /* "ZLIB Compressed Data Format Specification" */
00124 DEFLATE ( zlib, DEFLATE_ZLIB,
00125           DATA ( 0x78, 0x01, 0x8b, 0xf2, 0xf1, 0x74, 0x52, 0x70, 0xce, 0xcf,
00126                  0x2d, 0x28, 0x4a, 0x2d, 0x2e, 0x4e, 0x4d, 0x51, 0x70, 0x49,
00127                  0x2c, 0x49, 0x54, 0x70, 0xcb, 0x2f, 0xca, 0x4d, 0x2c, 0x51,
00128                  0x08, 0x2e, 0x48, 0x4d, 0xce, 0x4c, 0xcb, 0x4c, 0x4e, 0x2c,
00129                  0xc9, 0xcc, 0xcf, 0x03, 0x00, 0x2c, 0x0e, 0x0e, 0xeb ),
00130           DATA ( 0x5a, 0x4c, 0x49, 0x42, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x72,
00131                  0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x44, 0x61, 0x74, 0x61,
00132                  0x20, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x53, 0x70,
00133                  0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
00134                  0x6e ) );
00135 
00136 /* "ZLIB Compressed Data Format Specification" fragment list */
00137 static struct deflate_test_fragments zlib_fragments[] = {
00138         { { -1UL, } },
00139         { { 0, 1, 5, -1UL, } },
00140         { { 0, 0, 1, 0, 0, 1, -1UL } },
00141         { { 10, 8, 4, 7, 11, -1UL } },
00142         { { 45, -1UL } },
00143         { { 48, -1UL } },
00144 };
00145 
00146 /**
00147  * Report DEFLATE test result
00148  *
00149  * @v deflate           Decompressor
00150  * @v test              Deflate test
00151  * @v frags             Fragment list, or NULL
00152  * @v file              Test code file
00153  * @v line              Test code line
00154  */
00155 static void deflate_okx ( struct deflate *deflate,
00156                           struct deflate_test *test,
00157                           struct deflate_test_fragments *frags,
00158                           const char *file, unsigned int line ) {
00159         uint8_t data[ test->expected_len ];
00160         struct deflate_chunk in;
00161         struct deflate_chunk out;
00162         size_t frag_len = -1UL;
00163         size_t offset = 0;
00164         size_t remaining = test->compressed_len;
00165         unsigned int i;
00166 
00167         /* Initialise decompressor */
00168         deflate_init ( deflate, test->format );
00169 
00170         /* Initialise output chunk */
00171         deflate_chunk_init ( &out, virt_to_user ( data ), 0, sizeof ( data ) );
00172 
00173         /* Process input (in fragments, if applicable) */
00174         for ( i = 0 ; i < ( sizeof ( frags->len ) /
00175                             sizeof ( frags->len[0] ) ) ; i++ ) {
00176 
00177                 /* Initialise input chunk */
00178                 if ( frags )
00179                         frag_len = frags->len[i];
00180                 if ( frag_len > remaining )
00181                         frag_len = remaining;
00182                 deflate_chunk_init ( &in, virt_to_user ( test->compressed ),
00183                                      offset, ( offset + frag_len ) );
00184 
00185                 /* Decompress this fragment */
00186                 okx ( deflate_inflate ( deflate, &in, &out ) == 0, file, line );
00187                 okx ( in.len == ( offset + frag_len ), file, line );
00188                 okx ( in.offset == in.len, file, line );
00189 
00190                 /* Move to next fragment */
00191                 offset = in.offset;
00192                 remaining -= frag_len;
00193                 if ( ! remaining )
00194                         break;
00195 
00196                 /* Check that decompression has not terminated early */
00197                 okx ( ! deflate_finished ( deflate ), file, line );
00198         }
00199 
00200         /* Check decompression has terminated as expected */
00201         okx ( deflate_finished ( deflate ), file, line );
00202         okx ( offset == test->compressed_len, file, line );
00203         okx ( out.offset == test->expected_len, file, line );
00204         okx ( memcmp ( data, test->expected, test->expected_len ) == 0,
00205              file, line );
00206 }
00207 #define deflate_ok( deflate, test, frags ) \
00208         deflate_okx ( deflate, test, frags, __FILE__, __LINE__ )
00209 
00210 /**
00211  * Perform DEFLATE self-test
00212  *
00213  */
00214 static void deflate_test_exec ( void ) {
00215         struct deflate *deflate;
00216         unsigned int i;
00217 
00218         /* Allocate shared structure */
00219         deflate = malloc ( sizeof ( *deflate ) );
00220         ok ( deflate != NULL );
00221 
00222         /* Perform self-tests */
00223         if ( deflate ) {
00224 
00225                 /* Test as a single pass */
00226                 deflate_ok ( deflate, &empty_literal, NULL );
00227                 deflate_ok ( deflate, &literal, NULL );
00228                 deflate_ok ( deflate, &split_literal, NULL );
00229                 deflate_ok ( deflate, &empty, NULL );
00230                 deflate_ok ( deflate, &hello_world, NULL );
00231                 deflate_ok ( deflate, &hello_hello_world, NULL );
00232                 deflate_ok ( deflate, &rfc_sentence, NULL );
00233                 deflate_ok ( deflate, &zlib, NULL );
00234 
00235                 /* Test fragmentation */
00236                 for ( i = 0 ; i < ( sizeof ( zlib_fragments ) /
00237                                     sizeof ( zlib_fragments[0] ) ) ; i++ ) {
00238                         deflate_ok ( deflate, &zlib, &zlib_fragments[i] );
00239                 }
00240         }
00241 
00242         /* Free shared structure */
00243         free ( deflate );
00244 }
00245 
00246 /** DEFLATE self-test */
00247 struct self_test deflate_test __self_test = {
00248         .name = "deflate",
00249         .exec = deflate_test_exec,
00250 };