1 /*
2 * Copyright © 2011 Mozilla Foundation
3 *
4 * This program is made available under an ISC-style license. See the
5 * accompanying file LICENSE for details.
6 */
7 #include "gtest/gtest.h"
8 #if !defined(_XOPEN_SOURCE)
9 #define _XOPEN_SOURCE 600
10 #endif
11 #include "cubeb/cubeb.h"
12 #include <atomic>
13 #include <stdio.h>
14 #include <string.h>
15 #include <math.h>
16 #include "common.h"
17
18 #define STREAM_RATE 44100
19 #define STREAM_LATENCY 100 * STREAM_RATE / 1000
20 #define STREAM_CHANNELS 1
21 #define STREAM_LAYOUT CUBEB_LAYOUT_MONO
22 #define STREAM_FORMAT CUBEB_SAMPLE_S16LE
23
is_windows_7()24 int is_windows_7()
25 {
26 #ifdef __MINGW32__
27 fprintf(stderr, "Warning: this test was built with MinGW.\n"
28 "MinGW does not contain necessary version checking infrastructure. Claiming to be Windows 7, even if we're not.\n");
29 return 1;
30 #endif
31 #if (defined(_WIN32) || defined(__WIN32__)) && ( !defined(__MINGW32__))
32 OSVERSIONINFOEX osvi;
33 DWORDLONG condition_mask = 0;
34
35 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
36 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
37
38 // NT 6.1 is Windows 7
39 osvi.dwMajorVersion = 6;
40 osvi.dwMinorVersion = 1;
41
42 VER_SET_CONDITION(condition_mask, VER_MAJORVERSION, VER_EQUAL);
43 VER_SET_CONDITION(condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL);
44
45 return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, condition_mask);
46 #else
47 return 0;
48 #endif
49 }
50
51 static int dummy;
52 static std::atomic<uint64_t> total_frames_written;
53 static int delay_callback;
54
55 static long
test_data_callback(cubeb_stream * stm,void * user_ptr,const void *,void * outputbuffer,long nframes)56 test_data_callback(cubeb_stream * stm, void * user_ptr, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
57 {
58 EXPECT_TRUE(stm && user_ptr == &dummy && outputbuffer && nframes > 0);
59 assert(outputbuffer);
60 memset(outputbuffer, 0, nframes * sizeof(short));
61
62 total_frames_written += nframes;
63 if (delay_callback) {
64 delay(10);
65 }
66 return nframes;
67 }
68
69 void
test_state_callback(cubeb_stream *,void *,cubeb_state)70 test_state_callback(cubeb_stream * /*stm*/, void * /*user_ptr*/, cubeb_state /*state*/)
71 {
72 }
73
TEST(cubeb,init_destroy_context)74 TEST(cubeb, init_destroy_context)
75 {
76 int r;
77 cubeb * ctx;
78 char const* backend_id;
79
80 r = common_init(&ctx, "test_sanity");
81 ASSERT_EQ(r, CUBEB_OK);
82 ASSERT_NE(ctx, nullptr);
83
84 backend_id = cubeb_get_backend_id(ctx);
85 ASSERT_TRUE(backend_id);
86
87 fprintf(stderr, "Backend: %s\n", backend_id);
88
89 cubeb_destroy(ctx);
90 }
91
TEST(cubeb,init_destroy_multiple_contexts)92 TEST(cubeb, init_destroy_multiple_contexts)
93 {
94 size_t i;
95 int r;
96 cubeb * ctx[4];
97 int order[4] = {2, 0, 3, 1};
98 ASSERT_EQ(ARRAY_LENGTH(ctx), ARRAY_LENGTH(order));
99
100 for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
101 r = common_init(&ctx[i], NULL);
102 ASSERT_EQ(r, CUBEB_OK);
103 ASSERT_NE(ctx[i], nullptr);
104 }
105
106 /* destroy in a different order */
107 for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
108 cubeb_destroy(ctx[order[i]]);
109 }
110 }
111
TEST(cubeb,context_variables)112 TEST(cubeb, context_variables)
113 {
114 int r;
115 cubeb * ctx;
116 uint32_t value;
117 cubeb_channel_layout layout;
118 cubeb_stream_params params;
119
120 r = common_init(&ctx, "test_context_variables");
121 ASSERT_EQ(r, CUBEB_OK);
122 ASSERT_NE(ctx, nullptr);
123
124 params.channels = STREAM_CHANNELS;
125 params.format = STREAM_FORMAT;
126 params.rate = STREAM_RATE;
127 params.layout = STREAM_LAYOUT;
128 params.prefs = CUBEB_STREAM_PREF_NONE;
129
130 r = cubeb_get_min_latency(ctx, ¶ms, &value);
131 ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
132 if (r == CUBEB_OK) {
133 ASSERT_TRUE(value > 0);
134 }
135
136 r = cubeb_get_preferred_sample_rate(ctx, &value);
137 ASSERT_TRUE(r == CUBEB_OK || r == CUBEB_ERROR_NOT_SUPPORTED);
138 if (r == CUBEB_OK) {
139 ASSERT_TRUE(value > 0);
140 }
141
142 r = cubeb_get_preferred_channel_layout(ctx, &layout);
143 ASSERT_TRUE(r == CUBEB_ERROR_NOT_SUPPORTED ||
144 (r == CUBEB_OK && layout != CUBEB_LAYOUT_UNDEFINED) ||
145 (r == CUBEB_ERROR && layout == CUBEB_LAYOUT_UNDEFINED));
146
147 cubeb_destroy(ctx);
148 }
149
TEST(cubeb,init_destroy_stream)150 TEST(cubeb, init_destroy_stream)
151 {
152 int r;
153 cubeb * ctx;
154 cubeb_stream * stream;
155 cubeb_stream_params params;
156
157 r = common_init(&ctx, "test_sanity");
158 ASSERT_EQ(r, CUBEB_OK);
159 ASSERT_NE(ctx, nullptr);
160
161 params.format = STREAM_FORMAT;
162 params.rate = STREAM_RATE;
163 params.channels = STREAM_CHANNELS;
164 params.layout = STREAM_LAYOUT;
165 params.prefs = CUBEB_STREAM_PREF_NONE;
166
167 r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
168 test_data_callback, test_state_callback, &dummy);
169 ASSERT_EQ(r, CUBEB_OK);
170 ASSERT_NE(stream, nullptr);
171
172 cubeb_stream_destroy(stream);
173 cubeb_destroy(ctx);
174 }
175
TEST(cubeb,init_destroy_multiple_streams)176 TEST(cubeb, init_destroy_multiple_streams)
177 {
178 size_t i;
179 int r;
180 cubeb * ctx;
181 cubeb_stream * stream[8];
182 cubeb_stream_params params;
183
184 r = common_init(&ctx, "test_sanity");
185 ASSERT_EQ(r, CUBEB_OK);
186 ASSERT_NE(ctx, nullptr);
187
188 params.format = STREAM_FORMAT;
189 params.rate = STREAM_RATE;
190 params.channels = STREAM_CHANNELS;
191 params.layout = STREAM_LAYOUT;
192 params.prefs = CUBEB_STREAM_PREF_NONE;
193
194 for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
195 r = cubeb_stream_init(ctx, &stream[i], "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
196 test_data_callback, test_state_callback, &dummy);
197 ASSERT_EQ(r, CUBEB_OK);
198 ASSERT_NE(stream[i], nullptr);
199 }
200
201 for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
202 cubeb_stream_destroy(stream[i]);
203 }
204
205 cubeb_destroy(ctx);
206 }
207
TEST(cubeb,configure_stream)208 TEST(cubeb, configure_stream)
209 {
210 int r;
211 cubeb * ctx;
212 cubeb_stream * stream;
213 cubeb_stream_params params;
214
215 r = common_init(&ctx, "test_sanity");
216 ASSERT_EQ(r, CUBEB_OK);
217 ASSERT_NE(ctx, nullptr);
218
219 params.format = STREAM_FORMAT;
220 params.rate = STREAM_RATE;
221 params.channels = 2; // panning
222 params.layout = CUBEB_LAYOUT_STEREO;
223 params.prefs = CUBEB_STREAM_PREF_NONE;
224
225 r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
226 test_data_callback, test_state_callback, &dummy);
227 ASSERT_EQ(r, CUBEB_OK);
228 ASSERT_NE(stream, nullptr);
229
230 r = cubeb_stream_set_volume(stream, 1.0f);
231 ASSERT_TRUE(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
232
233 r = cubeb_stream_set_panning(stream, 0.0f);
234 ASSERT_TRUE(r == 0 || r == CUBEB_ERROR_NOT_SUPPORTED);
235
236 cubeb_stream_destroy(stream);
237 cubeb_destroy(ctx);
238 }
239
TEST(cubeb,configure_stream_undefined_layout)240 TEST(cubeb, configure_stream_undefined_layout)
241 {
242 int r;
243 cubeb * ctx;
244 cubeb_stream * stream;
245 cubeb_stream_params params;
246
247 r = common_init(&ctx, "test_sanity");
248 ASSERT_EQ(r, CUBEB_OK);
249 ASSERT_NE(ctx, nullptr);
250
251 params.format = STREAM_FORMAT;
252 params.rate = STREAM_RATE;
253 params.channels = 2; // panning
254 params.layout = CUBEB_LAYOUT_UNDEFINED;
255 params.prefs = CUBEB_STREAM_PREF_NONE;
256
257 r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
258 test_data_callback, test_state_callback, &dummy);
259 ASSERT_EQ(r, CUBEB_OK);
260 ASSERT_NE(stream, nullptr);
261
262 r = cubeb_stream_start(stream);
263 ASSERT_EQ(r, CUBEB_OK);
264
265 delay(100);
266
267 r = cubeb_stream_stop(stream);
268 ASSERT_EQ(r, CUBEB_OK);
269
270 cubeb_stream_destroy(stream);
271 cubeb_destroy(ctx);
272 }
273
274 static void
test_init_start_stop_destroy_multiple_streams(int early,int delay_ms)275 test_init_start_stop_destroy_multiple_streams(int early, int delay_ms)
276 {
277 size_t i;
278 int r;
279 cubeb * ctx;
280 cubeb_stream * stream[8];
281 cubeb_stream_params params;
282
283 r = common_init(&ctx, "test_sanity");
284 ASSERT_EQ(r, CUBEB_OK);
285 ASSERT_NE(ctx, nullptr);
286
287 params.format = STREAM_FORMAT;
288 params.rate = STREAM_RATE;
289 params.channels = STREAM_CHANNELS;
290 params.layout = STREAM_LAYOUT;
291 params.prefs = CUBEB_STREAM_PREF_NONE;
292
293 for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
294 r = cubeb_stream_init(ctx, &stream[i], "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
295 test_data_callback, test_state_callback, &dummy);
296 ASSERT_EQ(r, CUBEB_OK);
297 ASSERT_NE(stream[i], nullptr);
298 if (early) {
299 r = cubeb_stream_start(stream[i]);
300 ASSERT_EQ(r, CUBEB_OK);
301 }
302 }
303
304 if (!early) {
305 for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
306 r = cubeb_stream_start(stream[i]);
307 ASSERT_EQ(r, CUBEB_OK);
308 }
309 }
310
311 if (delay_ms) {
312 delay(delay_ms);
313 }
314
315 if (!early) {
316 for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
317 r = cubeb_stream_stop(stream[i]);
318 ASSERT_EQ(r, CUBEB_OK);
319 }
320 }
321
322 for (i = 0; i < ARRAY_LENGTH(stream); ++i) {
323 if (early) {
324 r = cubeb_stream_stop(stream[i]);
325 ASSERT_EQ(r, CUBEB_OK);
326 }
327 cubeb_stream_destroy(stream[i]);
328 }
329
330 cubeb_destroy(ctx);
331 }
332
TEST(cubeb,init_start_stop_destroy_multiple_streams)333 TEST(cubeb, init_start_stop_destroy_multiple_streams)
334 {
335 /* Sometimes, when using WASAPI on windows 7 (vista and 8 are okay), and
336 * calling Activate a lot on an AudioClient, 0x800700b7 is returned. This is
337 * the HRESULT value for "Cannot create a file when that file already exists",
338 * and is not documented as a possible return value for this call. Hence, we
339 * try to limit the number of streams we create in this test. */
340 if (!is_windows_7()) {
341 delay_callback = 0;
342 test_init_start_stop_destroy_multiple_streams(0, 0);
343 test_init_start_stop_destroy_multiple_streams(1, 0);
344 test_init_start_stop_destroy_multiple_streams(0, 150);
345 test_init_start_stop_destroy_multiple_streams(1, 150);
346 delay_callback = 1;
347 test_init_start_stop_destroy_multiple_streams(0, 0);
348 test_init_start_stop_destroy_multiple_streams(1, 0);
349 test_init_start_stop_destroy_multiple_streams(0, 150);
350 test_init_start_stop_destroy_multiple_streams(1, 150);
351 }
352 }
353
TEST(cubeb,init_destroy_multiple_contexts_and_streams)354 TEST(cubeb, init_destroy_multiple_contexts_and_streams)
355 {
356 size_t i, j;
357 int r;
358 cubeb * ctx[2];
359 cubeb_stream * stream[8];
360 cubeb_stream_params params;
361 size_t streams_per_ctx = ARRAY_LENGTH(stream) / ARRAY_LENGTH(ctx);
362 ASSERT_EQ(ARRAY_LENGTH(ctx) * streams_per_ctx, ARRAY_LENGTH(stream));
363
364 /* Sometimes, when using WASAPI on windows 7 (vista and 8 are okay), and
365 * calling Activate a lot on an AudioClient, 0x800700b7 is returned. This is
366 * the HRESULT value for "Cannot create a file when that file already exists",
367 * and is not documented as a possible return value for this call. Hence, we
368 * try to limit the number of streams we create in this test. */
369 if (is_windows_7())
370 return;
371
372 params.format = STREAM_FORMAT;
373 params.rate = STREAM_RATE;
374 params.channels = STREAM_CHANNELS;
375 params.layout = STREAM_LAYOUT;
376 params.prefs = CUBEB_STREAM_PREF_NONE;
377
378 for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
379 r = common_init(&ctx[i], "test_sanity");
380 ASSERT_EQ(r, CUBEB_OK);
381 ASSERT_NE(ctx[i], nullptr);
382
383 for (j = 0; j < streams_per_ctx; ++j) {
384 r = cubeb_stream_init(ctx[i], &stream[i * streams_per_ctx + j], "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
385 test_data_callback, test_state_callback, &dummy);
386 ASSERT_EQ(r, CUBEB_OK);
387 ASSERT_NE(stream[i * streams_per_ctx + j], nullptr);
388 }
389 }
390
391 for (i = 0; i < ARRAY_LENGTH(ctx); ++i) {
392 for (j = 0; j < streams_per_ctx; ++j) {
393 cubeb_stream_destroy(stream[i * streams_per_ctx + j]);
394 }
395 cubeb_destroy(ctx[i]);
396 }
397 }
398
TEST(cubeb,basic_stream_operations)399 TEST(cubeb, basic_stream_operations)
400 {
401 int r;
402 cubeb * ctx;
403 cubeb_stream * stream;
404 cubeb_stream_params params;
405 uint64_t position;
406
407 r = common_init(&ctx, "test_sanity");
408 ASSERT_EQ(r, CUBEB_OK);
409 ASSERT_NE(ctx, nullptr);
410
411 params.format = STREAM_FORMAT;
412 params.rate = STREAM_RATE;
413 params.channels = STREAM_CHANNELS;
414 params.layout = STREAM_LAYOUT;
415 params.prefs = CUBEB_STREAM_PREF_NONE;
416
417 r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
418 test_data_callback, test_state_callback, &dummy);
419 ASSERT_EQ(r, CUBEB_OK);
420 ASSERT_NE(stream, nullptr);
421
422 /* position and volume before stream has started */
423 r = cubeb_stream_get_position(stream, &position);
424 ASSERT_EQ(r, CUBEB_OK);
425 ASSERT_EQ(position, 0u);
426
427 r = cubeb_stream_start(stream);
428 ASSERT_EQ(r, CUBEB_OK);
429
430 /* position and volume after while stream running */
431 r = cubeb_stream_get_position(stream, &position);
432 ASSERT_EQ(r, CUBEB_OK);
433
434 r = cubeb_stream_stop(stream);
435 ASSERT_EQ(r, CUBEB_OK);
436
437 /* position and volume after stream has stopped */
438 r = cubeb_stream_get_position(stream, &position);
439 ASSERT_EQ(r, CUBEB_OK);
440
441 cubeb_stream_destroy(stream);
442 cubeb_destroy(ctx);
443 }
444
TEST(cubeb,stream_position)445 TEST(cubeb, stream_position)
446 {
447 size_t i;
448 int r;
449 cubeb * ctx;
450 cubeb_stream * stream;
451 cubeb_stream_params params;
452 uint64_t position, last_position;
453
454 total_frames_written = 0;
455
456 r = common_init(&ctx, "test_sanity");
457 ASSERT_EQ(r, CUBEB_OK);
458 ASSERT_NE(ctx, nullptr);
459
460 params.format = STREAM_FORMAT;
461 params.rate = STREAM_RATE;
462 params.channels = STREAM_CHANNELS;
463 params.layout = STREAM_LAYOUT;
464 params.prefs = CUBEB_STREAM_PREF_NONE;
465
466 r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
467 test_data_callback, test_state_callback, &dummy);
468 ASSERT_EQ(r, CUBEB_OK);
469 ASSERT_NE(stream, nullptr);
470
471 /* stream position should not advance before starting playback */
472 r = cubeb_stream_get_position(stream, &position);
473 ASSERT_EQ(r, CUBEB_OK);
474 ASSERT_EQ(position, 0u);
475
476 delay(500);
477
478 r = cubeb_stream_get_position(stream, &position);
479 ASSERT_EQ(r, CUBEB_OK);
480 ASSERT_EQ(position, 0u);
481
482 /* stream position should advance during playback */
483 r = cubeb_stream_start(stream);
484 ASSERT_EQ(r, CUBEB_OK);
485
486 /* XXX let start happen */
487 delay(500);
488
489 /* stream should have prefilled */
490 ASSERT_TRUE(total_frames_written.load() > 0);
491
492 r = cubeb_stream_get_position(stream, &position);
493 ASSERT_EQ(r, CUBEB_OK);
494 last_position = position;
495
496 delay(500);
497
498 r = cubeb_stream_get_position(stream, &position);
499 ASSERT_EQ(r, CUBEB_OK);
500 ASSERT_GE(position, last_position);
501 last_position = position;
502
503 /* stream position should not exceed total frames written */
504 for (i = 0; i < 5; ++i) {
505 r = cubeb_stream_get_position(stream, &position);
506 ASSERT_EQ(r, CUBEB_OK);
507 ASSERT_GE(position, last_position);
508 ASSERT_LE(position, total_frames_written.load());
509 last_position = position;
510 delay(500);
511 }
512
513 /* test that the position is valid even when starting and
514 * stopping the stream. */
515 for (i = 0; i < 5; ++i) {
516 r = cubeb_stream_stop(stream);
517 ASSERT_EQ(r, CUBEB_OK);
518 r = cubeb_stream_get_position(stream, &position);
519 ASSERT_EQ(r, CUBEB_OK);
520 ASSERT_TRUE(last_position < position);
521 last_position = position;
522 delay(500);
523 r = cubeb_stream_start(stream);
524 ASSERT_EQ(r, CUBEB_OK);
525 delay(500);
526 }
527
528 ASSERT_NE(last_position, 0u);
529
530 /* stream position should not advance after stopping playback */
531 r = cubeb_stream_stop(stream);
532 ASSERT_EQ(r, CUBEB_OK);
533
534 /* XXX allow stream to settle */
535 delay(500);
536
537 r = cubeb_stream_get_position(stream, &position);
538 ASSERT_EQ(r, CUBEB_OK);
539 last_position = position;
540
541 delay(500);
542
543 r = cubeb_stream_get_position(stream, &position);
544 ASSERT_EQ(r, CUBEB_OK);
545 ASSERT_EQ(position, last_position);
546
547 cubeb_stream_destroy(stream);
548 cubeb_destroy(ctx);
549 }
550
551 static std::atomic<int> do_drain;
552 static std::atomic<int> got_drain;
553
554 static long
test_drain_data_callback(cubeb_stream * stm,void * user_ptr,const void *,void * outputbuffer,long nframes)555 test_drain_data_callback(cubeb_stream * stm, void * user_ptr, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
556 {
557 EXPECT_TRUE(stm && user_ptr == &dummy && outputbuffer && nframes > 0);
558 assert(outputbuffer);
559 if (do_drain == 1) {
560 do_drain = 2;
561 return 0;
562 }
563 /* once drain has started, callback must never be called again */
564 EXPECT_TRUE(do_drain != 2);
565 memset(outputbuffer, 0, nframes * sizeof(short));
566 total_frames_written += nframes;
567 return nframes;
568 }
569
570 void
test_drain_state_callback(cubeb_stream *,void *,cubeb_state state)571 test_drain_state_callback(cubeb_stream * /*stm*/, void * /*user_ptr*/, cubeb_state state)
572 {
573 if (state == CUBEB_STATE_DRAINED) {
574 ASSERT_TRUE(!got_drain);
575 got_drain = 1;
576 }
577 }
578
TEST(cubeb,drain)579 TEST(cubeb, drain)
580 {
581 int r;
582 cubeb * ctx;
583 cubeb_stream * stream;
584 cubeb_stream_params params;
585 uint64_t position;
586
587 delay_callback = 0;
588 total_frames_written = 0;
589
590 r = common_init(&ctx, "test_sanity");
591 ASSERT_EQ(r, CUBEB_OK);
592 ASSERT_NE(ctx, nullptr);
593
594 params.format = STREAM_FORMAT;
595 params.rate = STREAM_RATE;
596 params.channels = STREAM_CHANNELS;
597 params.layout = STREAM_LAYOUT;
598 params.prefs = CUBEB_STREAM_PREF_NONE;
599
600 r = cubeb_stream_init(ctx, &stream, "test", NULL, NULL, NULL, ¶ms, STREAM_LATENCY,
601 test_drain_data_callback, test_drain_state_callback, &dummy);
602 ASSERT_EQ(r, CUBEB_OK);
603 ASSERT_NE(stream, nullptr);
604
605 r = cubeb_stream_start(stream);
606 ASSERT_EQ(r, CUBEB_OK);
607
608 delay(500);
609
610 do_drain = 1;
611
612 for (;;) {
613 r = cubeb_stream_get_position(stream, &position);
614 ASSERT_EQ(r, CUBEB_OK);
615 if (got_drain) {
616 break;
617 } else {
618 ASSERT_LE(position, total_frames_written.load());
619 }
620 delay(500);
621 }
622
623 r = cubeb_stream_get_position(stream, &position);
624 ASSERT_EQ(r, CUBEB_OK);
625 ASSERT_TRUE(got_drain);
626
627 // Really, we should be able to rely on position reaching our final written frame, but
628 // for now let's make sure it doesn't continue beyond that point.
629 //ASSERT_LE(position, total_frames_written.load());
630
631 cubeb_stream_destroy(stream);
632 cubeb_destroy(ctx);
633
634 got_drain = 0;
635 do_drain = 0;
636 }
637
TEST(cubeb,DISABLED_eos_during_prefill)638 TEST(cubeb, DISABLED_eos_during_prefill)
639 {
640 // This test needs to be implemented.
641 }
642
TEST(cubeb,DISABLED_stream_destroy_pending_drain)643 TEST(cubeb, DISABLED_stream_destroy_pending_drain)
644 {
645 // This test needs to be implemented.
646 }
647
TEST(cubeb,stable_devid)648 TEST(cubeb, stable_devid)
649 {
650 /* Test that the devid field of cubeb_device_info is stable
651 * (ie. compares equal) over two invocations of
652 * cubeb_enumerate_devices(). */
653
654 int r;
655 cubeb * ctx;
656 cubeb_device_collection first;
657 cubeb_device_collection second;
658 cubeb_device_type all_devices =
659 (cubeb_device_type) (CUBEB_DEVICE_TYPE_INPUT | CUBEB_DEVICE_TYPE_OUTPUT);
660 size_t n;
661
662 r = common_init(&ctx, "test_sanity");
663 ASSERT_EQ(r, CUBEB_OK);
664 ASSERT_NE(ctx, nullptr);
665
666 r = cubeb_enumerate_devices(ctx, all_devices, &first);
667 if (r == CUBEB_ERROR_NOT_SUPPORTED)
668 return;
669
670 ASSERT_EQ(r, CUBEB_OK);
671
672 r = cubeb_enumerate_devices(ctx, all_devices, &second);
673 ASSERT_EQ(r, CUBEB_OK);
674
675 ASSERT_EQ(first.count, second.count);
676 for (n = 0; n < first.count; n++) {
677 ASSERT_EQ(first.device[n].devid, second.device[n].devid);
678 }
679
680 r = cubeb_device_collection_destroy(ctx, &first);
681 ASSERT_EQ(r, CUBEB_OK);
682 r = cubeb_device_collection_destroy(ctx, &second);
683 ASSERT_EQ(r, CUBEB_OK);
684 cubeb_destroy(ctx);
685 }
686