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