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