testautomation_audio.c (38568B)
1/** 2 * Original code: automated SDL audio test written by Edgar Simo "bobbens" 3 * New/updated tests: aschiffler at ferzkopp dot net 4 */ 5 6/* quiet windows compiler warnings */ 7#define _CRT_SECURE_NO_WARNINGS 8 9#include <stdio.h> 10#include <string.h> 11 12#include "SDL.h" 13#include "SDL_test.h" 14 15/* ================= Test Case Implementation ================== */ 16 17/* Fixture */ 18 19void 20_audioSetUp(void *arg) 21{ 22 /* Start SDL audio subsystem */ 23 int ret = SDL_InitSubSystem( SDL_INIT_AUDIO ); 24 SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO)"); 25 SDLTest_AssertCheck(ret==0, "Check result from SDL_InitSubSystem(SDL_INIT_AUDIO)"); 26 if (ret != 0) { 27 SDLTest_LogError("%s", SDL_GetError()); 28 } 29} 30 31void 32_audioTearDown(void *arg) 33{ 34 /* Remove a possibly created file from SDL disk writer audio driver; ignore errors */ 35 remove("sdlaudio.raw"); 36 37 SDLTest_AssertPass("Cleanup of test files completed"); 38} 39 40 41/* Global counter for callback invocation */ 42int _audio_testCallbackCounter; 43 44/* Global accumulator for total callback length */ 45int _audio_testCallbackLength; 46 47 48/* Test callback function */ 49void _audio_testCallback(void *userdata, Uint8 *stream, int len) 50{ 51 /* track that callback was called */ 52 _audio_testCallbackCounter++; 53 _audio_testCallbackLength += len; 54} 55 56 57/* Test case functions */ 58 59/** 60 * \brief Stop and restart audio subsystem 61 * 62 * \sa https://wiki.libsdl.org/SDL_QuitSubSystem 63 * \sa https://wiki.libsdl.org/SDL_InitSubSystem 64 */ 65int audio_quitInitAudioSubSystem() 66{ 67 /* Stop SDL audio subsystem */ 68 SDL_QuitSubSystem( SDL_INIT_AUDIO ); 69 SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); 70 71 /* Restart audio again */ 72 _audioSetUp(NULL); 73 74 return TEST_COMPLETED; 75} 76 77/** 78 * \brief Start and stop audio directly 79 * 80 * \sa https://wiki.libsdl.org/SDL_InitAudio 81 * \sa https://wiki.libsdl.org/SDL_QuitAudio 82 */ 83int audio_initQuitAudio() 84{ 85 int result; 86 int i, iMax; 87 const char* audioDriver; 88 89 /* Stop SDL audio subsystem */ 90 SDL_QuitSubSystem( SDL_INIT_AUDIO ); 91 SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); 92 93 /* Loop over all available audio drivers */ 94 iMax = SDL_GetNumAudioDrivers(); 95 SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers"); 96 SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); 97 for (i = 0; i < iMax; i++) { 98 audioDriver = SDL_GetAudioDriver(i); 99 SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); 100 SDLTest_AssertCheck(audioDriver != NULL, "Audio driver name is not NULL"); 101 SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); 102 103 /* Call Init */ 104 result = SDL_AudioInit(audioDriver); 105 SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver); 106 SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result); 107 108 /* Call Quit */ 109 SDL_AudioQuit(); 110 SDLTest_AssertPass("Call to SDL_AudioQuit()"); 111 } 112 113 /* NULL driver specification */ 114 audioDriver = NULL; 115 116 /* Call Init */ 117 result = SDL_AudioInit(audioDriver); 118 SDLTest_AssertPass("Call to SDL_AudioInit(NULL)"); 119 SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result); 120 121 /* Call Quit */ 122 SDL_AudioQuit(); 123 SDLTest_AssertPass("Call to SDL_AudioQuit()"); 124 125 /* Restart audio again */ 126 _audioSetUp(NULL); 127 128 return TEST_COMPLETED; 129} 130 131/** 132 * \brief Start, open, close and stop audio 133 * 134 * \sa https://wiki.libsdl.org/SDL_InitAudio 135 * \sa https://wiki.libsdl.org/SDL_OpenAudio 136 * \sa https://wiki.libsdl.org/SDL_CloseAudio 137 * \sa https://wiki.libsdl.org/SDL_QuitAudio 138 */ 139int audio_initOpenCloseQuitAudio() 140{ 141 int result, expectedResult; 142 int i, iMax, j, k; 143 const char* audioDriver; 144 SDL_AudioSpec desired; 145 146 /* Stop SDL audio subsystem */ 147 SDL_QuitSubSystem( SDL_INIT_AUDIO ); 148 SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); 149 150 /* Loop over all available audio drivers */ 151 iMax = SDL_GetNumAudioDrivers(); 152 SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers"); 153 SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); 154 for (i = 0; i < iMax; i++) { 155 audioDriver = SDL_GetAudioDriver(i); 156 SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); 157 SDLTest_AssertCheck(audioDriver != NULL, "Audio driver name is not NULL"); 158 SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); 159 160 /* Change specs */ 161 for (j = 0; j < 2; j++) { 162 163 /* Call Init */ 164 result = SDL_AudioInit(audioDriver); 165 SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver); 166 SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result); 167 168 /* Set spec */ 169 SDL_memset(&desired, 0, sizeof(desired)); 170 switch (j) { 171 case 0: 172 /* Set standard desired spec */ 173 desired.freq = 22050; 174 desired.format = AUDIO_S16SYS; 175 desired.channels = 2; 176 desired.samples = 4096; 177 desired.callback = _audio_testCallback; 178 desired.userdata = NULL; 179 180 case 1: 181 /* Set custom desired spec */ 182 desired.freq = 48000; 183 desired.format = AUDIO_F32SYS; 184 desired.channels = 2; 185 desired.samples = 2048; 186 desired.callback = _audio_testCallback; 187 desired.userdata = NULL; 188 break; 189 } 190 191 /* Call Open (maybe multiple times) */ 192 for (k=0; k <= j; k++) { 193 result = SDL_OpenAudio(&desired, NULL); 194 SDLTest_AssertPass("Call to SDL_OpenAudio(desired_spec_%d, NULL), call %d", j, k+1); 195 expectedResult = (k==0) ? 0 : -1; 196 SDLTest_AssertCheck(result == expectedResult, "Verify return value; expected: %d, got: %d", expectedResult, result); 197 } 198 199 /* Call Close (maybe multiple times) */ 200 for (k=0; k <= j; k++) { 201 SDL_CloseAudio(); 202 SDLTest_AssertPass("Call to SDL_CloseAudio(), call %d", k+1); 203 } 204 205 /* Call Quit (maybe multiple times) */ 206 for (k=0; k <= j; k++) { 207 SDL_AudioQuit(); 208 SDLTest_AssertPass("Call to SDL_AudioQuit(), call %d", k+1); 209 } 210 211 } /* spec loop */ 212 } /* driver loop */ 213 214 /* Restart audio again */ 215 _audioSetUp(NULL); 216 217 return TEST_COMPLETED; 218} 219 220/** 221 * \brief Pause and unpause audio 222 * 223 * \sa https://wiki.libsdl.org/SDL_PauseAudio 224 */ 225int audio_pauseUnpauseAudio() 226{ 227 int result; 228 int i, iMax, j, k, l; 229 int totalDelay; 230 int pause_on; 231 int originalCounter; 232 const char* audioDriver; 233 SDL_AudioSpec desired; 234 235 /* Stop SDL audio subsystem */ 236 SDL_QuitSubSystem( SDL_INIT_AUDIO ); 237 SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); 238 239 /* Loop over all available audio drivers */ 240 iMax = SDL_GetNumAudioDrivers(); 241 SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers"); 242 SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); 243 for (i = 0; i < iMax; i++) { 244 audioDriver = SDL_GetAudioDriver(i); 245 SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); 246 SDLTest_AssertCheck(audioDriver != NULL, "Audio driver name is not NULL"); 247 SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); 248 249 /* Change specs */ 250 for (j = 0; j < 2; j++) { 251 252 /* Call Init */ 253 result = SDL_AudioInit(audioDriver); 254 SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver); 255 SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result); 256 257 /* Set spec */ 258 SDL_memset(&desired, 0, sizeof(desired)); 259 switch (j) { 260 case 0: 261 /* Set standard desired spec */ 262 desired.freq = 22050; 263 desired.format = AUDIO_S16SYS; 264 desired.channels = 2; 265 desired.samples = 4096; 266 desired.callback = _audio_testCallback; 267 desired.userdata = NULL; 268 269 case 1: 270 /* Set custom desired spec */ 271 desired.freq = 48000; 272 desired.format = AUDIO_F32SYS; 273 desired.channels = 2; 274 desired.samples = 2048; 275 desired.callback = _audio_testCallback; 276 desired.userdata = NULL; 277 break; 278 } 279 280 /* Call Open */ 281 result = SDL_OpenAudio(&desired, NULL); 282 SDLTest_AssertPass("Call to SDL_OpenAudio(desired_spec_%d, NULL)", j); 283 SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0 got: %d", result); 284 285 /* Start and stop audio multiple times */ 286 for (l=0; l<3; l++) { 287 SDLTest_Log("Pause/Unpause iteration: %d", l+1); 288 289 /* Reset callback counters */ 290 _audio_testCallbackCounter = 0; 291 _audio_testCallbackLength = 0; 292 293 /* Un-pause audio to start playing (maybe multiple times) */ 294 pause_on = 0; 295 for (k=0; k <= j; k++) { 296 SDL_PauseAudio(pause_on); 297 SDLTest_AssertPass("Call to SDL_PauseAudio(%d), call %d", pause_on, k+1); 298 } 299 300 /* Wait for callback */ 301 totalDelay = 0; 302 do { 303 SDL_Delay(10); 304 totalDelay += 10; 305 } 306 while (_audio_testCallbackCounter == 0 && totalDelay < 1000); 307 SDLTest_AssertCheck(_audio_testCallbackCounter > 0, "Verify callback counter; expected: >0 got: %d", _audio_testCallbackCounter); 308 SDLTest_AssertCheck(_audio_testCallbackLength > 0, "Verify callback length; expected: >0 got: %d", _audio_testCallbackLength); 309 310 /* Pause audio to stop playing (maybe multiple times) */ 311 for (k=0; k <= j; k++) { 312 pause_on = (k==0) ? 1 : SDLTest_RandomIntegerInRange(99, 9999); 313 SDL_PauseAudio(pause_on); 314 SDLTest_AssertPass("Call to SDL_PauseAudio(%d), call %d", pause_on, k+1); 315 } 316 317 /* Ensure callback is not called again */ 318 originalCounter = _audio_testCallbackCounter; 319 SDL_Delay(totalDelay + 10); 320 SDLTest_AssertCheck(originalCounter == _audio_testCallbackCounter, "Verify callback counter; expected: %d, got: %d", originalCounter, _audio_testCallbackCounter); 321 } 322 323 /* Call Close */ 324 SDL_CloseAudio(); 325 SDLTest_AssertPass("Call to SDL_CloseAudio()"); 326 327 /* Call Quit */ 328 SDL_AudioQuit(); 329 SDLTest_AssertPass("Call to SDL_AudioQuit()"); 330 331 } /* spec loop */ 332 } /* driver loop */ 333 334 /* Restart audio again */ 335 _audioSetUp(NULL); 336 337 return TEST_COMPLETED; 338} 339 340/** 341 * \brief Enumerate and name available audio devices (output and capture). 342 * 343 * \sa https://wiki.libsdl.org/SDL_GetNumAudioDevices 344 * \sa https://wiki.libsdl.org/SDL_GetAudioDeviceName 345 */ 346int audio_enumerateAndNameAudioDevices() 347{ 348 int t, tt; 349 int i, n, nn; 350 const char *name, *nameAgain; 351 352 /* Iterate over types: t=0 output device, t=1 input/capture device */ 353 for (t=0; t<2; t++) { 354 355 /* Get number of devices. */ 356 n = SDL_GetNumAudioDevices(t); 357 SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(%i)", t); 358 SDLTest_Log("Number of %s devices < 0, reported as %i", (t) ? "capture" : "output", n); 359 SDLTest_AssertCheck(n >= 0, "Validate result is >= 0, got: %i", n); 360 361 /* Variation of non-zero type */ 362 if (t==1) { 363 tt = t + SDLTest_RandomIntegerInRange(1,10); 364 nn = SDL_GetNumAudioDevices(tt); 365 SDLTest_AssertCheck(n==nn, "Verify result from SDL_GetNumAudioDevices(%i), expected same number of audio devices %i, got %i", tt, n, nn); 366 nn = SDL_GetNumAudioDevices(-tt); 367 SDLTest_AssertCheck(n==nn, "Verify result from SDL_GetNumAudioDevices(%i), expected same number of audio devices %i, got %i", -tt, n, nn); 368 } 369 370 /* List devices. */ 371 if (n>0) { 372 for (i=0; i<n; i++) { 373 name = SDL_GetAudioDeviceName(i, t); 374 SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i, %i)", i, t); 375 SDLTest_AssertCheck(name != NULL, "Verify result from SDL_GetAudioDeviceName(%i, %i) is not NULL", i, t); 376 if (name != NULL) { 377 SDLTest_AssertCheck(name[0] != '\0', "verify result from SDL_GetAudioDeviceName(%i, %i) is not empty, got: '%s'", i, t, name); 378 if (t==1) { 379 /* Also try non-zero type */ 380 tt = t + SDLTest_RandomIntegerInRange(1,10); 381 nameAgain = SDL_GetAudioDeviceName(i, tt); 382 SDLTest_AssertCheck(nameAgain != NULL, "Verify result from SDL_GetAudioDeviceName(%i, %i) is not NULL", i, tt); 383 if (nameAgain != NULL) { 384 SDLTest_AssertCheck(nameAgain[0] != '\0', "Verify result from SDL_GetAudioDeviceName(%i, %i) is not empty, got: '%s'", i, tt, nameAgain); 385 SDLTest_AssertCheck(SDL_strcmp(name, nameAgain)==0, 386 "Verify SDL_GetAudioDeviceName(%i, %i) and SDL_GetAudioDeviceName(%i %i) return the same string", 387 i, t, i, tt); 388 } 389 } 390 } 391 } 392 } 393 } 394 395 return TEST_COMPLETED; 396} 397 398/** 399 * \brief Negative tests around enumeration and naming of audio devices. 400 * 401 * \sa https://wiki.libsdl.org/SDL_GetNumAudioDevices 402 * \sa https://wiki.libsdl.org/SDL_GetAudioDeviceName 403 */ 404int audio_enumerateAndNameAudioDevicesNegativeTests() 405{ 406 int t; 407 int i, j, no, nc; 408 const char *name; 409 410 /* Get number of devices. */ 411 no = SDL_GetNumAudioDevices(0); 412 SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(0)"); 413 nc = SDL_GetNumAudioDevices(1); 414 SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(1)"); 415 416 /* Invalid device index when getting name */ 417 for (t=0; t<2; t++) { 418 /* Negative device index */ 419 i = SDLTest_RandomIntegerInRange(-10,-1); 420 name = SDL_GetAudioDeviceName(i, t); 421 SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i, %i)", i, t); 422 SDLTest_AssertCheck(name == NULL, "Check SDL_GetAudioDeviceName(%i, %i) result NULL, expected NULL, got: %s", i, t, (name == NULL) ? "NULL" : name); 423 424 /* Device index past range */ 425 for (j=0; j<3; j++) { 426 i = (t) ? nc+j : no+j; 427 name = SDL_GetAudioDeviceName(i, t); 428 SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i, %i)", i, t); 429 SDLTest_AssertCheck(name == NULL, "Check SDL_GetAudioDeviceName(%i, %i) result, expected: NULL, got: %s", i, t, (name == NULL) ? "NULL" : name); 430 } 431 432 /* Capture index past capture range but within output range */ 433 if ((no>0) && (no>nc) && (t==1)) { 434 i = no-1; 435 name = SDL_GetAudioDeviceName(i, t); 436 SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i, %i)", i, t); 437 SDLTest_AssertCheck(name == NULL, "Check SDL_GetAudioDeviceName(%i, %i) result, expected: NULL, got: %s", i, t, (name == NULL) ? "NULL" : name); 438 } 439 } 440 441 return TEST_COMPLETED; 442} 443 444 445/** 446 * \brief Checks available audio driver names. 447 * 448 * \sa https://wiki.libsdl.org/SDL_GetNumAudioDrivers 449 * \sa https://wiki.libsdl.org/SDL_GetAudioDriver 450 */ 451int audio_printAudioDrivers() 452{ 453 int i, n; 454 const char *name; 455 456 /* Get number of drivers */ 457 n = SDL_GetNumAudioDrivers(); 458 SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); 459 SDLTest_AssertCheck(n>=0, "Verify number of audio drivers >= 0, got: %i", n); 460 461 /* List drivers. */ 462 if (n>0) 463 { 464 for (i=0; i<n; i++) { 465 name = SDL_GetAudioDriver(i); 466 SDLTest_AssertPass("Call to SDL_GetAudioDriver(%i)", i); 467 SDLTest_AssertCheck(name != NULL, "Verify returned name is not NULL"); 468 if (name != NULL) { 469 SDLTest_AssertCheck(name[0] != '\0', "Verify returned name is not empty, got: '%s'", name); 470 } 471 } 472 } 473 474 return TEST_COMPLETED; 475} 476 477 478/** 479 * \brief Checks current audio driver name with initialized audio. 480 * 481 * \sa https://wiki.libsdl.org/SDL_GetCurrentAudioDriver 482 */ 483int audio_printCurrentAudioDriver() 484{ 485 /* Check current audio driver */ 486 const char *name = SDL_GetCurrentAudioDriver(); 487 SDLTest_AssertPass("Call to SDL_GetCurrentAudioDriver()"); 488 SDLTest_AssertCheck(name != NULL, "Verify returned name is not NULL"); 489 if (name != NULL) { 490 SDLTest_AssertCheck(name[0] != '\0', "Verify returned name is not empty, got: '%s'", name); 491 } 492 493 return TEST_COMPLETED; 494} 495 496/* Definition of all formats, channels, and frequencies used to test audio conversions */ 497const int _numAudioFormats = 18; 498SDL_AudioFormat _audioFormats[] = { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S16SYS, AUDIO_S16, AUDIO_U16LSB, 499 AUDIO_U16MSB, AUDIO_U16SYS, AUDIO_U16, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S32SYS, AUDIO_S32, 500 AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_F32SYS, AUDIO_F32 }; 501char *_audioFormatsVerbose[] = { "AUDIO_S8", "AUDIO_U8", "AUDIO_S16LSB", "AUDIO_S16MSB", "AUDIO_S16SYS", "AUDIO_S16", "AUDIO_U16LSB", 502 "AUDIO_U16MSB", "AUDIO_U16SYS", "AUDIO_U16", "AUDIO_S32LSB", "AUDIO_S32MSB", "AUDIO_S32SYS", "AUDIO_S32", 503 "AUDIO_F32LSB", "AUDIO_F32MSB", "AUDIO_F32SYS", "AUDIO_F32" }; 504const int _numAudioChannels = 4; 505Uint8 _audioChannels[] = { 1, 2, 4, 6 }; 506const int _numAudioFrequencies = 4; 507int _audioFrequencies[] = { 11025, 22050, 44100, 48000 }; 508 509 510/** 511 * \brief Builds various audio conversion structures 512 * 513 * \sa https://wiki.libsdl.org/SDL_BuildAudioCVT 514 */ 515int audio_buildAudioCVT() 516{ 517 int result; 518 SDL_AudioCVT cvt; 519 SDL_AudioSpec spec1; 520 SDL_AudioSpec spec2; 521 int i, ii, j, jj, k, kk; 522 523 /* No conversion needed */ 524 spec1.format = AUDIO_S16LSB; 525 spec1.channels = 2; 526 spec1.freq = 22050; 527 result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq, 528 spec1.format, spec1.channels, spec1.freq); 529 SDLTest_AssertPass("Call to SDL_BuildAudioCVT(spec1 ==> spec1)"); 530 SDLTest_AssertCheck(result == 0, "Verify result value; expected: 0, got: %i", result); 531 532 /* Typical conversion */ 533 spec1.format = AUDIO_S8; 534 spec1.channels = 1; 535 spec1.freq = 22050; 536 spec2.format = AUDIO_S16LSB; 537 spec2.channels = 2; 538 spec2.freq = 44100; 539 result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq, 540 spec2.format, spec2.channels, spec2.freq); 541 SDLTest_AssertPass("Call to SDL_BuildAudioCVT(spec1 ==> spec2)"); 542 SDLTest_AssertCheck(result == 1, "Verify result value; expected: 1, got: %i", result); 543 544 /* All source conversions with random conversion targets, allow 'null' conversions */ 545 for (i = 0; i < _numAudioFormats; i++) { 546 for (j = 0; j < _numAudioChannels; j++) { 547 for (k = 0; k < _numAudioFrequencies; k++) { 548 spec1.format = _audioFormats[i]; 549 spec1.channels = _audioChannels[j]; 550 spec1.freq = _audioFrequencies[k]; 551 ii = SDLTest_RandomIntegerInRange(0, _numAudioFormats - 1); 552 jj = SDLTest_RandomIntegerInRange(0, _numAudioChannels - 1); 553 kk = SDLTest_RandomIntegerInRange(0, _numAudioFrequencies - 1); 554 spec2.format = _audioFormats[ii]; 555 spec2.channels = _audioChannels[jj]; 556 spec2.freq = _audioFrequencies[kk]; 557 result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq, 558 spec2.format, spec2.channels, spec2.freq); 559 SDLTest_AssertPass("Call to SDL_BuildAudioCVT(format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i ==> format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i)", 560 i, _audioFormatsVerbose[i], spec1.format, j, spec1.channels, k, spec1.freq, ii, _audioFormatsVerbose[ii], spec2.format, jj, spec2.channels, kk, spec2.freq); 561 SDLTest_AssertCheck(result == 0 || result == 1, "Verify result value; expected: 0 or 1, got: %i", result); 562 if (result<0) { 563 SDLTest_LogError("%s", SDL_GetError()); 564 } else { 565 SDLTest_AssertCheck(cvt.len_mult > 0, "Verify that cvt.len_mult value; expected: >0, got: %i", cvt.len_mult); 566 } 567 } 568 } 569 } 570 571 return TEST_COMPLETED; 572} 573 574/** 575 * \brief Checkes calls with invalid input to SDL_BuildAudioCVT 576 * 577 * \sa https://wiki.libsdl.org/SDL_BuildAudioCVT 578 */ 579int audio_buildAudioCVTNegative() 580{ 581 const char *expectedError = "Parameter 'cvt' is invalid"; 582 const char *error; 583 int result; 584 SDL_AudioCVT cvt; 585 SDL_AudioSpec spec1; 586 SDL_AudioSpec spec2; 587 int i; 588 char message[256]; 589 590 /* Valid format */ 591 spec1.format = AUDIO_S8; 592 spec1.channels = 1; 593 spec1.freq = 22050; 594 spec2.format = AUDIO_S16LSB; 595 spec2.channels = 2; 596 spec2.freq = 44100; 597 598 SDL_ClearError(); 599 SDLTest_AssertPass("Call to SDL_ClearError()"); 600 601 /* NULL input for CVT buffer */ 602 result = SDL_BuildAudioCVT((SDL_AudioCVT *)NULL, spec1.format, spec1.channels, spec1.freq, 603 spec2.format, spec2.channels, spec2.freq); 604 SDLTest_AssertPass("Call to SDL_BuildAudioCVT(NULL,...)"); 605 SDLTest_AssertCheck(result == -1, "Verify result value; expected: -1, got: %i", result); 606 error = SDL_GetError(); 607 SDLTest_AssertPass("Call to SDL_GetError()"); 608 SDLTest_AssertCheck(error != NULL, "Validate that error message was not NULL"); 609 if (error != NULL) { 610 SDLTest_AssertCheck(SDL_strcmp(error, expectedError) == 0, 611 "Validate error message, expected: '%s', got: '%s'", expectedError, error); 612 } 613 614 /* Invalid conversions */ 615 for (i = 1; i < 64; i++) { 616 /* Valid format to start with */ 617 spec1.format = AUDIO_S8; 618 spec1.channels = 1; 619 spec1.freq = 22050; 620 spec2.format = AUDIO_S16LSB; 621 spec2.channels = 2; 622 spec2.freq = 44100; 623 624 SDL_ClearError(); 625 SDLTest_AssertPass("Call to SDL_ClearError()"); 626 627 /* Set various invalid format inputs */ 628 SDL_strlcpy(message, "Invalid: ", 256); 629 if (i & 1) { 630 SDL_strlcat(message, " spec1.format", 256); 631 spec1.format = 0; 632 } 633 if (i & 2) { 634 SDL_strlcat(message, " spec1.channels", 256); 635 spec1.channels = 0; 636 } 637 if (i & 4) { 638 SDL_strlcat(message, " spec1.freq", 256); 639 spec1.freq = 0; 640 } 641 if (i & 8) { 642 SDL_strlcat(message, " spec2.format", 256); 643 spec2.format = 0; 644 } 645 if (i & 16) { 646 SDL_strlcat(message, " spec2.channels", 256); 647 spec2.channels = 0; 648 } 649 if (i & 32) { 650 SDL_strlcat(message, " spec2.freq", 256); 651 spec2.freq = 0; 652 } 653 SDLTest_Log("%s", message); 654 result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq, 655 spec2.format, spec2.channels, spec2.freq); 656 SDLTest_AssertPass("Call to SDL_BuildAudioCVT(spec1 ==> spec2)"); 657 SDLTest_AssertCheck(result == -1, "Verify result value; expected: -1, got: %i", result); 658 error = SDL_GetError(); 659 SDLTest_AssertPass("Call to SDL_GetError()"); 660 SDLTest_AssertCheck(error != NULL && error[0] != '\0', "Validate that error message was not NULL or empty"); 661 } 662 663 SDL_ClearError(); 664 SDLTest_AssertPass("Call to SDL_ClearError()"); 665 666 return TEST_COMPLETED; 667} 668 669/** 670 * \brief Checks current audio status. 671 * 672 * \sa https://wiki.libsdl.org/SDL_GetAudioStatus 673 */ 674int audio_getAudioStatus() 675{ 676 SDL_AudioStatus result; 677 678 /* Check current audio status */ 679 result = SDL_GetAudioStatus(); 680 SDLTest_AssertPass("Call to SDL_GetAudioStatus()"); 681 SDLTest_AssertCheck(result == SDL_AUDIO_STOPPED || result == SDL_AUDIO_PLAYING || result == SDL_AUDIO_PAUSED, 682 "Verify returned value; expected: STOPPED (%i) | PLAYING (%i) | PAUSED (%i), got: %i", 683 SDL_AUDIO_STOPPED, SDL_AUDIO_PLAYING, SDL_AUDIO_PAUSED, result); 684 685 return TEST_COMPLETED; 686} 687 688 689 690/** 691 * \brief Opens, checks current audio status, and closes a device. 692 * 693 * \sa https://wiki.libsdl.org/SDL_GetAudioStatus 694 */ 695int audio_openCloseAndGetAudioStatus() 696{ 697 SDL_AudioStatus result; 698 int i; 699 int count; 700 char *device; 701 SDL_AudioDeviceID id; 702 SDL_AudioSpec desired, obtained; 703 704 /* Get number of devices. */ 705 count = SDL_GetNumAudioDevices(0); 706 SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(0)"); 707 if (count > 0) { 708 for (i = 0; i < count; i++) { 709 /* Get device name */ 710 device = (char *)SDL_GetAudioDeviceName(i, 0); 711 SDLTest_AssertPass("SDL_GetAudioDeviceName(%i,0)", i); 712 SDLTest_AssertCheck(device != NULL, "Validate device name is not NULL; got: %s", (device != NULL) ? device : "NULL"); 713 if (device == NULL) return TEST_ABORTED; 714 715 /* Set standard desired spec */ 716 desired.freq=22050; 717 desired.format=AUDIO_S16SYS; 718 desired.channels=2; 719 desired.samples=4096; 720 desired.callback=_audio_testCallback; 721 desired.userdata=NULL; 722 723 /* Open device */ 724 id = SDL_OpenAudioDevice((const char *)device, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE); 725 SDLTest_AssertPass("SDL_OpenAudioDevice('%s',...)", device); 726 SDLTest_AssertCheck(id > 1, "Validate device ID; expected: >=2, got: %i", id); 727 if (id > 1) { 728 729 /* Check device audio status */ 730 result = SDL_GetAudioDeviceStatus(id); 731 SDLTest_AssertPass("Call to SDL_GetAudioDeviceStatus()"); 732 SDLTest_AssertCheck(result == SDL_AUDIO_STOPPED || result == SDL_AUDIO_PLAYING || result == SDL_AUDIO_PAUSED, 733 "Verify returned value; expected: STOPPED (%i) | PLAYING (%i) | PAUSED (%i), got: %i", 734 SDL_AUDIO_STOPPED, SDL_AUDIO_PLAYING, SDL_AUDIO_PAUSED, result); 735 736 /* Close device again */ 737 SDL_CloseAudioDevice(id); 738 SDLTest_AssertPass("Call to SDL_CloseAudioDevice()"); 739 } 740 } 741 } else { 742 SDLTest_Log("No devices to test with"); 743 } 744 745 return TEST_COMPLETED; 746} 747 748/** 749 * \brief Locks and unlocks open audio device. 750 * 751 * \sa https://wiki.libsdl.org/SDL_LockAudioDevice 752 * \sa https://wiki.libsdl.org/SDL_UnlockAudioDevice 753 */ 754int audio_lockUnlockOpenAudioDevice() 755{ 756 int i; 757 int count; 758 char *device; 759 SDL_AudioDeviceID id; 760 SDL_AudioSpec desired, obtained; 761 762 /* Get number of devices. */ 763 count = SDL_GetNumAudioDevices(0); 764 SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(0)"); 765 if (count > 0) { 766 for (i = 0; i < count; i++) { 767 /* Get device name */ 768 device = (char *)SDL_GetAudioDeviceName(i, 0); 769 SDLTest_AssertPass("SDL_GetAudioDeviceName(%i,0)", i); 770 SDLTest_AssertCheck(device != NULL, "Validate device name is not NULL; got: %s", (device != NULL) ? device : "NULL"); 771 if (device == NULL) return TEST_ABORTED; 772 773 /* Set standard desired spec */ 774 desired.freq=22050; 775 desired.format=AUDIO_S16SYS; 776 desired.channels=2; 777 desired.samples=4096; 778 desired.callback=_audio_testCallback; 779 desired.userdata=NULL; 780 781 /* Open device */ 782 id = SDL_OpenAudioDevice((const char *)device, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE); 783 SDLTest_AssertPass("SDL_OpenAudioDevice('%s',...)", device); 784 SDLTest_AssertCheck(id > 1, "Validate device ID; expected: >=2, got: %i", id); 785 if (id > 1) { 786 /* Lock to protect callback */ 787 SDL_LockAudioDevice(id); 788 SDLTest_AssertPass("SDL_LockAudioDevice(%i)", id); 789 790 /* Simulate callback processing */ 791 SDL_Delay(10); 792 SDLTest_Log("Simulate callback processing - delay"); 793 794 /* Unlock again */ 795 SDL_UnlockAudioDevice(id); 796 SDLTest_AssertPass("SDL_UnlockAudioDevice(%i)", id); 797 798 /* Close device again */ 799 SDL_CloseAudioDevice(id); 800 SDLTest_AssertPass("Call to SDL_CloseAudioDevice()"); 801 } 802 } 803 } else { 804 SDLTest_Log("No devices to test with"); 805 } 806 807 return TEST_COMPLETED; 808} 809 810 811/** 812 * \brief Convert audio using various conversion structures 813 * 814 * \sa https://wiki.libsdl.org/SDL_BuildAudioCVT 815 * \sa https://wiki.libsdl.org/SDL_ConvertAudio 816 */ 817int audio_convertAudio() 818{ 819 int result; 820 SDL_AudioCVT cvt; 821 SDL_AudioSpec spec1; 822 SDL_AudioSpec spec2; 823 int c; 824 char message[128]; 825 int i, ii, j, jj, k, kk, l, ll; 826 827 /* Iterate over bitmask that determines which parameters are modified in the conversion */ 828 for (c = 1; c < 8; c++) { 829 SDL_strlcpy(message, "Changing:", 128); 830 if (c & 1) { 831 SDL_strlcat(message, " Format", 128); 832 } 833 if (c & 2) { 834 SDL_strlcat(message, " Channels", 128); 835 } 836 if (c & 4) { 837 SDL_strlcat(message, " Frequencies", 128); 838 } 839 SDLTest_Log("%s", message); 840 /* All source conversions with random conversion targets */ 841 for (i = 0; i < _numAudioFormats; i++) { 842 for (j = 0; j < _numAudioChannels; j++) { 843 for (k = 0; k < _numAudioFrequencies; k++) { 844 spec1.format = _audioFormats[i]; 845 spec1.channels = _audioChannels[j]; 846 spec1.freq = _audioFrequencies[k]; 847 848 /* Ensure we have a different target format */ 849 do { 850 if (c & 1) { 851 ii = SDLTest_RandomIntegerInRange(0, _numAudioFormats - 1); 852 } else { 853 ii = 1; 854 } 855 if (c & 2) { 856 jj = SDLTest_RandomIntegerInRange(0, _numAudioChannels - 1); 857 } else { 858 jj= j; 859 } 860 if (c & 4) { 861 kk = SDLTest_RandomIntegerInRange(0, _numAudioFrequencies - 1); 862 } else { 863 kk = k; 864 } 865 } while ((i == ii) && (j == jj) && (k == kk)); 866 spec2.format = _audioFormats[ii]; 867 spec2.channels = _audioChannels[jj]; 868 spec2.freq = _audioFrequencies[kk]; 869 870 result = SDL_BuildAudioCVT(&cvt, spec1.format, spec1.channels, spec1.freq, 871 spec2.format, spec2.channels, spec2.freq); 872 SDLTest_AssertPass("Call to SDL_BuildAudioCVT(format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i ==> format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i)", 873 i, _audioFormatsVerbose[i], spec1.format, j, spec1.channels, k, spec1.freq, ii, _audioFormatsVerbose[ii], spec2.format, jj, spec2.channels, kk, spec2.freq); 874 SDLTest_AssertCheck(result == 1, "Verify result value; expected: 1, got: %i", result); 875 if (result != 1) { 876 SDLTest_LogError("%s", SDL_GetError()); 877 } else { 878 SDLTest_AssertCheck(cvt.len_mult > 0, "Verify that cvt.len_mult value; expected: >0, got: %i", cvt.len_mult); 879 if (cvt.len_mult < 1) return TEST_ABORTED; 880 881 /* Create some random data to convert */ 882 l = 64; 883 ll = l * cvt.len_mult; 884 SDLTest_Log("Creating dummy sample buffer of %i length (%i bytes)", l, ll); 885 cvt.len = l; 886 cvt.buf = (Uint8 *)SDL_malloc(ll); 887 SDLTest_AssertCheck(cvt.buf != NULL, "Check data buffer to convert is not NULL"); 888 if (cvt.buf == NULL) return TEST_ABORTED; 889 890 /* Convert the data */ 891 result = SDL_ConvertAudio(&cvt); 892 SDLTest_AssertPass("Call to SDL_ConvertAudio()"); 893 SDLTest_AssertCheck(result == 0, "Verify result value; expected: 0; got: %i", result); 894 SDLTest_AssertCheck(cvt.buf != NULL, "Verify conversion buffer is not NULL"); 895 SDLTest_AssertCheck(cvt.len_ratio > 0.0, "Verify conversion length ratio; expected: >0; got: %f", cvt.len_ratio); 896 897 /* Free converted buffer */ 898 SDL_free(cvt.buf); 899 cvt.buf = NULL; 900 } 901 } 902 } 903 } 904 } 905 906 return TEST_COMPLETED; 907} 908 909 910/** 911 * \brief Opens, checks current connected status, and closes a device. 912 * 913 * \sa https://wiki.libsdl.org/SDL_AudioDeviceConnected 914 */ 915int audio_openCloseAudioDeviceConnected() 916{ 917 int result = -1; 918 int i; 919 int count; 920 char *device; 921 SDL_AudioDeviceID id; 922 SDL_AudioSpec desired, obtained; 923 924 /* Get number of devices. */ 925 count = SDL_GetNumAudioDevices(0); 926 SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(0)"); 927 if (count > 0) { 928 for (i = 0; i < count; i++) { 929 /* Get device name */ 930 device = (char *)SDL_GetAudioDeviceName(i, 0); 931 SDLTest_AssertPass("SDL_GetAudioDeviceName(%i,0)", i); 932 SDLTest_AssertCheck(device != NULL, "Validate device name is not NULL; got: %s", (device != NULL) ? device : "NULL"); 933 if (device == NULL) return TEST_ABORTED; 934 935 /* Set standard desired spec */ 936 desired.freq=22050; 937 desired.format=AUDIO_S16SYS; 938 desired.channels=2; 939 desired.samples=4096; 940 desired.callback=_audio_testCallback; 941 desired.userdata=NULL; 942 943 /* Open device */ 944 id = SDL_OpenAudioDevice((const char *)device, 0, &desired, &obtained, SDL_AUDIO_ALLOW_ANY_CHANGE); 945 SDLTest_AssertPass("SDL_OpenAudioDevice('%s',...)", device); 946 SDLTest_AssertCheck(id > 1, "Validate device ID; expected: >1, got: %i", id); 947 if (id > 1) { 948 949/* TODO: enable test code when function is available in SDL2 */ 950 951#ifdef AUDIODEVICECONNECTED_DEFINED 952 /* Get connected status */ 953 result = SDL_AudioDeviceConnected(id); 954 SDLTest_AssertPass("Call to SDL_AudioDeviceConnected()"); 955#endif 956 SDLTest_AssertCheck(result == 1, "Verify returned value; expected: 1; got: %i", result); 957 958 /* Close device again */ 959 SDL_CloseAudioDevice(id); 960 SDLTest_AssertPass("Call to SDL_CloseAudioDevice()"); 961 } 962 } 963 } else { 964 SDLTest_Log("No devices to test with"); 965 } 966 967 return TEST_COMPLETED; 968} 969 970 971 972/* ================= Test Case References ================== */ 973 974/* Audio test cases */ 975static const SDLTest_TestCaseReference audioTest1 = 976 { (SDLTest_TestCaseFp)audio_enumerateAndNameAudioDevices, "audio_enumerateAndNameAudioDevices", "Enumerate and name available audio devices (output and capture)", TEST_ENABLED }; 977 978static const SDLTest_TestCaseReference audioTest2 = 979 { (SDLTest_TestCaseFp)audio_enumerateAndNameAudioDevicesNegativeTests, "audio_enumerateAndNameAudioDevicesNegativeTests", "Negative tests around enumeration and naming of audio devices.", TEST_ENABLED }; 980 981static const SDLTest_TestCaseReference audioTest3 = 982 { (SDLTest_TestCaseFp)audio_printAudioDrivers, "audio_printAudioDrivers", "Checks available audio driver names.", TEST_ENABLED }; 983 984static const SDLTest_TestCaseReference audioTest4 = 985 { (SDLTest_TestCaseFp)audio_printCurrentAudioDriver, "audio_printCurrentAudioDriver", "Checks current audio driver name with initialized audio.", TEST_ENABLED }; 986 987static const SDLTest_TestCaseReference audioTest5 = 988 { (SDLTest_TestCaseFp)audio_buildAudioCVT, "audio_buildAudioCVT", "Builds various audio conversion structures.", TEST_ENABLED }; 989 990static const SDLTest_TestCaseReference audioTest6 = 991 { (SDLTest_TestCaseFp)audio_buildAudioCVTNegative, "audio_buildAudioCVTNegative", "Checks calls with invalid input to SDL_BuildAudioCVT", TEST_ENABLED }; 992 993static const SDLTest_TestCaseReference audioTest7 = 994 { (SDLTest_TestCaseFp)audio_getAudioStatus, "audio_getAudioStatus", "Checks current audio status.", TEST_ENABLED }; 995 996static const SDLTest_TestCaseReference audioTest8 = 997 { (SDLTest_TestCaseFp)audio_openCloseAndGetAudioStatus, "audio_openCloseAndGetAudioStatus", "Opens and closes audio device and get audio status.", TEST_ENABLED }; 998 999static const SDLTest_TestCaseReference audioTest9 = 1000 { (SDLTest_TestCaseFp)audio_lockUnlockOpenAudioDevice, "audio_lockUnlockOpenAudioDevice", "Locks and unlocks an open audio device.", TEST_ENABLED }; 1001 1002/* TODO: enable test when SDL_ConvertAudio segfaults on cygwin have been fixed. */ 1003/* For debugging, test case can be run manually using --filter audio_convertAudio */ 1004 1005static const SDLTest_TestCaseReference audioTest10 = 1006 { (SDLTest_TestCaseFp)audio_convertAudio, "audio_convertAudio", "Convert audio using available formats.", TEST_DISABLED }; 1007 1008/* TODO: enable test when SDL_AudioDeviceConnected has been implemented. */ 1009 1010static const SDLTest_TestCaseReference audioTest11 = 1011 { (SDLTest_TestCaseFp)audio_openCloseAudioDeviceConnected, "audio_openCloseAudioDeviceConnected", "Opens and closes audio device and get connected status.", TEST_DISABLED }; 1012 1013static const SDLTest_TestCaseReference audioTest12 = 1014 { (SDLTest_TestCaseFp)audio_quitInitAudioSubSystem, "audio_quitInitAudioSubSystem", "Quit and re-init audio subsystem.", TEST_ENABLED }; 1015 1016static const SDLTest_TestCaseReference audioTest13 = 1017 { (SDLTest_TestCaseFp)audio_initQuitAudio, "audio_initQuitAudio", "Init and quit audio drivers directly.", TEST_ENABLED }; 1018 1019static const SDLTest_TestCaseReference audioTest14 = 1020 { (SDLTest_TestCaseFp)audio_initOpenCloseQuitAudio, "audio_initOpenCloseQuitAudio", "Cycle through init, open, close and quit with various audio specs.", TEST_ENABLED }; 1021 1022static const SDLTest_TestCaseReference audioTest15 = 1023 { (SDLTest_TestCaseFp)audio_pauseUnpauseAudio, "audio_pauseUnpauseAudio", "Pause and Unpause audio for various audio specs while testing callback.", TEST_ENABLED }; 1024 1025/* Sequence of Audio test cases */ 1026static const SDLTest_TestCaseReference *audioTests[] = { 1027 &audioTest1, &audioTest2, &audioTest3, &audioTest4, &audioTest5, &audioTest6, 1028 &audioTest7, &audioTest8, &audioTest9, &audioTest10, &audioTest11, 1029 &audioTest12, &audioTest13, &audioTest14, &audioTest15, NULL 1030}; 1031 1032/* Audio test suite (global) */ 1033SDLTest_TestSuiteReference audioTestSuite = { 1034 "Audio", 1035 _audioSetUp, 1036 audioTests, 1037 _audioTearDown 1038};