aboutsummaryrefslogblamecommitdiff
path: root/tests/test_block_header.c
blob: a8ce09b69bf45b806501171d6c8d3deb8128bbe8 (plain) (tree)





















                                                                               
                                               


                                          
                                              

                                             


          

                                             
         

                                                          

                                             
         

  
 
                                              
         

                                      
            
                                      

                                
                                      
                                





                                                          


  

















                                                          
         
  

 

           
 
                                                                         
 

                                                                
                                                           
 




                                                                    
 



                                                              
 


                                                                     
 

                                                           






                                             
                                         

                                                            
                                
          
 
                                                                          
 

                                                                          
 

                                                                          
 

                                                                  
 

                                                                             
 
                                                                     
                                                                          
 

                                                                          
 


                                                                  
 

                                                                          



           
           

                                             
                                          

                                                            
                                        
          
 

                                                                  
 



                                                                  
 




                                                                      



           
           

                                             



                                                            
          
 


                                                                         
 



                                                                
 



















                                                                           
 






                                                                           



   
          





                    


                 
///////////////////////////////////////////////////////////////////////////////
//
/// \file       test_block_header.c
/// \brief      Tests Block Header coders
//
//  Copyright (C) 2007 Lasse Collin
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
///////////////////////////////////////////////////////////////////////////////

#include "tests.h"


static uint8_t buf[LZMA_BLOCK_HEADER_SIZE_MAX];
static lzma_options_block known_options;
static lzma_options_block decoded_options;

static lzma_options_filter filters_none[1] = {
	{
		.id = LZMA_VLI_VALUE_UNKNOWN,
	},
};


static lzma_options_filter filters_one[2] = {
	{
		.id = LZMA_FILTER_LZMA,
		.options = (void *)(&lzma_preset_lzma[0]),
	}, {
		.id = LZMA_VLI_VALUE_UNKNOWN,
	}
};


static lzma_options_filter filters_four[5] = {
	{
		.id = LZMA_FILTER_X86,
		.options = NULL,
	}, {
		.id = LZMA_FILTER_X86,
		.options = NULL,
	}, {
		.id = LZMA_FILTER_X86,
		.options = NULL,
	}, {
		.id = LZMA_FILTER_LZMA,
		.options = (void *)(&lzma_preset_lzma[0]),
	}, {
		.id = LZMA_VLI_VALUE_UNKNOWN,
	}
};


static lzma_options_filter filters_five[6] = {
	{
		.id = LZMA_FILTER_X86,
		.options = NULL,
	}, {
		.id = LZMA_FILTER_X86,
		.options = NULL,
	}, {
		.id = LZMA_FILTER_X86,
		.options = NULL,
	}, {
		.id = LZMA_FILTER_X86,
		.options = NULL,
	}, {
		.id = LZMA_FILTER_LZMA,
		.options = (void *)(&lzma_preset_lzma[0]),
	}, {
		.id = LZMA_VLI_VALUE_UNKNOWN,
	}
};


static void
code(void)
{
	expect(lzma_block_header_encode(&known_options, buf) == LZMA_OK);

	lzma_options_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
	memcrap(filters, sizeof(filters));
	memcrap(&decoded_options, sizeof(decoded_options));

	decoded_options.header_size = known_options.header_size;
	decoded_options.check = known_options.check;
	decoded_options.filters = filters;
	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
			== LZMA_OK);

	expect(known_options.compressed_size
			== decoded_options.compressed_size);
	expect(known_options.uncompressed_size
			== decoded_options.uncompressed_size);

	for (size_t i = 0; known_options.filters[i].id
			!= LZMA_VLI_VALUE_UNKNOWN; ++i)
		expect(known_options.filters[i].id == filters[i].id);

	for (size_t i = 0; i < LZMA_BLOCK_FILTERS_MAX; ++i)
		free(decoded_options.filters[i].options);
}


static void
test1(void)
{
	known_options = (lzma_options_block){
		.check = LZMA_CHECK_NONE,
		.compressed_size = LZMA_VLI_VALUE_UNKNOWN,
		.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
		.filters = NULL,
	};

	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);

	known_options.filters = filters_none;
	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);

	known_options.filters = filters_five;
	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);

	known_options.filters = filters_one;
	expect(lzma_block_header_size(&known_options) == LZMA_OK);

	known_options.check = 999; // Some invalid value, which gets ignored.
	expect(lzma_block_header_size(&known_options) == LZMA_OK);

	known_options.compressed_size = 5; // Not a multiple of four.
	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);

	known_options.compressed_size = 0; // Cannot be zero.
	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);

	known_options.compressed_size = LZMA_VLI_VALUE_UNKNOWN;
	known_options.uncompressed_size = 0;
	expect(lzma_block_header_size(&known_options) == LZMA_OK);

	known_options.uncompressed_size = LZMA_VLI_VALUE_MAX + 1;
	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
}


static void
test2(void)
{
	known_options = (lzma_options_block){
		.check = LZMA_CHECK_CRC32,
		.compressed_size = LZMA_VLI_VALUE_UNKNOWN,
		.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
		.filters = filters_four,
	};

	expect(lzma_block_header_size(&known_options) == LZMA_OK);
	code();

	known_options.compressed_size = 123456;
	known_options.uncompressed_size = 234567;
	expect(lzma_block_header_size(&known_options) == LZMA_OK);
	code();

	// We can make the sizes smaller while keeping the header size
	// the same.
	known_options.compressed_size = 12;
	known_options.uncompressed_size = 23;
	code();
}


static void
test3(void)
{
	known_options = (lzma_options_block){
		.check = LZMA_CHECK_CRC32,
		.compressed_size = LZMA_VLI_VALUE_UNKNOWN,
		.uncompressed_size = LZMA_VLI_VALUE_UNKNOWN,
		.filters = filters_one,
	};

	expect(lzma_block_header_size(&known_options) == LZMA_OK);
	known_options.header_size += 4;
	expect(lzma_block_header_encode(&known_options, buf) == LZMA_OK);

	lzma_options_filter filters[LZMA_BLOCK_FILTERS_MAX + 1];
	decoded_options.header_size = known_options.header_size;
	decoded_options.check = known_options.check;
	decoded_options.filters = filters;

	// Wrong size
	++buf[0];
	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
			== LZMA_PROG_ERROR);
	--buf[0];

	// Wrong CRC32
	buf[known_options.header_size - 1] ^= 1;
	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
			== LZMA_DATA_ERROR);
	buf[known_options.header_size - 1] ^= 1;

	// Unsupported filter
	// NOTE: This may need updating when new IDs become supported.
	buf[2] ^= 0x1F;
	integer_write_32(buf + known_options.header_size - 4,
			lzma_crc32(buf, known_options.header_size - 4, 0));
	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
			== LZMA_HEADER_ERROR);
	buf[2] ^= 0x1F;

	// Non-nul Padding
	buf[known_options.header_size - 4 - 1] ^= 1;
	integer_write_32(buf + known_options.header_size - 4,
			lzma_crc32(buf, known_options.header_size - 4, 0));
	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
			== LZMA_HEADER_ERROR);
	buf[known_options.header_size - 4 - 1] ^= 1;
}


int
main(void)
{
	lzma_init();

	test1();
	test2();
	test3();

	return 0;
}