| 205 | /// `expected` is the full sequence of booleans the run should decode to. |
| 206 | template <typename Decoder> |
| 207 | void CheckBitmapDecoder(const typename Decoder::RunType& run, |
| 208 | const std::vector<bool>& expected) { |
| 209 | const auto n_vals = static_cast<rle_size_t>(expected.size()); |
| 210 | |
| 211 | // remaining() reflects the run size before any value is read. |
| 212 | { |
| 213 | Decoder decoder(run); |
| 214 | EXPECT_EQ(decoder.remaining(), n_vals); |
| 215 | } |
| 216 | |
| 217 | // Empty requests are a no-op. |
| 218 | { |
| 219 | Decoder decoder(run); |
| 220 | uint8_t out = 0; |
| 221 | const auto got = decoder.GetBatch(BitmapSpanMut(&out), /*batch_size=*/0); |
| 222 | EXPECT_EQ(got, 0); |
| 223 | EXPECT_EQ(decoder.remaining(), n_vals); |
| 224 | } |
| 225 | |
| 226 | // Decode the whole run in several chunks. |
| 227 | for (const rle_size_t chunk_size : {rle_size_t{1}, rle_size_t{3}, rle_size_t{7}, |
| 228 | rle_size_t{8}, rle_size_t{9}, n_vals, n_vals + 1}) { |
| 229 | CheckDecoderValuesChunked<Decoder>(run, expected, chunk_size); |
| 230 | } |
| 231 | |
| 232 | // Decode the whole run in several chunks, after an initial Advance that shifts |
| 233 | // the run and output bit alignment. |
| 234 | for (const rle_size_t chunk_size : {rle_size_t{1}, rle_size_t{3}, rle_size_t{7}, |
| 235 | rle_size_t{8}, rle_size_t{9}, n_vals, n_vals + 1}) { |
| 236 | for (rle_size_t expected_skip = 1; expected_skip < 8 && expected_skip < n_vals; |
| 237 | ++expected_skip) { |
| 238 | // Check the decoding happens as expected |
| 239 | CheckDecoderValuesChunked<Decoder>(run, expected, chunk_size, expected_skip); |
| 240 | // Check the decoding does not write out of bounds |
| 241 | CheckDecoderClobber<Decoder>(run, expected, chunk_size, expected_skip); |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | // Get() one value at a time, then read past the end. |
| 246 | { |
| 247 | Decoder decoder(run); |
| 248 | std::vector<uint8_t> out(static_cast<size_t>(bit_util::BytesForBits(n_vals)) + 1, 0); |
| 249 | for (rle_size_t i = 0; i < n_vals; ++i) { |
| 250 | const bool ok = decoder.Get(BitmapSpanMut(out.data(), /*bit_start=*/i)); |
| 251 | EXPECT_TRUE(ok); |
| 252 | EXPECT_EQ(decoder.remaining(), n_vals - i - 1); |
| 253 | } |
| 254 | // Exhausted: nothing more can be read or advanced. |
| 255 | const bool ok = decoder.Get(BitmapSpanMut(out.data())); |
| 256 | EXPECT_FALSE(ok); |
| 257 | const auto advanced = decoder.Advance(1); |
| 258 | EXPECT_EQ(advanced, 0); |
| 259 | EXPECT_EQ(decoder.remaining(), 0); |
| 260 | CheckDecodedBits({.actual = out, .expected = expected, .count = n_vals}); |
| 261 | } |
| 262 | |
| 263 | // Advancing more than available stops at the run boundary. |
| 264 | { |
nothing calls this directly
no test coverage detected