diff options
-rw-r--r-- | firmware/lib/include/vboot_audio.h | 2 | ||||
-rw-r--r-- | firmware/lib/include/vboot_audio_private.h | 47 | ||||
-rw-r--r-- | firmware/lib/vboot_audio.c | 182 | ||||
-rw-r--r-- | tests/Makefile | 15 | ||||
-rw-r--r-- | tests/test_common.c | 22 | ||||
-rw-r--r-- | tests/test_common.h | 8 | ||||
-rw-r--r-- | tests/vboot_api_devmode_tests.c | 18 | ||||
-rw-r--r-- | tests/vboot_audio_tests.c | 229 |
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; +} |