1 /* Copyright (c) 2023 Amazon
2 Written by Michael Klingbeil */
3 /*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #ifndef _WIN32
37 #include <unistd.h>
38 #else
39 #include <process.h>
40 #define getpid _getpid
41 #endif
42
43 #include "../src/opus_private.h"
44 #include "test_opus_common.h"
45
test_extensions_generate_success(void)46 void test_extensions_generate_success(void)
47 {
48 static const opus_extension_data ext[] = {
49 {2, 0, (const unsigned char *)"a", 1},
50 {32, 10, (const unsigned char *)"DRED", 4},
51 {33, 1, (const unsigned char *)"NOT DRED", 8},
52 {3, 4, (const unsigned char *)NULL, 0}
53 };
54
55 int result;
56 unsigned char packet[32];
57 const unsigned char *p = packet;
58 result = opus_packet_extensions_generate(packet, 23+4, ext, 4, 1);
59 expect_true(result == 23+4, "expected length 23+4");
60
61 /* expect padding */
62 expect_true(p[0] == 1 && p[1] == 1 && p[2] == 1 && p[3] == 1, "expected padding");
63 p += 4;
64
65 /* extension ID=2 */
66 expect_true((p[0] >> 1) == 2, "expected extension id 2");
67 /* For extension IDs 1 through 31, L=0 means that no data follows the
68 extension, whereas L=1 means that exactly one byte of extension data follows. */
69 expect_true((p[0] & 0x01) == 1, "expected L-bit set");
70 /* content */
71 expect_true(p[1] == 'a', "expected extension content");
72 p += 2;
73
74 /* next byte should increment the frame count, ID=1, L=0 */
75 expect_true(p[0] == 0x02, "bad frame separator");
76 p += 1;
77 /* extension ID=33 */
78 expect_true((p[0] >> 1) == 33, "expected extension id 33");
79 /* For IDs 32 to 127, L=0 signals that the extension data takes up the
80 rest of the padding, and L=1 signals that a length indicator follows. */
81 expect_true((p[0] & 0x01) == 1, "expected L-bit set");
82 /* content */
83 expect_true(p[1] == ext[2].len, "expected length");
84 p += 2;
85 expect_true(0 == memcmp(p, ext[2].data, ext[2].len), "expected extension content");
86 p += ext[2].len;
87
88 /* advance to frame 4, increment by 3 */
89 /* next byte should increment the frame count, ID=1, L=1 */
90 expect_true(p[0] == 0x03, "bad frame separator");
91 expect_true(p[1] == 0x03, "bad frame increment");
92 p += 2;
93 /* extension ID=3 */
94 expect_true((p[0] >> 1) == 3, "expected extension id 3");
95 /* For extension IDs 1 through 31, L=0 means that no data follows the
96 extension, whereas L=1 means that exactly one byte of extension data follows. */
97 expect_true((p[0] & 0x01) == 0, "expected L-bit unset");
98 p += 1;
99
100 /* advance to frame 10, increment by 6 */
101 /* next byte should increment the frame count, ID=1, L=1 */
102 expect_true(p[0] == 0x03, "bad frame separator");
103 expect_true(p[1] == 0x06, "bad frame increment");
104 p += 2;
105 /* extension ID=32 */
106 expect_true((p[0] >> 1) == 32, "expected extension id 32");
107 /* For IDs 32 to 127, L=0 signals that the extension data takes up the
108 rest of the padding */
109 expect_true((p[0] & 0x01) == 0, "expected L-bit unset");
110 p += 1;
111 expect_true(0 == memcmp(p, ext[1].data, ext[1].len), "expected extension content");
112 }
113
test_extensions_generate_zero(void)114 void test_extensions_generate_zero(void)
115 {
116 int result;
117 unsigned char packet[32];
118
119 /* zero length packet, zero extensions */
120 result = opus_packet_extensions_generate(packet, 0, NULL, 0, 1);
121 expect_true(result == 0, "expected length 0");
122 }
123
test_extensions_generate_no_padding(void)124 void test_extensions_generate_no_padding(void)
125 {
126 static const opus_extension_data ext[] = {
127 {2, 0, (const unsigned char *)"a", 1},
128 {32, 10, (const unsigned char *)"DRED", 4},
129 {33, 1, (const unsigned char *)"NOT DRED", 8},
130 {3, 4, (const unsigned char *)NULL, 0}
131 };
132
133 int result;
134 unsigned char packet[32];
135 result = opus_packet_extensions_generate(packet, sizeof(packet), ext, 4, 0);
136 expect_true(result == 23, "expected length 23");
137 }
138
test_extensions_generate_fail(void)139 void test_extensions_generate_fail(void)
140 {
141 static const opus_extension_data ext[] = {
142 {2, 0, (const unsigned char *)"a", 1},
143 {32, 10, (const unsigned char *)"DRED", 4},
144 {33, 1, (const unsigned char *)"NOT DRED", 8},
145 {3, 4, (const unsigned char *)NULL, 0}
146 };
147
148 int result;
149 unsigned char packet[100];
150
151 /* buffer too small */
152 result = opus_packet_extensions_generate(packet, 4, ext, 4, 1);
153 expect_true(result == OPUS_BUFFER_TOO_SMALL, "expected OPUS_BUFFER_TOO_SMALL");
154
155 /* invalid id */
156 {
157 static const opus_extension_data id_too_big[] = {
158 {256, 0, (const unsigned char *)"a", 1},
159 };
160 result = opus_packet_extensions_generate(packet, sizeof(packet), id_too_big, 1, 1);
161 expect_true(result == OPUS_BAD_ARG, "expected OPUS_BAD_ARG");
162 }
163
164 /* invalid id */
165 {
166 static const opus_extension_data id_too_small[] = {
167 {1, 0, (const unsigned char *)"a", 1},
168 };
169 result = opus_packet_extensions_generate(packet, sizeof(packet), id_too_small, 1, 1);
170 expect_true(result == OPUS_BAD_ARG, "expected OPUS_BAD_ARG");
171 }
172
173 /* frame index too big */
174 {
175 static const opus_extension_data frame_too_big[] = {
176 {33, 48, (const unsigned char *)"a", 1},
177 };
178 result = opus_packet_extensions_generate(packet, sizeof(packet), frame_too_big, 1, 1);
179 expect_true(result == OPUS_BAD_ARG, "expected OPUS_BAD_ARG");
180 }
181
182 /* size too big for extension IDs 1 through 31 */
183 {
184 static const opus_extension_data size_too_big[] = {
185 {2, 0, (const unsigned char *)"abcd", 4},
186 };
187 result = opus_packet_extensions_generate(packet, sizeof(packet), size_too_big, 1, 1);
188 expect_true(result == OPUS_BAD_ARG, "expected OPUS_BAD_ARG");
189 }
190
191 /* negative size for extension IDs 1 through 31 */
192 {
193 static const opus_extension_data neg_size[] = {
194 {2, 0, NULL, -4},
195 };
196 result = opus_packet_extensions_generate(packet, sizeof(packet), neg_size, 1, 1);
197 expect_true(result == OPUS_BAD_ARG, "expected OPUS_BAD_ARG");
198 }
199
200 /* negative size for extension IDs 32 through 127 */
201 {
202 static const opus_extension_data neg_size_33[] = {
203 {33, 0, NULL, -4},
204 };
205 result = opus_packet_extensions_generate(packet, sizeof(packet), neg_size_33, 1, 1);
206 expect_true(result == OPUS_BAD_ARG, "expected OPUS_BAD_ARG");
207 }
208 }
209
test_extensions_parse_success(void)210 void test_extensions_parse_success(void)
211 {
212 static const opus_extension_data ext[] = {
213 {2, 0, (const unsigned char *)"a", 1},
214 {32, 10, (const unsigned char *)"DRED", 4},
215 {33, 1, (const unsigned char *)"NOT DRED", 8},
216 {3, 4, (const unsigned char *)NULL, 0}
217 };
218 opus_extension_data ext_out[10];
219 int nb_ext;
220 int len, result;
221 unsigned char packet[32];
222
223 nb_ext = 10;
224 len = opus_packet_extensions_generate(packet, 32, ext, 4, 1);
225 expect_true(len == 32, "expected length 32");
226 result = opus_packet_extensions_count(packet, len);
227 expect_true(result == 4, "expected opus_packet_extensions_count 4");
228 result = opus_packet_extensions_parse(packet, len, ext_out, &nb_ext);
229 expect_true(nb_ext == 4, "expected 4 extensions");
230
231 expect_true(ext_out[0].id == 2, "expected id 2");
232 expect_true(ext_out[0].frame == 0, "expected frame 0");
233 expect_true(ext_out[0].len == 1, "expected len 1");
234 expect_true(0 == memcmp(ext_out[0].data, ext[0].data, 1), "expected data");
235
236 expect_true(ext_out[1].id == 33, "expected id 33");
237 expect_true(ext_out[1].frame == 1, "expected frame 1");
238 expect_true(ext_out[1].len == 8, "expected len 8");
239 expect_true(0 == memcmp(ext_out[1].data, ext[2].data, 8), "expected data");
240
241 expect_true(ext_out[2].id == 3, "expected id 3");
242 expect_true(ext_out[2].frame == 4, "expected frame 4");
243 expect_true(ext_out[2].len == 0, "expected len 0");
244
245 expect_true(ext_out[3].id == 32, "expected id 32");
246 expect_true(ext_out[3].frame == 10, "expected frame 10");
247 expect_true(ext_out[3].len == 4, "expected len 4");
248 expect_true(0 == memcmp(ext_out[3].data, ext[1].data, 4), "expected data");
249 }
250
test_extensions_parse_zero(void)251 void test_extensions_parse_zero(void)
252 {
253 static const opus_extension_data ext[] = {
254 {32, 1, (const unsigned char *)"DRED", 4},
255 };
256 int nb_ext;
257 int len, result;
258 unsigned char packet[32];
259
260 len = opus_packet_extensions_generate(packet, 32, ext, 1, 1);
261 expect_true(len == 32, "expected length 32");
262
263 nb_ext = 0;
264 result = opus_packet_extensions_parse(packet, len, NULL, &nb_ext);
265 expect_true(result == OPUS_BUFFER_TOO_SMALL, "expected OPUS_BUFFER_TOO_SMALL");
266 }
267
test_extensions_parse_fail(void)268 void test_extensions_parse_fail(void)
269 {
270 static const opus_extension_data ext[] = {
271 {2, 0, (const unsigned char *)"a", 1},
272 {33, 1, (const unsigned char *)"NOT DRED", 8},
273 {3, 4, (const unsigned char *)NULL, 0},
274 {32, 10, (const unsigned char *)"DRED", 4}
275 };
276 opus_extension_data ext_out[10];
277 int nb_ext;
278 int len, result;
279 unsigned char packet[32];
280
281 /* create invalid length */
282 len = opus_packet_extensions_generate(packet, sizeof(packet), ext, 4, 0);
283 packet[4] = 255;
284 nb_ext = 10;
285 result = opus_packet_extensions_parse(packet, len, ext_out, &nb_ext);
286 expect_true(result == OPUS_INVALID_PACKET, "expected OPUS_INVALID_PACKET");
287 result = opus_packet_extensions_count(packet, len);
288 expect_true(result == OPUS_INVALID_PACKET, "expected OPUS_INVALID_PACKET");
289
290 /* create invalid frame increment */
291 nb_ext = 10;
292 len = opus_packet_extensions_generate(packet, sizeof(packet), ext, 4, 0);
293 packet[14] = 255;
294 result = opus_packet_extensions_parse(packet, len, ext_out, &nb_ext);
295 expect_true(result == OPUS_INVALID_PACKET, "expected OPUS_INVALID_PACKET");
296 /* note, opus_packet_extensions_count does not read the invalid frame increment
297 and tells us that we have 4 extensions */
298 result = opus_packet_extensions_count(packet, len);
299 expect_true(result == 4, "expected opus_packet_extensions_count to return 4");
300
301 /* not enough space */
302 nb_ext = 1;
303 len = opus_packet_extensions_generate(packet, sizeof(packet), ext, 4, 0);
304 result = opus_packet_extensions_parse(packet, len, ext_out, &nb_ext);
305 expect_true(result == OPUS_BUFFER_TOO_SMALL, "expected OPUS_BUFFER_TOO_SMALL");
306 }
307
308 #define NB_RANDOM_EXTENSIONS 100000000
309 #define MAX_EXTENSION_SIZE 200
310 #define MAX_NB_EXTENSIONS 100
311
test_random_extensions_parse(void)312 void test_random_extensions_parse(void)
313 {
314 int i;
315 for (i=0;i<NB_RANDOM_EXTENSIONS;i++)
316 {
317 opus_extension_data ext_out[MAX_NB_EXTENSIONS];
318 int nb_ext;
319 unsigned char payload[MAX_EXTENSION_SIZE];
320 int len;
321 int j;
322 int result;
323 len = fast_rand()%(MAX_EXTENSION_SIZE+1);
324 for (j=0;j<len;j++)
325 payload[j] = fast_rand()&0xFF;
326 nb_ext = fast_rand()%(MAX_NB_EXTENSIONS+1);
327 result = opus_packet_extensions_parse(payload, len, ext_out, &nb_ext);
328 expect_true(result == OPUS_OK || result == OPUS_BUFFER_TOO_SMALL || result == OPUS_INVALID_PACKET, "expected OPUS_OK, OPUS_BUFFER_TOO_SMALL or OPUS_INVALID_PACKET");
329 /* Even if parsing fails, check that the extensions that got extracted make sense. */
330 for (j=0;j<nb_ext;j++)
331 {
332 expect_true(ext_out[j].frame >= 0 && ext_out[j].frame < 48, "expected frame between 0 and 47");
333 expect_true(ext_out[j].id >= 2 && ext_out[j].id <= 127, "expected id between 2 and 127");
334 expect_true(ext_out[j].data >= payload && ext_out[j].data+ext_out[j].len <= payload+len, "expected data to be within packet");
335 }
336 }
337 }
338
test_opus_repacketizer_out_range_impl(void)339 void test_opus_repacketizer_out_range_impl(void)
340 {
341 OpusRepacketizer rp;
342 unsigned char packet[1024];
343 unsigned char packet_out[1024];
344 opus_int16 size[48];
345 const unsigned char *padding;
346 opus_int32 padding_len;
347 opus_extension_data ext_out[10];
348 int i;
349 int nb_ext;
350 int res, len;
351 int first_count = 0, second_count = 0;
352 static const opus_extension_data ext[] = {
353 {33, 0, (const unsigned char *)"abcdefg", 7},
354 {100, 0, (const unsigned char *)"uvwxyz", 6},
355 };
356
357 opus_repacketizer_init(&rp);
358
359 memset(packet, 0, sizeof(packet));
360 /* Hybrid Packet with 20 msec frames, Code 3 */
361 packet[0] = (15 << 3) | 3;
362 /* Code 3, padding bit set, 1 frame */
363 packet[1] = 1 << 6 | 1;
364 packet[2] = 0;
365 packet[3] = 0;
366
367 /* generate 2 extensions, id 33 and 100 */
368 len = opus_packet_extensions_generate(&packet[4], sizeof(packet)-4, ext, 2, 0);
369 /* update the padding length */
370 packet[2] = len;
371
372 /* concatenate 3 frames */
373 res = opus_repacketizer_cat(&rp, packet, 4+len);
374 /* for the middle frame, no padding, no extensions */
375 packet[1] = 1;
376 res = opus_repacketizer_cat(&rp, packet, 4);
377 /* switch back to extensions for the last frame extensions */
378 packet[1] = 1 << 6 | 1;
379 res = opus_repacketizer_cat(&rp, packet, 4+len);
380
381 expect_true(rp.nb_frames == 3, "Expected 3 frames");
382 res = opus_repacketizer_out_range_impl(&rp,
383 0, 3, /* begin, end */
384 packet_out, /* unsigned char *data */
385 sizeof(packet_out), /* opus_int32 maxlen */
386 0, /*int self_delimited */
387 0, /* int pad */
388 NULL, /* const opus_extension_data *extensions */
389 0 /* int nb_extensions */);
390 expect_true(res > 0, "expected valid packet length");
391
392 /* now verify that we have the expected extensions */
393 res = opus_packet_parse_impl(packet_out, res, 0, NULL, NULL, size,
394 NULL, NULL, &padding, &padding_len);
395 nb_ext = 10;
396 res = opus_packet_extensions_parse(padding, padding_len, ext_out, &nb_ext);
397 expect_true(nb_ext == 4, "Expected 4 extensions");
398 for (i = 0 ; i < nb_ext; i++)
399 {
400 if (ext_out[i].id == 33)
401 {
402 opus_test_assert(ext_out[i].len == ext[0].len);
403 opus_test_assert(0 == memcmp(ext_out[i].data, ext[0].data, ext[0].len));
404 first_count++;
405 }
406 else if (ext_out[i].id == 100)
407 {
408 opus_test_assert(ext_out[i].len == ext[1].len);
409 opus_test_assert(0 == memcmp(ext_out[i].data, ext[1].data, ext[1].len));
410 second_count++;
411 }
412 if (i < 2)
413 opus_test_assert(ext_out[i].frame == 0)
414 else
415 opus_test_assert(ext_out[i].frame == 2)
416 }
417 opus_test_assert(first_count == 2);
418 opus_test_assert(second_count == 2);
419 }
420
main(int argc,char ** argv)421 int main(int argc, char **argv)
422 {
423 int env_used;
424 char *env_seed;
425 env_used=0;
426 env_seed=getenv("SEED");
427 if(argc>1)iseed=atoi(argv[1]);
428 else if(env_seed)
429 {
430 iseed=atoi(env_seed);
431 env_used=1;
432 }
433 else iseed=(opus_uint32)time(NULL)^(((opus_uint32)getpid()&65535)<<16);
434 Rw=Rz=iseed;
435
436 fprintf(stderr,"Testing extensions. Random seed: %u (%.4X)\n", iseed, fast_rand() % 65535);
437 if(env_used)fprintf(stderr," Random seed set from the environment (SEED=%s).\n", env_seed);
438
439 test_extensions_generate_success();
440 test_extensions_generate_zero();
441 test_extensions_generate_no_padding();
442 test_extensions_generate_fail();
443 test_extensions_parse_success();
444 test_extensions_parse_zero();
445 test_extensions_parse_fail();
446 test_random_extensions_parse();
447 test_opus_repacketizer_out_range_impl();
448 fprintf(stderr,"Tests completed successfully.\n");
449 return 0;
450 }
451