305 lines
9.0 KiB
C
305 lines
9.0 KiB
C
/*
|
|
* Copyright (c) 2019 Peter Bigot Consulting, LLC
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/* Constants, data types, and functions that support testing the Zephyr FS API.
|
|
*
|
|
* Includes:
|
|
*
|
|
* * A data type that supports building and modifying absolute paths
|
|
* without worrying about snprintf or buffer overflow;
|
|
* * Functions to write known content into files, and to verify that
|
|
* content when reading the file.
|
|
* * A data type that is used to describe file system contents, with
|
|
* functions to create the file system and verify file system
|
|
* content against the build command description.
|
|
*/
|
|
|
|
#ifndef _ZEPHYR_TESTS_SUBSYS_FS_LITTLEFS_TESTFS_UTIL_H_
|
|
#define _ZEPHYR_TESTS_SUBSYS_FS_LITTLEFS_TESTFS_UTIL_H_
|
|
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <zephyr/types.h>
|
|
#include <zephyr/fs/fs.h>
|
|
|
|
/** Maximum length of a path supported by the test infrastructure. */
|
|
#define TESTFS_PATH_MAX 127
|
|
|
|
/** Structure holding an absolute file system path. */
|
|
struct testfs_path {
|
|
/* Storage for a maximal path plus NUL */
|
|
char path[TESTFS_PATH_MAX + 1];
|
|
|
|
/* Pointer to the NUL character marking end of string. */
|
|
char *eos;
|
|
};
|
|
|
|
/** A properly cast terminator for variadic arguments to testfs_path
|
|
* functions.
|
|
*/
|
|
#define TESTFS_PATH_END ((const char *)NULL)
|
|
|
|
#define TESTFS_BUFFER_SIZE 64
|
|
|
|
/** Initialize the file system path within a mount point.
|
|
*
|
|
* Creates an absolute path that begins with the mount point, then
|
|
* extends it with an arbitrary number of path elements as with
|
|
* testfs_path_extend().
|
|
*
|
|
* @param pp a pointer to the path structure.
|
|
*
|
|
* @param mp pointer to the mount point. A null pointer may be passed
|
|
* to create the root path without a mount point.
|
|
*
|
|
* @param... as with testfs_path_extend()
|
|
*
|
|
* @return a pointer to the start of the path.
|
|
*/
|
|
const char *testfs_path_init(struct testfs_path *pp,
|
|
const struct fs_mount_t *mp,
|
|
...);
|
|
|
|
/** Extend/modify an existing file system path.
|
|
*
|
|
* Given an absolute path this function extends it with additional
|
|
* path elements. A forward slash is added between each element.
|
|
*
|
|
* If ".." is passed the last element of the path is removed.
|
|
*
|
|
* The final argument must be a const char * null pointer such as @ref
|
|
* TESTFS_PATH_END.
|
|
*
|
|
* If adding an element would exceed the maximum allowed path length
|
|
* extension stops, and the path existing to that point is returned.
|
|
*
|
|
* @param pp a pointer to the path structure.
|
|
*
|
|
* @param... a sequence of const char * pointers terminating with a
|
|
* null pointer.
|
|
*
|
|
* @return a pointer to the start of the path.
|
|
*/
|
|
const char *testfs_path_extend(struct testfs_path *pp,
|
|
...);
|
|
|
|
static inline struct testfs_path *testfs_path_copy(struct testfs_path *dp,
|
|
const struct testfs_path *sp)
|
|
{
|
|
size_t len = sp->eos - sp->path;
|
|
|
|
memcpy(dp->path, sp->path, len + 1);
|
|
dp->eos = dp->path + len;
|
|
|
|
return dp;
|
|
}
|
|
|
|
/** Write a sequence of constant data to the file.
|
|
*
|
|
* Writes are generated in blocks up to TESTFS_BUFFER_SIZE in length.
|
|
*
|
|
* @param fp pointer to the file to write
|
|
*
|
|
* @param value value of the bytes to write
|
|
*
|
|
* @param len number of octets to write
|
|
*
|
|
* @return number of octets written, or a negative error code.
|
|
*/
|
|
int testfs_write_constant(struct fs_file_t *fp,
|
|
uint8_t value,
|
|
unsigned int len);
|
|
|
|
/** Verify that the file contains a sequence of constant data.
|
|
*
|
|
* Reads are performed in blocks up to TESTFS_BUFFER_SIZE in length.
|
|
*
|
|
* @param fp pointer to the file to read
|
|
*
|
|
* @param value the expected value of the constant data.
|
|
*
|
|
* @param len the number of times the constant value should appear
|
|
*
|
|
* @return the number of times the constant value did appear before
|
|
* len was reached or a mismatch occurred, or a negative error on file
|
|
* read failure.
|
|
*/
|
|
int testfs_verify_constant(struct fs_file_t *fp,
|
|
uint8_t value,
|
|
unsigned int len);
|
|
|
|
/** Write an increasing sequence of bytes to the file.
|
|
*
|
|
* Writes are generated in blocks up to TESTFS_BUFFER_SIZE in length.
|
|
*
|
|
* @param fp pointer to the file to write
|
|
*
|
|
* @param value value of the first byte to write
|
|
*
|
|
* @param len number of octets to write
|
|
*
|
|
* @return number of octets written, or a negative error code.
|
|
*/
|
|
int testfs_write_incrementing(struct fs_file_t *fp,
|
|
uint8_t value,
|
|
unsigned int len);
|
|
|
|
/** Verify that the file contains a sequence of increasing data.
|
|
*
|
|
* Reads are performed in blocks up to TESTFS_BUFFER_SIZE in length.
|
|
*
|
|
* @param fp pointer to the file to read
|
|
*
|
|
* @param value the expected value of the first byte of data.
|
|
*
|
|
* @param len the number of successive increasing values expected
|
|
*
|
|
* @return the number of times the expected value did appear before
|
|
* len was reached or a mismatch occurred, or a negative error on file
|
|
* read failure.
|
|
*/
|
|
int testfs_verify_incrementing(struct fs_file_t *fp,
|
|
uint8_t value,
|
|
unsigned int len);
|
|
|
|
/** Structure used to describe a filesystem layout. */
|
|
struct testfs_bcmd {
|
|
enum fs_dir_entry_type type;
|
|
const char *name;
|
|
uint32_t size;
|
|
uint8_t value;
|
|
bool matched;
|
|
};
|
|
|
|
/* Specify that a directory named _n is to be created, and all entries
|
|
* up to the next matching EXIT_DIR command are to be created within
|
|
* that directory.
|
|
*/
|
|
#define TESTFS_BCMD_ENTER_DIR(_n) { \
|
|
.type = FS_DIR_ENTRY_DIR, \
|
|
.name = _n, \
|
|
}
|
|
|
|
/* Specify that a file named _n is to be created, with _sz bytes of
|
|
* content that starts with _val and increments with each byte.
|
|
*/
|
|
#define TESTFS_BCMD_FILE(_n, _val, _sz) { \
|
|
.type = FS_DIR_ENTRY_FILE, \
|
|
.name = _n, \
|
|
.size = _sz, \
|
|
.value = _val, \
|
|
}
|
|
|
|
/* Specify that the content of the previous matching ENTER_DIR is
|
|
* complete and subsequent entries should be created in the parent
|
|
* directory.
|
|
*/
|
|
#define TESTFS_BCMD_EXIT_DIR(_n) { \
|
|
.type = FS_DIR_ENTRY_DIR, \
|
|
}
|
|
|
|
/* Specify that all build commands have been provided. */
|
|
#define TESTFS_BCMD_END() { \
|
|
}
|
|
|
|
#define TESTFS_BCMD_IS_ENTER_DIR(cp) (((cp)->type == FS_DIR_ENTRY_DIR) \
|
|
&& ((cp)->name != NULL))
|
|
#define TESTFS_BCMD_IS_EXIT_DIR(cp) (((cp)->type == FS_DIR_ENTRY_DIR) \
|
|
&& ((cp)->name == NULL))
|
|
#define TESTFS_BCMD_IS_FILE(cp) (((cp)->type == FS_DIR_ENTRY_FILE) \
|
|
&& ((cp)->name != NULL))
|
|
#define TESTFS_BCMD_IS_END(cp) (((cp)->type == FS_DIR_ENTRY_FILE) \
|
|
&& ((cp)->name == NULL))
|
|
|
|
/** Create a file system hierarchy.
|
|
*
|
|
* If an error is returned the
|
|
*
|
|
* @param root a path to the directory in which the hierarchy will be
|
|
* created. If an error is returned the content of this may identify
|
|
* where the problem occurred.
|
|
*
|
|
* @param cp pointer to a sequence of commands that specify the
|
|
* directory layout.
|
|
*
|
|
* @return Zero after successfully building the hierarchy, or a
|
|
* negative errno code.
|
|
*/
|
|
int testfs_build(struct testfs_path *root,
|
|
const struct testfs_bcmd *cp);
|
|
|
|
/** Get the end range pointer for a sequence of build commands.
|
|
*
|
|
* @param cp a command within the range
|
|
*
|
|
* @return a pointer to the END command in the range.
|
|
*/
|
|
static inline struct testfs_bcmd *testfs_bcmd_end(struct testfs_bcmd *cp)
|
|
{
|
|
while (!TESTFS_BCMD_IS_END(cp)) {
|
|
++cp;
|
|
}
|
|
return cp;
|
|
}
|
|
|
|
/** Verify file system contents against build commands.
|
|
*
|
|
* The specified directory is opened and its contents recursively
|
|
* compared against the build commands for name, size, and content.
|
|
* Build command record entries that are that are matched will have
|
|
* their matched flag set; unmatched entries will have a cleared
|
|
* matched flag.
|
|
*
|
|
* @param pp the path to a directory in the file system.
|
|
*
|
|
* @param scp the first build command relevant to the directory.
|
|
*
|
|
* @param ecp the exclusive last entry in the sequence of build
|
|
* commands relevant to the directory.
|
|
*
|
|
* @return the number of file system entries found that did not match
|
|
* build command content, or a negative error code on compare or file
|
|
* system failures.
|
|
*/
|
|
int testfs_bcmd_verify_layout(struct testfs_path *pp,
|
|
struct testfs_bcmd *scp,
|
|
struct testfs_bcmd *ecp);
|
|
|
|
/** Search a build command range for a match to an entry.
|
|
*
|
|
* A match is identified if the directory entry type, name, and size
|
|
* match between the build command and the file status. The content
|
|
* of the file is not verified.
|
|
*
|
|
* @param statp pointer to a file system entry
|
|
*
|
|
* @param scp pointer to the first build command associated with the
|
|
* hierarchy level of the entry.
|
|
*
|
|
* @param ecp pointer to the exclusive last entry in the build command
|
|
* range.
|
|
*
|
|
* @return a pointer to a build command that matches in type and name,
|
|
* or a null pointer if no match is found at the top level.
|
|
*/
|
|
struct testfs_bcmd *testfs_bcmd_find(struct fs_dirent *statp,
|
|
struct testfs_bcmd *scp,
|
|
struct testfs_bcmd *ecp);
|
|
|
|
/** Find the exit dir command that balances the enter dir command.
|
|
*
|
|
* @param cp pointer to an ENTER_DIR command.
|
|
*
|
|
* @param ecp pointer to the exclusive range end of this level of the
|
|
* hierarchy.
|
|
*
|
|
* @return a pointer to the paired EXIT_DIR command.
|
|
*/
|
|
struct testfs_bcmd *testfs_bcmd_exitdir(struct testfs_bcmd *cp,
|
|
struct testfs_bcmd *ecp);
|
|
|
|
#endif /* _ZEPHYR_TESTS_SUBSYS_FS_LITTLEFS_TESTFS_UTIL_H_ */
|