Skip to content

Commit 9b611dd

Browse files
committed
Add parameterized unit tests for unchecked varint helpers
Extend varint test coverage for decode_varint_unchecked() and skip_varint_unchecked() using shared decoder adapters and template helpers.
1 parent b18fc8b commit 9b611dd

1 file changed

Lines changed: 144 additions & 0 deletions

File tree

test/unit/test_varint.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11

22
#include <test.hpp>
33

4+
namespace {
5+
6+
struct checked_varint_decoder {
7+
static uint64_t decode(const char** data, const char* end) {
8+
return protozero::decode_varint(data, end);
9+
}
10+
11+
static void skip(const char** data, const char* end) {
12+
protozero::skip_varint(data, end);
13+
}
14+
};
15+
16+
struct unchecked_varint_decoder {
17+
static uint64_t decode(const char** data, const char* end) {
18+
(void)end;
19+
return protozero::decode_varint_unchecked(data);
20+
}
21+
22+
static void skip(const char** data, const char* end) {
23+
(void)end;
24+
protozero::skip_varint_unchecked(data);
25+
}
26+
};
27+
28+
} // namespace
29+
430
TEST_CASE("max varint length") {
531
REQUIRE(protozero::max_varint_length == 10);
632
}
@@ -248,6 +274,124 @@ TEST_CASE("call decode_varint_unchecked with every possible value of terminal va
248274
}
249275
}
250276

277+
template <typename Decoder>
278+
void test_decode_various_lengths() {
279+
const std::vector<uint64_t> values{
280+
0,
281+
127,
282+
128,
283+
16383,
284+
16384,
285+
2097151,
286+
2097152,
287+
0xffffffffULL,
288+
0xffffffffffffffffULL,
289+
1ULL << 40U,
290+
};
291+
292+
for (const auto value : values) {
293+
std::string buffer;
294+
protozero::add_varint_to_buffer(&buffer, value);
295+
const char* b = buffer.data();
296+
const char* const end = buffer.data() + buffer.size();
297+
REQUIRE(Decoder::decode(&b, end) == value);
298+
REQUIRE(b == end);
299+
}
300+
}
301+
302+
TEST_CASE("decode_varint with varints of various lengths") {
303+
SECTION("checked") {
304+
test_decode_various_lengths<checked_varint_decoder>();
305+
}
306+
307+
SECTION("unchecked") {
308+
test_decode_various_lengths<unchecked_varint_decoder>();
309+
}
310+
}
311+
312+
template <typename Decoder>
313+
void test_skip_various_lengths() {
314+
const std::vector<uint64_t> values{
315+
0,
316+
127,
317+
128,
318+
16383,
319+
16384,
320+
2097151,
321+
2097152,
322+
0xffffffffULL,
323+
0xffffffffffffffffULL,
324+
1ULL << 40U,
325+
};
326+
327+
for (const auto value : values) {
328+
std::string buffer;
329+
protozero::add_varint_to_buffer(&buffer, value);
330+
const char* b = buffer.data();
331+
const char* const end = buffer.data() + buffer.size();
332+
Decoder::skip(&b, end);
333+
REQUIRE(b == end);
334+
}
335+
}
336+
337+
TEST_CASE("skip_varint with varints of various lengths") {
338+
SECTION("checked") {
339+
test_skip_various_lengths<checked_varint_decoder>();
340+
}
341+
342+
SECTION("unchecked") {
343+
test_skip_various_lengths<unchecked_varint_decoder>();
344+
}
345+
}
346+
347+
template <typename Decoder>
348+
void test_decode_multiple_varints_in_sequence() {
349+
std::string buffer;
350+
protozero::add_varint_to_buffer(&buffer, 5);
351+
protozero::add_varint_to_buffer(&buffer, 1);
352+
protozero::add_varint_to_buffer(&buffer, 300);
353+
354+
const char* b = buffer.data();
355+
const char* const end = buffer.data() + buffer.size();
356+
REQUIRE(Decoder::decode(&b, end) == 5);
357+
REQUIRE(Decoder::decode(&b, end) == 1);
358+
REQUIRE(Decoder::decode(&b, end) == 300);
359+
REQUIRE(b == end);
360+
}
361+
362+
TEST_CASE("decode multiple varints in sequence") {
363+
SECTION("checked") {
364+
test_decode_multiple_varints_in_sequence<checked_varint_decoder>();
365+
}
366+
367+
SECTION("unchecked") {
368+
test_decode_multiple_varints_in_sequence<unchecked_varint_decoder>();
369+
}
370+
}
371+
372+
template <typename Decoder>
373+
void test_overlong_varint_throws() {
374+
std::string buffer(10, static_cast<char>(0xffU));
375+
const char* b = buffer.data();
376+
const char* const end = buffer.data() + buffer.size();
377+
REQUIRE_THROWS_AS(Decoder::decode(&b, end), protozero::varint_too_long_exception);
378+
REQUIRE(b == buffer.data());
379+
380+
b = buffer.data();
381+
REQUIRE_THROWS_AS([&]() { Decoder::skip(&b, end); }(), protozero::varint_too_long_exception);
382+
REQUIRE(b == buffer.data());
383+
}
384+
385+
TEST_CASE("overlong varint throws varint_too_long_exception") {
386+
SECTION("checked") {
387+
test_overlong_varint_throws<checked_varint_decoder>();
388+
}
389+
390+
SECTION("unchecked") {
391+
test_overlong_varint_throws<unchecked_varint_decoder>();
392+
}
393+
}
394+
251395
TEST_CASE("check lengths of varint") {
252396
REQUIRE(protozero::length_of_varint(0) == 1);
253397
REQUIRE(protozero::length_of_varint(127) == 1);

0 commit comments

Comments
 (0)