158 lines
4.5 KiB
C
158 lines
4.5 KiB
C
#include <string.h>
|
|
#include "unity.h"
|
|
#include "fake_flash.h"
|
|
#include "config/nl_flash_layout.h"
|
|
#include "config/nl_state_log.h"
|
|
#include "light/nl_boot_state.h"
|
|
|
|
static nl_light_state_t st(uint8_t bri)
|
|
{
|
|
nl_light_state_t s = {true, bri, NL_MODE_COLOR, 10, 20, 30, 3000};
|
|
return s;
|
|
}
|
|
|
|
static void reboot(void)
|
|
{
|
|
nl_state_log_init(NL_FL_STATE_0, NL_FL_STATE_1);
|
|
}
|
|
|
|
void setUp(void)
|
|
{
|
|
fake_flash_reset();
|
|
reboot();
|
|
}
|
|
|
|
void tearDown(void)
|
|
{
|
|
TEST_ASSERT_EQUAL_UINT(0, fake_flash_dirty_writes);
|
|
}
|
|
|
|
static void test_empty(void)
|
|
{
|
|
nl_light_state_t s;
|
|
TEST_ASSERT_FALSE(nl_state_log_load(&s));
|
|
}
|
|
|
|
static void test_append_and_reload(void)
|
|
{
|
|
nl_light_state_t in = st(42), out;
|
|
in.mode = NL_MODE_WHITE;
|
|
in.on = false;
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&in));
|
|
reboot();
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_TRUE(nl_light_state_equal(&in, &out));
|
|
}
|
|
|
|
static void test_equal_state_is_not_written_again(void)
|
|
{
|
|
nl_light_state_t s = st(42);
|
|
nl_state_log_append(&s);
|
|
nl_state_log_append(&s);
|
|
for (int i = 0; i < 16; i++)
|
|
TEST_ASSERT_EQUAL_HEX8(0xFF, fake_flash_mem[NL_FL_STATE_0 + 16 + i]);
|
|
}
|
|
|
|
static void test_wraps_into_second_sector(void)
|
|
{
|
|
nl_light_state_t s, out;
|
|
for (int i = 0; i < 300; i++) {
|
|
s = st((uint8_t)(1 + i % 100));
|
|
s.r = (uint8_t)i; /* make every entry distinct */
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s));
|
|
}
|
|
TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[NL_FL_STATE_1 / NL_FLASH_SECTOR_SIZE]);
|
|
reboot();
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_TRUE(nl_light_state_equal(&s, &out));
|
|
/* keep going after the reboot */
|
|
s = st(77);
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s));
|
|
reboot();
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_EQUAL_UINT8(77, out.brightness);
|
|
}
|
|
|
|
static void test_wraps_back_to_first_sector(void)
|
|
{
|
|
nl_light_state_t s, out;
|
|
for (int i = 0; i < 600; i++) {
|
|
s = st(50);
|
|
s.r = (uint8_t)i;
|
|
s.g = (uint8_t)(i >> 8);
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s));
|
|
}
|
|
TEST_ASSERT_EQUAL_UINT(1, fake_flash_erases[NL_FL_STATE_0 / NL_FLASH_SECTOR_SIZE]);
|
|
reboot();
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_TRUE(nl_light_state_equal(&s, &out));
|
|
}
|
|
|
|
static void test_power_loss_during_append(void)
|
|
{
|
|
nl_light_state_t a = st(10), b = st(20), c = st(30), out;
|
|
nl_state_log_append(&a);
|
|
fake_flash_fail_after(5);
|
|
TEST_ASSERT_NOT_EQUAL(0, nl_state_log_append(&b));
|
|
fake_flash_fail_after(-1);
|
|
reboot();
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_EQUAL_UINT8(10, out.brightness);
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&c));
|
|
reboot();
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_EQUAL_UINT8(30, out.brightness);
|
|
}
|
|
|
|
static void test_garbage_in_empty_log_is_erased_first(void)
|
|
{
|
|
nl_light_state_t s = st(60), out;
|
|
fake_flash_mem[NL_FL_STATE_0 + 3] = 0x12; /* leftovers from the old firmware */
|
|
reboot();
|
|
TEST_ASSERT_FALSE(nl_state_log_load(&out));
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&s));
|
|
reboot();
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_EQUAL_UINT8(60, out.brightness);
|
|
}
|
|
|
|
static void test_erase(void)
|
|
{
|
|
nl_light_state_t s = st(60), out;
|
|
nl_state_log_append(&s);
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_erase());
|
|
TEST_ASSERT_FALSE(nl_state_log_load(&out));
|
|
reboot();
|
|
TEST_ASSERT_FALSE(nl_state_log_load(&out));
|
|
}
|
|
|
|
static void test_erase_failure_rescans_flash(void)
|
|
{
|
|
nl_light_state_t old = st(10), new = st(20), out;
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&old));
|
|
fake_flash_fail_after(0);
|
|
TEST_ASSERT_NOT_EQUAL(0, nl_state_log_erase());
|
|
fake_flash_fail_after(-1);
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_EQUAL_UINT8(10, out.brightness);
|
|
TEST_ASSERT_EQUAL_INT(0, nl_state_log_append(&new));
|
|
reboot();
|
|
TEST_ASSERT_TRUE(nl_state_log_load(&out));
|
|
TEST_ASSERT_EQUAL_UINT8(20, out.brightness);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
UNITY_BEGIN();
|
|
RUN_TEST(test_empty);
|
|
RUN_TEST(test_append_and_reload);
|
|
RUN_TEST(test_equal_state_is_not_written_again);
|
|
RUN_TEST(test_wraps_into_second_sector);
|
|
RUN_TEST(test_wraps_back_to_first_sector);
|
|
RUN_TEST(test_power_loss_during_append);
|
|
RUN_TEST(test_garbage_in_empty_log_is_erased_first);
|
|
RUN_TEST(test_erase);
|
|
RUN_TEST(test_erase_failure_rescans_flash);
|
|
return UNITY_END();
|
|
}
|