Try to use latest spiffs but not success.
This commit is contained in:
parent
fc8fa2cc91
commit
a1e67c5cf0
|
@ -13,8 +13,11 @@
|
|||
#define LUA_USE_MODULES
|
||||
|
||||
#ifdef LUA_USE_MODULES
|
||||
/*
|
||||
#define LUA_USE_MODULES_NODE
|
||||
*/
|
||||
#define LUA_USE_MODULES_FILE
|
||||
/*
|
||||
#define LUA_USE_MODULES_GPIO
|
||||
#define LUA_USE_MODULES_WIFI
|
||||
#define LUA_USE_MODULES_NET
|
||||
|
@ -31,6 +34,7 @@
|
|||
#define LUA_USE_MODULES_U8G
|
||||
#define LUA_USE_MODULES_WS2812
|
||||
#define LUA_USE_MODULES_CJSON
|
||||
*/
|
||||
#endif /* LUA_USE_MODULES */
|
||||
|
||||
#endif /* __USER_MODULES_H__ */
|
||||
|
|
|
@ -303,4 +303,4 @@ Having these figures you can disable SPIFFS_BUFFER_HELP again to save flash.
|
|||
|
||||
* HOW TO CONFIG
|
||||
|
||||
TODO
|
||||
TODO
|
||||
|
|
|
@ -1 +1,15 @@
|
|||
* When mending lost pages, also see if they fit into length specified in object index header
|
||||
* When mending lost pages, also see if they fit into length specified in object index header
|
||||
|
||||
SPIFFS2 thoughts
|
||||
|
||||
* Instead of exact object id:s in the object lookup tables, use a hash of span index and object id.
|
||||
Eg. object id xor:ed with bit-reversed span index.
|
||||
This should decrease number of actual pages that needs to be visited when looking thru the obj lut.
|
||||
|
||||
* Logical number of each block. When moving stuff in a garbage collected page, the free
|
||||
page is assigned the same number as the garbage collected. Thus, object index pages do not have to
|
||||
be rewritten.
|
||||
|
||||
* Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit
|
||||
as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a
|
||||
check is automatically run.
|
|
@ -1,6 +1,8 @@
|
|||
#include "c_stdio.h"
|
||||
#include "platform.h"
|
||||
#include "spiffs.h"
|
||||
#undef NODE_DBG
|
||||
#define NODE_DBG c_printf
|
||||
|
||||
spiffs fs;
|
||||
|
||||
|
@ -78,6 +80,15 @@ void myspiffs_unmount() {
|
|||
int myspiffs_format( void )
|
||||
{
|
||||
SPIFFS_unmount(&fs);
|
||||
if(0 == SPIFFS_format(&fs))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
u32_t sect_first, sect_last;
|
||||
sect_first = ( u32_t )platform_flash_get_first_free_block_address( NULL );
|
||||
sect_first += 0x3000;
|
||||
|
@ -90,7 +101,9 @@ int myspiffs_format( void )
|
|||
if( platform_flash_erase_sector( sect_first ++ ) == PLATFORM_ERR )
|
||||
return 0;
|
||||
myspiffs_mount();
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int myspiffs_check( void )
|
||||
|
@ -116,7 +129,7 @@ size_t myspiffs_write( int fd, const void* ptr, size_t len ){
|
|||
return len;
|
||||
}
|
||||
#endif
|
||||
int res = SPIFFS_write(&fs, (spiffs_file)fd, (void *)ptr, len);
|
||||
int res = SPIFFS_write(&fs, (spiffs_file)fd, (void *)ptr, (size_t)len);
|
||||
if (res < 0) {
|
||||
NODE_DBG("write errno %i\n", SPIFFS_errno(&fs));
|
||||
return 0;
|
||||
|
@ -124,7 +137,7 @@ size_t myspiffs_write( int fd, const void* ptr, size_t len ){
|
|||
return res;
|
||||
}
|
||||
size_t myspiffs_read( int fd, void* ptr, size_t len){
|
||||
int res = SPIFFS_read(&fs, (spiffs_file)fd, ptr, len);
|
||||
int res = SPIFFS_read(&fs, (spiffs_file)fd, ptr, (size_t)len);
|
||||
if (res < 0) {
|
||||
NODE_DBG("read errno %i\n", SPIFFS_errno(&fs));
|
||||
return 0;
|
||||
|
|
|
@ -41,6 +41,13 @@ extern "C" {
|
|||
#define SPIFFS_ERR_NOT_WRITABLE -10021
|
||||
#define SPIFFS_ERR_NOT_READABLE -10022
|
||||
#define SPIFFS_ERR_CONFLICTING_NAME -10023
|
||||
#define SPIFFS_ERR_NOT_CONFIGURED -10024
|
||||
|
||||
#define SPIFFS_ERR_NOT_A_FS -10025
|
||||
#define SPIFFS_ERR_MOUNTED -10026
|
||||
#define SPIFFS_ERR_ERASE_FAIL -10027
|
||||
#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028
|
||||
|
||||
|
||||
#define SPIFFS_ERR_INTERNAL -10050
|
||||
|
||||
|
@ -215,6 +222,11 @@ typedef struct {
|
|||
|
||||
// check callback function
|
||||
spiffs_check_callback check_cb_f;
|
||||
|
||||
// mounted flag
|
||||
u8_t mounted;
|
||||
// config magic
|
||||
u32_t config_magic;
|
||||
} spiffs;
|
||||
|
||||
/* spiffs file status struct */
|
||||
|
@ -242,7 +254,10 @@ typedef struct {
|
|||
// functions
|
||||
|
||||
/**
|
||||
* Initializes the file system dynamic parameters and mounts the filesystem
|
||||
* Initializes the file system dynamic parameters and mounts the filesystem.
|
||||
* If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
|
||||
* if the flash does not contain a recognizable file system.
|
||||
* In this case, SPIFFS_format must be called prior to remounting.
|
||||
* @param fs the file system struct
|
||||
* @param config the physical and logical configuration of the file system
|
||||
* @param work a memory work buffer comprising 2*config->log_page_size
|
||||
|
@ -441,6 +456,24 @@ s32_t SPIFFS_check(spiffs *fs);
|
|||
*/
|
||||
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used);
|
||||
|
||||
/**
|
||||
* Formats the entire file system. All data will be lost.
|
||||
* The filesystem must not be mounted when calling this.
|
||||
*
|
||||
* NB: formatting is awkward. Due to backwards compatibility, SPIFFS_mount
|
||||
* MUST be called prior to formatting in order to configure the filesystem.
|
||||
* If SPIFFS_mount succeeds, SPIFFS_unmount must be called before calling
|
||||
* SPIFFS_format.
|
||||
* If SPIFFS_mount fails, SPIFFS_format can be called directly without calling
|
||||
* SPIFFS_unmount first.
|
||||
*/
|
||||
s32_t SPIFFS_format(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Returns nonzero if spiffs is mounted, or zero if unmounted.
|
||||
*/
|
||||
u8_t SPIFFS_mounted(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Check if EOF reached.
|
||||
* @param fs the file system struct
|
||||
|
|
|
@ -195,7 +195,7 @@ s32_t spiffs_phys_wr(
|
|||
cache->last_access++;
|
||||
cp->last_access = cache->last_access;
|
||||
|
||||
if (cp->flags && SPIFFS_CACHE_FLAG_WRTHRU) {
|
||||
if (cp->flags & SPIFFS_CACHE_FLAG_WRTHRU) {
|
||||
// page is being updated, no write-cache, just pass thru
|
||||
return fs->cfg.hal_write_f(addr, len, src);
|
||||
} else {
|
||||
|
|
|
@ -30,19 +30,19 @@ typedef uint8_t u8_t;
|
|||
|
||||
// Set generic spiffs debug output call.
|
||||
#ifndef SPIFFS_DGB
|
||||
#define SPIFFS_DBG(...) //printf(__VA_ARGS__)
|
||||
#define SPIFFS_DBG(...) c_printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for garbage collecting.
|
||||
#ifndef SPIFFS_GC_DGB
|
||||
#define SPIFFS_GC_DBG(...) //printf(__VA_ARGS__)
|
||||
#define SPIFFS_GC_DBG(...) //c_printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for caching.
|
||||
#ifndef SPIFFS_CACHE_DGB
|
||||
#define SPIFFS_CACHE_DBG(...) //printf(__VA_ARGS__)
|
||||
#define SPIFFS_CACHE_DBG(...) //c_printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for system consistency checks.
|
||||
#ifndef SPIFFS_CHECK_DGB
|
||||
#define SPIFFS_CHECK_DBG(...) //printf(__VA_ARGS__)
|
||||
#define SPIFFS_CHECK_DBG(...) //c_printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
// Enable/disable API functions to determine exact number of bytes
|
||||
|
@ -119,14 +119,22 @@ typedef uint8_t u8_t;
|
|||
#define SPIFFS_COPY_BUFFER_STACK (64)
|
||||
#endif
|
||||
|
||||
// Enable this to have an identifiable spiffs filesystem. This will look for
|
||||
// a magic in all sectors to determine if this is a valid spiffs system or
|
||||
// not on mount point. If not, SPIFFS_format must be called prior to mounting
|
||||
// again.
|
||||
#ifndef SPIFFS_USE_MAGIC
|
||||
#define SPIFFS_USE_MAGIC (0)
|
||||
#endif
|
||||
|
||||
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
||||
// These should be defined on a multithreaded system
|
||||
|
||||
// define this to entering a mutex if you're running on a multithreaded system
|
||||
// define this to enter a mutex if you're running on a multithreaded system
|
||||
#ifndef SPIFFS_LOCK
|
||||
#define SPIFFS_LOCK(fs)
|
||||
#endif
|
||||
// define this to exiting a mutex if you're running on a multithreaded system
|
||||
// define this to exit a mutex if you're running on a multithreaded system
|
||||
#ifndef SPIFFS_UNLOCK
|
||||
#define SPIFFS_UNLOCK(fs)
|
||||
#endif
|
||||
|
@ -159,7 +167,12 @@ typedef uint8_t u8_t;
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// Set SPFIFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
|
||||
// Enable this if your target needs aligned data for index tables
|
||||
#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
|
||||
#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 0
|
||||
#endif
|
||||
|
||||
// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
|
||||
// in the api. This function will visualize all filesystem using given printf
|
||||
// function.
|
||||
#ifndef SPIFFS_TEST_VISUALISATION
|
||||
|
|
|
@ -8,31 +8,11 @@ static s32_t spiffs_gc_erase_block(
|
|||
spiffs *fs,
|
||||
spiffs_block_ix bix) {
|
||||
s32_t res;
|
||||
u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
|
||||
s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
|
||||
SPIFFS_GC_DBG("gc: erase block %i\n", bix);
|
||||
|
||||
// here we ignore res, just try erasing the block
|
||||
while (size > 0) {
|
||||
SPIFFS_GC_DBG("gc: erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
(void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
}
|
||||
fs->free_blocks++;
|
||||
|
||||
// register erase count for this block
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_ERASE_COUNT_PADDR(fs, bix),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
|
||||
res = spiffs_erase_block(fs, bix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
fs->max_erase_count++;
|
||||
if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
|
||||
fs->max_erase_count = 0;
|
||||
}
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
{
|
||||
u32_t i;
|
||||
|
@ -130,12 +110,15 @@ s32_t spiffs_gc_check(
|
|||
}
|
||||
|
||||
u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs);
|
||||
if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
|
||||
// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
|
||||
// SPIFFS_GC_DBG("gc: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
|
||||
// return SPIFFS_ERR_FULL;
|
||||
// }
|
||||
if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) {
|
||||
SPIFFS_GC_DBG("gc_check: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
|
||||
return SPIFFS_ERR_FULL;
|
||||
}
|
||||
|
||||
//printf("gcing started %i dirty, blocks %i free, want %i bytes\n", fs->stats_p_allocated + fs->stats_p_deleted, fs->free_blocks, len);
|
||||
|
||||
do {
|
||||
SPIFFS_GC_DBG("\ngc_check #%i: run gc free_blocks:%i pfree:%i pallo:%i pdele:%i [%i] len:%i of %i\n",
|
||||
tries,
|
||||
|
@ -145,11 +128,13 @@ s32_t spiffs_gc_check(
|
|||
spiffs_block_ix *cands;
|
||||
int count;
|
||||
spiffs_block_ix cand;
|
||||
res = spiffs_gc_find_candidate(fs, &cands, &count);
|
||||
s32_t prev_free_pages = free_pages;
|
||||
// if the fs is crammed, ignore block age when selecting candidate - kind of a bad state
|
||||
res = spiffs_gc_find_candidate(fs, &cands, &count, free_pages <= 0);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (count == 0) {
|
||||
SPIFFS_GC_DBG("gc_check: no candidates, return\n");
|
||||
return res;
|
||||
return (s32_t)needed_pages < free_pages ? SPIFFS_OK : SPIFFS_ERR_FULL;
|
||||
}
|
||||
#if SPIFFS_GC_STATS
|
||||
fs->stats_gc_runs++;
|
||||
|
@ -176,6 +161,12 @@ s32_t spiffs_gc_check(
|
|||
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
|
||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||
|
||||
if (prev_free_pages <= 0 && prev_free_pages == free_pages) {
|
||||
// abort early to reduce wear, at least tried once
|
||||
SPIFFS_GC_DBG("gc_check: early abort, no result on gc when fs crammed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
} while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
|
||||
(s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)));
|
||||
|
||||
|
@ -234,7 +225,8 @@ s32_t spiffs_gc_erase_page_stats(
|
|||
s32_t spiffs_gc_find_candidate(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix **block_candidates,
|
||||
int *candidate_count) {
|
||||
int *candidate_count,
|
||||
char fs_crammed) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t blocks = fs->block_count;
|
||||
spiffs_block_ix cur_block = 0;
|
||||
|
@ -307,7 +299,7 @@ s32_t spiffs_gc_find_candidate(
|
|||
s32_t score =
|
||||
deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
|
||||
used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
|
||||
erase_age * SPIFFS_GC_HEUR_W_ERASE_AGE;
|
||||
erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE);
|
||||
int cand_ix = 0;
|
||||
SPIFFS_GC_DBG("gc_check: bix:%i del:%i use:%i score:%i\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
|
||||
while (cand_ix < max_candidates) {
|
||||
|
|
|
@ -21,6 +21,36 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
u8_t SPIFFS_mounted(spiffs *fs) {
|
||||
return SPIFFS_CHECK_MOUNT(fs);
|
||||
}
|
||||
|
||||
s32_t SPIFFS_format(spiffs *fs) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
if (SPIFFS_CHECK_MOUNT(fs)) {
|
||||
fs->err_code = SPIFFS_ERR_MOUNTED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32_t res;
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_block_ix bix = 0;
|
||||
while (bix < fs->block_count) {
|
||||
fs->max_erase_count = 0;
|
||||
res = spiffs_erase_block(fs, bix);
|
||||
if (res != SPIFFS_OK) {
|
||||
res = SPIFFS_ERR_ERASE_FAIL;
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
bix++;
|
||||
}
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
||||
u8_t *fd_space, u32_t fd_space_size,
|
||||
void *cache, u32_t cache_size,
|
||||
|
@ -65,7 +95,16 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||
spiffs_cache_init(fs);
|
||||
#endif
|
||||
|
||||
s32_t res = spiffs_obj_lu_scan(fs);
|
||||
s32_t res;
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
res = SPIFFS_CHECK_MAGIC_POSSIBLE(fs) ? SPIFFS_OK : SPIFFS_ERR_MAGIC_NOT_POSSIBLE;
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
#endif
|
||||
|
||||
fs->config_magic = SPIFFS_CONFIG_MAGIC;
|
||||
|
||||
res = spiffs_obj_lu_scan(fs);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
SPIFFS_DBG("page index byte len: %i\n", SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
|
@ -79,13 +118,15 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
|||
|
||||
fs->check_cb_f = check_cb_f;
|
||||
|
||||
fs->mounted = 1;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SPIFFS_unmount(spiffs *fs) {
|
||||
if (!SPIFFS_CHECK_MOUNT(fs)) return;
|
||||
if (!SPIFFS_CHECK_CFG(fs) || !SPIFFS_CHECK_MOUNT(fs)) return;
|
||||
SPIFFS_LOCK(fs);
|
||||
u32_t i;
|
||||
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
|
||||
|
@ -98,7 +139,8 @@ void SPIFFS_unmount(spiffs *fs) {
|
|||
spiffs_fd_return(fs, cur_fd->file_nbr);
|
||||
}
|
||||
}
|
||||
fs->block_count = 0;
|
||||
fs->mounted = 0;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
}
|
||||
|
||||
|
@ -112,6 +154,7 @@ void SPIFFS_clearerr(spiffs *fs) {
|
|||
|
||||
s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode) {
|
||||
(void)mode;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
spiffs_obj_id obj_id;
|
||||
|
@ -127,6 +170,7 @@ s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode) {
|
|||
|
||||
spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode) {
|
||||
(void)mode;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -185,6 +229,7 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
|
|||
}
|
||||
|
||||
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -214,6 +259,7 @@ spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_fl
|
|||
}
|
||||
|
||||
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -282,6 +328,7 @@ static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offs
|
|||
}
|
||||
|
||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -400,6 +447,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -444,6 +492,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_remove(spiffs *fs, char *path) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -477,6 +526,7 @@ s32_t SPIFFS_remove(spiffs *fs, char *path) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -525,6 +575,7 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi
|
|||
}
|
||||
|
||||
s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -542,6 +593,7 @@ s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -595,6 +647,7 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
s32_t res = SPIFFS_OK;
|
||||
#if SPIFFS_CACHE_WR
|
||||
|
@ -608,6 +661,11 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
|
|||
}
|
||||
|
||||
void SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
||||
if (!SPIFFS_CHECK_CFG((fs))) {
|
||||
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
||||
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
|
||||
return;
|
||||
|
@ -623,6 +681,7 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -664,10 +723,17 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
|
|||
|
||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d) {
|
||||
(void)name;
|
||||
|
||||
if (!SPIFFS_CHECK_CFG((fs))) {
|
||||
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SPIFFS_CHECK_MOUNT(fs)) {
|
||||
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->fs = fs;
|
||||
d->block = 0;
|
||||
d->entry = 0;
|
||||
|
@ -743,12 +809,14 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_closedir(spiffs_DIR *d) {
|
||||
SPIFFS_API_CHECK_CFG(d->fs);
|
||||
SPIFFS_API_CHECK_MOUNT(d->fs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_check(spiffs *fs) {
|
||||
s32_t res;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -766,6 +834,7 @@ s32_t SPIFFS_check(spiffs *fs) {
|
|||
|
||||
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
@ -788,11 +857,13 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_fd *fd;
|
||||
s32_t res;
|
||||
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
|
||||
|
@ -807,11 +878,13 @@ s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_fd *fd;
|
||||
s32_t res;
|
||||
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
|
||||
|
@ -826,11 +899,13 @@ s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
|
|||
}
|
||||
|
||||
s32_t SPIFFS_size(spiffs *fs, spiffs_file fh) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_fd *fd;
|
||||
s32_t res;
|
||||
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
|
||||
|
@ -847,6 +922,7 @@ s32_t SPIFFS_size(spiffs *fs, spiffs_file fh) {
|
|||
#if SPIFFS_TEST_VISUALISATION
|
||||
s32_t SPIFFS_vis(spiffs *fs) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_API_CHECK_CFG(fs);
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
|
|
|
@ -142,9 +142,13 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||
cur_block++;
|
||||
cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
if (cur_block >= fs->block_count) {
|
||||
// block wrap
|
||||
cur_block = 0;
|
||||
cur_block_addr = 0;
|
||||
if (flags & SPIFFS_VIS_NO_WRAP) {
|
||||
return SPIFFS_VIS_END;
|
||||
} else {
|
||||
// block wrap
|
||||
cur_block = 0;
|
||||
cur_block_addr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,6 +217,45 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||
return SPIFFS_VIS_END;
|
||||
}
|
||||
|
||||
s32_t spiffs_erase_block(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix) {
|
||||
s32_t res;
|
||||
u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
|
||||
s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
|
||||
// here we ignore res, just try erasing the block
|
||||
while (size > 0) {
|
||||
SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
(void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
}
|
||||
fs->free_blocks++;
|
||||
|
||||
// register erase count for this block
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_ERASE_COUNT_PADDR(fs, bix),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
// finally, write magic
|
||||
spiffs_obj_id magic = SPIFFS_MAGIC(fs);
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_MAGIC_PADDR(fs, bix),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&magic);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
#endif
|
||||
|
||||
fs->max_erase_count++;
|
||||
if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
|
||||
fs->max_erase_count = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static s32_t spiffs_obj_lu_scan_v(
|
||||
spiffs *fs,
|
||||
|
@ -238,40 +281,44 @@ static s32_t spiffs_obj_lu_scan_v(
|
|||
return SPIFFS_VIS_COUNTINUE;
|
||||
}
|
||||
|
||||
|
||||
// Scans thru all obj lu and counts free, deleted and used pages
|
||||
// Find the maximum block erase count
|
||||
// Checks magic if enabled
|
||||
s32_t spiffs_obj_lu_scan(
|
||||
spiffs *fs) {
|
||||
s32_t res;
|
||||
spiffs_block_ix bix;
|
||||
int entry;
|
||||
#if SPIFFS_USE_MAGIC
|
||||
spiffs_block_ix unerased_bix = (spiffs_block_ix)-1;
|
||||
#endif
|
||||
|
||||
fs->free_blocks = 0;
|
||||
fs->stats_p_allocated = 0;
|
||||
fs->stats_p_deleted = 0;
|
||||
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
spiffs_obj_lu_scan_v,
|
||||
0,
|
||||
0,
|
||||
&bix,
|
||||
&entry);
|
||||
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
// find out erase count
|
||||
// if enabled, check magic
|
||||
bix = 0;
|
||||
spiffs_obj_id erase_count_final;
|
||||
spiffs_obj_id erase_count_min = SPIFFS_OBJ_ID_FREE;
|
||||
spiffs_obj_id erase_count_max = 0;
|
||||
while (bix < fs->block_count) {
|
||||
#if SPIFFS_USE_MAGIC
|
||||
spiffs_obj_id magic;
|
||||
res = _spiffs_rd(fs,
|
||||
SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_MAGIC_PADDR(fs, bix) ,
|
||||
sizeof(spiffs_obj_id), (u8_t *)&magic);
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (magic != SPIFFS_MAGIC(fs)) {
|
||||
if (unerased_bix == (spiffs_block_ix)-1) {
|
||||
// allow one unerased block as it might be powered down during an erase
|
||||
unerased_bix = bix;
|
||||
} else {
|
||||
// more than one unerased block, bail out
|
||||
SPIFFS_CHECK_RES(SPIFFS_ERR_NOT_A_FS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
spiffs_obj_id erase_count;
|
||||
res = _spiffs_rd(fs,
|
||||
SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
|
@ -297,6 +344,38 @@ s32_t spiffs_obj_lu_scan(
|
|||
|
||||
fs->max_erase_count = erase_count_final;
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
if (unerased_bix != (spiffs_block_ix)-1) {
|
||||
// found one unerased block, remedy
|
||||
SPIFFS_DBG("mount: erase block %i\n", bix);
|
||||
res = spiffs_erase_block(fs, unerased_bix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
#endif
|
||||
|
||||
// count blocks
|
||||
|
||||
fs->free_blocks = 0;
|
||||
fs->stats_p_allocated = 0;
|
||||
fs->stats_p_deleted = 0;
|
||||
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
spiffs_obj_lu_scan_v,
|
||||
0,
|
||||
0,
|
||||
&bix,
|
||||
&entry);
|
||||
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,6 +131,10 @@
|
|||
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
|
||||
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
|
||||
|
||||
#define SPIFFS_MAGIC(fs) ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
|
||||
|
||||
#define SPIFFS_CONFIG_MAGIC (0x20090315)
|
||||
|
||||
#if SPIFFS_SINGLETON == 0
|
||||
#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
|
||||
((fs)->cfg.log_page_size)
|
||||
|
@ -189,9 +193,18 @@
|
|||
// returns data size in a data page
|
||||
#define SPIFFS_DATA_PAGE_SIZE(fs) \
|
||||
( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
|
||||
// returns physical address for block's erase count
|
||||
// returns physical address for block's erase count,
|
||||
// always in the physical last entry of the last object lookup page
|
||||
#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
|
||||
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
|
||||
// returns physical address for block's magic,
|
||||
// always in the physical second last entry of the last object lookup page
|
||||
#define SPIFFS_MAGIC_PADDR(fs, bix) \
|
||||
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
|
||||
// checks if there is any room for magic in the object luts
|
||||
#define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
|
||||
( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
|
||||
<= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
|
||||
|
||||
// define helpers object
|
||||
|
||||
|
@ -238,7 +251,10 @@
|
|||
|
||||
|
||||
#define SPIFFS_CHECK_MOUNT(fs) \
|
||||
((fs)->block_count > 0)
|
||||
((fs)->mounted != 0)
|
||||
|
||||
#define SPIFFS_CHECK_CFG(fs) \
|
||||
((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
|
||||
|
||||
#define SPIFFS_CHECK_RES(res) \
|
||||
do { \
|
||||
|
@ -251,6 +267,12 @@
|
|||
return -1; \
|
||||
}
|
||||
|
||||
#define SPIFFS_API_CHECK_CFG(fs) \
|
||||
if (!SPIFFS_CHECK_CFG((fs))) { \
|
||||
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
#define SPIFFS_API_CHECK_RES(fs, res) \
|
||||
if ((res) < SPIFFS_OK) { \
|
||||
(fs)->err_code = (res); \
|
||||
|
@ -381,6 +403,8 @@ typedef struct {
|
|||
// object structs
|
||||
|
||||
// page header, part of each page except object lookup pages
|
||||
// NB: this is always aligned when the data page is an object index,
|
||||
// as in this case struct spiffs_page_object_ix is used
|
||||
typedef struct __attribute(( packed )) {
|
||||
// object id
|
||||
spiffs_obj_id obj_id;
|
||||
|
@ -391,11 +415,15 @@ typedef struct __attribute(( packed )) {
|
|||
} spiffs_page_header;
|
||||
|
||||
// object index header page header
|
||||
typedef struct __attribute(( packed )) {
|
||||
typedef struct __attribute(( packed ))
|
||||
#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
|
||||
__attribute(( aligned(sizeof(spiffs_page_ix)) ))
|
||||
#endif
|
||||
{
|
||||
// common page header
|
||||
spiffs_page_header p_hdr;
|
||||
// alignment
|
||||
u8_t _align[4 - ((sizeof(spiffs_page_header)+sizeof(spiffs_obj_type)+SPIFFS_OBJ_NAME_LEN)&3)==0 ? 4 : ((sizeof(spiffs_page_header)+sizeof(spiffs_obj_type)+SPIFFS_OBJ_NAME_LEN)&3)];
|
||||
u8_t _align[4 - (sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3)];
|
||||
// size of object
|
||||
u32_t size;
|
||||
// type of object
|
||||
|
@ -478,6 +506,10 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
|||
spiffs_block_ix *block_ix,
|
||||
int *lu_entry);
|
||||
|
||||
s32_t spiffs_erase_block(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix);
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_obj_lu_scan(
|
||||
|
@ -625,7 +657,8 @@ s32_t spiffs_gc_erase_page_stats(
|
|||
s32_t spiffs_gc_find_candidate(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix **block_candidate,
|
||||
int *candidate_count);
|
||||
int *candidate_count,
|
||||
char fs_crammed);
|
||||
|
||||
s32_t spiffs_gc_clean(
|
||||
spiffs *fs,
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
// spiffs file system offset in emulated spi flash
|
||||
#define SPIFFS_PHYS_ADDR (4*1024*1024)
|
||||
|
||||
// test using filesystem magic
|
||||
//#define SPIFFS_USE_MAGIC 1
|
||||
|
||||
#define SECTOR_SIZE 65536
|
||||
#define LOG_BLOCK (SECTOR_SIZE*2)
|
||||
#define LOG_PAGE (SECTOR_SIZE/256)
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
SUITE(bug_tests)
|
||||
void setup() {
|
||||
_setup_test_only();
|
||||
|
@ -27,7 +26,7 @@ void teardown() {
|
|||
}
|
||||
|
||||
TEST(nodemcu_full_fs_1) {
|
||||
fs_reset_specific(0, 4096*20, 4096, 4096, 256);
|
||||
fs_reset_specific(0, 0, 4096*20, 4096, 4096, 256);
|
||||
|
||||
int res;
|
||||
spiffs_file fd;
|
||||
|
@ -86,7 +85,7 @@ TEST(nodemcu_full_fs_1) {
|
|||
} TEST_END(nodemcu_full_fs_1)
|
||||
|
||||
TEST(nodemcu_full_fs_2) {
|
||||
fs_reset_specific(0, 4096*22, 4096, 4096, 256);
|
||||
fs_reset_specific(0, 0, 4096*22, 4096, 4096, 256);
|
||||
|
||||
int res;
|
||||
spiffs_file fd;
|
||||
|
@ -116,6 +115,8 @@ TEST(nodemcu_full_fs_2) {
|
|||
SPIFFS_clearerr(FS);
|
||||
printf(" create small file\n");
|
||||
fd = SPIFFS_open(FS, "test2.txt", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0);
|
||||
#if 0
|
||||
// before gc in v3.1
|
||||
TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_OK);
|
||||
TEST_CHECK(fd > 0);
|
||||
|
||||
|
@ -130,12 +131,17 @@ TEST(nodemcu_full_fs_2) {
|
|||
printf(" >>> file %s size: %i\n", s.name, s.size);
|
||||
TEST_CHECK(s.size == 0);
|
||||
SPIFFS_clearerr(FS);
|
||||
|
||||
#else
|
||||
TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FULL);
|
||||
SPIFFS_clearerr(FS);
|
||||
#endif
|
||||
printf(" remove files\n");
|
||||
res = SPIFFS_remove(FS, "test1.txt");
|
||||
TEST_CHECK(res == SPIFFS_OK);
|
||||
#if 0
|
||||
res = SPIFFS_remove(FS, "test2.txt");
|
||||
TEST_CHECK(res == SPIFFS_OK);
|
||||
#endif
|
||||
|
||||
printf(" create medium file\n");
|
||||
fd = SPIFFS_open(FS, "test3.txt", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0);
|
||||
|
@ -157,4 +163,169 @@ TEST(nodemcu_full_fs_2) {
|
|||
|
||||
} TEST_END(nodemcu_full_fs_2)
|
||||
|
||||
TEST(magic_test) {
|
||||
// one obj lu page, not full
|
||||
fs_reset_specific(0, 0, 4096*16, 4096, 4096*1, 128);
|
||||
TEST_CHECK(SPIFFS_CHECK_MAGIC_POSSIBLE(FS));
|
||||
// one obj lu page, full
|
||||
fs_reset_specific(0, 0, 4096*16, 4096, 4096*2, 128);
|
||||
TEST_CHECK(!SPIFFS_CHECK_MAGIC_POSSIBLE(FS));
|
||||
// two obj lu pages, not full
|
||||
fs_reset_specific(0, 0, 4096*16, 4096, 4096*4, 128);
|
||||
TEST_CHECK(SPIFFS_CHECK_MAGIC_POSSIBLE(FS));
|
||||
|
||||
return TEST_RES_OK;
|
||||
|
||||
} TEST_END(magic_test)
|
||||
|
||||
TEST(nodemcu_309) {
|
||||
fs_reset_specific(0, 0, 4096*20, 4096, 4096, 256);
|
||||
|
||||
int res;
|
||||
spiffs_file fd;
|
||||
int j;
|
||||
|
||||
for (j = 1; j <= 3; j++) {
|
||||
char fname[32];
|
||||
sprintf(fname, "20K%i.txt", j);
|
||||
fd = SPIFFS_open(FS, fname, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_DIRECT, 0);
|
||||
TEST_CHECK(fd > 0);
|
||||
int i;
|
||||
spiffs_stat s;
|
||||
res = SPIFFS_OK;
|
||||
u8_t err = 0;
|
||||
for (i = 1; i <= 1280; i++) {
|
||||
char *buf = "0123456789ABCDE\n";
|
||||
res = SPIFFS_write(FS, fd, buf, strlen(buf));
|
||||
if (!err && res < 0) {
|
||||
printf("err @ %i,%i\n", i, j);
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int errno = SPIFFS_errno(FS);
|
||||
TEST_CHECK(errno == SPIFFS_ERR_FULL);
|
||||
|
||||
u32_t total;
|
||||
u32_t used;
|
||||
|
||||
SPIFFS_info(FS, &total, &used);
|
||||
printf("total:%i\nused:%i\nremain:%i\nerrno:%i\n", total, used, total-used, errno);
|
||||
TEST_CHECK(total-used < 11000);
|
||||
|
||||
spiffs_DIR d;
|
||||
struct spiffs_dirent e;
|
||||
struct spiffs_dirent *pe = &e;
|
||||
|
||||
SPIFFS_opendir(FS, "/", &d);
|
||||
int spoon_guard = 0;
|
||||
while ((pe = SPIFFS_readdir(&d, pe))) {
|
||||
printf("%s [%04x] size:%i\n", pe->name, pe->obj_id, pe->size);
|
||||
TEST_CHECK(spoon_guard++ < 3);
|
||||
}
|
||||
TEST_CHECK(spoon_guard == 3);
|
||||
SPIFFS_closedir(&d);
|
||||
|
||||
return TEST_RES_OK;
|
||||
|
||||
} TEST_END(nodemcu_309)
|
||||
|
||||
|
||||
TEST(robert) {
|
||||
// create a clean file system starting at address 0, 2 megabytes big,
|
||||
// sector size 65536, block size 65536, page size 256
|
||||
fs_reset_specific(0, 0, 1024*1024*2, 65536, 65536, 256);
|
||||
|
||||
int res;
|
||||
spiffs_file fd;
|
||||
char fname[32];
|
||||
|
||||
sprintf(fname, "test.txt");
|
||||
fd = SPIFFS_open(FS, fname, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0);
|
||||
TEST_CHECK(fd > 0);
|
||||
int i;
|
||||
res = SPIFFS_OK;
|
||||
char buf[500];
|
||||
memset(buf, 0xaa, 500);
|
||||
res = SPIFFS_write(FS, fd, buf, 500);
|
||||
TEST_CHECK(res >= SPIFFS_OK);
|
||||
SPIFFS_close(FS, fd);
|
||||
|
||||
int errno = SPIFFS_errno(FS);
|
||||
TEST_CHECK(errno == SPIFFS_OK);
|
||||
|
||||
//SPIFFS_vis(FS);
|
||||
// unmount
|
||||
SPIFFS_unmount(FS);
|
||||
|
||||
// remount
|
||||
res = fs_mount_specific(0, 1024*1024*2, 65536, 65536, 256);
|
||||
TEST_CHECK(res== SPIFFS_OK);
|
||||
|
||||
//SPIFFS_vis(FS);
|
||||
|
||||
spiffs_stat s;
|
||||
TEST_CHECK(SPIFFS_stat(FS, fname, &s) == SPIFFS_OK);
|
||||
printf("file %s stat size %i\n", s.name, s.size);
|
||||
TEST_CHECK(s.size == 500);
|
||||
|
||||
return TEST_RES_OK;
|
||||
|
||||
} TEST_END(robert)
|
||||
|
||||
|
||||
TEST(spiffs_12) {
|
||||
fs_reset_specific(0x4024c000, 0x4024c000 + 0, 192*1024, 4096, 4096*2, 256);
|
||||
|
||||
int res;
|
||||
spiffs_file fd;
|
||||
int j = 1;
|
||||
|
||||
while (1) {
|
||||
char fname[32];
|
||||
sprintf(fname, "file%i.txt", j);
|
||||
fd = SPIFFS_open(FS, fname, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_DIRECT, 0);
|
||||
if (fd <=0) break;
|
||||
|
||||
int i;
|
||||
res = SPIFFS_OK;
|
||||
for (i = 1; i <= 100; i++) {
|
||||
char *buf = "0123456789ABCDE\n";
|
||||
res = SPIFFS_write(FS, fd, buf, strlen(buf));
|
||||
if (res < 0) break;
|
||||
}
|
||||
SPIFFS_close(FS, fd);
|
||||
j++;
|
||||
}
|
||||
|
||||
int errno = SPIFFS_errno(FS);
|
||||
TEST_CHECK(errno == SPIFFS_ERR_FULL);
|
||||
|
||||
u32_t total;
|
||||
u32_t used;
|
||||
|
||||
SPIFFS_info(FS, &total, &used);
|
||||
printf("total:%i (%iK)\nused:%i (%iK)\nremain:%i (%iK)\nerrno:%i\n", total, total/1024, used, used/1024, total-used, (total-used)/1024, errno);
|
||||
|
||||
spiffs_DIR d;
|
||||
struct spiffs_dirent e;
|
||||
struct spiffs_dirent *pe = &e;
|
||||
|
||||
SPIFFS_opendir(FS, "/", &d);
|
||||
while ((pe = SPIFFS_readdir(&d, pe))) {
|
||||
printf("%s [%04x] size:%i\n", pe->name, pe->obj_id, pe->size);
|
||||
}
|
||||
SPIFFS_closedir(&d);
|
||||
|
||||
//SPIFFS_vis(FS);
|
||||
|
||||
//dump_page(FS, 0);
|
||||
//dump_page(FS, 1);
|
||||
|
||||
return TEST_RES_OK;
|
||||
|
||||
} TEST_END(spiffs_12)
|
||||
|
||||
|
||||
SUITE_END(bug_tests)
|
||||
|
|
|
@ -592,7 +592,6 @@ TEST(simultaneous_write_append) {
|
|||
}
|
||||
TEST_END(simultaneous_write_append)
|
||||
|
||||
|
||||
TEST(file_uniqueness)
|
||||
{
|
||||
int res;
|
||||
|
|
|
@ -24,9 +24,12 @@
|
|||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static unsigned char area[PHYS_FLASH_SIZE];
|
||||
#define AREA(x) area[(x) - addr_offset]
|
||||
|
||||
static int erases[256];
|
||||
static unsigned char area[PHYS_FLASH_SIZE];
|
||||
static u32_t addr_offset = 0;
|
||||
|
||||
static int erases[PHYS_FLASH_SIZE/SECTOR_SIZE];
|
||||
static char _path[256];
|
||||
static u32_t bytes_rd = 0;
|
||||
static u32_t bytes_wr = 0;
|
||||
|
@ -88,7 +91,7 @@ static s32_t _read(u32_t addr, u32_t size, u8_t *dst) {
|
|||
printf("FATAL read addr too high %08x + %08x > %08x\n", addr, size, SPIFFS_PHYS_ADDR + SPIFFS_FLASH_SIZE);
|
||||
exit(0);
|
||||
}
|
||||
memcpy(dst, &area[addr], size);
|
||||
memcpy(dst, &AREA(addr), size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -117,14 +120,14 @@ static s32_t _write(u32_t addr, u32_t size, u8_t *src) {
|
|||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (((addr + i) & (__fs.cfg.log_page_size-1)) != offsetof(spiffs_page_header, flags)) {
|
||||
if (check_valid_flash && ((area[addr + i] ^ src[i]) & src[i])) {
|
||||
printf("trying to write %02x to %02x at addr %08x\n", src[i], area[addr + i], addr+i);
|
||||
if (check_valid_flash && ((AREA(addr + i) ^ src[i]) & src[i])) {
|
||||
printf("trying to write %02x to %02x at addr %08x\n", src[i], AREA(addr + i), addr+i);
|
||||
spiffs_page_ix pix = (addr + i) / LOG_PAGE;
|
||||
dump_page(&__fs, pix);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
area[addr + i] &= src[i];
|
||||
AREA(addr + i) &= src[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -139,7 +142,7 @@ static s32_t _erase(u32_t addr, u32_t size) {
|
|||
return -1;
|
||||
}
|
||||
erases[(addr-__fs.cfg.phys_addr)/__fs.cfg.phys_erase_block]++;
|
||||
memset(&area[addr], 0xff, size);
|
||||
memset(&AREA(addr), 0xff, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -165,7 +168,7 @@ void hexdump(u32_t addr, u32_t len) {
|
|||
if (a-32+j < addr)
|
||||
printf(" ");
|
||||
else {
|
||||
printf("%c", (area[a-32+j] < 32 || area[a-32+j] >= 0x7f) ? '.' : area[a-32+j]);
|
||||
printf("%c", (AREA(a-32+j) < 32 || AREA(a-32+j) >= 0x7f) ? '.' : AREA(a-32+j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +177,7 @@ void hexdump(u32_t addr, u32_t len) {
|
|||
if (a < addr) {
|
||||
printf(" ");
|
||||
} else {
|
||||
printf("%02x", area[a]);
|
||||
printf("%02x", AREA(a));
|
||||
}
|
||||
}
|
||||
int j;
|
||||
|
@ -183,7 +186,7 @@ void hexdump(u32_t addr, u32_t len) {
|
|||
if (a-32+j < addr)
|
||||
printf(" ");
|
||||
else {
|
||||
printf("%c", (area[a-32+j] < 32 || area[a-32+j] >= 0x7f) ? '.' : area[a-32+j]);
|
||||
printf("%c", (AREA(a-32+j) < 32 || AREA(a-32+j) >= 0x7f) ? '.' : AREA(a-32+j));
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
@ -198,9 +201,9 @@ void dump_page(spiffs *fs, spiffs_page_ix p) {
|
|||
} else {
|
||||
u32_t obj_id_addr = SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs , p)) +
|
||||
SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, p) * sizeof(spiffs_obj_id);
|
||||
spiffs_obj_id obj_id = *((spiffs_obj_id *)&area[obj_id_addr]);
|
||||
spiffs_obj_id obj_id = *((spiffs_obj_id *)&AREA(obj_id_addr));
|
||||
// data page
|
||||
spiffs_page_header *ph = (spiffs_page_header *)&area[addr];
|
||||
spiffs_page_header *ph = (spiffs_page_header *)&AREA(addr);
|
||||
printf("DATA %04x:%04x ", obj_id, ph->span_ix);
|
||||
printf("%s", ((ph->flags & SPIFFS_PH_FLAG_FINAL) == 0) ? "FIN " : "fin ");
|
||||
printf("%s", ((ph->flags & SPIFFS_PH_FLAG_DELET) == 0) ? "DEL " : "del ");
|
||||
|
@ -212,7 +215,7 @@ void dump_page(spiffs *fs, spiffs_page_ix p) {
|
|||
printf("OBJ_IX");
|
||||
if (ph->span_ix == 0) {
|
||||
printf("_HDR ");
|
||||
spiffs_page_object_ix_header *oix_hdr = (spiffs_page_object_ix_header *)&area[addr];
|
||||
spiffs_page_object_ix_header *oix_hdr = (spiffs_page_object_ix_header *)&AREA(addr);
|
||||
printf("'%s' %i bytes type:%02x", oix_hdr->name, oix_hdr->size, oix_hdr->type);
|
||||
}
|
||||
} else {
|
||||
|
@ -228,14 +231,14 @@ void dump_page(spiffs *fs, spiffs_page_ix p) {
|
|||
void area_write(u32_t addr, u8_t *buf, u32_t size) {
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
area[addr + i] = *buf++;
|
||||
AREA(addr + i) = *buf++;
|
||||
}
|
||||
}
|
||||
|
||||
void area_read(u32_t addr, u8_t *buf, u32_t size) {
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
*buf++ = area[addr + i];
|
||||
*buf++ = AREA(addr + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,12 +316,13 @@ static void spiffs_check_cb_f(spiffs_check_type type, spiffs_check_report report
|
|||
}
|
||||
}
|
||||
|
||||
void fs_reset_specific(u32_t phys_addr, u32_t phys_size,
|
||||
void fs_set_addr_offset(u32_t offset) {
|
||||
addr_offset = offset;
|
||||
}
|
||||
|
||||
s32_t fs_mount_specific(u32_t phys_addr, u32_t phys_size,
|
||||
u32_t phys_sector_size,
|
||||
u32_t log_block_size, u32_t log_page_size) {
|
||||
memset(area, 0xcc, sizeof(area));
|
||||
memset(&area[phys_addr], 0xff, phys_size);
|
||||
|
||||
spiffs_config c;
|
||||
c.hal_erase_f = _erase;
|
||||
c.hal_read_f = _read;
|
||||
|
@ -329,10 +333,35 @@ void fs_reset_specific(u32_t phys_addr, u32_t phys_size,
|
|||
c.phys_erase_block = phys_sector_size;
|
||||
c.phys_size = phys_size;
|
||||
|
||||
return SPIFFS_mount(&__fs, &c, _work, _fds, sizeof(_fds), _cache, sizeof(_cache), spiffs_check_cb_f);
|
||||
}
|
||||
|
||||
void fs_reset_specific(u32_t addr_offset, u32_t phys_addr, u32_t phys_size,
|
||||
u32_t phys_sector_size,
|
||||
u32_t log_block_size, u32_t log_page_size) {
|
||||
fs_set_addr_offset(addr_offset);
|
||||
memset(area, 0xcc, sizeof(area));
|
||||
memset(&AREA(phys_addr), 0xff, phys_size);
|
||||
memset(&__fs, 0, sizeof(__fs));
|
||||
|
||||
memset(erases,0,sizeof(erases));
|
||||
memset(_cache,0,sizeof(_cache));
|
||||
|
||||
SPIFFS_mount(&__fs, &c, _work, _fds, sizeof(_fds), _cache, sizeof(_cache), spiffs_check_cb_f);
|
||||
s32_t res = fs_mount_specific(phys_addr, phys_size, phys_sector_size, log_block_size, log_page_size);
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
if (res == SPIFFS_OK) {
|
||||
SPIFFS_unmount(&__fs);
|
||||
}
|
||||
res = SPIFFS_format(&__fs);
|
||||
if (res != SPIFFS_OK) {
|
||||
printf("format failed, %i\n", SPIFFS_errno(&__fs));
|
||||
}
|
||||
res = SPIFFS_mount(&__fs, &c, _work, _fds, sizeof(_fds), _cache, sizeof(_cache), spiffs_check_cb_f);
|
||||
if (res != SPIFFS_OK) {
|
||||
printf("mount failed, %i\n", SPIFFS_errno(&__fs));
|
||||
}
|
||||
#endif
|
||||
|
||||
clear_flash_ops_log();
|
||||
log_flash_ops = 1;
|
||||
|
@ -340,7 +369,7 @@ void fs_reset_specific(u32_t phys_addr, u32_t phys_size,
|
|||
}
|
||||
|
||||
void fs_reset() {
|
||||
fs_reset_specific(SPIFFS_PHYS_ADDR, SPIFFS_FLASH_SIZE, SECTOR_SIZE, LOG_BLOCK, LOG_PAGE);
|
||||
fs_reset_specific(0, SPIFFS_PHYS_ADDR, SPIFFS_FLASH_SIZE, SECTOR_SIZE, LOG_BLOCK, LOG_PAGE);
|
||||
}
|
||||
|
||||
void set_flash_ops_log(int enable) {
|
||||
|
@ -574,6 +603,8 @@ void _teardown() {
|
|||
printf(" cache hits : %i (sum %i)\n", (FS)->cache_hits, chits_tot);
|
||||
printf(" cache misses : %i (sum %i)\n", (FS)->cache_misses, cmiss_tot);
|
||||
printf(" cache utiliz : %f\n", ((float)chits_tot/(float)(chits_tot + cmiss_tot)));
|
||||
chits_tot = 0;
|
||||
cmiss_tot = 0;
|
||||
#endif
|
||||
#endif
|
||||
dump_flash_access_stats();
|
||||
|
@ -586,8 +617,8 @@ void _teardown() {
|
|||
SPIFFS_check(FS);
|
||||
clear_test_path();
|
||||
|
||||
//hexdump_mem(&area[SPIFFS_PHYS_ADDR - 16], 32);
|
||||
//hexdump_mem(&area[SPIFFS_PHYS_ADDR + SPIFFS_FLASH_SIZE - 16], 32);
|
||||
//hexdump_mem(&AREA(SPIFFS_PHYS_ADDR - 16), 32);
|
||||
//hexdump_mem(&AREA(SPIFFS_PHYS_ADDR + SPIFFS_FLASH_SIZE - 16), 32);
|
||||
}
|
||||
|
||||
u32_t tfile_get_size(tfile_size s) {
|
||||
|
|
|
@ -57,9 +57,13 @@ typedef struct {
|
|||
|
||||
|
||||
void fs_reset();
|
||||
void fs_reset_specific(u32_t phys_addr, u32_t phys_size,
|
||||
void fs_reset_specific(u32_t addr_offset, u32_t phys_addr, u32_t phys_size,
|
||||
u32_t phys_sector_size,
|
||||
u32_t log_block_size, u32_t log_page_size);
|
||||
s32_t fs_mount_specific(u32_t phys_addr, u32_t phys_size,
|
||||
u32_t phys_sector_size,
|
||||
u32_t log_block_size, u32_t log_page_size);
|
||||
void fs_set_addr_offset(u32_t offset);
|
||||
int read_and_verify(char *name);
|
||||
int read_and_verify_fd(spiffs_file fd, char *name);
|
||||
void dump_page(spiffs *fs, spiffs_page_ix p);
|
||||
|
|
|
@ -28,6 +28,8 @@ static struct {
|
|||
test_res *stopped;
|
||||
test_res *stopped_last;
|
||||
FILE *spec;
|
||||
char incl_filter[256];
|
||||
char excl_filter[256];
|
||||
} test_main;
|
||||
|
||||
void test_init(void (*on_stop)(test *t)) {
|
||||
|
@ -41,7 +43,7 @@ static char check_spec(char *name) {
|
|||
size_t sz;
|
||||
ssize_t read;
|
||||
while ((read = getline(&line, &sz, test_main.spec)) != -1) {
|
||||
if (strncmp(line, name, strlen(name)) == 0) {
|
||||
if (strncmp(line, name, strlen(line)-1) == 0) {
|
||||
free(line);
|
||||
return 1;
|
||||
}
|
||||
|
@ -53,9 +55,21 @@ static char check_spec(char *name) {
|
|||
}
|
||||
}
|
||||
|
||||
static char check_incl_filter(char *name) {
|
||||
if (strlen(test_main.incl_filter)== 0) return 1;
|
||||
return strstr(name, test_main.incl_filter) == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
static char check_excl_filter(char *name) {
|
||||
if (strlen(test_main.excl_filter)== 0) return 1;
|
||||
return strstr(name, test_main.excl_filter) == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
void add_test(test_f f, char *name, void (*setup)(test *t), void (*teardown)(test *t)) {
|
||||
if (f == 0) return;
|
||||
if (!check_spec(name)) return;
|
||||
if (!check_incl_filter(name)) return;
|
||||
if (!check_excl_filter(name)) return;
|
||||
DBGT("adding test %s\n", name);
|
||||
test *t = malloc(sizeof(test));
|
||||
memset(t, 0, sizeof(test));
|
||||
|
@ -94,16 +108,36 @@ static void dump_res(test_res **head) {
|
|||
}
|
||||
}
|
||||
|
||||
void run_tests(int argc, char **args) {
|
||||
int run_tests(int argc, char **args) {
|
||||
memset(&test_main, 0, sizeof(test_main));
|
||||
if (argc > 1) {
|
||||
printf("running tests from %s\n", args[1]);
|
||||
FILE *fd = fopen(args[1], "r");
|
||||
if (fd == NULL) {
|
||||
printf("%s not found\n", args[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
int arg;
|
||||
int incl_filter = 0;
|
||||
int excl_filter = 0;
|
||||
for (arg = 1; arg < argc; arg++) {
|
||||
if (strlen(args[arg]) == 0) continue;
|
||||
if (0 == strcmp("-f", args[arg])) {
|
||||
incl_filter = 1;
|
||||
continue;
|
||||
}
|
||||
if (0 == strcmp("-e", args[arg])) {
|
||||
excl_filter = 1;
|
||||
continue;
|
||||
}
|
||||
if (incl_filter) {
|
||||
strcpy(test_main.incl_filter, args[arg]);
|
||||
incl_filter = 0;
|
||||
} else if (excl_filter) {
|
||||
strcpy(test_main.excl_filter, args[arg]);
|
||||
excl_filter = 0;
|
||||
} else {
|
||||
printf("running tests from %s\n", args[arg]);
|
||||
FILE *fd = fopen(args[1], "r");
|
||||
if (fd == NULL) {
|
||||
printf("%s not found\n", args[arg]);
|
||||
return -2;
|
||||
}
|
||||
test_main.spec = fd;
|
||||
}
|
||||
test_main.spec = fd;
|
||||
}
|
||||
|
||||
DBGT("adding suites...\n");
|
||||
|
@ -115,7 +149,7 @@ void run_tests(int argc, char **args) {
|
|||
|
||||
if (test_main.test_count == 0) {
|
||||
printf("No tests to run\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd_success = open("_tests_ok", O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
|
@ -133,6 +167,7 @@ void run_tests(int argc, char **args) {
|
|||
DBGT("TEST %i/%i : running test %s\n", i, test_main.test_count, cur_t->name);
|
||||
i++;
|
||||
int res = cur_t->f(cur_t);
|
||||
cur_t->test_result = res;
|
||||
cur_t->teardown(cur_t);
|
||||
int fd = res == TEST_RES_OK ? fd_success : fd_bad;
|
||||
write(fd, cur_t->name, strlen(cur_t->name));
|
||||
|
@ -169,7 +204,9 @@ void run_tests(int argc, char **args) {
|
|||
dump_res(&test_main.stopped);
|
||||
if (ok < test_main.test_count) {
|
||||
printf("\nFAILED\n");
|
||||
return -1;
|
||||
} else {
|
||||
printf("\nALL TESTS OK\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,8 +48,8 @@ void add_suites() {
|
|||
}
|
||||
*/
|
||||
|
||||
#ifndef TESTS_H_
|
||||
#define TESTS_H_
|
||||
#ifndef TESTRUNNER_H_
|
||||
#define TESTRUNNER_H_
|
||||
|
||||
#define TEST_RES_OK 0
|
||||
#define TEST_RES_FAIL -1
|
||||
|
@ -66,6 +66,7 @@ typedef struct test_s {
|
|||
void (*setup)(struct test_s *t);
|
||||
void (*teardown)(struct test_s *t);
|
||||
struct test_s *_next;
|
||||
unsigned char test_result;
|
||||
} test;
|
||||
|
||||
typedef struct test_res_s {
|
||||
|
@ -77,6 +78,30 @@ typedef struct test_res_s {
|
|||
printf(" TEST FAIL %s:%i\n", __FILE__, __LINE__); \
|
||||
goto __fail_stop; \
|
||||
}
|
||||
#define TEST_CHECK_EQ(x, y) if ((x) != (y)) { \
|
||||
printf(" TEST FAIL %s:%i, %i != %i\n", __FILE__, __LINE__, (x), (y)); \
|
||||
goto __fail_stop; \
|
||||
}
|
||||
#define TEST_CHECK_NEQ(x, y) if ((x) == (y)) { \
|
||||
printf(" TEST FAIL %s:%i, %i == %i\n", __FILE__, __LINE__, (x), (y)); \
|
||||
goto __fail_stop; \
|
||||
}
|
||||
#define TEST_CHECK_GT(x, y) if ((x) <= (y)) { \
|
||||
printf(" TEST FAIL %s:%i, %i <= %i\n", __FILE__, __LINE__, (x), (y)); \
|
||||
goto __fail_stop; \
|
||||
}
|
||||
#define TEST_CHECK_LT(x, y) if ((x) >= (y)) { \
|
||||
printf(" TEST FAIL %s:%i, %i >= %i\n", __FILE__, __LINE__, (x), (y)); \
|
||||
goto __fail_stop; \
|
||||
}
|
||||
#define TEST_CHECK_GE(x, y) if ((x) < (y)) { \
|
||||
printf(" TEST FAIL %s:%i, %i < %i\n", __FILE__, __LINE__, (x), (y)); \
|
||||
goto __fail_stop; \
|
||||
}
|
||||
#define TEST_CHECK_LE(x, y) if ((x) > (y)) { \
|
||||
printf(" TEST FAIL %s:%i, %i > %i\n", __FILE__, __LINE__, (x), (y)); \
|
||||
goto __fail_stop; \
|
||||
}
|
||||
#define TEST_ASSERT(x) if (!(x)) { \
|
||||
printf(" TEST ASSERT %s:%i\n", __FILE__, __LINE__); \
|
||||
goto __fail_assert; \
|
||||
|
@ -105,6 +130,7 @@ typedef struct test_res_s {
|
|||
void add_suites();
|
||||
void test_init(void (*on_stop)(test *t));
|
||||
void add_test(test_f f, char *name, void (*setup)(test *t), void (*teardown)(test *t));
|
||||
void run_tests(int argc, char **args);
|
||||
// returns 0 if all tests ok, -1 if any test failed, -2 on badness
|
||||
int run_tests(int argc, char **args);
|
||||
|
||||
#endif /* TESTS_H_ */
|
||||
#endif /* TESTRUNNER_H_ */
|
||||
|
|
Loading…
Reference in New Issue