1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
25392f7a3SLiteSpeed Tech#include <assert.h>
35392f7a3SLiteSpeed Tech#include <stddef.h>
45392f7a3SLiteSpeed Tech#include <stdint.h>
55392f7a3SLiteSpeed Tech
65392f7a3SLiteSpeed Tech#include "lsquic_varint.h"
75392f7a3SLiteSpeed Tech
8f07b3eaeSTyler Young#ifdef _MSC_VER
9f07b3eaeSTyler Young#include "vc_compat.h"
10f07b3eaeSTyler Young#endif
11f07b3eaeSTyler Young
125392f7a3SLiteSpeed Tech#define MAX_INPUT_SZ 8
135392f7a3SLiteSpeed Tech
145392f7a3SLiteSpeed Techstruct test_read_varint
155392f7a3SLiteSpeed Tech{
165392f7a3SLiteSpeed Tech    /* Input: */
175392f7a3SLiteSpeed Tech    unsigned char       input[MAX_INPUT_SZ];
185392f7a3SLiteSpeed Tech    size_t              in_sz;
195392f7a3SLiteSpeed Tech    /* Output: */
205392f7a3SLiteSpeed Tech    int                 rv;
215392f7a3SLiteSpeed Tech    uint64_t            val;
225392f7a3SLiteSpeed Tech};
235392f7a3SLiteSpeed Tech
245392f7a3SLiteSpeed Techstatic const struct test_read_varint read_tests[] =
255392f7a3SLiteSpeed Tech{
265392f7a3SLiteSpeed Tech    {
275392f7a3SLiteSpeed Tech        .input = "\x25",
285392f7a3SLiteSpeed Tech        .in_sz = 0,
295392f7a3SLiteSpeed Tech        .rv = -1,
305392f7a3SLiteSpeed Tech    },
315392f7a3SLiteSpeed Tech    {
325392f7a3SLiteSpeed Tech        .input = "\x25",
335392f7a3SLiteSpeed Tech        .in_sz = 2,
345392f7a3SLiteSpeed Tech        .rv = 1,
355392f7a3SLiteSpeed Tech        .val = 0x25,
365392f7a3SLiteSpeed Tech    },
375392f7a3SLiteSpeed Tech    {
385392f7a3SLiteSpeed Tech        .input = "\x40\x25",
395392f7a3SLiteSpeed Tech        .in_sz = 1,
405392f7a3SLiteSpeed Tech        .rv = -1,
415392f7a3SLiteSpeed Tech    },
425392f7a3SLiteSpeed Tech    {
435392f7a3SLiteSpeed Tech        .input = "\x40\x25",
445392f7a3SLiteSpeed Tech        .in_sz = 2,
455392f7a3SLiteSpeed Tech        .rv = 2,
465392f7a3SLiteSpeed Tech        .val = 0x25,
475392f7a3SLiteSpeed Tech    },
485392f7a3SLiteSpeed Tech    {
495392f7a3SLiteSpeed Tech        .input = "\x9d\x7f\x3e\x7d",
505392f7a3SLiteSpeed Tech        .in_sz = 2,
515392f7a3SLiteSpeed Tech        .rv = -1,
525392f7a3SLiteSpeed Tech    },
535392f7a3SLiteSpeed Tech    {
545392f7a3SLiteSpeed Tech        .input = "\x9d\x7f\x3e\x7d",
555392f7a3SLiteSpeed Tech        .in_sz = 4,
565392f7a3SLiteSpeed Tech        .rv = 4,
575392f7a3SLiteSpeed Tech        .val = 494878333,
585392f7a3SLiteSpeed Tech    },
595392f7a3SLiteSpeed Tech    {
605392f7a3SLiteSpeed Tech        .input = "\xc2\x19\x7c\x5e\xff\x14\xe8\x8c",
615392f7a3SLiteSpeed Tech        .in_sz = 7,
625392f7a3SLiteSpeed Tech        .rv = -1,
635392f7a3SLiteSpeed Tech    },
645392f7a3SLiteSpeed Tech    {
655392f7a3SLiteSpeed Tech        .input = "\xc2\x19\x7c\x5e\xff\x14\xe8\x8c",
665392f7a3SLiteSpeed Tech        .in_sz = 8,
675392f7a3SLiteSpeed Tech        .rv = 8,
685392f7a3SLiteSpeed Tech        .val = 151288809941952652ull,
695392f7a3SLiteSpeed Tech    },
705392f7a3SLiteSpeed Tech};
715392f7a3SLiteSpeed Tech
725392f7a3SLiteSpeed Tech
735392f7a3SLiteSpeed Techint
745392f7a3SLiteSpeed Techmain (void)
755392f7a3SLiteSpeed Tech{
765392f7a3SLiteSpeed Tech    const struct test_read_varint *test;
775392f7a3SLiteSpeed Tech    const struct test_read_varint *const end
785392f7a3SLiteSpeed Tech        = read_tests + sizeof(read_tests) / sizeof(read_tests[0]);
795392f7a3SLiteSpeed Tech    size_t input_sz, avail;
805392f7a3SLiteSpeed Tech    struct varint_read_state state;
815392f7a3SLiteSpeed Tech    const unsigned char *p, *endp;
825392f7a3SLiteSpeed Tech    int s;
835392f7a3SLiteSpeed Tech
845392f7a3SLiteSpeed Tech    for (test = read_tests; test < end; ++test)
855392f7a3SLiteSpeed Tech    {
865392f7a3SLiteSpeed Tech        uint64_t val;
875392f7a3SLiteSpeed Tech        const int rv = vint_read(test->input, test->input + test->in_sz, &val);
885392f7a3SLiteSpeed Tech        assert(rv == test->rv);
895392f7a3SLiteSpeed Tech        if (test->rv > 0)
905392f7a3SLiteSpeed Tech            assert(val == test->val);
915392f7a3SLiteSpeed Tech
925392f7a3SLiteSpeed Tech        /* Test non-blocking read */
935392f7a3SLiteSpeed Tech        for (input_sz = MAX_INPUT_SZ; input_sz > 0; --input_sz)
945392f7a3SLiteSpeed Tech        {
955392f7a3SLiteSpeed Tech            state.pos = 0;
965392f7a3SLiteSpeed Tech            p = test->input;
975392f7a3SLiteSpeed Tech            endp = p + test->in_sz;
985392f7a3SLiteSpeed Tech            while (p < endp)
995392f7a3SLiteSpeed Tech            {
1005392f7a3SLiteSpeed Tech                avail = (uintptr_t) (endp - p);
1015392f7a3SLiteSpeed Tech                if (avail > input_sz)
1025392f7a3SLiteSpeed Tech                    avail = input_sz;
1035392f7a3SLiteSpeed Tech                s = lsquic_varint_read_nb(&p, p + avail, &state);
1045392f7a3SLiteSpeed Tech                if (0 == s)
1055392f7a3SLiteSpeed Tech                {
1065392f7a3SLiteSpeed Tech                    assert(state.val == test->val);
1075392f7a3SLiteSpeed Tech                    assert(p <= endp);
1085392f7a3SLiteSpeed Tech                    break;
1095392f7a3SLiteSpeed Tech                }
1105392f7a3SLiteSpeed Tech                else if (p == endp)
1115392f7a3SLiteSpeed Tech                {
1125392f7a3SLiteSpeed Tech                    assert(test->rv == -1);
1135392f7a3SLiteSpeed Tech                    break;
1145392f7a3SLiteSpeed Tech                }
1155392f7a3SLiteSpeed Tech                else
1165392f7a3SLiteSpeed Tech                {
1175392f7a3SLiteSpeed Tech                    assert(p < endp);
1185392f7a3SLiteSpeed Tech                }
1195392f7a3SLiteSpeed Tech            }
1205392f7a3SLiteSpeed Tech        }
1215392f7a3SLiteSpeed Tech    }
1225392f7a3SLiteSpeed Tech
1235392f7a3SLiteSpeed Tech    return 0;
1245392f7a3SLiteSpeed Tech}
125