TestBitStream.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * Copyright (c) 2023, Tim Schumacher <timschumi@gmx.de>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/BitStream.h>
  7. #include <AK/MemoryStream.h>
  8. #include <LibTest/TestCase.h>
  9. using namespace Test::Randomized;
  10. // Note: This does not do any checks on the internal representation, it just ensures that the behavior of the input and output streams match.
  11. TEST_CASE(little_endian_bit_stream_input_output_match)
  12. {
  13. auto memory_stream = make<AllocatingMemoryStream>();
  14. // Note: The bit stream only ever reads from/writes to the underlying stream in one byte chunks,
  15. // so testing with sizes that will not trigger a write will yield unexpected results.
  16. LittleEndianOutputBitStream bit_write_stream { MaybeOwned<Stream>(*memory_stream) };
  17. LittleEndianInputBitStream bit_read_stream { MaybeOwned<Stream>(*memory_stream) };
  18. // Test two mirrored chunks of a fully mirrored pattern to check that we are not dropping bits.
  19. {
  20. MUST(bit_write_stream.write_bits(0b1111u, 4));
  21. MUST(bit_write_stream.write_bits(0b1111u, 4));
  22. MUST(bit_write_stream.flush_buffer_to_stream());
  23. auto result = MUST(bit_read_stream.read_bits(4));
  24. EXPECT_EQ(0b1111u, result);
  25. result = MUST(bit_read_stream.read_bits(4));
  26. EXPECT_EQ(0b1111u, result);
  27. }
  28. {
  29. MUST(bit_write_stream.write_bits(0b0000u, 4));
  30. MUST(bit_write_stream.write_bits(0b0000u, 4));
  31. MUST(bit_write_stream.flush_buffer_to_stream());
  32. auto result = MUST(bit_read_stream.read_bits(4));
  33. EXPECT_EQ(0b0000u, result);
  34. result = MUST(bit_read_stream.read_bits(4));
  35. EXPECT_EQ(0b0000u, result);
  36. }
  37. // Test two mirrored chunks of a non-mirrored pattern to check that we are writing bits within a pattern in the correct order.
  38. {
  39. MUST(bit_write_stream.write_bits(0b1000u, 4));
  40. MUST(bit_write_stream.write_bits(0b1000u, 4));
  41. MUST(bit_write_stream.flush_buffer_to_stream());
  42. auto result = MUST(bit_read_stream.read_bits(4));
  43. EXPECT_EQ(0b1000u, result);
  44. result = MUST(bit_read_stream.read_bits(4));
  45. EXPECT_EQ(0b1000u, result);
  46. }
  47. // Test two different chunks to check that we are not confusing their order.
  48. {
  49. MUST(bit_write_stream.write_bits(0b1000u, 4));
  50. MUST(bit_write_stream.write_bits(0b0100u, 4));
  51. MUST(bit_write_stream.flush_buffer_to_stream());
  52. auto result = MUST(bit_read_stream.read_bits(4));
  53. EXPECT_EQ(0b1000u, result);
  54. result = MUST(bit_read_stream.read_bits(4));
  55. EXPECT_EQ(0b0100u, result);
  56. }
  57. // Test a pattern that spans multiple bytes.
  58. {
  59. MUST(bit_write_stream.write_bits(0b1101001000100001u, 16));
  60. MUST(bit_write_stream.flush_buffer_to_stream());
  61. auto result = MUST(bit_read_stream.read_bits(16));
  62. EXPECT_EQ(0b1101001000100001u, result);
  63. }
  64. }
  65. // Note: This does not do any checks on the internal representation, it just ensures that the behavior of the input and output streams match.
  66. TEST_CASE(big_endian_bit_stream_input_output_match)
  67. {
  68. auto memory_stream = make<AllocatingMemoryStream>();
  69. // Note: The bit stream only ever reads from/writes to the underlying stream in one byte chunks,
  70. // so testing with sizes that will not trigger a write will yield unexpected results.
  71. BigEndianOutputBitStream bit_write_stream { MaybeOwned<Stream>(*memory_stream) };
  72. BigEndianInputBitStream bit_read_stream { MaybeOwned<Stream>(*memory_stream) };
  73. // Test two mirrored chunks of a fully mirrored pattern to check that we are not dropping bits.
  74. {
  75. MUST(bit_write_stream.write_bits(0b1111u, 4));
  76. MUST(bit_write_stream.write_bits(0b1111u, 4));
  77. auto result = MUST(bit_read_stream.read_bits(4));
  78. EXPECT_EQ(0b1111u, result);
  79. result = MUST(bit_read_stream.read_bits(4));
  80. EXPECT_EQ(0b1111u, result);
  81. }
  82. {
  83. MUST(bit_write_stream.write_bits(0b0000u, 4));
  84. MUST(bit_write_stream.write_bits(0b0000u, 4));
  85. auto result = MUST(bit_read_stream.read_bits(4));
  86. EXPECT_EQ(0b0000u, result);
  87. result = MUST(bit_read_stream.read_bits(4));
  88. EXPECT_EQ(0b0000u, result);
  89. }
  90. // Test two mirrored chunks of a non-mirrored pattern to check that we are writing bits within a pattern in the correct order.
  91. {
  92. MUST(bit_write_stream.write_bits(0b1000u, 4));
  93. MUST(bit_write_stream.write_bits(0b1000u, 4));
  94. auto result = MUST(bit_read_stream.read_bits(4));
  95. EXPECT_EQ(0b1000u, result);
  96. result = MUST(bit_read_stream.read_bits(4));
  97. EXPECT_EQ(0b1000u, result);
  98. }
  99. // Test two different chunks to check that we are not confusing their order.
  100. {
  101. MUST(bit_write_stream.write_bits(0b1000u, 4));
  102. MUST(bit_write_stream.write_bits(0b0100u, 4));
  103. auto result = MUST(bit_read_stream.read_bits(4));
  104. EXPECT_EQ(0b1000u, result);
  105. result = MUST(bit_read_stream.read_bits(4));
  106. EXPECT_EQ(0b0100u, result);
  107. }
  108. // Test a pattern that spans multiple bytes.
  109. {
  110. MUST(bit_write_stream.write_bits(0b1101001000100001u, 16));
  111. auto result = MUST(bit_read_stream.read_bits(16));
  112. EXPECT_EQ(0b1101001000100001u, result);
  113. }
  114. }
  115. TEST_CASE(bit_reads_beyond_stream_limits)
  116. {
  117. Array<u8, 1> const test_data { 0xFF };
  118. {
  119. auto memory_stream = make<FixedMemoryStream>(test_data);
  120. auto bit_stream = make<LittleEndianInputBitStream>(move(memory_stream), LittleEndianInputBitStream::UnsatisfiableReadBehavior::Reject);
  121. {
  122. auto result = TRY_OR_FAIL(bit_stream->read_bits<u8>(6));
  123. EXPECT_EQ(result, 0b111111);
  124. }
  125. {
  126. auto result = bit_stream->read_bits<u8>(6);
  127. EXPECT(result.is_error());
  128. }
  129. {
  130. auto result = bit_stream->read_bits<u8>(6);
  131. EXPECT(result.is_error());
  132. }
  133. }
  134. {
  135. // LittleEndianInputBitStream allows reading null bits beyond the original data
  136. // for compatibility purposes if enabled.
  137. auto memory_stream = make<FixedMemoryStream>(test_data);
  138. auto bit_stream = make<LittleEndianInputBitStream>(move(memory_stream), LittleEndianInputBitStream::UnsatisfiableReadBehavior::FillWithZero);
  139. {
  140. auto result = TRY_OR_FAIL(bit_stream->read_bits<u8>(6));
  141. EXPECT_EQ(result, 0b111111);
  142. }
  143. {
  144. auto result = TRY_OR_FAIL(bit_stream->read_bits<u8>(6));
  145. EXPECT_EQ(result, 0b000011);
  146. }
  147. {
  148. auto result = TRY_OR_FAIL(bit_stream->read_bits<u8>(6));
  149. EXPECT_EQ(result, 0b000000);
  150. }
  151. }
  152. {
  153. auto memory_stream = make<FixedMemoryStream>(test_data);
  154. auto bit_stream = make<BigEndianInputBitStream>(move(memory_stream));
  155. {
  156. auto result = TRY_OR_FAIL(bit_stream->read_bits<u8>(6));
  157. EXPECT_EQ(result, 0b111111);
  158. }
  159. {
  160. auto result = bit_stream->read_bits<u8>(6);
  161. EXPECT(result.is_error());
  162. }
  163. {
  164. auto result = bit_stream->read_bits<u8>(6);
  165. EXPECT(result.is_error());
  166. }
  167. }
  168. }
  169. RANDOMIZED_TEST_CASE(roundtrip_u8_little_endian)
  170. {
  171. GEN(n, Gen::unsigned_int(NumericLimits<u8>::max()));
  172. auto memory_stream = make<AllocatingMemoryStream>();
  173. LittleEndianOutputBitStream sut_write { MaybeOwned<Stream>(*memory_stream) };
  174. LittleEndianInputBitStream sut_read { MaybeOwned<Stream>(*memory_stream) };
  175. MUST(sut_write.write_bits(n, 8));
  176. MUST(sut_write.flush_buffer_to_stream());
  177. auto result = MUST(sut_read.read_bits<u64>(8));
  178. EXPECT_EQ(result, n);
  179. }
  180. RANDOMIZED_TEST_CASE(roundtrip_u16_little_endian)
  181. {
  182. GEN(n, Gen::unsigned_int(NumericLimits<u16>::max()));
  183. auto memory_stream = make<AllocatingMemoryStream>();
  184. LittleEndianOutputBitStream sut_write { MaybeOwned<Stream>(*memory_stream) };
  185. LittleEndianInputBitStream sut_read { MaybeOwned<Stream>(*memory_stream) };
  186. MUST(sut_write.write_bits(n, 16));
  187. MUST(sut_write.flush_buffer_to_stream());
  188. auto result = MUST(sut_read.read_bits<u64>(16));
  189. EXPECT_EQ(result, n);
  190. }
  191. RANDOMIZED_TEST_CASE(roundtrip_u32_little_endian)
  192. {
  193. GEN(n, Gen::unsigned_int(NumericLimits<u32>::max()));
  194. auto memory_stream = make<AllocatingMemoryStream>();
  195. LittleEndianOutputBitStream sut_write { MaybeOwned<Stream>(*memory_stream) };
  196. LittleEndianInputBitStream sut_read { MaybeOwned<Stream>(*memory_stream) };
  197. MUST(sut_write.write_bits(n, 32));
  198. MUST(sut_write.flush_buffer_to_stream());
  199. auto result = MUST(sut_read.read_bits<u64>(32));
  200. EXPECT_EQ(result, n);
  201. }
  202. RANDOMIZED_TEST_CASE(roundtrip_u8_big_endian)
  203. {
  204. GEN(n, Gen::unsigned_int(NumericLimits<u8>::max()));
  205. auto memory_stream = make<AllocatingMemoryStream>();
  206. BigEndianOutputBitStream sut_write { MaybeOwned<Stream>(*memory_stream) };
  207. BigEndianInputBitStream sut_read { MaybeOwned<Stream>(*memory_stream) };
  208. MUST(sut_write.write_bits(n, 8));
  209. auto result = MUST(sut_read.read_bits<u64>(8));
  210. EXPECT_EQ(result, n);
  211. }
  212. RANDOMIZED_TEST_CASE(roundtrip_u16_big_endian)
  213. {
  214. GEN(n, Gen::unsigned_int(NumericLimits<u16>::max()));
  215. auto memory_stream = make<AllocatingMemoryStream>();
  216. BigEndianOutputBitStream sut_write { MaybeOwned<Stream>(*memory_stream) };
  217. BigEndianInputBitStream sut_read { MaybeOwned<Stream>(*memory_stream) };
  218. MUST(sut_write.write_bits(n, 16));
  219. auto result = MUST(sut_read.read_bits<u64>(16));
  220. EXPECT_EQ(result, n);
  221. }
  222. RANDOMIZED_TEST_CASE(roundtrip_u32_big_endian)
  223. {
  224. GEN(n, Gen::unsigned_int(NumericLimits<u32>::max()));
  225. auto memory_stream = make<AllocatingMemoryStream>();
  226. BigEndianOutputBitStream sut_write { MaybeOwned<Stream>(*memory_stream) };
  227. BigEndianInputBitStream sut_read { MaybeOwned<Stream>(*memory_stream) };
  228. MUST(sut_write.write_bits(n, 32));
  229. auto result = MUST(sut_read.read_bits<u64>(32));
  230. EXPECT_EQ(result, n);
  231. }