1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2#include <assert.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#ifndef WIN32
7#include <sys/time.h>
8#endif
9
10#include "lsquic.h"
11#include "lsquic_types.h"
12#include "lsquic_parse.h"
13
14
15//static const struct parse_funcs *const pf = select_pf_by_ver(LSQVER_043); // will not work on MSVC
16#define pf ((const struct parse_funcs *const)select_pf_by_ver(LSQVER_043))
17
18struct float_test {
19    uint64_t    long_time;
20    uint8_t     float_time[2];
21};
22
23static const struct float_test to_float_tests[] = {
24    /* Small numbers represent themselves. */
25    { 0, { 0x00, 0x00, }, },
26    { 1, { 0x00, 0x01, }, },
27    { 2, { 0x00, 0x02, }, },
28    { 3, { 0x00, 0x03, }, },
29    { 4, { 0x00, 0x04, }, },
30    { 5, { 0x00, 0x05, }, },
31    { 6, { 0x00, 0x06, }, },
32    { 7, { 0x00, 0x07, }, },
33    { 15, { 0x00, 0x0F, }, },
34    { 31, { 0x00, 0x1F, }, },
35    { 42, { 0x00, 0x2A, }, },
36    { 123, { 0x00, 0x7B, }, },
37    { 1234, { 0x04, 0xD2, }, },
38    /*  Check transition through 2^11. */
39    { 2046, { 0x07, 0xFE, }, },
40    { 2047, { 0x07, 0xFF, }, },
41    { 2048, { 0x08, 0x00, }, },
42    { 2049, { 0x08, 0x01, }, },
43    /*  Running out of mantissa at 2^12. */
44    { 4094, { 0x0F, 0xFE, }, },
45    { 4095, { 0x0F, 0xFF, }, },
46    { 4096, { 0x10, 0x00, }, },
47    { 4097, { 0x10, 0x00, }, },
48    { 4098, { 0x10, 0x01, }, },
49    { 4099, { 0x10, 0x01, }, },
50    { 4100, { 0x10, 0x02, }, },
51    { 4101, { 0x10, 0x02, }, },
52    /*  Check transition through 2^13. */
53    { 8190, { 0x17, 0xFF, }, },
54    { 8191, { 0x17, 0xFF, }, },
55    { 8192, { 0x18, 0x00, }, },
56    { 8193, { 0x18, 0x00, }, },
57    { 8194, { 0x18, 0x00, }, },
58    { 8195, { 0x18, 0x00, }, },
59    { 8196, { 0x18, 0x01, }, },
60    { 8197, { 0x18, 0x01, }, },
61    /*  Half-way through the exponents. */
62    { 0x7FF8000, { 0x87, 0xFF, }, },
63    { 0x7FFFFFF, { 0x87, 0xFF, }, },
64    { 0x8000000, { 0x88, 0x00, }, },
65    { 0xFFF0000, { 0x8F, 0xFF, }, },
66    { 0xFFFFFFF, { 0x8F, 0xFF, }, },
67    { 0x10000000, { 0x90, 0x00, }, },
68    /*  Transition into the largest exponent. */
69    { 0x1FFFFFFFFFE, { 0xF7, 0xFF, }, },
70    { 0x1FFFFFFFFFF, { 0xF7, 0xFF, }, },
71    { 0x20000000000, { 0xF8, 0x00, }, },
72    { 0x20000000001, { 0xF8, 0x00, }, },
73    { 0x2003FFFFFFE, { 0xF8, 0x00, }, },
74    { 0x2003FFFFFFF, { 0xF8, 0x00, }, },
75    { 0x20040000000, { 0xF8, 0x01, }, },
76    { 0x20040000001, { 0xF8, 0x01, }, },
77    /*  Transition into the max value and clamping. */
78    { 0x3FF80000000, { 0xFF, 0xFE, }, },
79    { 0x3FFBFFFFFFF, { 0xFF, 0xFE, }, },
80    { 0x3FFC0000000, { 0xFF, 0xFF, }, },
81    { 0x3FFC0000001, { 0xFF, 0xFF, }, },
82    { 0x3FFFFFFFFFF, { 0xFF, 0xFF, }, },
83    { 0x40000000000, { 0xFF, 0xFF, }, },
84    { 0xFFFFFFFFFFFFFFFF, { 0xFF, 0xFF, }, },
85};
86
87
88static void
89run_to_float_tests (void)
90{
91    const struct float_test *test;
92    const struct float_test *const test_end =
93        &to_float_tests[ sizeof(to_float_tests) / sizeof(to_float_tests[0]) ];
94    for (test = to_float_tests; test < test_end; ++test)
95    {
96        char out[2];
97        pf->pf_write_float_time16(test->long_time, out);
98        assert(("Convertion to QUIC float format is successful",
99                                0 == memcmp(out, test->float_time, 2)));
100    }
101}
102
103
104static const struct float_test from_float_tests[] = {
105    /*  Small numbers represent themselves. */
106    { 0, { 0x00, 0x00, }, },
107    { 1, { 0x00, 0x01, }, },
108    { 2, { 0x00, 0x02, }, },
109    { 3, { 0x00, 0x03, }, },
110    { 4, { 0x00, 0x04, }, },
111    { 5, { 0x00, 0x05, }, },
112    { 6, { 0x00, 0x06, }, },
113    { 7, { 0x00, 0x07, }, },
114    { 15, { 0x00, 0x0F, }, },
115    { 31, { 0x00, 0x1F, }, },
116    { 42, { 0x00, 0x2A, }, },
117    { 123, { 0x00, 0x7B, }, },
118    { 1234, { 0x04, 0xD2, }, },
119    /*  Check transition through 2^11. */
120    { 2046, { 0x07, 0xFE, }, },
121    { 2047, { 0x07, 0xFF, }, },
122    { 2048, { 0x08, 0x00, }, },
123    { 2049, { 0x08, 0x01, }, },
124    /*  Running out of mantissa at 2^12. */
125    { 4094, { 0x0F, 0xFE, }, },
126    { 4095, { 0x0F, 0xFF, }, },
127    { 4096, { 0x10, 0x00, }, },
128    { 4098, { 0x10, 0x01, }, },
129    { 4100, { 0x10, 0x02, }, },
130    /*  Check transition through 2^13. */
131    { 8190, { 0x17, 0xFF, }, },
132    { 8192, { 0x18, 0x00, }, },
133    { 8196, { 0x18, 0x01, }, },
134    /*  Half-way through the exponents. */
135    { 0x7FF8000, { 0x87, 0xFF, }, },
136    { 0x8000000, { 0x88, 0x00, }, },
137    { 0xFFF0000, { 0x8F, 0xFF, }, },
138    { 0x10000000, { 0x90, 0x00, }, },
139    /*  Transition into the largest exponent. */
140    { 0x1FFE0000000, { 0xF7, 0xFF, }, },
141    { 0x20000000000, { 0xF8, 0x00, }, },
142    { 0x20040000000, { 0xF8, 0x01, }, },
143    /*  Transition into the max value. */
144    { 0x3FF80000000, { 0xFF, 0xFE, }, },
145    { 0x3FFC0000000, { 0xFF, 0xFF, }, },
146};
147
148
149static void
150run_from_float_tests (void)
151{
152    const struct float_test *test;
153    const struct float_test *const test_end =
154        &from_float_tests[ sizeof(from_float_tests) / sizeof(from_float_tests[0]) ];
155    for (test = from_float_tests; test < test_end; ++test)
156    {
157        uint64_t result = pf->pf_read_float_time16(test->float_time);
158        assert(("Convertion to QUIC float format is successful",
159                                                result == test->long_time));
160    }
161}
162
163
164int
165main (void)
166{
167    run_to_float_tests();
168    run_from_float_tests();
169    return 0;
170}
171