Add a real test suite for the save system (previously had none)
Covers save.c (device discovery/orchestration), savedevice.c (the generic device state machine and platform dispatch), and the Linux platform backend (path building, availability checks, JSON read/write, corrupt/missing-file handling), plus saveslot.c/savesettings.c JSON round-trips. 88 tests across 5 files, all run against the real Linux filesystem backend sandboxed to a temp $HOME (there's no mockable platform layer - the hooks are compile-time macros, not function pointers). Deliberately locks in two existing behaviors rather than working around them: saveSaveSettings() is a permanent no-op because nothing anywhere ever sets SAVE.settingsDirty = true, and saveUpdate() unconditionally rewrites settings back out the moment a device is found regardless of that same dirty flag. Both are pre-existing, not introduced here. Does not cover the SAVE_DEVICE_DATA_RAW blob codec (PSP/GameCube/Wii only) or GameCube's 2-device fallback chain - neither compiles into the Linux host test build. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,602 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "dusktest.h"
|
||||
#include "savetestfixture.h"
|
||||
#include "save/save.h"
|
||||
#include "save/savedevicelinux.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// ============================================================
|
||||
// Helpers
|
||||
// ============================================================
|
||||
|
||||
static void noopAvailabilityCallback(savedevice_t *device, void *user) {}
|
||||
|
||||
// Skips saveFindAvailableDevice()'s bookkeeping (findingAvailableDevice
|
||||
// etc.) and goes straight to "device 0 is current" - used by tests that
|
||||
// only care about behavior once a device has been selected, not how it got
|
||||
// selected. Still runs the real availability check underneath, since that
|
||||
// is what actually creates the on-disk save directory via mkdirp - reads
|
||||
// and writes fail without it.
|
||||
static void makeDeviceAvailable(void) {
|
||||
saveDeviceCheckAvailability(&SAVE.devices[0], noopAvailabilityCallback, NULL);
|
||||
saveDeviceUpdate(&SAVE.devices[0]);
|
||||
assert_int_equal(SAVE.devices[0].state, SAVE_DEVICE_STATE_AVAILABLE);
|
||||
SAVE.deviceCurrent = 0;
|
||||
}
|
||||
|
||||
static bool_t g_findCallbackFired;
|
||||
static savedevice_t *g_findCallbackDevice;
|
||||
|
||||
static void findAvailableCallback(savedevice_t *device, void *user) {
|
||||
g_findCallbackFired = true;
|
||||
g_findCallbackDevice = device;
|
||||
}
|
||||
|
||||
static void resetFindCallbackState(void) {
|
||||
g_findCallbackFired = false;
|
||||
g_findCallbackDevice = NULL;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveInit
|
||||
// ============================================================
|
||||
|
||||
static void test_saveInit_setsDefaults(void **state) {
|
||||
// saveTestFixtureSetup already called the real saveInit() - just assert
|
||||
// on the state it left behind.
|
||||
assert_int_equal(SAVE.deviceCurrent, 0xFF);
|
||||
assert_int_equal(SAVE.slotCurrent, 0xFF);
|
||||
assert_false(SAVE.findingAvailableDevice);
|
||||
assert_false(SAVE.noAvailableDeviceFound);
|
||||
assert_int_equal(SAVE.settings.someSetting, 0);
|
||||
assert_int_equal(SAVE.devices[0].state, SAVE_DEVICE_STATE_UNKNOWN);
|
||||
|
||||
for(uint8_t i = 0; i < SAVE_SLOT_COUNT; i++) {
|
||||
assert_int_equal(SAVE.caches[i].name[0], '\0');
|
||||
assert_int_equal(SAVE.caches[i].playerLevel, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveUpdate - no-op path
|
||||
// ============================================================
|
||||
|
||||
static void test_saveUpdate_noopWhenNotFinding(void **state) {
|
||||
errorret_t ret = saveUpdate();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_int_equal(SAVE.deviceCurrent, 0xFF);
|
||||
assert_false(SAVE.findingAvailableDevice);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveFindAvailableDevice / saveUpdate - discovery flow
|
||||
// ============================================================
|
||||
|
||||
static void test_saveFindAvailableDevice_nullCallbackAsserts(void **state) {
|
||||
expect_assert_failure(saveFindAvailableDevice(NULL, NULL));
|
||||
}
|
||||
|
||||
static void test_saveFindAvailableDevice_reentrantAsserts(void **state) {
|
||||
resetFindCallbackState();
|
||||
saveFindAvailableDevice(findAvailableCallback, NULL);
|
||||
expect_assert_failure(saveFindAvailableDevice(findAvailableCallback, NULL));
|
||||
}
|
||||
|
||||
static void test_saveFindAvailableDevice_deviceAlreadyAvailable(void **state) {
|
||||
resetFindCallbackState();
|
||||
// Mark the device available ahead of time via a real check (this is also
|
||||
// what creates the on-disk save directory that the "found device" flow
|
||||
// below needs to write settings back out to).
|
||||
saveDeviceCheckAvailability(&SAVE.devices[0], noopAvailabilityCallback, NULL);
|
||||
saveDeviceUpdate(&SAVE.devices[0]);
|
||||
assert_int_equal(SAVE.devices[0].state, SAVE_DEVICE_STATE_AVAILABLE);
|
||||
|
||||
saveFindAvailableDevice(findAvailableCallback, NULL);
|
||||
|
||||
// Set synchronously inside the call itself - no need to wait for update.
|
||||
assert_int_equal(SAVE.deviceCurrent, 0);
|
||||
assert_false(g_findCallbackFired);
|
||||
|
||||
errorret_t ret = saveUpdate();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_true(g_findCallbackFired);
|
||||
assert_ptr_equal(g_findCallbackDevice, &SAVE.devices[0]);
|
||||
assert_false(SAVE.findingAvailableDevice);
|
||||
}
|
||||
|
||||
static void test_saveFindAvailableDevice_coldPath_oneUpdateResolves(
|
||||
void **state
|
||||
) {
|
||||
resetFindCallbackState();
|
||||
|
||||
saveFindAvailableDevice(findAvailableCallback, NULL);
|
||||
|
||||
// Nothing resolved synchronously yet - the Linux availability check is
|
||||
// synchronous, but the callback it queues is only drained by an explicit
|
||||
// saveDeviceUpdate() inside saveUpdate().
|
||||
assert_int_equal(SAVE.deviceCurrent, 0xFF);
|
||||
assert_false(g_findCallbackFired);
|
||||
|
||||
errorret_t ret = saveUpdate();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_true(g_findCallbackFired);
|
||||
assert_ptr_equal(g_findCallbackDevice, &SAVE.devices[0]);
|
||||
assert_int_equal(SAVE.deviceCurrent, 0);
|
||||
assert_false(SAVE.findingAvailableDevice);
|
||||
}
|
||||
|
||||
static void test_saveFindAvailableDevice_allUnavailable_firesNullCallback(
|
||||
void **state
|
||||
) {
|
||||
unsetenv("HOME");
|
||||
resetFindCallbackState();
|
||||
|
||||
saveFindAvailableDevice(findAvailableCallback, NULL);
|
||||
|
||||
errorret_t ret = saveUpdate();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_true(g_findCallbackFired);
|
||||
assert_null(g_findCallbackDevice);
|
||||
assert_int_equal(SAVE.deviceCurrent, 0xFF);
|
||||
assert_false(SAVE.findingAvailableDevice);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveOnDeviceAvailabilityChecked
|
||||
// ============================================================
|
||||
|
||||
static void test_saveOnDeviceAvailabilityChecked_nullDeviceAsserts(
|
||||
void **state
|
||||
) {
|
||||
SAVE.findingAvailableDevice = true;
|
||||
expect_assert_failure(saveOnDeviceAvailabilityChecked(NULL, NULL));
|
||||
}
|
||||
|
||||
static void test_saveOnDeviceAvailabilityChecked_notFindingAsserts(
|
||||
void **state
|
||||
) {
|
||||
SAVE.findingAvailableDevice = false;
|
||||
expect_assert_failure(
|
||||
saveOnDeviceAvailabilityChecked(&SAVE.devices[0], NULL)
|
||||
);
|
||||
}
|
||||
|
||||
static void test_saveOnDeviceAvailabilityChecked_ignoresIfAlreadyResolved(
|
||||
void **state
|
||||
) {
|
||||
SAVE.findingAvailableDevice = true;
|
||||
SAVE.deviceCurrent = 0;
|
||||
SAVE.devices[0].state = SAVE_DEVICE_STATE_UNAVAILABLE;
|
||||
|
||||
saveOnDeviceAvailabilityChecked(&SAVE.devices[0], NULL);
|
||||
|
||||
// Already resolved - unavailable status on a re-delivered callback must
|
||||
// not clobber the winning device or flip noAvailableDeviceFound.
|
||||
assert_int_equal(SAVE.deviceCurrent, 0);
|
||||
assert_false(SAVE.noAvailableDeviceFound);
|
||||
}
|
||||
|
||||
static void test_saveOnDeviceAvailabilityChecked_singleDeviceUnavailable(
|
||||
void **state
|
||||
) {
|
||||
SAVE.findingAvailableDevice = true;
|
||||
SAVE.deviceCurrent = 0xFF;
|
||||
SAVE.devices[0].state = SAVE_DEVICE_STATE_UNAVAILABLE;
|
||||
|
||||
saveOnDeviceAvailabilityChecked(&SAVE.devices[0], NULL);
|
||||
|
||||
// SAVE_DEVICE_COUNT is 1 on Linux, so an unavailable device 0 is always
|
||||
// "the last device" - there's no next device to chain to.
|
||||
assert_true(SAVE.noAvailableDeviceFound);
|
||||
assert_int_equal(SAVE.deviceCurrent, 0xFF);
|
||||
}
|
||||
|
||||
static void test_saveOnDeviceAvailabilityChecked_deviceAvailable(
|
||||
void **state
|
||||
) {
|
||||
SAVE.findingAvailableDevice = true;
|
||||
SAVE.deviceCurrent = 0xFF;
|
||||
SAVE.devices[0].state = SAVE_DEVICE_STATE_AVAILABLE;
|
||||
|
||||
saveOnDeviceAvailabilityChecked(&SAVE.devices[0], NULL);
|
||||
|
||||
assert_int_equal(SAVE.deviceCurrent, 0);
|
||||
assert_false(SAVE.noAvailableDeviceFound);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveSaveSettings / saveLoadSettings
|
||||
// ============================================================
|
||||
|
||||
static void test_saveSaveSettings_noCurrentDeviceAsserts(void **state) {
|
||||
expect_assert_failure(saveSaveSettings());
|
||||
}
|
||||
|
||||
static void test_saveSaveSettings_notDirty_isNoop(void **state) {
|
||||
// Documents a real, currently-shipping bug: nothing anywhere in the
|
||||
// codebase ever sets SAVE.settingsDirty = true, so saveSaveSettings() is
|
||||
// permanently a no-op in practice. This test locks in that (surprising)
|
||||
// behavior rather than the presumably-intended one, so it fails loudly
|
||||
// if someone changes the no-op condition without meaning to.
|
||||
makeDeviceAvailable();
|
||||
assert_false(SAVE.settingsDirty);
|
||||
SAVE.settings.someSetting = 123;
|
||||
|
||||
errorret_t ret = saveSaveSettings();
|
||||
assert_true(errorIsOk(ret));
|
||||
|
||||
savesettings_t onDisk;
|
||||
saveSettingsInit(&onDisk);
|
||||
errorret_t readRet = saveDeviceSettingsRead(&SAVE.devices[0], &onDisk);
|
||||
assert_true(errorIsOk(readRet));
|
||||
assert_int_equal(onDisk.someSetting, 0);// never actually written
|
||||
}
|
||||
|
||||
static void test_saveSaveSettings_dirtyForced_writesAndClearsFlag(
|
||||
void **state
|
||||
) {
|
||||
makeDeviceAvailable();
|
||||
SAVE.settingsDirty = true;// nothing in real code sets this - forced here
|
||||
SAVE.settings.someSetting = 55;
|
||||
|
||||
errorret_t ret = saveSaveSettings();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_false(SAVE.settingsDirty);
|
||||
|
||||
savesettings_t onDisk;
|
||||
saveSettingsInit(&onDisk);
|
||||
errorret_t readRet = saveDeviceSettingsRead(&SAVE.devices[0], &onDisk);
|
||||
assert_true(errorIsOk(readRet));
|
||||
assert_int_equal(onDisk.someSetting, 55);
|
||||
}
|
||||
|
||||
static void test_saveLoadSettings_noCurrentDeviceAsserts(void **state) {
|
||||
expect_assert_failure(saveLoadSettings());
|
||||
}
|
||||
|
||||
static void test_saveLoadSettings_readsAndClearsDirtyFlag(void **state) {
|
||||
makeDeviceAvailable();
|
||||
|
||||
savesettings_t onDisk;
|
||||
saveSettingsInit(&onDisk);
|
||||
onDisk.someSetting = 99;
|
||||
errorret_t writeRet = saveDeviceSettingsWrite(&SAVE.devices[0], &onDisk);
|
||||
assert_true(errorIsOk(writeRet));
|
||||
|
||||
SAVE.settingsDirty = true;
|
||||
SAVE.settings.someSetting = 0;
|
||||
|
||||
errorret_t ret = saveLoadSettings();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_int_equal(SAVE.settings.someSetting, 99);
|
||||
assert_false(SAVE.settingsDirty);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveSaveSlot / saveLoadSlot
|
||||
// ============================================================
|
||||
|
||||
static void test_saveSaveSlot_noCurrentDeviceAsserts(void **state) {
|
||||
expect_assert_failure(saveSaveSlot());
|
||||
}
|
||||
|
||||
static void test_saveSaveSlot_invalidSlotIndexAsserts(void **state) {
|
||||
makeDeviceAvailable();
|
||||
// slotCurrent is still 0xFF (unset) from saveInit().
|
||||
expect_assert_failure(saveSaveSlot());
|
||||
}
|
||||
|
||||
static void test_saveSaveSlot_success(void **state) {
|
||||
makeDeviceAvailable();
|
||||
SAVE.slotCurrent = 1;
|
||||
saveSlotInit(&SAVE.slot);
|
||||
stringCopy(SAVE.slot.cachedData.name, "Hero", sizeof(SAVE.slot.cachedData.name));
|
||||
SAVE.slot.cachedData.playerLevel = 12;
|
||||
SAVE.slotDirty = true;
|
||||
|
||||
errorret_t ret = saveSaveSlot();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_false(SAVE.slotDirty);
|
||||
assert_true(stringEquals(SAVE.caches[1].name, "Hero"));
|
||||
assert_int_equal(SAVE.caches[1].playerLevel, 12);
|
||||
|
||||
saveslot_t onDisk;
|
||||
saveSlotInit(&onDisk);
|
||||
errorret_t readRet = saveDeviceSlotRead(&SAVE.devices[0], &onDisk, 1);
|
||||
assert_true(errorIsOk(readRet));
|
||||
assert_true(stringEquals(onDisk.cachedData.name, "Hero"));
|
||||
assert_int_equal(onDisk.cachedData.playerLevel, 12);
|
||||
}
|
||||
|
||||
static void test_saveLoadSlot_noCurrentDeviceAsserts(void **state) {
|
||||
expect_assert_failure(saveLoadSlot());
|
||||
}
|
||||
|
||||
static void test_saveLoadSlot_invalidSlotIndexAsserts(void **state) {
|
||||
makeDeviceAvailable();
|
||||
expect_assert_failure(saveLoadSlot());
|
||||
}
|
||||
|
||||
static void test_saveLoadSlot_success(void **state) {
|
||||
makeDeviceAvailable();
|
||||
|
||||
saveslot_t onDisk;
|
||||
saveSlotInit(&onDisk);
|
||||
stringCopy(onDisk.cachedData.name, "Zelda", sizeof(onDisk.cachedData.name));
|
||||
onDisk.cachedData.playerLevel = 30;
|
||||
errorret_t writeRet = saveDeviceSlotWrite(&SAVE.devices[0], &onDisk, 2);
|
||||
assert_true(errorIsOk(writeRet));
|
||||
|
||||
SAVE.slotCurrent = 2;
|
||||
saveSlotInit(&SAVE.slot);
|
||||
SAVE.slotDirty = true;
|
||||
|
||||
errorret_t ret = saveLoadSlot();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_false(SAVE.slotDirty);
|
||||
assert_true(stringEquals(SAVE.slot.cachedData.name, "Zelda"));
|
||||
assert_int_equal(SAVE.slot.cachedData.playerLevel, 30);
|
||||
assert_true(stringEquals(SAVE.caches[2].name, "Zelda"));
|
||||
assert_int_equal(SAVE.caches[2].playerLevel, 30);
|
||||
}
|
||||
|
||||
static void test_saveLoadSlot_deviceReadFails_cacheStaysStale(void **state) {
|
||||
makeDeviceAvailable();
|
||||
|
||||
char_t slotPath[512];
|
||||
errorret_t pathRet = saveDeviceLinuxGetSlotPath(slotPath, sizeof(slotPath), 0);
|
||||
assert_true(errorIsOk(pathRet));
|
||||
FILE *file = fopen(slotPath, "w");
|
||||
assert_non_null(file);
|
||||
fprintf(file, "not valid json {{{");
|
||||
fclose(file);
|
||||
|
||||
SAVE.slotCurrent = 0;
|
||||
saveSlotInit(&SAVE.slot);
|
||||
SAVE.caches[0].playerLevel = 77;// sentinel
|
||||
|
||||
errorret_t ret = saveLoadSlot();
|
||||
assert_true(errorIsNotOk(ret));
|
||||
errorCatch(ret);
|
||||
|
||||
// The device read failed before the cache-sync line ever ran.
|
||||
assert_int_equal(SAVE.caches[0].playerLevel, 77);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveLoadAllSlots
|
||||
// ============================================================
|
||||
|
||||
static void test_saveLoadAllSlots_loadsAllAndEndsAtLastIndex(void **state) {
|
||||
makeDeviceAvailable();
|
||||
|
||||
for(uint8_t i = 0; i < SAVE_SLOT_COUNT; i++) {
|
||||
SAVE.slotCurrent = i;
|
||||
saveSlotInit(&SAVE.slot);
|
||||
SAVE.slot.cachedData.playerLevel = (int32_t)(i + 1);
|
||||
errorret_t saveRet = saveSaveSlot();
|
||||
assert_true(errorIsOk(saveRet));
|
||||
}
|
||||
|
||||
errorret_t ret = saveLoadAllSlots();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_int_equal(SAVE.slotCurrent, SAVE_SLOT_COUNT - 1);
|
||||
|
||||
for(uint8_t i = 0; i < SAVE_SLOT_COUNT; i++) {
|
||||
assert_int_equal(SAVE.caches[i].playerLevel, (int32_t)(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_saveLoadAllSlots_missingFileLeavesInitDefaults(void **state) {
|
||||
makeDeviceAvailable();
|
||||
|
||||
SAVE.slotCurrent = 0;
|
||||
saveSlotInit(&SAVE.slot);
|
||||
SAVE.slot.cachedData.playerLevel = 5;
|
||||
errorret_t saveRet = saveSaveSlot();
|
||||
assert_true(errorIsOk(saveRet));
|
||||
// Slots 1 and 2 are never written - no file exists for them.
|
||||
|
||||
errorret_t ret = saveLoadAllSlots();
|
||||
assert_true(errorIsOk(ret));
|
||||
|
||||
assert_int_equal(SAVE.caches[0].playerLevel, 5);
|
||||
// Missing-file slots fall back to saveSlotInit()'s default (0), not the
|
||||
// JSON-missing-field default of 1 that a corrupt-but-present file with no
|
||||
// playerLevel key would produce - these are two different defaults.
|
||||
assert_int_equal(SAVE.caches[1].playerLevel, 0);
|
||||
assert_int_equal(SAVE.caches[2].playerLevel, 0);
|
||||
}
|
||||
|
||||
static void test_saveLoadAllSlots_middleSlotCorrupt_stopsAtFailingIndex(
|
||||
void **state
|
||||
) {
|
||||
makeDeviceAvailable();
|
||||
|
||||
SAVE.slotCurrent = 0;
|
||||
saveSlotInit(&SAVE.slot);
|
||||
errorret_t saveRet = saveSaveSlot();
|
||||
assert_true(errorIsOk(saveRet));
|
||||
|
||||
char_t slotPath[512];
|
||||
errorret_t pathRet = saveDeviceLinuxGetSlotPath(slotPath, sizeof(slotPath), 1);
|
||||
assert_true(errorIsOk(pathRet));
|
||||
FILE *file = fopen(slotPath, "w");
|
||||
assert_non_null(file);
|
||||
fprintf(file, "not valid json {{{");
|
||||
fclose(file);
|
||||
|
||||
errorret_t ret = saveLoadAllSlots();
|
||||
assert_true(errorIsNotOk(ret));
|
||||
errorCatch(ret);
|
||||
|
||||
// The loop bails out as soon as slot 1 fails - it never reaches slot 2.
|
||||
assert_int_equal(SAVE.slotCurrent, 1);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveDispose
|
||||
// ============================================================
|
||||
|
||||
static void test_saveDispose_succeeds(void **state) {
|
||||
errorret_t ret = saveDispose();
|
||||
assert_true(errorIsOk(ret));
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// saveUpdate - the unconditional settings write-back on device found
|
||||
// ============================================================
|
||||
|
||||
static void test_saveUpdate_foundDevice_rewritesSettingsUnconditionally(
|
||||
void **state
|
||||
) {
|
||||
// Documents another surprising bit of current behavior: as soon as a
|
||||
// device is found, saveUpdate() writes SAVE.settings straight back out to
|
||||
// it, regardless of settingsDirty - independent of (and unguarded by) the
|
||||
// same dirty-flag check saveSaveSettings() itself honors.
|
||||
resetFindCallbackState();
|
||||
SAVE.settings.someSetting = 321;
|
||||
assert_false(SAVE.settingsDirty);
|
||||
|
||||
saveFindAvailableDevice(findAvailableCallback, NULL);
|
||||
errorret_t ret = saveUpdate();
|
||||
assert_true(errorIsOk(ret));
|
||||
assert_true(g_findCallbackFired);
|
||||
|
||||
savesettings_t onDisk;
|
||||
saveSettingsInit(&onDisk);
|
||||
errorret_t readRet = saveDeviceSettingsRead(&SAVE.devices[0], &onDisk);
|
||||
assert_true(errorIsOk(readRet));
|
||||
assert_int_equal(onDisk.someSetting, 321);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
assertInit();
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveInit_setsDefaults, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveUpdate_noopWhenNotFinding, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveFindAvailableDevice_nullCallbackAsserts,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveFindAvailableDevice_reentrantAsserts,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveFindAvailableDevice_deviceAlreadyAvailable,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveFindAvailableDevice_coldPath_oneUpdateResolves,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveFindAvailableDevice_allUnavailable_firesNullCallback,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveOnDeviceAvailabilityChecked_nullDeviceAsserts,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveOnDeviceAvailabilityChecked_notFindingAsserts,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveOnDeviceAvailabilityChecked_ignoresIfAlreadyResolved,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveOnDeviceAvailabilityChecked_singleDeviceUnavailable,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveOnDeviceAvailabilityChecked_deviceAvailable,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveSaveSettings_noCurrentDeviceAsserts,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveSaveSettings_notDirty_isNoop, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveSaveSettings_dirtyForced_writesAndClearsFlag,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadSettings_noCurrentDeviceAsserts,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadSettings_readsAndClearsDirtyFlag,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveSaveSlot_noCurrentDeviceAsserts, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveSaveSlot_invalidSlotIndexAsserts, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveSaveSlot_success, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadSlot_noCurrentDeviceAsserts, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadSlot_invalidSlotIndexAsserts, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadSlot_success, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadSlot_deviceReadFails_cacheStaysStale,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadAllSlots_loadsAllAndEndsAtLastIndex,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadAllSlots_missingFileLeavesInitDefaults,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveLoadAllSlots_middleSlotCorrupt_stopsAtFailingIndex,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveDispose_succeeds, saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
|
||||
cmocka_unit_test_setup_teardown(
|
||||
test_saveUpdate_foundDevice_rewritesSettingsUnconditionally,
|
||||
saveTestFixtureSetup, saveTestFixtureTeardown
|
||||
),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user