Spiffs Test

Source: src/spiffs_test.c · 170 lines · 8 functions.

Module entry points

These functions are exposed to the rest of the project. Open one to follow its decisions and the helpers it calls.

How to read these diagrams

Each function has its own expandable diagram using the actual expressions and statements from this file. Decisions split into True and False; loop bodies are indented. Returns end the function immediately; break and continue follow their C meanings. Arrows between statements show their order when execution reaches them.

These are structural source diagrams before preprocessing, not runtime traces. Conditional compilation and macros remain source expressions. Ternary choices remain inside their statement. Calls are linked separately; callback execution and task scheduling are not inferred.

Functions in this file

setFailure() · source line 23
static void setFailure(const char *operation, const char *path)
  1. Executeconst int saved_errno = errno;
  2. Executepassed = false;
  3. Executesnprintf(stage, sizeof(stage), "%s FAILED", operation);
  4. Executesnprintf(detail, sizeof(detail), "%s E%d %.42s", path, saved_errno, strerror(saved_errno));
  5. ExecuteESP_LOGE(TAG, "%s failed for %s: errno=%d (%s)", operation, path, saved_errno, strerror(saved_errno));
Read original function source
static void setFailure(const char *operation, const char *path)
{
    const int saved_errno = errno;
    passed = false;
    snprintf(stage, sizeof(stage), "%s FAILED", operation);
    snprintf(detail, sizeof(detail), "%s E%d %.42s", path, saved_errno, strerror(saved_errno));
    ESP_LOGE(TAG, "%s failed for %s: errno=%d (%s)", operation, path, saved_errno,
             strerror(saved_errno));
}
updateSpace() · source line 33
static bool updateSpace(void)
  1. Executesize_t total_bytes = 0U;
  2. Executesize_t used_bytes = 0U;
  3. Executeconst esp_err_t result = esp_spiffs_info(SPIFFS_PARTITION, &total_bytes, &used_bytes);
  4. Decisionresult != ESP_OK
    True
      1. Executepassed = false;
      2. Executesnprintf(stage, sizeof(stage), "INFO FAILED");
      3. Executesnprintf(detail, sizeof(detail), "%s 0x%lx", esp_err_to_name(result), (unsigned long)result);
      4. ExecuteESP_LOGE(TAG, "esp_spiffs_info failed: %s (0x%lx)", esp_err_to_name(result), (unsigned long)result);
      5. Exit this functionreturn false;
    False

    Continue after this decision.

  5. Executesnprintf(space_text, sizeof(space_text), "TOTAL %uK USED %uK FREE %uK", (unsigned)(total_bytes / 1024U), (unsigned)(used_bytes / 1024U), (unsigned)((total_bytes - used_bytes) / 1024U));
  6. ExecuteESP_LOGI(TAG, "%s", space_text);
  7. Exit this functionreturn true;
Read original function source
static bool updateSpace(void)
{
    size_t total_bytes = 0U;
    size_t used_bytes = 0U;
    const esp_err_t result = esp_spiffs_info(SPIFFS_PARTITION, &total_bytes, &used_bytes);
    if (result != ESP_OK) {
        passed = false;
        snprintf(stage, sizeof(stage), "INFO FAILED");
        snprintf(detail, sizeof(detail), "%s 0x%lx", esp_err_to_name(result),
                 (unsigned long)result);
        ESP_LOGE(TAG, "esp_spiffs_info failed: %s (0x%lx)", esp_err_to_name(result),
                 (unsigned long)result);
        return false;
    }
    snprintf(space_text, sizeof(space_text), "TOTAL %uK  USED %uK  FREE %uK",
             (unsigned)(total_bytes / 1024U), (unsigned)(used_bytes / 1024U),
             (unsigned)((total_bytes - used_bytes) / 1024U));
    ESP_LOGI(TAG, "%s", space_text);
    return true;
}
writeAndVerify() · source line 54
static bool writeAndVerify(void)

