mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-25 10:45:02 +00:00
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>
This commit is contained in:
@@ -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_
|
||||
|
||||
47
firmware/lib/include/vboot_audio_private.h
Normal file
47
firmware/lib/include/vboot_audio_private.h
Normal file
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
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;
|
||||
|
||||
static struct VbAudioContext {
|
||||
uint32_t note_count;
|
||||
VbDevMusicNote* music_notes;
|
||||
uint32_t current_note;
|
||||
uint32_t current_note_loops;
|
||||
int background_beep;
|
||||
} au;
|
||||
|
||||
|
||||
#define DEV_LOOP_TIME 10 /* Minimum note granularity in msecs */
|
||||
|
||||
|
||||
static uint16_t VbMsecToLoops(uint16_t msec) {
|
||||
return (DEV_LOOP_TIME / 2 + msec) / DEV_LOOP_TIME;
|
||||
}
|
||||
|
||||
static VbDevMusicNote default_notes[] = { {20000, 0}, /* 20 seconds */
|
||||
/* 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 VbDevMusicNote short_notes[] = { {2000, 0} }; /* two seconds */
|
||||
VbDevMusicNote short_notes_[] = { {2000, 0} }; /* two seconds */
|
||||
uint32_t short_count_ = sizeof(short_notes_) / sizeof(VbDevMusicNote);
|
||||
|
||||
/* Return a valid set of note events. */
|
||||
static VbDevMusicNote* VbGetDevMusicNotes(uint32_t* count, int use_short) {
|
||||
/* No need to dynamically allocate this, is there? */
|
||||
static VbAudioContext au;
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
|
||||
if (use_short) {
|
||||
*count = sizeof(short_notes) / sizeof(short_notes[0]);
|
||||
return short_notes;
|
||||
builtin = short_notes_;
|
||||
count = short_count_;
|
||||
goto nope;
|
||||
}
|
||||
|
||||
*count = sizeof(default_notes) / sizeof(default_notes[0]);
|
||||
return default_notes;
|
||||
builtin = default_notes_;
|
||||
count = default_count_;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
229
tests/vboot_audio_tests.c
Normal file
229
tests/vboot_audio_tests.c
Normal file
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user