huffman_testing.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. /**
  6. * See aws/testing/compression/huffman.h for docs.
  7. */
  8. #define AWS_UNSTABLE_TESTING_API
  9. #include <aws/compression/private/huffman_testing.h>
  10. #include <aws/common/byte_buf.h>
  11. #include <aws/common/common.h>
  12. int huffman_test_transitive(
  13. struct aws_huffman_symbol_coder *coder,
  14. const char *input,
  15. size_t size,
  16. size_t encoded_size,
  17. const char **error_string) {
  18. struct aws_huffman_encoder encoder;
  19. aws_huffman_encoder_init(&encoder, coder);
  20. struct aws_huffman_decoder decoder;
  21. aws_huffman_decoder_init(&decoder, coder);
  22. const size_t intermediate_buffer_size = size * 2;
  23. AWS_VARIABLE_LENGTH_ARRAY(uint8_t, intermediate_buffer, intermediate_buffer_size);
  24. memset(intermediate_buffer, 0, intermediate_buffer_size);
  25. AWS_VARIABLE_LENGTH_ARRAY(char, output_buffer, size);
  26. memset(output_buffer, 0, size);
  27. struct aws_byte_cursor to_encode = aws_byte_cursor_from_array((uint8_t *)input, size);
  28. struct aws_byte_buf intermediate_buf = aws_byte_buf_from_empty_array(intermediate_buffer, intermediate_buffer_size);
  29. struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, size);
  30. int result = aws_huffman_encode(&encoder, &to_encode, &intermediate_buf);
  31. if (result != AWS_OP_SUCCESS) {
  32. *error_string = "aws_huffman_encode failed";
  33. return AWS_OP_ERR;
  34. }
  35. if (to_encode.len != 0) {
  36. *error_string = "not all data encoded";
  37. return AWS_OP_ERR;
  38. }
  39. if (encoded_size && intermediate_buf.len != encoded_size) {
  40. *error_string = "encoded length is incorrect";
  41. return AWS_OP_ERR;
  42. }
  43. struct aws_byte_cursor intermediate_cur = aws_byte_cursor_from_buf(&intermediate_buf);
  44. result = aws_huffman_decode(&decoder, &intermediate_cur, &output_buf);
  45. if (result != AWS_OP_SUCCESS) {
  46. *error_string = "aws_huffman_decode failed";
  47. return AWS_OP_ERR;
  48. }
  49. if (intermediate_cur.len != 0) {
  50. *error_string = "not all encoded data was decoded";
  51. return AWS_OP_ERR;
  52. }
  53. if (output_buf.len != size) {
  54. *error_string = "decode output size incorrect";
  55. return AWS_OP_ERR;
  56. }
  57. if (memcmp(input, output_buffer, size) != 0) {
  58. *error_string = "decoded data does not match input data";
  59. return AWS_OP_ERR;
  60. }
  61. return AWS_OP_SUCCESS;
  62. }
  63. int huffman_test_transitive_chunked(
  64. struct aws_huffman_symbol_coder *coder,
  65. const char *input,
  66. size_t size,
  67. size_t encoded_size,
  68. size_t output_chunk_size,
  69. const char **error_string) {
  70. struct aws_huffman_encoder encoder;
  71. aws_huffman_encoder_init(&encoder, coder);
  72. struct aws_huffman_decoder decoder;
  73. aws_huffman_decoder_init(&decoder, coder);
  74. const size_t intermediate_buffer_size = size * 2;
  75. AWS_VARIABLE_LENGTH_ARRAY(uint8_t, intermediate_buffer, intermediate_buffer_size);
  76. memset(intermediate_buffer, 0, intermediate_buffer_size);
  77. AWS_VARIABLE_LENGTH_ARRAY(char, output_buffer, size);
  78. memset(output_buffer, 0, size);
  79. struct aws_byte_cursor to_encode = aws_byte_cursor_from_array(input, size);
  80. struct aws_byte_buf intermediate_buf = aws_byte_buf_from_empty_array(intermediate_buffer, (size_t)-1);
  81. intermediate_buf.capacity = 0;
  82. struct aws_byte_buf output_buf = aws_byte_buf_from_empty_array(output_buffer, (size_t)-1);
  83. output_buf.capacity = 0;
  84. int result = AWS_OP_SUCCESS;
  85. {
  86. do {
  87. const size_t previous_intermediate_len = intermediate_buf.len;
  88. intermediate_buf.capacity += output_chunk_size;
  89. result = aws_huffman_encode(&encoder, &to_encode, &intermediate_buf);
  90. if (intermediate_buf.len == previous_intermediate_len) {
  91. *error_string = "encode didn't write any data";
  92. return AWS_OP_ERR;
  93. }
  94. if (result != AWS_OP_SUCCESS && aws_last_error() != AWS_ERROR_SHORT_BUFFER) {
  95. *error_string = "encode returned wrong error code";
  96. return AWS_OP_ERR;
  97. }
  98. } while (result != AWS_OP_SUCCESS);
  99. }
  100. if (result != AWS_OP_SUCCESS) {
  101. *error_string = "aws_huffman_encode failed";
  102. return AWS_OP_ERR;
  103. }
  104. if (intermediate_buf.len > intermediate_buffer_size) {
  105. *error_string = "too much data encoded";
  106. return AWS_OP_ERR;
  107. }
  108. if (encoded_size && intermediate_buf.len != encoded_size) {
  109. *error_string = "encoded length is incorrect";
  110. return AWS_OP_ERR;
  111. }
  112. struct aws_byte_cursor intermediate_cur = aws_byte_cursor_from_buf(&intermediate_buf);
  113. {
  114. do {
  115. const size_t previous_output_len = output_buf.len;
  116. output_buf.capacity += output_chunk_size;
  117. if (output_buf.capacity > size) {
  118. output_buf.capacity = size;
  119. }
  120. result = aws_huffman_decode(&decoder, &intermediate_cur, &output_buf);
  121. if (output_buf.len == previous_output_len) {
  122. *error_string = "decode didn't write any data";
  123. return AWS_OP_ERR;
  124. }
  125. if (result != AWS_OP_SUCCESS && aws_last_error() != AWS_ERROR_SHORT_BUFFER) {
  126. *error_string = "decode returned wrong error code";
  127. return AWS_OP_ERR;
  128. }
  129. } while (result != AWS_OP_SUCCESS);
  130. }
  131. if (result != AWS_OP_SUCCESS) {
  132. *error_string = "aws_huffman_decode failed";
  133. return AWS_OP_ERR;
  134. }
  135. if (output_buf.len != size) {
  136. *error_string = "decode output size incorrect";
  137. return AWS_OP_ERR;
  138. }
  139. if (memcmp(input, output_buffer, size) != 0) {
  140. *error_string = "decoded data does not match input data";
  141. return AWS_OP_ERR;
  142. }
  143. return AWS_OP_SUCCESS;
  144. }