]> git.sesse.net Git - fjl/blob - unstuff_test.c
863aef500c041f198d84482e81cae128a56b3b14
[fjl] / unstuff_test.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <assert.h>
4 #include <time.h>
5 #include <sys/time.h>
6
7 #include "unstuff.h"
8
9 void test_basic_unstuff(unstuff_func_t* unstuff)
10 {
11         uint8_t bytes[] = { 1, 2, 3, 4, 5, 6, 0xff, 0x00, 7, 8, 9, 0xff, 0x00, 10, 11, 12, 13, 14 };
12         uint8_t ref[] = { 1, 2, 3, 4, 5, 6, 0xff, 7, 8, 9, 0xff, 10, 11, 12, 13, 14 };
13         uint8_t dst[sizeof(bytes)];
14         int ret = (*unstuff)(dst, bytes, sizeof(bytes));
15
16         assert(ret == sizeof(ref));
17         assert(memcmp(dst, ref, ret) == 0);
18 }
19
20 // Stuff byte crossing the 16-byte boundaries the SSE4.1 function uses.
21 void test_edge_unstuff(unstuff_func_t* unstuff)
22 {
23         uint8_t bytes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0xff, 0x00, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
24         uint8_t ref[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0xff, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
25         uint8_t dst[sizeof(bytes)];
26         int ret = (*unstuff)(dst, bytes, sizeof(bytes));
27
28         assert(ret == sizeof(ref));
29         assert(memcmp(dst, ref, ret) == 0);
30 }
31
32 void test_marker(unstuff_func_t* unstuff)
33 {
34         uint8_t bytes[] = { 1, 2, 3, 4, 5, 6, 0xff, 0x01, 7, 8, 9, 0xff, 0x00, 10, 11, 12, 13, 14 };
35         uint8_t dst[sizeof(bytes)];
36         int ret = (*unstuff)(dst, bytes, sizeof(bytes));
37
38         assert(ret == -1);
39 }
40
41 void test_marker_end(unstuff_func_t* unstuff)
42 {
43         uint8_t bytes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff };
44         uint8_t dst[sizeof(bytes)];
45         int ret = (*unstuff)(dst, bytes, sizeof(bytes));
46
47         assert(ret == -1);
48 }
49
50 void gen_random_stuffed_data(uint8_t* dst, size_t len)
51 {
52         // Standard NR LCG (we avoid rand() to get consistent behavior across platforms).
53         uint32_t seed = 1234;
54         for (unsigned i = 0; i < len; ++i) {
55                 seed = seed * 1664525 + 1013904223;
56                 uint8_t byte = (uint8_t)(seed & 0xff);
57                 if (byte != 0xff) {
58                         dst[i] = byte;
59                         continue;
60                 } else if (i == len - 1) {
61                         // Don't make a partial marker.
62                         dst[i] = 0x00;
63                 } else {
64                         dst[i] = 0xff;
65                         dst[++i] = 0x00;
66                 }
67         }
68 }
69
70 double timediff(const struct timeval* a, const struct timeval* b)
71 {
72         return (double)(b->tv_sec - a->tv_sec) +
73                 (double)(b->tv_usec - a->tv_usec) * 1e-6;
74 }
75
76 void test_performance(unstuff_func_t* unstuff)
77 {
78         const size_t len = 4096;
79         const unsigned num_runs = 400000;
80
81         uint8_t src[len], dst[len];
82         gen_random_stuffed_data(src, len);
83
84         struct timeval start, now;
85         gettimeofday(&start, NULL);
86
87         for (unsigned i = 0; i < num_runs; ++i) {
88                 int ret = unstuff(dst, src, len);
89                 assert(ret != -1);
90         }
91         
92         gettimeofday(&now, NULL);
93
94         double diff = timediff(&start, &now);
95         double mb_sec = (len * num_runs) / (1048576.0 * diff);
96         printf("%u runs with %zu bytes in %.2f seconds = %.2f MB/sec\n",
97                 num_runs, len, diff, mb_sec);
98 }
99
100 void test_all_unstuff(unstuff_func_t* unstuff)
101 {
102         printf("  test_basic_unstuff()\n");
103         test_basic_unstuff(unstuff);    
104
105         printf("  test_edge_unstuff()\n");
106         test_edge_unstuff(unstuff);
107
108         printf("  test_marker()\n");
109         test_marker(unstuff);
110
111         printf("  test_marker_end()\n");
112         test_marker_end(unstuff);
113
114         printf("  performance test: ");
115         test_performance(unstuff);
116 }
117
118 int main(void)
119 {
120         printf("unstuff_reference:\n");
121         test_all_unstuff(unstuff_reference);
122         
123         printf("unstuff_fast:\n");
124         test_all_unstuff(unstuff_fast);
125
126         printf("unstuff_sse41:\n");
127         test_all_unstuff(unstuff_sse41);
128
129         printf("All tests pass.\n");
130         return 0;
131 }