Calls into this documentation:

  1. Executestatic const char first_record[] = "SPIFFS TEST\\nphase=create-and-readback\\n";
  2. Executestatic const char second_record[] = "phase=rename-and-append\\nresult=PASS\\n";
  3. Executeerrno = 0;
  4. ExecuteFILE *file = fopen(TEST_TEMP_PATH, "wb");
  5. Decisionfile == NULL
    True
      1. ExecutesetFailure("OPEN WRITE", TEST_TEMP_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  6. Executeconst size_t first_size = sizeof(first_record) - 1U;
  7. Decisionfwrite(first_record, 1U, first_size, file) != first_size
    True
      1. ExecutesetFailure("WRITE", TEST_TEMP_PATH);
      2. Executefclose(file);
      3. Exit this functionreturn false;
    False

    Continue after this decision.

  8. Decisionfflush(file) != 0
    True
      1. ExecutesetFailure("FLUSH", TEST_TEMP_PATH);
      2. Executefclose(file);
      3. Exit this functionreturn false;
    False

    Continue after this decision.

  9. Decisionfclose(file) != 0
    True
      1. ExecutesetFailure("CLOSE", TEST_TEMP_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  10. Executestruct stat information = {0};
  11. Executeerrno = 0;
  12. Decisionstat(TEST_TEMP_PATH, &information) != 0 || (size_t)information.st_size != first_size
    True
      1. ExecutesetFailure("STAT", TEST_TEMP_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  13. Executeerrno = 0;
  14. Executefile = fopen(TEST_TEMP_PATH, "rb");
  15. Decisionfile == NULL
    True
      1. ExecutesetFailure("OPEN READ", TEST_TEMP_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  16. Executechar readback[sizeof(first_record)] = {0};
  17. Executeconst size_t read_count = fread(readback, 1U, first_size, file);
  18. Executeconst int close_result = fclose(file);
  19. Decisionread_count != first_size || close_result != 0 || memcmp(readback, first_record, first_size) != 0
    True
      1. ExecutesetFailure("READBACK", TEST_TEMP_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  20. Executeerrno = 0;
  21. Decisionremove(TEST_RESULT_PATH) != 0 && errno != ENOENT
    True
      1. ExecutesetFailure("REMOVE OLD", TEST_RESULT_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  22. Executeerrno = 0;
  23. Decisionrename(TEST_TEMP_PATH, TEST_RESULT_PATH) != 0
    True
      1. ExecutesetFailure("RENAME", TEST_RESULT_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  24. Executeerrno = 0;
  25. Executefile = fopen(TEST_RESULT_PATH, "ab");
  26. Decisionfile == NULL
    True
      1. ExecutesetFailure("OPEN APPEND", TEST_RESULT_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  27. Executeconst size_t second_size = sizeof(second_record) - 1U;
  28. Executeconst size_t second_written = fwrite(second_record, 1U, second_size, file);
  29. Executeconst int append_close_result = fclose(file);
  30. Decisionsecond_written != second_size || append_close_result != 0
    True
      1. ExecutesetFailure("APPEND", TEST_RESULT_PATH);
      2. Exit this functionreturn false;
    False

    Continue after this decision.

  31. ExecuteESP_LOGI(TAG, "PASS: retained %s (%u bytes)", TEST_RESULT_PATH, (unsigned)(first_size + second_size));
  32. Exit this functionreturn true;
Read original function source
static bool writeAndVerify(void)
{
    static const char first_record[] = "SPIFFS TEST\\nphase=create-and-readback\\n";
    static const char second_record[] = "phase=rename-and-append\\nresult=PASS\\n";

    errno = 0;
    FILE *file = fopen(TEST_TEMP_PATH, "wb");
    if (file == NULL) {
        setFailure("OPEN WRITE", TEST_TEMP_PATH);
        return false;
    }
    const size_t first_size = sizeof(first_record) - 1U;
    if (fwrite(first_record, 1U, first_size, file) != first_size) {
        setFailure("WRITE", TEST_TEMP_PATH);
        fclose(file);
        return false;
    }
    if (fflush(file) != 0) {
        setFailure("FLUSH", TEST_TEMP_PATH);
        fclose(file);
        return false;
    }
    if (fclose(file) != 0) {
        setFailure("CLOSE", TEST_TEMP_PATH);
        return false;
    }

    struct stat information = {0};
    errno = 0;
    if (stat(TEST_TEMP_PATH, &information) != 0 || (size_t)information.st_size != first_size) {
        setFailure("STAT", TEST_TEMP_PATH);
        return false;
    }

    errno = 0;
    file = fopen(TEST_TEMP_PATH, "rb");
    if (file == NULL) {
        setFailure("OPEN READ", TEST_TEMP_PATH);
        return false;
    }
    char readback[sizeof(first_record)] = {0};
    const size_t read_count = fread(readback, 1U, first_size, file);
    const int close_result = fclose(file);
    if (read_count != first_size || close_result != 0 || memcmp(readback, first_record, first_size) != 0) {
        setFailure("READBACK", TEST_TEMP_PATH);
        return false;
    }

    errno = 0;
    if (remove(TEST_RESULT_PATH) != 0 && errno != ENOENT) {
        setFailure("REMOVE OLD", TEST_RESULT_PATH);
        return false;
    }
    errno = 0;
    if (rename(TEST_TEMP_PATH, TEST_RESULT_PATH) != 0) {
        setFailure("RENAME", TEST_RESULT_PATH);
        return false;
    }

    errno = 0;
    file = fopen(TEST_RESULT_PATH, "ab");
    if (file == NULL) {
        setFailure("OPEN APPEND", TEST_RESULT_PATH);
        return false;
    }
    const size_t second_size = sizeof(second_record) - 1U;
    const size_t second_written = fwrite(second_record, 1U, second_size, file);
    const int append_close_result = fclose(file);
    if (second_written != second_size || append_close_result != 0) {
        setFailure("APPEND", TEST_RESULT_PATH);
        return false;
    }
    ESP_LOGI(TAG, "PASS: retained %s (%u bytes)", TEST_RESULT_PATH,
             (unsigned)(first_size + second_size));
    return true;
}
runTest() · source line 131
static void runTest(void)

Calls into this documentation:

  1. Executepassed = true;
  2. Executesnprintf(stage, sizeof(stage), "CHECKING SPIFFS");
  3. Executedetail[0] = '\0';
  4. Executespace_text[0] = '\0';
  5. ExecuteESP_LOGI(TAG, "Starting SPIFFS diagnostic; Dungeon files are not touched");
  6. Decision!updateSpace()
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  7. Decision!writeAndVerify()
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  8. Decision!updateSpace()
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  9. Executesnprintf(stage, sizeof(stage), "PASS");
  10. Executesnprintf(detail, sizeof(detail), "CREATED _spiffs_test.result");
Read original function source
static void runTest(void)
{
    passed = true;
    snprintf(stage, sizeof(stage), "CHECKING SPIFFS");
    detail[0] = '\0';
    space_text[0] = '\0';
    ESP_LOGI(TAG, "Starting SPIFFS diagnostic; Dungeon files are not touched");
    if (!updateSpace()) return;

    if (!writeAndVerify()) return;
    if (!updateSpace()) return;
    snprintf(stage, sizeof(stage), "PASS");
    snprintf(detail, sizeof(detail), "CREATED _spiffs_test.result");
}
startSpiffsTest() · source line 146
void startSpiffsTest(void)

Calls into this documentation:

  1. Executerunning = true;
  2. ExecuterunTest();
Read original function source
void startSpiffsTest(void)
{
    running = true;
    runTest();
}
stopSpiffsTest() · source line 152
void stopSpiffsTest(void)
  1. Executerunning = false;
Read original function source
void stopSpiffsTest(void) { running = false; }
spiffsTestAction() · source line 154
void spiffsTestAction(bool action)

Calls into this documentation:

  1. Decisionrunning && action
    True
    1. ExecuterunTest();
    False

    Continue after this decision.

Read original function source
void spiffsTestAction(bool action)
{
    if (running && action) runTest();
}
drawSpiffsTest() · source line 159
void drawSpiffsTest(uint16_t *frame)

Calls into this documentation:

  1. Decision!running || frame == NULL
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  2. Executeclear(frame, COLOR_BLACK);
  3. Executedraw_text_centred(frame, 160, 8, "SPIFFS TEST", 2, COLOR_CYAN);
  4. Executedraw_text_centred(frame, 160, 42, stage, 2, passed ? COLOR_GREEN : COLOR_RED);
  5. Executedraw_text_centred(frame, 160, 70, detail, 1, COLOR_WHITE);
  6. Executedraw_text_centred(frame, 160, 92, space_text, 1, COLOR_LIGHTGRAY);
  7. Executedraw_text_centred(frame, 160, 118, "DUNGEON FILES NOT TOUCHED", 1, COLOR_YELLOW);
  8. Executedraw_text_centred(frame, 160, 156, "A/K RERUN BOOT BACK", 1, COLOR_LIGHTGRAY);
Read original function source
void drawSpiffsTest(uint16_t *frame)
{
    if (!running || frame == NULL) return;
    clear(frame, COLOR_BLACK);
    draw_text_centred(frame, 160, 8, "SPIFFS TEST", 2, COLOR_CYAN);
    draw_text_centred(frame, 160, 42, stage, 2, passed ? COLOR_GREEN : COLOR_RED);
    draw_text_centred(frame, 160, 70, detail, 1, COLOR_WHITE);
    draw_text_centred(frame, 160, 92, space_text, 1, COLOR_LIGHTGRAY);
    draw_text_centred(frame, 160, 118, "DUNGEON FILES NOT TOUCHED", 1, COLOR_YELLOW);
    draw_text_centred(frame, 160, 156, "A/K RERUN  BOOT BACK", 1, COLOR_LIGHTGRAY);
}
Complete original file, including constants and data
/* Coded By JD(2026) */
#error "Reference listing only — not provided as build-ready source."
#include "spiffs_test.h"

#include "game_graphics.h"
#include "PET2001_font.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_spiffs.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

#define SPIFFS_PARTITION "assets"
#define TEST_TEMP_PATH "/spiffs/_spiffs_test.tmp"
#define TEST_RESULT_PATH "/spiffs/_spiffs_test.result"

static const char *TAG = "spiffs_test";
static bool running;
static bool passed;
static char stage[32];
static char detail[64];
static char space_text[48];

static void setFailure(const char *operation, const char *path)
{
    const int saved_errno = errno;
    passed = false;
    snprintf(stage, sizeof(stage), "%s FAILED", operation);
    snprintf(detail, sizeof(detail), "%s E%d %.42s", path, saved_errno, strerror(saved_errno));
    ESP_LOGE(TAG, "%s failed for %s: errno=%d (%s)", operation, path, saved_errno,
             strerror(saved_errno));
}

static bool updateSpace(void)
{
    size_t total_bytes = 0U;
    size_t used_bytes = 0U;
    const esp_err_t result = esp_spiffs_info(SPIFFS_PARTITION, &total_bytes, &used_bytes);
    if (result != ESP_OK) {
        passed = false;
        snprintf(stage, sizeof(stage), "INFO FAILED");
        snprintf(detail, sizeof(detail), "%s 0x%lx", esp_err_to_name(result),
                 (unsigned long)result);
        ESP_LOGE(TAG, "esp_spiffs_info failed: %s (0x%lx)", esp_err_to_name(result),
                 (unsigned long)result);
        return false;
    }
    snprintf(space_text, sizeof(space_text), "TOTAL %uK  USED %uK  FREE %uK",
             (unsigned)(total_bytes / 1024U), (unsigned)(used_bytes / 1024U),
             (unsigned)((total_bytes - used_bytes) / 1024U));
    ESP_LOGI(TAG, "%s", space_text);
    return true;
}

static bool writeAndVerify(void)
{
    static const char first_record[] = "SPIFFS TEST\\nphase=create-and-readback\\n";
    static const char second_record[] = "phase=rename-and-append\\nresult=PASS\\n";

    errno = 0;
    FILE *file = fopen(TEST_TEMP_PATH, "wb");
    if (file == NULL) {
        setFailure("OPEN WRITE", TEST_TEMP_PATH);
        return false;
    }
    const size_t first_size = sizeof(first_record) - 1U;
    if (fwrite(first_record, 1U, first_size, file) != first_size) {
        setFailure("WRITE", TEST_TEMP_PATH);
        fclose(file);
        return false;
    }
    if (fflush(file) != 0) {
        setFailure("FLUSH", TEST_TEMP_PATH);
        fclose(file);
        return false;
    }
    if (fclose(file) != 0) {
        setFailure("CLOSE", TEST_TEMP_PATH);
        return false;
    }

    struct stat information = {0};
    errno = 0;
    if (stat(TEST_TEMP_PATH, &information) != 0 || (size_t)information.st_size != first_size) {
        setFailure("STAT", TEST_TEMP_PATH);
        return false;
    }

    errno = 0;
    file = fopen(TEST_TEMP_PATH, "rb");
    if (file == NULL) {
        setFailure("OPEN READ", TEST_TEMP_PATH);
        return false;
    }
    char readback[sizeof(first_record)] = {0};
    const size_t read_count = fread(readback, 1U, first_size, file);
    const int close_result = fclose(file);
    if (read_count != first_size || close_result != 0 || memcmp(readback, first_record, first_size) != 0) {
        setFailure("READBACK", TEST_TEMP_PATH);
        return false;
    }

    errno = 0;
    if (remove(TEST_RESULT_PATH) != 0 && errno != ENOENT) {
        setFailure("REMOVE OLD", TEST_RESULT_PATH);
        return false;
    }
    errno = 0;
    if (rename(TEST_TEMP_PATH, TEST_RESULT_PATH) != 0) {
        setFailure("RENAME", TEST_RESULT_PATH);
        return false;
    }

    errno = 0;
    file = fopen(TEST_RESULT_PATH, "ab");
    if (file == NULL) {
        setFailure("OPEN APPEND", TEST_RESULT_PATH);
        return false;
    }
    const size_t second_size = sizeof(second_record) - 1U;
    const size_t second_written = fwrite(second_record, 1U, second_size, file);
    const int append_close_result = fclose(file);
    if (second_written != second_size || append_close_result != 0) {
        setFailure("APPEND", TEST_RESULT_PATH);
        return false;
    }
    ESP_LOGI(TAG, "PASS: retained %s (%u bytes)", TEST_RESULT_PATH,
             (unsigned)(first_size + second_size));
    return true;
}

static void runTest(void)
{
    passed = true;
    snprintf(stage, sizeof(stage), "CHECKING SPIFFS");
    detail[0] = '\0';
    space_text[0] = '\0';
    ESP_LOGI(TAG, "Starting SPIFFS diagnostic; Dungeon files are not touched");
    if (!updateSpace()) return;

    if (!writeAndVerify()) return;
    if (!updateSpace()) return;
    snprintf(stage, sizeof(stage), "PASS");
    snprintf(detail, sizeof(detail), "CREATED _spiffs_test.result");
}

void startSpiffsTest(void)
{
    running = true;
    runTest();
}

void stopSpiffsTest(void) { running = false; }

void spiffsTestAction(bool action)
{
    if (running && action) runTest();
}

void drawSpiffsTest(uint16_t *frame)
{
    if (!running || frame == NULL) return;
    clear(frame, COLOR_BLACK);
    drawPet2001TextCentredTransparent(frame, 160, 8, "SPIFFS TEST", COLOR_CYAN, 2);
    drawPet2001TextCentredTransparent(frame, 160, 42, stage, passed ? COLOR_GREEN : COLOR_RED, 2);
    drawPet2001TextCentredTransparent(frame, 160, 70, detail, COLOR_WHITE, 1);
    drawPet2001TextCentredTransparent(frame, 160, 92, space_text, COLOR_LIGHTGRAY, 1);
    drawPet2001TextCentredTransparent(frame, 160, 118, "DUNGEON FILES NOT TOUCHED", COLOR_YELLOW, 1);
    drawPet2001TextCentredTransparent(frame, 160, 156, "A/K RERUN  BOOT BACK", COLOR_LIGHTGRAY, 1);
}