tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

bit_reader_test.cc (8309B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include <jxl/memory_manager.h>
      7 
      8 #include <cstddef>
      9 #include <cstdint>
     10 #include <utility>
     11 #include <vector>
     12 
     13 #include "lib/jxl/base/common.h"
     14 #include "lib/jxl/base/data_parallel.h"
     15 #include "lib/jxl/base/random.h"
     16 #include "lib/jxl/base/span.h"
     17 #include "lib/jxl/base/status.h"
     18 #include "lib/jxl/dec_bit_reader.h"
     19 #include "lib/jxl/enc_aux_out.h"
     20 #include "lib/jxl/enc_bit_writer.h"
     21 #include "lib/jxl/test_memory_manager.h"
     22 #include "lib/jxl/test_utils.h"
     23 #include "lib/jxl/testing.h"
     24 
     25 namespace jxl {
     26 namespace {
     27 
     28 TEST(BitReaderTest, ExtendsWithZeroes) {
     29  for (size_t size = 4; size < 32; ++size) {
     30    std::vector<uint8_t> data(size, 0xff);
     31 
     32    for (size_t n_bytes = 0; n_bytes < size; n_bytes++) {
     33      BitReader br(Bytes(data.data(), n_bytes));
     34      // Read all the bits
     35      for (size_t i = 0; i < n_bytes * kBitsPerByte; i++) {
     36        ASSERT_EQ(br.ReadBits(1), 1u) << "n_bytes=" << n_bytes << " i=" << i;
     37      }
     38 
     39      // PEEK more than the declared size - all will be zero. Cannot consume.
     40      for (size_t i = 0; i < BitReader::kMaxBitsPerCall; i++) {
     41        ASSERT_EQ(br.PeekBits(i), 0u)
     42            << "size=" << size << "n_bytes=" << n_bytes << " i=" << i;
     43      }
     44 
     45      EXPECT_TRUE(br.Close());
     46    }
     47  }
     48 }
     49 
     50 struct Symbol {
     51  uint32_t num_bits;
     52  uint32_t value;
     53 };
     54 
     55 // Reading from output gives the same values.
     56 TEST(BitReaderTest, TestRoundTrip) {
     57  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
     58  test::ThreadPoolForTests pool(8);
     59  const auto do_test = [&memory_manager](const uint32_t task,
     60                                         size_t /* thread */) -> Status {
     61    constexpr size_t kMaxBits = 8000;
     62    BitWriter writer{memory_manager};
     63    std::vector<Symbol> symbols;
     64    symbols.reserve(1000);
     65    JXL_RETURN_IF_ERROR(
     66        writer.WithMaxBits(kMaxBits, LayerType::Header, nullptr, [&] {
     67          Rng rng(55537 + 129 * task);
     68 
     69          for (;;) {
     70            const uint32_t num_bits = rng.UniformU(1, 33);
     71            if (writer.BitsWritten() + num_bits > kMaxBits) break;
     72            const uint32_t value = rng.UniformU(0, 1ULL << num_bits);
     73            symbols.push_back({num_bits, value});
     74            writer.Write(num_bits, value);
     75          }
     76 
     77          writer.ZeroPadToByte();
     78          return true;
     79        }));
     80    BitReader reader(writer.GetSpan());
     81    for (const Symbol& s : symbols) {
     82      EXPECT_EQ(s.value, reader.ReadBits(s.num_bits));
     83    }
     84    JXL_RETURN_IF_ERROR(reader.Close());
     85    return true;
     86  };
     87  EXPECT_TRUE(RunOnPool(pool.get(), 0, 1000, ThreadPool::NoInit, do_test,
     88                        "TestTBitReaderRoundTrip"));
     89 }
     90 
     91 // SkipBits is the same as reading that many bits.
     92 TEST(BitReaderTest, TestSkip) {
     93  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
     94  test::ThreadPoolForTests pool(8);
     95  const auto do_test = [&memory_manager](const uint32_t task,
     96                                         size_t /* thread */) -> Status {
     97    constexpr size_t kSize = 100;
     98 
     99    for (size_t skip = 0; skip < 128; ++skip) {
    100      BitWriter writer{memory_manager};
    101      AuxOut aux_out;
    102      JXL_RETURN_IF_ERROR(writer.WithMaxBits(
    103          kSize * kBitsPerByte, LayerType::Header, &aux_out, [&] {
    104            // Start with "task" 1-bits.
    105            for (size_t i = 0; i < task; ++i) {
    106              writer.Write(1, 1);
    107            }
    108 
    109            // Write 0-bits that we will skip over
    110            for (size_t i = 0; i < skip; ++i) {
    111              writer.Write(1, 0);
    112            }
    113 
    114            // Write terminator bits '101'
    115            writer.Write(3, 5);
    116            EXPECT_EQ(task + skip + 3, writer.BitsWritten());
    117            writer.ZeroPadToByte();
    118            return true;
    119          }));
    120      EXPECT_LT(aux_out.layer(LayerType::Header).total_bits, kSize * 8);
    121 
    122      Bytes bytes = writer.GetSpan();
    123      BitReader reader1(bytes);
    124      BitReader reader2(bytes);
    125      // Verify initial 1-bits
    126      for (size_t i = 0; i < task; ++i) {
    127        EXPECT_EQ(1u, reader1.ReadBits(1));
    128        EXPECT_EQ(1u, reader2.ReadBits(1));
    129      }
    130 
    131      // SkipBits or manually read "skip" bits
    132      reader1.SkipBits(skip);
    133      for (size_t i = 0; i < skip; ++i) {
    134        EXPECT_EQ(0u, reader2.ReadBits(1)) << " skip=" << skip << " i=" << i;
    135      }
    136      EXPECT_EQ(reader1.TotalBitsConsumed(), reader2.TotalBitsConsumed());
    137 
    138      // Ensure both readers see the terminator bits.
    139      EXPECT_EQ(5u, reader1.ReadBits(3));
    140      EXPECT_EQ(5u, reader2.ReadBits(3));
    141 
    142      JXL_RETURN_IF_ERROR(reader1.Close());
    143      JXL_RETURN_IF_ERROR(reader2.Close());
    144    }
    145    return true;
    146  };
    147  EXPECT_TRUE(
    148      RunOnPool(pool.get(), 0, 96, ThreadPool::NoInit, do_test, "TestSkip"));
    149 }
    150 
    151 // Verifies byte order and different groupings of bits.
    152 TEST(BitReaderTest, TestOrder) {
    153  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
    154  constexpr size_t kMaxBits = 16;
    155 
    156  // u(1) - bits written into LSBs of first byte
    157  {
    158    BitWriter writer{memory_manager};
    159    ASSERT_TRUE(writer.WithMaxBits(kMaxBits, LayerType::Header, nullptr, [&] {
    160      for (size_t i = 0; i < 5; ++i) {
    161        writer.Write(1, 1);
    162      }
    163      for (size_t i = 0; i < 5; ++i) {
    164        writer.Write(1, 0);
    165      }
    166      for (size_t i = 0; i < 6; ++i) {
    167        writer.Write(1, 1);
    168      }
    169 
    170      writer.ZeroPadToByte();
    171      return true;
    172    }));
    173    BitReader reader(writer.GetSpan());
    174    EXPECT_EQ(0x1Fu, reader.ReadFixedBits<8>());
    175    EXPECT_EQ(0xFCu, reader.ReadFixedBits<8>());
    176    EXPECT_TRUE(reader.Close());
    177  }
    178 
    179  // u(8) - get bytes in the same order
    180  {
    181    BitWriter writer{memory_manager};
    182    ASSERT_TRUE(writer.WithMaxBits(kMaxBits, LayerType::Header, nullptr, [&] {
    183      writer.Write(8, 0xF8);
    184      writer.Write(8, 0x3F);
    185 
    186      writer.ZeroPadToByte();
    187      return true;
    188    }));
    189    BitReader reader(writer.GetSpan());
    190    EXPECT_EQ(0xF8u, reader.ReadFixedBits<8>());
    191    EXPECT_EQ(0x3Fu, reader.ReadFixedBits<8>());
    192    EXPECT_TRUE(reader.Close());
    193  }
    194 
    195  // u(16) - little-endian bytes
    196  {
    197    BitWriter writer{memory_manager};
    198    ASSERT_TRUE(writer.WithMaxBits(kMaxBits, LayerType::Header, nullptr, [&] {
    199      writer.Write(16, 0xF83F);
    200 
    201      writer.ZeroPadToByte();
    202      return true;
    203    }));
    204    BitReader reader(writer.GetSpan());
    205    EXPECT_EQ(0x3Fu, reader.ReadFixedBits<8>());
    206    EXPECT_EQ(0xF8u, reader.ReadFixedBits<8>());
    207    EXPECT_TRUE(reader.Close());
    208  }
    209 
    210  // Non-byte-aligned, mixed sizes
    211  {
    212    BitWriter writer{memory_manager};
    213    ASSERT_TRUE(writer.WithMaxBits(kMaxBits, LayerType::Header, nullptr, [&] {
    214      writer.Write(1, 1);
    215      writer.Write(3, 6);
    216      writer.Write(8, 0xDB);
    217      writer.Write(4, 8);
    218 
    219      writer.ZeroPadToByte();
    220      return true;
    221    }));
    222    BitReader reader(writer.GetSpan());
    223    EXPECT_EQ(0xBDu, reader.ReadFixedBits<8>());
    224    EXPECT_EQ(0x8Du, reader.ReadFixedBits<8>());
    225    EXPECT_TRUE(reader.Close());
    226  }
    227 }
    228 
    229 TEST(BitReaderTest, TotalCountersTest) {
    230  uint8_t buf[8] = {1, 2, 3, 4};
    231  BitReader reader(Bytes(buf, sizeof(buf)));
    232 
    233  EXPECT_EQ(sizeof(buf), reader.TotalBytes());
    234  EXPECT_EQ(0u, reader.TotalBitsConsumed());
    235  reader.ReadFixedBits<1>();
    236  EXPECT_EQ(1u, reader.TotalBitsConsumed());
    237 
    238  reader.ReadFixedBits<10>();
    239  EXPECT_EQ(11u, reader.TotalBitsConsumed());
    240 
    241  reader.ReadFixedBits<4>();
    242  EXPECT_EQ(15u, reader.TotalBitsConsumed());
    243 
    244  reader.ReadFixedBits<1>();
    245  EXPECT_EQ(16u, reader.TotalBitsConsumed());
    246 
    247  reader.ReadFixedBits<16>();
    248  EXPECT_EQ(32u, reader.TotalBitsConsumed());
    249 
    250  EXPECT_TRUE(reader.Close());
    251 }
    252 
    253 TEST(BitReaderTest, MoveTest) {
    254  uint8_t buf[8] = {1, 2, 3, 4};
    255  BitReader reader2;
    256  {
    257    BitReader reader1(Bytes(buf, sizeof(buf)));
    258 
    259    EXPECT_EQ(0u, reader1.TotalBitsConsumed());
    260    reader1.ReadFixedBits<16>();
    261    EXPECT_EQ(16u, reader1.TotalBitsConsumed());
    262 
    263    reader2 = std::move(reader1);
    264    // From this point reader1 is invalid, but can continue to access reader2
    265    // and we don't need to call Close() on reader1.
    266  }
    267 
    268  EXPECT_EQ(16u, reader2.TotalBitsConsumed());
    269  EXPECT_EQ(3U, reader2.ReadFixedBits<8>());
    270  EXPECT_EQ(24u, reader2.TotalBitsConsumed());
    271 
    272  EXPECT_TRUE(reader2.Close());
    273 }
    274 
    275 }  // namespace
    276 }  // namespace jxl