(root)/
xz-5.4.5/
tests/
test_index_hash.c
       1  ///////////////////////////////////////////////////////////////////////////////
       2  //
       3  /// \file       test_index_hash.c
       4  /// \brief      Tests src/liblzma/common/index_hash.c API functions
       5  ///
       6  /// \note       No test included for lzma_index_hash_end since it
       7  ///             would be trivial unless tested for memory leaks
       8  ///             with something like valgrind
       9  //
      10  //  Author:     Jia Tan
      11  //
      12  //  This file has been put into the public domain.
      13  //  You can do whatever you want with this file.
      14  //
      15  ///////////////////////////////////////////////////////////////////////////////
      16  
      17  #include "tests.h"
      18  
      19  // Needed for UNPADDED_SIZE_MIN and UNPADDED_SIZE_MAX macro definitions
      20  // and index_size and vli_ceil4 helper functions
      21  #include "common/index.h"
      22  
      23  
      24  static void
      25  test_lzma_index_hash_init(void)
      26  {
      27  #ifndef HAVE_DECODERS
      28  	assert_skip("Decoder support disabled");
      29  #else
      30  	// First test with NULL index_hash.
      31  	// This should create a fresh index_hash.
      32  	lzma_index_hash *index_hash = lzma_index_hash_init(NULL, NULL);
      33  	assert_true(index_hash != NULL);
      34  
      35  	// Next test with non-NULL index_hash.
      36  	lzma_index_hash *second_hash = lzma_index_hash_init(index_hash, NULL);
      37  
      38  	// It should not create a new index_hash pointer.
      39  	// Instead it must just re-init the first index_hash.
      40  	assert_true(index_hash == second_hash);
      41  
      42  	lzma_index_hash_end(index_hash, NULL);
      43  #endif
      44  }
      45  
      46  
      47  static void
      48  test_lzma_index_hash_append(void)
      49  {
      50  #ifndef HAVE_DECODERS
      51  	assert_skip("Decoder support disabled");
      52  #else
      53  	// Test all invalid parameters
      54  	assert_lzma_ret(lzma_index_hash_append(NULL, 0, 0),
      55  			LZMA_PROG_ERROR);
      56  
      57  	// Test NULL index_hash
      58  	assert_lzma_ret(lzma_index_hash_append(NULL, UNPADDED_SIZE_MIN,
      59  			LZMA_VLI_MAX), LZMA_PROG_ERROR);
      60  
      61  	// Test with invalid Unpadded Size
      62  	lzma_index_hash *index_hash = lzma_index_hash_init(NULL, NULL);
      63  	assert_true(index_hash != NULL);
      64  	assert_lzma_ret(lzma_index_hash_append(index_hash,
      65  			UNPADDED_SIZE_MIN - 1, LZMA_VLI_MAX),
      66  			LZMA_PROG_ERROR);
      67  
      68  	// Test with invalid Uncompressed Size
      69  	assert_lzma_ret(lzma_index_hash_append(index_hash,
      70  			UNPADDED_SIZE_MIN, LZMA_VLI_MAX + 1),
      71  			LZMA_PROG_ERROR);
      72  
      73  	// First append a Record describing a small Block.
      74  	// This should succeed.
      75  	assert_lzma_ret(lzma_index_hash_append(index_hash,
      76  			UNPADDED_SIZE_MIN, 1), LZMA_OK);
      77  
      78  	// Append another small Record.
      79  	assert_lzma_ret(lzma_index_hash_append(index_hash,
      80  			UNPADDED_SIZE_MIN, 1), LZMA_OK);
      81  
      82  	// Append a Record that would cause the compressed size to grow
      83  	// too big
      84  	assert_lzma_ret(lzma_index_hash_append(index_hash,
      85  			UNPADDED_SIZE_MAX, 1), LZMA_DATA_ERROR);
      86  
      87  	lzma_index_hash_end(index_hash, NULL);
      88  #endif
      89  }
      90  
      91  
      92  #if defined(HAVE_ENCODERS) && defined(HAVE_DECODERS)
      93  // Fill an index_hash with unpadded and uncompressed VLIs
      94  // by calling lzma_index_hash_append
      95  static void
      96  fill_index_hash(lzma_index_hash *index_hash, const lzma_vli *unpadded_sizes,
      97  		const lzma_vli *uncomp_sizes, uint32_t block_count)
      98  {
      99  	for (uint32_t i = 0; i < block_count; ++i)
     100  		assert_lzma_ret(lzma_index_hash_append(index_hash,
     101  			unpadded_sizes[i], uncomp_sizes[i]), LZMA_OK);
     102  }
     103  
     104  
     105  // Set the contents of buf to the expected Index based on the
     106  // .xz specification. This needs the unpadded and uncompressed VLIs
     107  // to correctly create the Index.
     108  static void
     109  generate_index(uint8_t *buf, const lzma_vli *unpadded_sizes,
     110  		const lzma_vli *uncomp_sizes, uint32_t block_count,
     111  		size_t index_max_size)
     112  {
     113  	size_t in_pos = 0;
     114  	size_t out_pos = 0;
     115  
     116  	// First set Index Indicator
     117  	buf[out_pos++] = INDEX_INDICATOR;
     118  
     119  	// Next write out Number of Records
     120  	assert_lzma_ret(lzma_vli_encode(block_count, &in_pos, buf,
     121  			&out_pos, index_max_size), LZMA_STREAM_END);
     122  
     123  	// Next write out each Record.
     124  	// A Record consists of Unpadded Size and Uncompressed Size
     125  	// written next to each other as VLIs.
     126  	for (uint32_t i = 0; i < block_count; ++i) {
     127  		in_pos = 0;
     128  		assert_lzma_ret(lzma_vli_encode(unpadded_sizes[i], &in_pos,
     129  			buf, &out_pos, index_max_size), LZMA_STREAM_END);
     130  		in_pos = 0;
     131  		assert_lzma_ret(lzma_vli_encode(uncomp_sizes[i], &in_pos,
     132  			buf, &out_pos, index_max_size), LZMA_STREAM_END);
     133  	}
     134  
     135  	// Add Index Padding
     136  	lzma_vli rounded_out_pos = vli_ceil4(out_pos);
     137  	memzero(buf + out_pos, rounded_out_pos - out_pos);
     138  	out_pos = rounded_out_pos;
     139  
     140  	// Add the CRC32
     141  	write32le(buf + out_pos, lzma_crc32(buf, out_pos, 0));
     142  	out_pos += 4;
     143  
     144  	assert_uint_eq(out_pos, index_max_size);
     145  }
     146  #endif
     147  
     148  
     149  static void
     150  test_lzma_index_hash_decode(void)
     151  {
     152  #if !defined(HAVE_ENCODERS) || !defined(HAVE_DECODERS)
     153  	assert_skip("Encoder or decoder support disabled");
     154  #else
     155  	lzma_index_hash *index_hash = lzma_index_hash_init(NULL, NULL);
     156  	assert_true(index_hash != NULL);
     157  
     158  	size_t in_pos = 0;
     159  
     160  	// Six valid values for the Unpadded Size fields in an Index
     161  	const lzma_vli unpadded_sizes[6] = {
     162  		UNPADDED_SIZE_MIN,
     163  		1000,
     164  		4000,
     165  		8000,
     166  		16000,
     167  		32000
     168  	};
     169  
     170  	// Six valid values for the Uncompressed Size fields in an Index
     171  	const lzma_vli uncomp_sizes[6] = {
     172  		1,
     173  		500,
     174  		8000,
     175  		20,
     176  		1,
     177  		500
     178  	};
     179  
     180  	// Add two Records to an index_hash
     181  	fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 2);
     182  
     183  	const lzma_vli size_two_records = lzma_index_hash_size(index_hash);
     184  	assert_uint(size_two_records, >, 0);
     185  	uint8_t *index_two_records = tuktest_malloc(size_two_records);
     186  
     187  	generate_index(index_two_records, unpadded_sizes, uncomp_sizes, 2,
     188  			size_two_records);
     189  
     190  	// First test for basic buffer size error
     191  	in_pos = size_two_records + 1;
     192  	assert_lzma_ret(lzma_index_hash_decode(index_hash,
     193  			index_two_records, &in_pos,
     194  			size_two_records), LZMA_BUF_ERROR);
     195  
     196  	// Next test for invalid Index Indicator
     197  	in_pos = 0;
     198  	index_two_records[0] ^= 1;
     199  	assert_lzma_ret(lzma_index_hash_decode(index_hash,
     200  			index_two_records, &in_pos,
     201  			size_two_records), LZMA_DATA_ERROR);
     202  	index_two_records[0] ^= 1;
     203  
     204  	// Next verify the index_hash as expected
     205  	in_pos = 0;
     206  	assert_lzma_ret(lzma_index_hash_decode(index_hash,
     207  			index_two_records, &in_pos,
     208  			size_two_records), LZMA_STREAM_END);
     209  
     210  	// Next test an index_hash with three Records
     211  	index_hash = lzma_index_hash_init(index_hash, NULL);
     212  	fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 3);
     213  
     214  	const lzma_vli size_three_records = lzma_index_hash_size(
     215  			index_hash);
     216  	assert_uint(size_three_records, >, 0);
     217  	uint8_t *index_three_records = tuktest_malloc(size_three_records);
     218  
     219  	generate_index(index_three_records, unpadded_sizes, uncomp_sizes,
     220  			3, size_three_records);
     221  
     222  	in_pos = 0;
     223  	assert_lzma_ret(lzma_index_hash_decode(index_hash,
     224  			index_three_records, &in_pos,
     225  			size_three_records), LZMA_STREAM_END);
     226  
     227  	// Next test an index_hash with five Records
     228  	index_hash = lzma_index_hash_init(index_hash, NULL);
     229  	fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 5);
     230  
     231  	const lzma_vli size_five_records = lzma_index_hash_size(
     232  			index_hash);
     233  	assert_uint(size_five_records, >, 0);
     234  	uint8_t *index_five_records = tuktest_malloc(size_five_records);
     235  
     236  	generate_index(index_five_records, unpadded_sizes, uncomp_sizes, 5,
     237  			size_five_records);
     238  
     239  	// Instead of testing all input at once, give input
     240  	// one byte at a time
     241  	in_pos = 0;
     242  	for (lzma_vli i = 0; i < size_five_records - 1; ++i) {
     243  		assert_lzma_ret(lzma_index_hash_decode(index_hash,
     244  				index_five_records, &in_pos, in_pos + 1),
     245  				LZMA_OK);
     246  	}
     247  
     248  	// Last byte should return LZMA_STREAM_END
     249  	assert_lzma_ret(lzma_index_hash_decode(index_hash,
     250  			index_five_records, &in_pos,
     251  			in_pos + 1), LZMA_STREAM_END);
     252  
     253  	// Next test if the index_hash is given an incorrect Unpadded
     254  	// Size. Should detect and report LZMA_DATA_ERROR
     255  	index_hash = lzma_index_hash_init(index_hash, NULL);
     256  	fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 5);
     257  	// The sixth Record will have an invalid Unpadded Size
     258  	assert_lzma_ret(lzma_index_hash_append(index_hash,
     259  			unpadded_sizes[5] + 1,
     260  			uncomp_sizes[5]), LZMA_OK);
     261  
     262  	const lzma_vli size_six_records = lzma_index_hash_size(
     263  			index_hash);
     264  
     265  	assert_uint(size_six_records, >, 0);
     266  	uint8_t *index_six_records = tuktest_malloc(size_six_records);
     267  
     268  	generate_index(index_six_records, unpadded_sizes, uncomp_sizes, 6,
     269  			size_six_records);
     270  	in_pos = 0;
     271  	assert_lzma_ret(lzma_index_hash_decode(index_hash,
     272  			index_six_records, &in_pos,
     273  			size_six_records), LZMA_DATA_ERROR);
     274  
     275  	// Next test if the Index is corrupt (invalid CRC32).
     276  	// Should detect and report LZMA_DATA_ERROR
     277  	index_hash = lzma_index_hash_init(index_hash, NULL);
     278  	fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 2);
     279  
     280  	index_two_records[size_two_records - 1] ^= 1;
     281  
     282  	in_pos = 0;
     283  	assert_lzma_ret(lzma_index_hash_decode(index_hash,
     284  			index_two_records, &in_pos,
     285  			size_two_records), LZMA_DATA_ERROR);
     286  
     287  	// Next test with Index and index_hash struct not matching
     288  	// a Record
     289  	index_hash = lzma_index_hash_init(index_hash, NULL);
     290  	fill_index_hash(index_hash, unpadded_sizes, uncomp_sizes, 2);
     291  	// Recalculate Index with invalid Unpadded Size
     292  	const lzma_vli unpadded_sizes_invalid[2] = {
     293  		unpadded_sizes[0],
     294  		unpadded_sizes[1] + 1
     295  	};
     296  
     297  	generate_index(index_two_records, unpadded_sizes_invalid,
     298  			uncomp_sizes, 2, size_two_records);
     299  
     300  	in_pos = 0;
     301  	assert_lzma_ret(lzma_index_hash_decode(index_hash,
     302  			index_two_records, &in_pos,
     303  			size_two_records), LZMA_DATA_ERROR);
     304  
     305  	lzma_index_hash_end(index_hash, NULL);
     306  #endif
     307  }
     308  
     309  
     310  static void
     311  test_lzma_index_hash_size(void)
     312  {
     313  #ifndef HAVE_DECODERS
     314  	assert_skip("Decoder support disabled");
     315  #else
     316  	lzma_index_hash *index_hash = lzma_index_hash_init(NULL, NULL);
     317  	assert_true(index_hash != NULL);
     318  
     319  	// First test empty index_hash
     320  	// Expected size should be:
     321  	// Index Indicator - 1 byte
     322  	// Number of Records - 1 byte
     323  	// List of Records - 0 bytes
     324  	// Index Padding - 2 bytes
     325  	// CRC32 - 4 bytes
     326  	// Total - 8 bytes
     327  	assert_uint_eq(lzma_index_hash_size(index_hash), 8);
     328  
     329  	// Append a Record describing a small Block to the index_hash
     330  	assert_lzma_ret(lzma_index_hash_append(index_hash,
     331  			UNPADDED_SIZE_MIN, 1), LZMA_OK);
     332  
     333  	// Expected size should be:
     334  	// Index Indicator - 1 byte
     335  	// Number of Records - 1 byte
     336  	// List of Records - 2 bytes
     337  	// Index Padding - 0 bytes
     338  	// CRC32 - 4 bytes
     339  	// Total - 8 bytes
     340  	lzma_vli expected_size = 8;
     341  	assert_uint_eq(lzma_index_hash_size(index_hash), expected_size);
     342  
     343  	// Append additional small Record
     344  	assert_lzma_ret(lzma_index_hash_append(index_hash,
     345  			UNPADDED_SIZE_MIN, 1), LZMA_OK);
     346  
     347  	// Expected size should be:
     348  	// Index Indicator - 1 byte
     349  	// Number of Records - 1 byte
     350  	// List of Records - 4 bytes
     351  	// Index Padding - 2 bytes
     352  	// CRC32 - 4 bytes
     353  	// Total - 12 bytes
     354  	expected_size = 12;
     355  	assert_uint_eq(lzma_index_hash_size(index_hash), expected_size);
     356  
     357  	// Append a larger Record to the index_hash (3 bytes for each VLI)
     358  	const lzma_vli three_byte_vli = 0x10000;
     359  	assert_lzma_ret(lzma_index_hash_append(index_hash,
     360  			three_byte_vli, three_byte_vli), LZMA_OK);
     361  
     362  	// Expected size should be:
     363  	// Index Indicator - 1 byte
     364  	// Number of Records - 1 byte
     365  	// List of Records - 10 bytes
     366  	// Index Padding - 0 bytes
     367  	// CRC32 - 4 bytes
     368  	// Total - 16 bytes
     369  	expected_size = 16;
     370  	assert_uint_eq(lzma_index_hash_size(index_hash), expected_size);
     371  
     372  	lzma_index_hash_end(index_hash, NULL);
     373  #endif
     374  }
     375  
     376  
     377  extern int
     378  main(int argc, char **argv)
     379  {
     380  	tuktest_start(argc, argv);
     381  	tuktest_run(test_lzma_index_hash_init);
     382  	tuktest_run(test_lzma_index_hash_append);
     383  	tuktest_run(test_lzma_index_hash_decode);
     384  	tuktest_run(test_lzma_index_hash_size);
     385  	return tuktest_end();
     386  }