VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/AudioTest.cpp@ 89045

Last change on this file since 89045 was 89045, checked in by vboxsync, 4 years ago

Audio/ValKit: Allow re-running the same test set (with the same tag) by using different sub directories. bugref:10008

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.0 KB
Line 
1/* $Id: AudioTest.cpp 89045 2021-05-14 13:17:36Z vboxsync $ */
2/** @file
3 * Audio testing routines.
4 * Common code which is being used by the ValidationKit and the debug / ValdikationKit audio driver(s).
5 */
6
7/*
8 * Copyright (C) 2021 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19
20/*********************************************************************************************************************************
21* Header Files *
22*********************************************************************************************************************************/
23
24#include <package-generated.h>
25#include "product-generated.h"
26
27#include <iprt/buildconfig.h>
28#include <iprt/dir.h>
29#include <iprt/file.h>
30#include <iprt/inifile.h>
31#include <iprt/list.h>
32#include <iprt/rand.h>
33#include <iprt/system.h>
34#include <iprt/uuid.h>
35#include <iprt/vfs.h>
36
37#define _USE_MATH_DEFINES
38#include <math.h> /* sin, M_PI */
39
40#include <VBox/version.h>
41#include <VBox/vmm/pdmaudioifs.h>
42#include <VBox/vmm/pdmaudioinline.h>
43
44#include "AudioTest.h"
45
46
47/*********************************************************************************************************************************
48* Defines *
49*********************************************************************************************************************************/
50/** The test manifest file name. */
51#define AUDIOTEST_MANIFEST_FILE_STR "vkat_manifest.ini"
52/** The current test manifest version. */
53#define AUDIOTEST_MANIFEST_VER 1
54
55/** Test manifest header name. */
56#define AUDIOTEST_INI_SEC_HDR_STR "header"
57
58
59/*********************************************************************************************************************************
60* Structures and Typedefs *
61*********************************************************************************************************************************/
62
63
64/*********************************************************************************************************************************
65* Global Variables *
66*********************************************************************************************************************************/
67/** Well-known frequency selection test tones. */
68static const double s_aAudioTestToneFreqsHz[] =
69{
70 349.2282 /*F4*/,
71 440.0000 /*A4*/,
72 523.2511 /*C5*/,
73 698.4565 /*F5*/,
74 880.0000 /*A5*/,
75 1046.502 /*C6*/,
76 1174.659 /*D6*/,
77 1396.913 /*F6*/,
78 1760.0000 /*A6*/
79};
80
81/**
82 * Initializes a test tone by picking a random but well-known frequency (in Hz).
83 *
84 * @returns Randomly picked frequency (in Hz).
85 * @param pTone Pointer to test tone to initialize.
86 * @param pProps PCM properties to use for the test tone.
87 */
88double AudioTestToneInitRandom(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps)
89{
90 /* Pick a frequency from our selection, so that every time a recording starts
91 * we'll hopfully generate a different note. */
92 pTone->rdFreqHz = s_aAudioTestToneFreqsHz[RTRandU32Ex(0, RT_ELEMENTS(s_aAudioTestToneFreqsHz) - 1)];
93 pTone->rdFixed = 2.0 * M_PI * pTone->rdFreqHz / PDMAudioPropsHz(pProps);
94 pTone->uSample = 0;
95
96 memcpy(&pTone->Props, pProps, sizeof(PDMAUDIOPCMPROPS));
97
98 pTone->enmType = AUDIOTESTTONETYPE_SINE; /* Only type implemented so far. */
99
100 return pTone->rdFreqHz;
101}
102
103/**
104 * Writes (and iterates) a given test tone to an output buffer.
105 *
106 * @returns VBox status code.
107 * @param pTone Pointer to test tone to write.
108 * @param pvBuf Pointer to output buffer to write test tone to.
109 * @param cbBuf Size (in bytes) of output buffer.
110 * @param pcbWritten How many bytes were written on success.
111 */
112int AudioTestToneWrite(PAUDIOTESTTONE pTone, void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)
113{
114 /*
115 * Clear the buffer first so we don't need to thing about additional channels.
116 */
117 uint32_t cFrames = PDMAudioPropsBytesToFrames(&pTone->Props, cbBuf);
118 PDMAudioPropsClearBuffer(&pTone->Props, pvBuf, cbBuf, cFrames);
119
120 /*
121 * Generate the select sin wave in the first channel:
122 */
123 uint32_t const cbFrame = PDMAudioPropsFrameSize(&pTone->Props);
124 double const rdFixed = pTone->rdFixed;
125 uint64_t iSrcFrame = pTone->uSample;
126 switch (PDMAudioPropsSampleSize(&pTone->Props))
127 {
128 case 1:
129 /* untested */
130 if (PDMAudioPropsIsSigned(&pTone->Props))
131 {
132 int8_t *piSample = (int8_t *)pvBuf;
133 while (cFrames-- > 0)
134 {
135 *piSample = (int8_t)(126 /*Amplitude*/ * sin(rdFixed * iSrcFrame));
136 iSrcFrame++;
137 piSample += cbFrame;
138 }
139 }
140 else
141 {
142 /* untested */
143 uint8_t *pbSample = (uint8_t *)pvBuf;
144 while (cFrames-- > 0)
145 {
146 *pbSample = (uint8_t)(126 /*Amplitude*/ * sin(rdFixed * iSrcFrame) + 0x80);
147 iSrcFrame++;
148 pbSample += cbFrame;
149 }
150 }
151 break;
152
153 case 2:
154 if (PDMAudioPropsIsSigned(&pTone->Props))
155 {
156 int16_t *piSample = (int16_t *)pvBuf;
157 while (cFrames-- > 0)
158 {
159 *piSample = (int16_t)(32760 /*Amplitude*/ * sin(rdFixed * iSrcFrame));
160 iSrcFrame++;
161 piSample = (int16_t *)((uint8_t *)piSample + cbFrame);
162 }
163 }
164 else
165 {
166 /* untested */
167 uint16_t *puSample = (uint16_t *)pvBuf;
168 while (cFrames-- > 0)
169 {
170 *puSample = (uint16_t)(32760 /*Amplitude*/ * sin(rdFixed * iSrcFrame) + 0x8000);
171 iSrcFrame++;
172 puSample = (uint16_t *)((uint8_t *)puSample + cbFrame);
173 }
174 }
175 break;
176
177 case 4:
178 /* untested */
179 if (PDMAudioPropsIsSigned(&pTone->Props))
180 {
181 int32_t *piSample = (int32_t *)pvBuf;
182 while (cFrames-- > 0)
183 {
184 *piSample = (int32_t)((32760 << 16) /*Amplitude*/ * sin(rdFixed * iSrcFrame));
185 iSrcFrame++;
186 piSample = (int32_t *)((uint8_t *)piSample + cbFrame);
187 }
188 }
189 else
190 {
191 uint32_t *puSample = (uint32_t *)pvBuf;
192 while (cFrames-- > 0)
193 {
194 *puSample = (uint32_t)((32760 << 16) /*Amplitude*/ * sin(rdFixed * iSrcFrame) + UINT32_C(0x80000000));
195 iSrcFrame++;
196 puSample = (uint32_t *)((uint8_t *)puSample + cbFrame);
197 }
198 }
199 break;
200
201 default:
202 AssertFailedReturn(VERR_NOT_SUPPORTED);
203 }
204
205 pTone->uSample = iSrcFrame;
206
207 if (pcbWritten)
208 *pcbWritten = PDMAudioPropsFramesToBytes(&pTone->Props, cFrames);
209
210 return VINF_SUCCESS;
211}
212
213/**
214 * Initializes an audio test tone parameters struct with random values.
215 * @param pToneParams Test tone parameters to initialize.
216 * @param pProps PCM properties to use for the test tone.
217 */
218int AudioTestToneParamsInitRandom(PAUDIOTESTTONEPARMS pToneParams, PPDMAUDIOPCMPROPS pProps)
219{
220 AssertReturn(PDMAudioPropsAreValid(pProps), VERR_INVALID_PARAMETER);
221
222 memcpy(&pToneParams->Props, pProps, sizeof(PDMAUDIOPCMPROPS));
223
224 /** @todo Make this a bit more sophisticated later, e.g. muting and prequel/sequel are not very balanced. */
225
226 pToneParams->msPrequel = RTRandU32Ex(0, RT_MS_5SEC);
227 pToneParams->msDuration = RTRandU32Ex(0, RT_MS_10SEC); /** @todo Probably a bit too long, but let's see. */
228 pToneParams->msSequel = RTRandU32Ex(0, RT_MS_5SEC);
229 pToneParams->uVolumePercent = RTRandU32Ex(0, 100);
230
231 return VINF_SUCCESS;
232}
233
234/**
235 * Creates a new path (directory) for a specific audio test set tag.
236 *
237 * @returns VBox status code.
238 * @param pszPath On input, specifies the absolute base path where to create the test set path.
239 * On output this specifies the absolute path created.
240 * @param cbPath Size (in bytes) of \a pszPath.
241 * @param pszTag Tag to use for path creation.
242 *
243 * @note Can be used multiple times with the same tag; a sub directory with an ISO time string will be used
244 * on each call.
245 */
246int AudioTestPathCreate(char *pszPath, size_t cbPath, const char *pszTag)
247{
248 int rc;
249
250 char szTag[RTUUID_STR_LENGTH + 1];
251 if (pszTag)
252 {
253 rc = RTStrCopy(szTag, sizeof(szTag), pszTag);
254 AssertRCReturn(rc, rc);
255 }
256 else /* Create an UUID if no tag is specified. */
257 {
258 RTUUID UUID;
259 rc = RTUuidCreate(&UUID);
260 AssertRCReturn(rc, rc);
261 rc = RTUuidToStr(&UUID, szTag, sizeof(szTag));
262 AssertRCReturn(rc, rc);
263 }
264
265 char szName[128];
266 if (RTStrPrintf2(szName, sizeof(szName), "%s%s", AUDIOTEST_PATH_PREFIX_STR, szTag) < 0)
267 AssertFailedReturn(VERR_BUFFER_OVERFLOW);
268
269 rc = RTPathAppend(pszPath, cbPath, szName);
270 AssertRCReturn(rc, rc);
271
272 char szTime[64];
273 RTTIMESPEC time;
274 if (!RTTimeSpecToString(RTTimeNow(&time), szTime, sizeof(szTime)))
275 return VERR_BUFFER_UNDERFLOW;
276
277 rc = RTPathAppend(pszPath, cbPath, szTime);
278 AssertRCReturn(rc, rc);
279
280 return RTDirCreateFullPath(pszPath, RTFS_UNIX_IRWXU);
281}
282
283/**
284 * Writes string data to a test set manifest.
285 *
286 * @returns VBox status code.
287 * @param pSet Test set to write manifest for.
288 * @param pszFormat Format string to write.
289 * @param args Variable arguments for \a pszFormat.
290 */
291static int audioTestManifestWriteV(PAUDIOTESTSET pSet, const char *pszFormat, va_list args)
292{
293 char *psz = NULL;
294 RTStrAPrintfV(&psz, pszFormat, args);
295 AssertPtr(psz);
296
297 /** @todo Use RTIniFileWrite once its implemented. */
298 int rc = RTFileWrite(pSet->f.hFile, psz, strlen(psz), NULL);
299 AssertRC(rc);
300
301 RTStrFree(psz);
302
303 return rc;
304}
305
306/**
307 * Writes a terminated string line to a test set manifest.
308 * Convenience function.
309 *
310 * @returns VBox status code.
311 * @param pSet Test set to write manifest for.
312 * @param pszFormat Format string to write.
313 * @param ... Variable arguments for \a pszFormat. Optional.
314 */
315static int audioTestManifestWriteLn(PAUDIOTESTSET pSet, const char *pszFormat, ...)
316{
317 va_list va;
318 va_start(va, pszFormat);
319
320 int rc = audioTestManifestWriteV(pSet, pszFormat, va);
321 AssertRC(rc);
322
323 va_end(va);
324
325 /** @todo Keep it as simple as possible for now. Improve this later. */
326 rc = RTFileWrite(pSet->f.hFile, "\n", strlen("\n"), NULL);
327 AssertRC(rc);
328
329 return rc;
330}
331
332/**
333 * Writes a section entry to a test set manifest.
334 *
335 * @returns VBox status code.
336 * @param pSet Test set to write manifest for.
337 * @param pszSection Format string of section to write.
338 * @param ... Variable arguments for \a pszSection. Optional.
339 */
340static int audioTestManifestWriteSection(PAUDIOTESTSET pSet, const char *pszSection, ...)
341{
342 va_list va;
343 va_start(va, pszSection);
344
345 /** @todo Keep it as simple as possible for now. Improve this later. */
346 int rc = RTFileWrite(pSet->f.hFile, "[", strlen("["), NULL);
347 AssertRC(rc);
348
349 rc = audioTestManifestWriteV(pSet, pszSection, va);
350 AssertRC(rc);
351
352 rc = RTFileWrite(pSet->f.hFile, "]\n", strlen("]\n"), NULL);
353 AssertRC(rc);
354
355 va_end(va);
356
357 return rc;
358}
359
360/**
361 * Initializes an audio test set, internal function.
362 * @param pSet Test set to initialize.
363 */
364static void audioTestSetInitInternal(PAUDIOTESTSET pSet)
365{
366 pSet->f.hFile = NIL_RTFILE;
367}
368
369/**
370 * Returns whether a test set's manifest file is open (and thus ready) or not.
371 *
372 * @returns \c true if open (and ready), or \c false if not.
373 * @retval VERR_
374 * @param pSet Test set to return open status for.
375 */
376static bool audioTestManifestIsOpen(PAUDIOTESTSET pSet)
377{
378 if ( pSet->enmMode == AUDIOTESTSETMODE_TEST
379 && pSet->f.hFile != NIL_RTFILE)
380 return true;
381 else if ( pSet->enmMode == AUDIOTESTSETMODE_VERIFY
382 && pSet->f.hIniFile != NIL_RTINIFILE)
383 return true;
384
385 return false;
386}
387
388/**
389 * Initializes an audio test error description.
390 *
391 * @param pErr Test error description to initialize.
392 */
393static void audioTestErrorDescInit(PAUDIOTESTERRORDESC pErr)
394{
395 RTListInit(&pErr->List);
396 pErr->cErrors = 0;
397}
398
399/**
400 * Destroys an audio test error description.
401 *
402 * @param pErr Test error description to destroy.
403 */
404void AudioTestErrorDescDestroy(PAUDIOTESTERRORDESC pErr)
405{
406 if (!pErr)
407 return;
408
409 PAUDIOTESTERRORENTRY pErrEntry, pErrEntryNext;
410 RTListForEachSafe(&pErr->List, pErrEntry, pErrEntryNext, AUDIOTESTERRORENTRY, Node)
411 {
412 RTListNodeRemove(&pErrEntry->Node);
413
414 RTMemFree(pErrEntry);
415
416 Assert(pErr->cErrors);
417 pErr->cErrors--;
418 }
419
420 Assert(pErr->cErrors == 0);
421}
422
423/**
424 * Returns if an audio test error description contains any errors or not.
425 *
426 * @returns \c true if it contains errors, or \c false if not.
427 *
428 * @param pErr Test error description to return error status for.
429 */
430bool AudioTestErrorDescFailed(PAUDIOTESTERRORDESC pErr)
431{
432 if (pErr->cErrors)
433 {
434 Assert(!RTListIsEmpty(&pErr->List));
435 return true;
436 }
437
438 return false;
439}
440
441/**
442 * Adds a single error entry to an audio test error description, va_list version.
443 *
444 * @returns VBox status code.
445 * @param pErr Test error description to add entry for.
446 * @param rc Result code of entry to add.
447 * @param pszDesc Error description format string to add.
448 * @param args Optional format arguments of \a pszDesc to add.
449 */
450static int audioTestErrorDescAddV(PAUDIOTESTERRORDESC pErr, int rc, const char *pszDesc, va_list args)
451{
452 PAUDIOTESTERRORENTRY pEntry = (PAUDIOTESTERRORENTRY)RTMemAlloc(sizeof(AUDIOTESTERRORENTRY));
453 AssertReturn(pEntry, VERR_NO_MEMORY);
454
455 if (RTStrPrintf2V(pEntry->szDesc, sizeof(pEntry->szDesc), pszDesc, args) < 0)
456 AssertFailedReturn(VERR_BUFFER_OVERFLOW);
457
458 pEntry->rc = rc;
459
460 RTListAppend(&pErr->List, &pEntry->Node);
461
462 pErr->cErrors++;
463
464 return VINF_SUCCESS;
465}
466
467/**
468 * Adds a single error entry to an audio test error description, va_list version.
469 *
470 * @returns VBox status code.
471 * @param pErr Test error description to add entry for.
472 * @param pszDesc Error description format string to add.
473 * @param ... Optional format arguments of \a pszDesc to add.
474 */
475static int audioTestErrorDescAdd(PAUDIOTESTERRORDESC pErr, const char *pszDesc, ...)
476{
477 va_list va;
478 va_start(va, pszDesc);
479
480 int rc = audioTestErrorDescAddV(pErr, VERR_GENERAL_FAILURE /** @todo Fudge! */, pszDesc, va);
481
482 va_end(va);
483 return rc;
484}
485
486#if 0
487static int audioTestErrorDescAddRc(PAUDIOTESTERRORDESC pErr, int rc, const char *pszFormat, ...)
488{
489 va_list va;
490 va_start(va, pszFormat);
491
492 int rc2 = audioTestErrorDescAddV(pErr, rc, pszFormat, va);
493
494 va_end(va);
495 return rc2;
496}
497#endif
498
499/**
500 * Creates a new temporary directory with a specific (test) tag.
501 *
502 * @returns VBox status code.
503 * @param pszPath Where to return the absolute path of the created directory on success.
504 * @param cbPath Size (in bytes) of \a pszPath.
505 * @param pszTag Tag name to use for directory creation.
506 *
507 * @note Can be used multiple times with the same tag; a sub directory with an ISO time string will be used
508 * on each call.
509 */
510int AudioTestPathCreateTemp(char *pszPath, size_t cbPath, const char *pszTag)
511{
512 char szPath[RTPATH_MAX];
513
514 int rc = RTPathTemp(szPath, sizeof(szPath));
515 AssertRCReturn(rc, rc);
516 rc = AudioTestPathCreate(szPath, sizeof(szPath), pszTag);
517 AssertRCReturn(rc, rc);
518
519 return RTStrCopy(pszPath, cbPath, szPath);
520}
521
522/**
523 * Creates a new audio test set.
524 *
525 * @returns VBox status code.
526 * @param pSet Test set to create.
527 * @param pszPath Absolute path to use for the test set's temporary directory.
528 * If NULL, the OS' temporary directory will be used.
529 * @param pszTag Tag name to use for this test set.
530 */
531int AudioTestSetCreate(PAUDIOTESTSET pSet, const char *pszPath, const char *pszTag)
532{
533 int rc;
534
535 audioTestSetInitInternal(pSet);
536
537 if (pszPath)
538 {
539 rc = RTStrCopy(pSet->szPathAbs, sizeof(pSet->szPathAbs), pszPath);
540 AssertRCReturn(rc, rc);
541
542 rc = AudioTestPathCreate(pSet->szPathAbs, sizeof(pSet->szPathAbs), pszTag);
543 }
544 else
545 rc = AudioTestPathCreateTemp(pSet->szPathAbs, sizeof(pSet->szPathAbs), pszTag);
546 AssertRCReturn(rc, rc);
547
548 if (RT_SUCCESS(rc))
549 {
550 char szManifest[RTPATH_MAX];
551 rc = RTStrCopy(szManifest, sizeof(szManifest), pSet->szPathAbs);
552 AssertRCReturn(rc, rc);
553
554 rc = RTPathAppend(szManifest, sizeof(szManifest), AUDIOTEST_MANIFEST_FILE_STR);
555 AssertRCReturn(rc, rc);
556
557 rc = RTFileOpen(&pSet->f.hFile, szManifest,
558 RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
559 AssertRCReturn(rc, rc);
560
561 rc = audioTestManifestWriteSection(pSet, "header");
562 AssertRCReturn(rc, rc);
563
564 rc = audioTestManifestWriteLn(pSet, "magic=vkat_ini"); /* VKAT Manifest, .INI-style. */
565 AssertRCReturn(rc, rc);
566 rc = audioTestManifestWriteLn(pSet, "ver=%d", AUDIOTEST_MANIFEST_VER);
567 AssertRCReturn(rc, rc);
568 rc = audioTestManifestWriteLn(pSet, "tag=%s", pszTag);
569 AssertRCReturn(rc, rc);
570
571 char szVal[64];
572 RTTIMESPEC time;
573 if (!RTTimeSpecToString(RTTimeNow(&time), szVal, sizeof(szVal)))
574 AssertFailedReturn(VERR_BUFFER_OVERFLOW);
575
576 rc = audioTestManifestWriteLn(pSet, "date_created=%s", szVal);
577 AssertRCReturn(rc, rc);
578
579 rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szVal, sizeof(szVal));
580 AssertRCReturn(rc, rc);
581 rc = audioTestManifestWriteLn(pSet, "os_product=%s", szVal);
582 AssertRCReturn(rc, rc);
583 rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, szVal, sizeof(szVal));
584 AssertRCReturn(rc, rc);
585 rc = audioTestManifestWriteLn(pSet, "os_rel=%s", szVal);
586 AssertRCReturn(rc, rc);
587 rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, szVal, sizeof(szVal));
588 AssertRCReturn(rc, rc);
589 rc = audioTestManifestWriteLn(pSet, "os_ver=%s", szVal);
590 AssertRCReturn(rc, rc);
591
592 rc = audioTestManifestWriteLn(pSet, "vbox_ver=%s r%u %s (%s %s)",
593 VBOX_VERSION_STRING, RTBldCfgRevision(),
594 RTBldCfgTargetDotArch(), __DATE__, __TIME__);
595 AssertRCReturn(rc, rc);
596
597 pSet->enmMode = AUDIOTESTSETMODE_TEST;
598 }
599
600 return rc;
601}
602
603/**
604 * Destroys a test set.
605 *
606 * @param pSet Test set to destroy.
607 */
608void AudioTestSetDestroy(PAUDIOTESTSET pSet)
609{
610 if (!pSet)
611 return;
612
613 if (RTFileIsValid(pSet->f.hFile))
614 {
615 RTFileClose(pSet->f.hFile);
616 pSet->f.hFile = NIL_RTFILE;
617 }
618}
619
620/**
621 * Opens an existing audio test set.
622 *
623 * @returns VBox status code.
624 * @param pSet Test set to open.
625 * @param pszPath Absolute path of the test set to open.
626 */
627int AudioTestSetOpen(PAUDIOTESTSET pSet, const char *pszPath)
628{
629 audioTestSetInitInternal(pSet);
630
631 char szManifest[RTPATH_MAX];
632 int rc = RTStrCopy(szManifest, sizeof(szManifest), pszPath);
633 AssertRCReturn(rc, rc);
634
635 rc = RTPathAppend(szManifest, sizeof(szManifest), AUDIOTEST_MANIFEST_FILE_STR);
636 AssertRCReturn(rc, rc);
637
638 RTVFSFILE hVfsFile;
639 rc = RTVfsFileOpenNormal(szManifest, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, &hVfsFile);
640 if (RT_FAILURE(rc))
641 return rc;
642
643 rc = RTIniFileCreateFromVfsFile(&pSet->f.hIniFile, hVfsFile, RTINIFILE_F_READONLY);
644 RTVfsFileRelease(hVfsFile);
645 AssertRCReturn(rc, rc);
646
647 pSet->enmMode = AUDIOTESTSETMODE_VERIFY;
648
649 return rc;
650}
651
652/**
653 * Closes an opened audio test set.
654 *
655 * @param pSet Test set to close.
656 */
657void AudioTestSetClose(PAUDIOTESTSET pSet)
658{
659 AudioTestSetDestroy(pSet);
660}
661
662/**
663 * Packs an audio test so that it's ready for transmission.
664 *
665 * @returns VBox status code.
666 * @param pSet Test set to pack.
667 * @param pszOutDir Where to store the packed test set.
668 */
669int AudioTestSetPack(PAUDIOTESTSET pSet, const char *pszOutDir)
670{
671 RT_NOREF(pSet, pszOutDir);
672
673 AssertReturn(audioTestManifestIsOpen(pSet), VERR_WRONG_ORDER);
674 // RTZipTarCmd()
675
676 return VERR_NOT_IMPLEMENTED;
677}
678
679/**
680 * Unpacks a formerly packed audio test set.
681 *
682 * @returns VBox status code.
683 * @param pszFile Test set file to unpack.
684 * @param pszOutDir Directory where to unpack the test set into.
685 * If the directory does not exist it will be created.
686 */
687int AudioTestSetUnpack(const char *pszFile, const char *pszOutDir)
688{
689 RT_NOREF(pszFile, pszOutDir);
690
691 // RTZipTarCmd()
692
693 return VERR_NOT_IMPLEMENTED;
694}
695
696/**
697 * Verifies an opened audio test set.
698 *
699 * @returns VBox status code.
700 * @param pSet Test set to verify.
701 * @param pszTag Tag to use for verification purpose.
702 * @param pErrDesc Where to return the test verification errors.
703 *
704 * @note Test verification errors have to be checked for errors, regardless of the
705 * actual return code.
706 */
707int AudioTestSetVerify(PAUDIOTESTSET pSet, const char *pszTag, PAUDIOTESTERRORDESC pErrDesc)
708{
709 AssertReturn(audioTestManifestIsOpen(pSet), VERR_WRONG_ORDER);
710
711 /* We ASSUME the caller has not init'd pErrDesc. */
712 audioTestErrorDescInit(pErrDesc);
713
714 char szVal[_1K]; /** @todo Enough, too much? */
715
716 int rc2 = RTIniFileQueryValue(pSet->f.hIniFile, AUDIOTEST_INI_SEC_HDR_STR, "tag", szVal, sizeof(szVal), NULL);
717 if ( RT_FAILURE(rc2)
718 || RTStrICmp(pszTag, szVal))
719 audioTestErrorDescAdd(pErrDesc, "Tag '%s' does not match with manifest's tag '%s'", pszTag, szVal);
720
721 /* Only return critical stuff not related to actual testing here. */
722 return VINF_SUCCESS;
723}
724
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette