summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2011-10-04 08:36:09 -0700
committerBill Richardson <wfrichar@chromium.org>2011-10-05 11:09:23 -0700
commit94d703459063fd144ec31ea0b70b9e94b208cfc8 (patch)
treed4e225c96debee2fdf0d5e05b4e42acca7e75aba
parent253a58e3834631e4688da45d31b0c475926bcbd6 (diff)
downloadvboot-94d703459063fd144ec31ea0b70b9e94b208cfc8.tar.gz
Enable (and test) custom dev-mode sounds
BUG=none TEST=manual cd src/platform/vboot_reference make && make runtests Change-Id: I7f7d50d7c9c5541e0b99031245f882996a6b88ec Reviewed-on: http://gerrit.chromium.org/gerrit/8731 Reviewed-by: Bill Richardson <wfrichar@chromium.org> Tested-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--firmware/lib/include/vboot_audio.h2
-rw-r--r--firmware/lib/include/vboot_audio_private.h47
-rw-r--r--firmware/lib/vboot_audio.c182
-rw-r--r--tests/Makefile15
-rw-r--r--tests/test_common.c22
-rw-r--r--tests/test_common.h8
-rw-r--r--tests/vboot_api_devmode_tests.c18
-rw-r--r--tests/vboot_audio_tests.c229
8 files changed, 461 insertions, 62 deletions
diff --git a/firmware/lib/include/vboot_audio.h b/firmware/lib/include/vboot_audio.h
index efa241b3..eea5a65a 100644
--- a/firmware/lib/include/vboot_audio.h
+++ b/firmware/lib/include/vboot_audio.h
@@ -2,7 +2,7 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
- * Display functions used in kernel selection.
+ * Delay/beep functions used in dev-mode kernel selection.
*/
#ifndef VBOOT_REFERENCE_VBOOT_AUDIO_H_
diff --git a/firmware/lib/include/vboot_audio_private.h b/firmware/lib/include/vboot_audio_private.h
new file mode 100644
index 00000000..e78d7d23
--- /dev/null
+++ b/firmware/lib/include/vboot_audio_private.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Private declarations for vboot_audio.c. Defined here for easier testing.
+ */
+
+#ifndef VBOOT_REFERENCE_VBOOT_AUDIO_PRIVATE_H_
+#define VBOOT_REFERENCE_VBOOT_AUDIO_PRIVATE_H_
+
+#include "vboot_api.h"
+#include "vboot_audio.h"
+
+typedef struct VbDevMusicNote {
+ uint16_t msec;
+ uint16_t frequency;
+} __attribute__((packed)) VbDevMusicNote;
+
+typedef struct VbDevMusic {
+ uint8_t sig[4]; /* "$SND" */
+ uint32_t checksum; /* crc32 over count & all notes */
+ uint32_t count; /* number of notes */
+ VbDevMusicNote notes[1]; /* gcc allows [0], MSVC doesn't */
+ /* more VbDevMusicNotes follow immediately */
+} __attribute__((packed)) VbDevMusic;
+
+struct VbAudioContext {
+ uint32_t note_count;
+ VbDevMusicNote* music_notes;
+ int free_notes_when_done;
+ uint32_t current_note;
+ uint32_t current_note_loops;
+ int background_beep;
+};
+
+#ifdef CUSTOM_MUSIC
+void *VbExGetMusicPtr(void);
+uint32_t VbExMaxMusicSize(void);
+#define CUSTOM_MUSIC_NOTES VbExGetMusicPtr()
+#define CUSTOM_MUSIC_MAXSIZE VbExMaxMusicSize()
+#else
+#define CUSTOM_MUSIC_NOTES 0
+#define CUSTOM_MUSIC_MAXSIZE 0
+#endif
+
+#endif /* VBOOT_REFERENCE_VBOOT_AUDIO_PRIVATE_H_ */
+
diff --git a/firmware/lib/vboot_audio.c b/firmware/lib/vboot_audio.c
index 45e9f175..b689bbd4 100644
--- a/firmware/lib/vboot_audio.c
+++ b/firmware/lib/vboot_audio.c
@@ -2,63 +2,163 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
- * Audio functions used in dev-mode kernel selection.
+ * Delay/beep functions used in dev-mode kernel selection.
*/
+#include "crc32.h"
#include "gbb_header.h"
#include "utility.h"
#include "vboot_api.h"
#include "vboot_audio.h"
+#include "vboot_audio_private.h"
#include "vboot_common.h"
-typedef struct VbDevMusicNote {
- uint16_t msec;
- uint16_t frequency;
-} __attribute__((packed)) VbDevMusicNote;
+#define DEV_LOOP_TIME 10 /* Minimum note granularity in msecs */
-typedef struct VbDevMusic {
- uint8_t sig[4]; /* "$SND" */
- uint32_t checksum; /* crc32 over count & all notes */
- uint32_t count; /* number of notes */
- VbDevMusicNote notes[1]; /* gcc allows [0], MSVC doesn't */
- /* more VbDevMusicNotes follow immediately */
-} __attribute__((packed)) VbDevMusic;
+/* These are visible externally only to make testing easier */
+VbDevMusicNote default_notes_[] = { {20000, 0}, /* 20 seconds */
+ {250, 400}, /* two beeps */
+ {250, 0},
+ {250, 400},
+ {9250, 0} }; /* total 30 seconds */
+uint32_t default_count_ = sizeof(default_notes_) / sizeof(VbDevMusicNote);
-static struct VbAudioContext {
- uint32_t note_count;
- VbDevMusicNote* music_notes;
- uint32_t current_note;
- uint32_t current_note_loops;
- int background_beep;
-} au;
+VbDevMusicNote short_notes_[] = { {2000, 0} }; /* two seconds */
+uint32_t short_count_ = sizeof(short_notes_) / sizeof(VbDevMusicNote);
+/* No need to dynamically allocate this, is there? */
+static VbAudioContext au;
-#define DEV_LOOP_TIME 10 /* Minimum note granularity in msecs */
-
-static uint16_t VbMsecToLoops(uint16_t msec) {
+/* Arg is 16-bit, but use 32-bit to avoid rollover */
+static uint32_t VbMsecToLoops(uint32_t msec) {
return (DEV_LOOP_TIME / 2 + msec) / DEV_LOOP_TIME;
}
-static VbDevMusicNote default_notes[] = { {20000, 0}, /* 20 seconds */
- {250, 400}, /* two beeps */
- {250, 0},
- {250, 400},
- {9250, 0} }; /* total 30 seconds */
+/* Find and return a valid set of note events. We'll use the user's struct
+ * if possible, but we will still enforce the 30-second timeout and require at
+ * least a second of audible noise within that period. We allocate storage for
+ * two reasons: the user's struct will be in flash, which is slow to read, and
+ * we may need one extra note at the end to pad out the user's notes to a full
+ * 30 seconds. The caller should free it when finished.
+ */
+static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
+ VbDevMusicNote *notebuf = 0;
+ VbDevMusicNote *builtin = 0;
+ VbDevMusic *hdr = CUSTOM_MUSIC_NOTES;
+ uint32_t maxsize = CUSTOM_MUSIC_MAXSIZE;
+ uint32_t maxnotes, mysum, mylen, i;
+ uint64_t on_loops, total_loops, min_loops;
+ uint32_t this_loops;
+ uint32_t count;
+
+ VBDEBUG(("VbGetDevMusicNotes: use_short is %d, hdr is %lx, maxsize is %d\n",
+ use_short, hdr, maxsize));
-static VbDevMusicNote short_notes[] = { {2000, 0} }; /* two seconds */
+ if (use_short) {
+ builtin = short_notes_;
+ count = short_count_;
+ goto nope;
+ }
-/* Return a valid set of note events. */
-static VbDevMusicNote* VbGetDevMusicNotes(uint32_t* count, int use_short) {
+ builtin = default_notes_;
+ count = default_count_;
- if (use_short) {
- *count = sizeof(short_notes) / sizeof(short_notes[0]);
- return short_notes;
+ /* If we can't beep in the background, don't allow customization. */
+ if (!audio->background_beep)
+ goto nope;
+
+ if (!hdr || maxsize < sizeof(VbDevMusic))
+ goto nope;
+
+ if (0 != Memcmp(hdr->sig, "$SND", sizeof(hdr->sig))) {
+ VBDEBUG(("VbGetDevMusicNotes: bad sig\n"));
+ goto nope;
}
- *count = sizeof(default_notes) / sizeof(default_notes[0]);
- return default_notes;
+ maxnotes = 1 + (maxsize - sizeof(VbDevMusic)) / sizeof(VbDevMusicNote);
+ if (hdr->count == 0 || hdr->count > maxnotes) {
+ VBDEBUG(("VbGetDevMusicNotes: count=%d maxnotes=%d\n",
+ hdr->count, maxnotes));
+ goto nope;
+ }
+
+ mylen = (uint32_t)(sizeof(hdr->count) + hdr->count * sizeof(VbDevMusicNote));
+ mysum = Crc32(&(hdr->count), mylen);
+
+ if (mysum != hdr->checksum) {
+ VBDEBUG(("VbGetDevMusicNotes: mysum=%08x, want=%08x\n",
+ mysum, hdr->checksum));
+ goto nope;
+ }
+
+ VBDEBUG(("VbGetDevMusicNotes: custom notes struct found at %lx\n", hdr));
+
+ /* Measure the audible sound up to the first 22 seconds, being careful to
+ * avoid rollover. The note time is 16 bits, and the note count is 32 bits.
+ * The product should fit in 64 bits.
+ */
+ total_loops = 0;
+ on_loops = 0;
+ min_loops = VbMsecToLoops(22000);
+ for (i=0; i < hdr->count; i++) {
+ this_loops = VbMsecToLoops(hdr->notes[i].msec);
+ if (this_loops) {
+ total_loops += this_loops;
+ if (total_loops <= min_loops &&
+ hdr->notes[i].frequency >= 100 && hdr->notes[i].frequency <= 2000)
+ on_loops += this_loops;
+ }
+ }
+
+ /* We require at least one second of noise in the first 22 seconds */
+ VBDEBUG(("VbGetDevMusicNotes: with %ld msecs of sound to begin\n",
+ on_loops * DEV_LOOP_TIME));
+ if (on_loops < VbMsecToLoops(1000)) {
+ goto nope;
+ }
+
+ /* We'll also require that the total time be less than a minute. No real
+ * reason, it just gives us less to worry about.
+ */
+ VBDEBUG(("VbGetDevMusicNotes: lasting %ld msecs\n",
+ total_loops * DEV_LOOP_TIME));
+ if (total_loops > VbMsecToLoops(60000)) {
+ goto nope;
+ }
+
+ /* Okay, it looks good. Allocate the space (plus one) and copy it over */
+ notebuf = VbExMalloc((hdr->count + 1) * sizeof(VbDevMusicNote));
+ Memcpy(notebuf, hdr->notes, hdr->count * sizeof(VbDevMusicNote));
+ count = hdr->count;
+
+ /* We also require at least 30 seconds of delay. */
+ min_loops = VbMsecToLoops(30000);
+ if (total_loops < min_loops) {
+ /* If the total time is less than 30 seconds, the needed difference will
+ * fit in 16 bits.
+ */
+ this_loops = (min_loops - total_loops) & 0xffff;
+ notebuf[hdr->count].msec = (uint16_t)(this_loops * DEV_LOOP_TIME);
+ notebuf[hdr->count].frequency = 0;
+ count++;
+ VBDEBUG(("VbGetDevMusicNotes: adding %ld msecs of silence\n",
+ this_loops * DEV_LOOP_TIME));
+ }
+
+ /* done */
+ audio->music_notes = notebuf;
+ audio->note_count = count;
+ audio->free_notes_when_done = 1;
+ return;
+
+nope:
+ /* No custom notes, use the default. The count is already set. */
+ VBDEBUG(("VbGetDevMusicNotes: using %d default notes\n", count));
+ audio->music_notes = builtin;
+ audio->note_count = count;
+ audio->free_notes_when_done = 0;
}
@@ -66,6 +166,7 @@ static VbDevMusicNote* VbGetDevMusicNotes(uint32_t* count, int use_short) {
VbAudioContext* VbAudioOpen(VbCommonParams* cparams) {
GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data;
VbAudioContext* audio = &au;
+ int use_short = 0;
/* Note: may need to allocate things here in future */
@@ -76,7 +177,6 @@ VbAudioContext* VbAudioOpen(VbCommonParams* cparams) {
audio->current_note_loops = 0;
audio->background_beep = 1;
-
/* See if we have full background sound capability or not. */
if (VBERROR_SUCCESS != VbExBeep(0,0)) {
VBDEBUG(("VbAudioOpen() - VbExBeep() is limited\n"));
@@ -89,11 +189,10 @@ VbAudioContext* VbAudioOpen(VbCommonParams* cparams) {
if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1
&& (gbb->flags & GBB_FLAG_DEV_SCREEN_SHORT_DELAY)) {
VBDEBUG(("VbAudioOpen() - using short developer screen delay\n"));
- audio->music_notes = VbGetDevMusicNotes(&(audio->note_count), 1);
- } else {
- audio->music_notes = VbGetDevMusicNotes(&(audio->note_count), 0);
+ use_short = 1;
}
+ VbGetDevMusicNotes(audio, use_short);
VBDEBUG(("VbAudioOpen() - note count %d\n", audio->note_count));
return audio;
@@ -144,8 +243,7 @@ int VbAudioLooping(VbAudioContext* audio) {
/* Caller should call this prior to booting */
void VbAudioClose(VbAudioContext* audio) {
-
VbExBeep(0,0);
-
- /* Note: Free any allocated structs here */
+ if (audio->free_notes_when_done)
+ VbExFree(audio->music_notes);
}
diff --git a/tests/Makefile b/tests/Makefile
index 55d0ccd8..20c19dd4 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -28,7 +28,8 @@ TEST_NAMES = cgptlib_test \
vboot_common3_tests \
vboot_firmware_tests \
vboot_nvstorage_test \
- vboot_api_devmode_tests
+ vboot_api_devmode_tests \
+ vboot_audio_tests
TEST_BINS = $(addprefix ${BUILD_ROOT}/,$(TEST_NAMES))
@@ -53,14 +54,13 @@ ${TEST_LIB}: ${TEST_LIB_OBJS}
rm -f $@
ar qc $@ $^
-${BUILD_ROOT}/vboot_api_kernel_for_test.o : $(FWDIR)/lib/vboot_api_kernel.c
- $(CC) $(CFLAGS) $(INCLUDES) \
+${BUILD_ROOT}/vboot_audio_for_test.o : $(FWDIR)/lib/vboot_audio.c
+ $(CC) $(CFLAGS) -DCUSTOM_MUSIC $(INCLUDES) \
-MMD -MF $@.d -c -o $@ $<
-${BUILD_ROOT}/vboot_api_devmode_tests: vboot_api_devmode_tests.c \
- ${BUILD_ROOT}/vboot_api_kernel_for_test.o ${LIBS}
- $(CC) $(CFLAGS) $(INCLUDES) $< \
- ${BUILD_ROOT}/vboot_api_kernel_for_test.o \
+${BUILD_ROOT}/vboot_audio_tests: vboot_audio_tests.c \
+ ${BUILD_ROOT}/vboot_audio_for_test.o ${LIBS}
+ $(CC) $(CFLAGS) $(INCLUDES) $< ${BUILD_ROOT}/vboot_audio_for_test.o \
${LIBS} -o $@ -lcrypto -lrt
${BUILD_ROOT}/rollback_index_test.o : rollback_index_test.c
@@ -142,6 +142,7 @@ runbmptests:
runsoundtests:
${BUILD_ROOT}/vboot_api_devmode_tests
+ ${BUILD_ROOT}/vboot_audio_tests
ALLTESTS=runcgpttests runcryptotests runmisctests runfuzztests \
runbmptests runsoundtests
diff --git a/tests/test_common.c b/tests/test_common.c
index 48ee7fd0..e57fe21e 100644
--- a/tests/test_common.c
+++ b/tests/test_common.c
@@ -89,3 +89,25 @@ int TEST_STR_EQ(const char* result, const char* expected_result,
}
}
+
+int TEST_TRUE(int result, const char* testname) {
+ if (result) {
+ fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname);
+ } else {
+ fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname);
+ fprintf(stderr, " Expected TRUE, got 0\n");
+ gTestSuccess = 0;
+ }
+ return result;
+}
+
+int TEST_FALSE(int result, const char* testname) {
+ if (!result) {
+ fprintf(stderr, "%s Test " COL_GREEN "PASSED\n" COL_STOP, testname);
+ } else {
+ fprintf(stderr, "%s Test " COL_RED "FAILED\n" COL_STOP, testname);
+ fprintf(stderr, " Expected FALSE, got: 0x%lx\n", (long)result);
+ gTestSuccess = 0;
+ }
+ return !result;
+}
diff --git a/tests/test_common.h b/tests/test_common.h
index 6f594f93..f5d73d1d 100644
--- a/tests/test_common.h
+++ b/tests/test_common.h
@@ -34,6 +34,14 @@ int TEST_PTR_NEQ(const void* result, const void* expected_result,
int TEST_STR_EQ(const char* result, const char* expected_result,
const char* testname);
+/* Return 1 if the result is true, else return 0.
+ * Also update the global gTestSuccess flag if test fails. */
+int TEST_TRUE(int result, const char* testname);
+
+/* Return 1 if the result is false, else return 0.
+ * Also update the global gTestSuccess flag if test fails. */
+int TEST_FALSE(int result, const char* testname);
+
/* ANSI Color coding sequences.
*
* Don't use \e as MSC does not recognize it as a valid escape sequence.
diff --git a/tests/vboot_api_devmode_tests.c b/tests/vboot_api_devmode_tests.c
index c42795cd..8b5989df 100644
--- a/tests/vboot_api_devmode_tests.c
+++ b/tests/vboot_api_devmode_tests.c
@@ -5,20 +5,20 @@
* Tests for vboot_api_firmware
*/
-#include <stdio.h>
#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include "crc32.h"
+#include "gbb_header.h"
#include "host_common.h"
+#include "load_kernel_fw.h"
#include "rollback_index.h"
#include "test_common.h"
#include "vboot_common.h"
+#include "vboot_display.h"
#include "vboot_nvstorage.h"
#include "vboot_struct.h"
-#include "load_kernel_fw.h"
-#include "gbb_header.h"
-#include "vboot_display.h"
/* Expected results */
@@ -128,12 +128,8 @@ test_case_t test[] = {
{0, 0, 30360}, // returns at 30 seconds + 360ms
}},
-
-
-
};
-
/* Mock data */
static VbCommonParams cparams;
static LoadKernelParams lkparams;
@@ -150,7 +146,6 @@ static uint32_t kbd_fire_key;
static VbError_t beep_return;
static note_event_t *expected_event;
-
/* Reset mock data (for use before each test) */
static void ResetMocks(void) {
@@ -282,7 +277,6 @@ VbError_t VbExDisplayScreen(uint32_t screen_type) {
return VBERROR_SUCCESS;
}
-
/****************************************************************************/
VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p);
@@ -304,8 +298,8 @@ static void VbBootDeveloperSoundTest(void) {
(void) VbBootDeveloper(&cparams, &lkparams);
VBDEBUG(("INFO: matched %d total %d expected %d\n",
matched_events, current_event, test[i].num_events));
- TEST_EQ(matched_events, test[i].num_events, test[i].name);
- TEST_EQ(current_event, test[i].num_events, test[i].name);
+ TEST_TRUE(matched_events == test[i].num_events &&
+ current_event == test[i].num_events, test[i].name);
}
}
diff --git a/tests/vboot_audio_tests.c b/tests/vboot_audio_tests.c
new file mode 100644
index 00000000..4d633516
--- /dev/null
+++ b/tests/vboot_audio_tests.c
@@ -0,0 +1,229 @@
+/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Tests for vboot_audio
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "crc32.h"
+#include "gbb_header.h"
+#include "host_common.h"
+#include "load_kernel_fw.h"
+#include "rollback_index.h"
+#include "test_common.h"
+#include "vboot_audio.h"
+#include "vboot_audio_private.h"
+#include "vboot_common.h"
+#include "vboot_display.h"
+#include "vboot_nvstorage.h"
+#include "vboot_struct.h"
+
+
+/* Builtin notes */
+extern VbDevMusicNote default_notes_[], short_notes_[];
+extern uint32_t default_count_, short_count_;
+
+/* Mock data */
+static VbCommonParams cparams;
+static GoogleBinaryBlockHeader gbb;
+static VbDevMusicNote good_notes[] = { {100, 100},
+ {100, 0},
+ {200, 200},
+ {100, 0},
+ {300, 300},
+ {100, 0},
+ {400, 400},
+ {30000, 0} };
+static VbDevMusic good_header =
+{ .sig = { '$', 'S', 'N', 'D' },
+ .count = sizeof(good_notes) / sizeof(VbDevMusicNote),
+};
+
+static uint8_t notebuf[sizeof(good_header) +
+ sizeof(good_notes) - sizeof(VbDevMusicNote)];
+
+static VbDevMusic *use_hdr;
+static VbDevMusicNote *use_notes;
+static uint32_t use_size;
+
+/* Set correct checksum for custom notes */
+void FixChecksum(VbDevMusic *hdr) {
+ hdr->checksum = Crc32(&(hdr->count), sizeof(hdr->count) +
+ hdr->count * sizeof(hdr->notes[0]));
+}
+
+/* Reset mock data (for use before each test) */
+static void ResetMocks(void) {
+ VBDEBUG(("ResetMocks()\n"));
+ Memset(&cparams, 0, sizeof(cparams));
+ cparams.gbb_data = &gbb;
+ Memset(&gbb, 0, sizeof(gbb));
+ gbb.major_version = GBB_MAJOR_VER;
+ gbb.minor_version = GBB_MINOR_VER;
+ gbb.flags = 0;
+ use_hdr = (VbDevMusic *)notebuf;
+ use_notes = use_hdr->notes;
+ Memcpy(use_hdr, &good_header, sizeof(good_header));
+ Memcpy(use_notes, good_notes, sizeof(good_notes));
+ FixChecksum(use_hdr);
+ use_size = sizeof(notebuf);
+}
+
+/* Compare two sets of notes */
+static int NotesMatch(VbDevMusicNote *a, VbDevMusicNote *b, uint32_t count) {
+ int i;
+ if (!a || !b)
+ return 0;
+
+ for ( i=0; i<count; i++) {
+ if ( a[i].msec != b[i].msec || a[i].frequency != b[i].frequency)
+ return 0;
+ }
+
+ return count;
+}
+
+
+
+
+/****************************************************************************/
+/* Mocked verification functions */
+
+void *VbExGetMusicPtr(void) {
+ return use_hdr;
+}
+
+uint32_t VbExMaxMusicSize(void) {
+ return use_size;
+}
+
+
+/****************************************************************************/
+
+static void VbAudioTest(void) {
+ VbAudioContext* a = 0;
+
+ /* default is okay */
+ ResetMocks();
+ use_hdr = 0;
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == default_notes_ &&
+ a->note_count == default_count_,
+ "VbAudioTest( default )");
+ VbAudioClose(a);
+
+ /* short is okay */
+ ResetMocks();
+ use_hdr = 0;
+ gbb.flags = 0x00000001;
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == short_notes_ &&
+ a->note_count == short_count_,
+ "VbAudioTest( short )");
+ VbAudioClose(a);
+
+ /* good custom is okay */
+ ResetMocks();
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(NotesMatch(a->music_notes, good_notes, good_header.count) &&
+ a->note_count == good_header.count,
+ "VbAudioTest( custom good )");
+ VbAudioClose(a);
+
+ /* good custom is rejected when short flag is set */
+ ResetMocks();
+ gbb.flags = 0x00000001;
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == short_notes_ &&
+ a->note_count == short_count_,
+ "VbAudioTest( short has priority )");
+ VbAudioClose(a);
+
+ /* too short gets extended */
+ ResetMocks();
+ use_hdr->count--;
+ FixChecksum(use_hdr);
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(NotesMatch(a->music_notes, use_notes, use_hdr->count) &&
+ a->note_count == use_hdr->count + 1 &&
+ a->music_notes[use_hdr->count].msec == 28700 &&
+ a->music_notes[use_hdr->count].frequency == 0,
+ "VbAudioTest( too short )");
+ VbAudioClose(a);
+
+ /* too quiet is rejected */
+ ResetMocks();
+ use_notes[6].msec = 10;
+ FixChecksum(use_hdr);
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == default_notes_ &&
+ a->note_count == default_count_,
+ "VbAudioTest( too quiet )");
+ VbAudioClose(a);
+
+ /* inaudible is rejected */
+ ResetMocks();
+ use_notes[0].frequency = 99;
+ use_notes[2].frequency = 2001;
+ FixChecksum(use_hdr);
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == default_notes_ &&
+ a->note_count == default_count_,
+ "VbAudioTest( inaudible )");
+ VbAudioClose(a);
+
+ /* bad signature is rejected */
+ ResetMocks();
+ use_hdr->sig[0] = 'C';
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == default_notes_ &&
+ a->note_count == default_count_,
+ "VbAudioTest( bad signature )");
+ VbAudioClose(a);
+
+ /* count == 0 is rejected */
+ ResetMocks();
+ use_hdr->count = 0;
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == default_notes_ &&
+ a->note_count == default_count_,
+ "VbAudioTest( count == 0 )");
+ VbAudioClose(a);
+
+ /* too big is rejected */
+ ResetMocks();
+ use_hdr->count = 999;
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == default_notes_ &&
+ a->note_count == default_count_,
+ "VbAudioTest( count too big )");
+ VbAudioClose(a);
+
+ /* bad checksum is rejected */
+ ResetMocks();
+ use_hdr->checksum++;
+ a = VbAudioOpen(&cparams);
+ TEST_TRUE(a->music_notes == default_notes_ &&
+ a->note_count == default_count_,
+ "VbAudioTest( count too big )");
+ VbAudioClose(a);
+}
+
+
+/* disable MSVC warnings on unused arguments */
+__pragma(warning (disable: 4100))
+
+int main(int argc, char* argv[]) {
+ int error_code = 0;
+
+ VbAudioTest();
+
+ if (!gTestSuccess)
+ error_code = 255;
+
+ return error_code;
+}