Some asm() correction.
[fjl] / bytesource_test.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <assert.h>
4
5 #include "bytesource.h"
6 #include "choice.h"
7
8 struct custom_read_userdata {
9         uint8_t* bytes;
10         unsigned bytes_left;
11 };
12
13 ssize_t custom_read(void* userdata, uint8_t* buf, size_t count)
14 {
15         struct custom_read_userdata* ud = (struct custom_read_userdata*)userdata;
16         size_t num_to_read = (ud->bytes_left > count ? count : ud->bytes_left);
17         memcpy(buf, ud->bytes, num_to_read);
18         ud->bytes += num_to_read;
19         ud->bytes_left -= num_to_read;
20         return num_to_read;     
21 }
22
23 ssize_t custom_read_slow(void* userdata, uint8_t* buf, size_t count)
24 {
25         struct custom_read_userdata* ud = (struct custom_read_userdata*)userdata;
26         size_t num_to_read = ((count > 0 && ud->bytes_left > 0) ? 1 : 0);
27         memcpy(buf, ud->bytes, num_to_read);
28         ud->bytes += num_to_read;
29         ud->bytes_left -= num_to_read;
30         return num_to_read;
31 }
32
33 // Two streams, separated by a marker.
34 uint8_t stream_bytes[] = {
35         0x01, 0x02, 0x03, 0xff, 0x00, 0x04,     // some bytes
36         0xff, 0xf7,                             // a marker
37         0x05, 0x06, 0x07, 0x08, 0xff, 0x00      // more bytes
38 };
39
40 // Expected data.
41 uint8_t first_stream[] = {
42         0x01, 0x02, 0x03, 0xff, 0x04
43 };
44 uint8_t second_stream[] = {
45         0x05, 0x06, 0x07, 0x08, 0xff
46 };
47
48 // Reading with a regular source.
49 void test_basic_reading()
50 {
51         struct custom_read_userdata ud;
52         ud.bytes = stream_bytes;
53         ud.bytes_left = sizeof(stream_bytes);
54
55         struct byte_source source;
56         init_byte_source(&source, custom_read, &ud);
57
58         // Read the first stream.
59         uint8_t buf[4096];
60         ssize_t ret;
61         ret = byte_source_input_func(&source, buf, 4096);
62         assert(ret == sizeof(first_stream));
63         assert(memcmp(buf, first_stream, sizeof(first_stream)) == 0);
64
65         // Now we should get EOF.
66         ret = byte_source_input_func(&source, buf, 4096);
67         assert(ret == 0);
68
69         // Read the marker.
70         uint8_t marker = byte_source_read_marker(&source);
71         assert(marker == 0xf7);
72
73         // Read the second stream.
74         ret = byte_source_input_func(&source, buf, 4096);
75         assert(ret == sizeof(second_stream));
76         assert(memcmp(buf, second_stream, sizeof(second_stream)) == 0);
77
78         // ...and EOF again.
79         ret = byte_source_input_func(&source, buf, 4096);
80         assert(ret == 0);
81 }
82
83 // Reading with a slow source.
84 void test_slow_source()
85 {
86         struct custom_read_userdata ud;
87         ud.bytes = stream_bytes;
88         ud.bytes_left = sizeof(stream_bytes);
89
90         struct byte_source source;
91         init_byte_source(&source, custom_read_slow, &ud);
92                 
93         uint8_t buf[4096];
94         ssize_t ret;
95         
96         // Read the first stream. Since the source is slow, we'll get one by
97         // one byte, even though we asked for 4096.
98         for (unsigned i = 0; i < sizeof(first_stream); ++i) {
99                 ret = byte_source_input_func(&source, buf, 4096);
100                 assert(ret == 1);
101                 assert(buf[0] == first_stream[i]);
102         }
103
104         // Now we should get EOF.
105         ret = byte_source_input_func(&source, buf, 4096);
106         assert(ret == 0);
107
108         // Read the marker.
109         uint8_t marker = byte_source_read_marker(&source);
110         assert(marker == 0xf7);
111
112         // Read the second stream.
113         for (unsigned i = 0; i < sizeof(second_stream); ++i) {
114                 uint8_t buf[4096];
115                 ssize_t ret;
116                 ret = byte_source_input_func(&source, buf, 4096);
117                 assert(ret == 1);
118                 assert(buf[0] == second_stream[i]);
119         }
120
121         // ...and EOF again.
122         ret = byte_source_input_func(&source, buf, 4096);
123         assert(ret == 0);
124 }
125
126 // Data with a truncated marker should first give the first bytes, then failure
127 // on next read since the stream EOFs.
128 void test_broken_marker()
129 {
130         uint8_t bytes[] = { 0x01, 0x02, 0x03, 0x04, 0xff };
131         uint8_t expected_bytes[] = { 0x01, 0x02, 0x03, 0x04 };
132
133         struct custom_read_userdata ud;
134         ud.bytes = bytes;
135         ud.bytes_left = sizeof(bytes);
136
137         struct byte_source source;
138         init_byte_source(&source, custom_read, &ud);
139         
140         uint8_t buf[4096];
141         ssize_t ret;
142
143         ret = byte_source_input_func(&source, buf, 4096);
144         assert(ret == sizeof(expected_bytes));
145         assert(memcmp(buf, expected_bytes, sizeof(expected_bytes)) == 0);
146
147         ret = byte_source_input_func(&source, buf, 4096);
148         assert(ret == -1);
149 }
150
151 // Testing small reads -- even with a fast source, we shouldn't get more data
152 // back than we asked for.
153 void test_small_reads()
154 {
155         uint8_t bytes[] = { 0xff, 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
156
157         struct custom_read_userdata ud;
158         ud.bytes = bytes;
159         ud.bytes_left = sizeof(bytes);
160
161         struct byte_source source;
162         init_byte_source(&source, custom_read, &ud);
163
164         uint8_t buf[4096];
165         ssize_t ret;
166
167         ret = byte_source_input_func(&source, buf, 4096);
168         assert(ret == 0);       
169
170         uint8_t marker = byte_source_read_marker(&source);
171         assert(marker == 0x80);
172
173         for (unsigned i = 0; i < 8; ++i) {
174                 ret = byte_source_input_func(&source, buf, 1);
175                 assert(ret == 1);
176                 assert(buf[0] == i);
177         }
178         
179         // Now EOF.
180         ret = byte_source_input_func(&source, buf, 4096);
181         assert(ret == 0);
182 }
183
184 int main(void)
185 {
186         init_choices();
187
188         printf("test_basic_reading()\n");
189         test_basic_reading();
190
191         printf("test_slow_source()\n");
192         test_slow_source();
193         
194         printf("test_broken_marker()\n");
195         test_broken_marker();
196         
197         printf("test_small_reads()\n");
198         test_small_reads();
199         
200         printf("All tests pass.\n");
201         return 0;
202 }