📄 tcases.c
字号:
/******************************************************************************
* Atomic Tests
******************************************************************************/
int case_init(int p0, int p1)
{
error = tffs_initialize();
// ignore error
error = test_ffs_params_get();
expect(error, EFFS_OK);
return 0;
}
int case_exit(int p0, int p1)
{
error = tffs_exit();
expect(error, EFFS_OK);
return 0;
}
int case_only_preformat(int p0, int p1)
{
tffs_preformat(0xDEAD);
expect(error, EFFS_OK);
return 0;
}
int case_only_format(int p0, int p1)
{
tffs_format("/ffs", 0x2BAD);
expect(error, EFFS_OK);
return 0;
}
int case_reset(int p0, int p1)
{
error = tffs_initialize();
// ignore result
error = tffs_preformat(0xDEAD);
expect(error, EFFS_OK);
error = tffs_format("/ffs", 0x2BAD);
expect(error, EFFS_OK);
error = tffs_exit();
expect(error, EFFS_OK);
return 0;
}
int case_status(int p0, int p1)
{
error = test_run("lsr");
return error;
}
/******************************************************************************
* Special Tests
******************************************************************************/
// Test FFS with only 2 blocks in device
int case_twob(int p0, int p1)
{
int space_left;
int size, i;
char myname[] = "/two_block99";
// Format ffs to use only 2 block no journal file and no reserved space.
// Make some directoryes.
// Fill ffs allmost to the edge and try to write over the edge.
// Read back all the files.
error = tffs_preformat(0xDEAD);
expect(error, EFFS_OK);
error = tffs_format("/ffs/b2j0m0", 0x2BAD);
expect(error, EFFS_OK);
error = test_run("i;world;eu;x");
if(error) return 1;
// Calculate the amount of space that is left to user data because some space
// is used to directoryes
space_left = dev.blocksize - (13 * 20);
tw(tr(TR_FUNC, TrTestHigh, "Space left: %d\n", space_left));
size = space_left;
for(i = 0; i < 6; i++) {
size = size/2;
sprintf(myname, "/two_block%d", i);
error = tffs_file_write(myname, (char*)tdata[TDATA_HUGE],
size >= 20 ? size - 20 : 0, FFS_O_CREATE | FFS_O_TRUNC);
expect(error, EFFS_OK);
}
error = tffs_file_write(myname, (char*)tdata[TDATA_HUGE], space_left/5, FFS_O_CREATE | FFS_O_TRUNC);
expect(error, EFFS_NOSPACE);
// 20 is the average space used to the file name + word align.
size = space_left;
for(i = 0; i < 6; i++) {
size = size/2;
sprintf(myname, "/two_block%d", i);
error = tffs_fread(myname, bigbuf, bigbuf_size);
expect(error, size >= 20 ? size - 20 : 0);
}
//error = ffs_object_control(0, OC_DEV_DEVICE, 0x080D);
//if (error < 0) return error;
return 0;
}
// Test FFS with only 3 blocks in device
int case_threeb(int p0, int p1)
{
char mytest[20];
// Format ffs to use only 3 blocks, make directoryes and run test case
// rand <p0> number of times.
error = tffs_preformat(0xDEAD);
expect(error, EFFS_OK);
error = tffs_format("/ffs/b3r24", 0x2BAD);
expect(error, EFFS_OK);
error = test_run("i;world;eu;x");
if (error) return 1;
if(p0 == 0) p0 = 233;
sprintf(mytest, "rand%d", p0);
return test_run(mytest);
}
// Simulate a typical usage of ffs. We expect one part of the data will be
// what we call 'static' data (calibration files etc) the other part is the
// 'dynamic' data (wap, sms etc) we do also expect that they don't fill FFS
// completely thus we have a 'free' part.
int case_customer(int nblocks, int nloops)
{
int free_part = 5, static_part = 47, dynamic_part = 47;
int free_size, static_size, dynamic_size;
int bytes_free, bytes_max, bytes_used;
int file_size_max, file_size_min, file_size_avg;
int i, j, max_obj_block, num_static_files;
char myname[] = "/ffs/bxxx/";
char file_name[FFS_FILENAME_MAX + 1];
char path[FFS_FILENAME_MAX * 2];
char static_dir[] ="/READONLY";
char dynamic_dir[] = "/rand";
struct dir_s dir;
if (nblocks == 0)
nblocks = 7;
if (nloops == 0)
nloops = 300;
error = tffs_preformat(0xDEAD); expect(error, EFFS_OK);
sprintf(myname, "/ffs/b%d", nblocks);
error = tffs_format(myname, 0x2BAD); expect(error, EFFS_OK);
tffs_mkdir(dynamic_dir); expect(error, EFFS_OK);
tffs_mkdir(static_dir); expect(error, EFFS_OK);
ffs_query(Q_BYTES_FREE, &bytes_max);
free_size = bytes_max * free_part / 100;
static_size = bytes_max * static_part / 100;
dynamic_size = bytes_max * dynamic_part / 100;
tw(tr(TR_FUNC, TrTest, "Free:%d,%dkB. Static:%d,%dkB, Dynamic:%d,%dkB\n",
free_part, free_size/1024, static_part, static_size/1024,
dynamic_part, dynamic_size/1024));
// Find max average objects per block
max_obj_block = fs.block_files_max;
if (max_obj_block > fs.objects_max / (dev.numblocks -1 - fs.blocks_free_min))
max_obj_block = fs.objects_max / (dev.numblocks -1 - fs.blocks_free_min);
tw(tr(TR_FUNC, TrTest, "Max average objects per block %d\n", max_obj_block));
ttw(ttr(TTrTest, "Max avg obj per block %d" NL, max_obj_block));
// Average (minimum) file size (avoid to reach block_files_max and
// objects_max)
file_size_avg = dev.blocksize / max_obj_block;
ffs_query(Q_BYTES_USED, &bytes_used);
tw(tr(TR_FUNC, TrTest, "Write static files (avg size %d)\n", file_size_avg));
ttw(ttr(TTrTest, "avg size %d" NL, file_size_avg));
do {
i++;
file_size_min = 5;
// For each 5 file we make one huge.
file_size_max = i % 5 ? file_size_avg * 2 : file_size_avg * 15;
// For each 6 file we make one small.
file_size_max = i % 6 ? file_size_max : 5;
// Saturate, avoid to make one file that parses the total static_size
if (file_size_max > static_size - bytes_used)
file_size_max = file_size_min = static_size - bytes_used;
// For each 7 file we create one dynamic (If the block is full with only
// valid objects do we risk that this block never will be reclaimed!).
if (i % 7)
error = make_random_file(dynamic_dir, file_size_max, file_size_min);
else
error = make_random_file(static_dir, file_size_max, file_size_min);
expect_ok(error);
ffs_query(Q_BYTES_USED, &bytes_used);
} while (bytes_used < static_size);
num_static_files = tffs_opendir(static_dir, &dir);
expect_ok(num_static_files);
tw(tr(TR_FUNC, TrTest, "Written %d files\n", num_static_files));
ttw(ttr(TTrTest, "Written %d files" NL, num_static_files));
// In a loop we continue to write data until only the wanted free_part is
// left, after that we remove half of the just created files and then write
// again and again...
j = 0;
tw(tr(TR_FUNC, TrTest, "Write and remove dynamic files\n"));
ttw(ttr(TTrTest, "Write and remove dynamic files" NL));
for (i = 0; i < nloops; i++) {
if (i % 10 == 0) {
tw(tr(TR_FUNC, TrTest, "loop %d\n", i));
ttw(ttr(TTrTest, "loop %d" NL, i));
}
ffs_query(Q_BYTES_FREE, &bytes_free);
do {
j++;
file_size_min = 5;
file_size_max = j % 5 ? file_size_avg * 2 : file_size_avg * 15;
file_size_max = j % 6 ? file_size_max : 5;
// Saturate, avoid using the free space.
if (file_size_max > bytes_free - free_size)
file_size_max = file_size_min = bytes_free - free_size;
if (file_size_max < 0)
break;
error = make_random_file(dynamic_dir, file_size_max, file_size_min);
// NOTE it is very difficult to avoid EFFS_FSFULL because cleanup will
// sometimes only remove the big files thus there will exist a lot of small
// that use all the inodes.
if (error == EFFS_FSFULL) {
tw(tr(TR_FUNC, TrTest, "Warning no free inodes\n"));
ttw(ttr(TTrTest, "Warning no free inodes" NL));
error = cleanup(free_size + dynamic_size);
}
else
expect_ok(error);
ffs_query(Q_BYTES_FREE, &bytes_free);
} while (bytes_free > free_size);
error = cleanup(free_size + dynamic_size / 2);
expect_ok(error);
}
error = case_reinit(0, 0);
expect(EFFS_OK, error);
tw(tr(TR_FUNC, TrTest, "Verify all files\n"));
ttw(ttr(TTrTest, "Verify all files" NL));
for (i = 0; i < 2; i++) {
if (i == 0) {
error = tffs_opendir(static_dir, &dir);
expect_eq(error, num_static_files);
}
else {
error = tffs_opendir(dynamic_dir, &dir);
expect_ok(error);
}
while ((error = tffs_readdir(&dir, file_name, sizeof(file_name))) > 0) {
if (i == 0)
strcpy(path, static_dir);
else
strcpy(path, dynamic_dir);
strcat(path, "/");
strcat(path, file_name);
error = tffs_stat(path, &tstat);
expect_ok(error);
error = test_expect_file(path, tdata[TDATA_HUGE], tstat.size);
if (error) return 1;
}
}
test_statistics_print();
return 0;
}
// TODO cleanup this test. Use stat and verify some of the files etc.
// Used to test ConQuest issue FFS_FIX-11368 We fill FFS with a lot of small
// files. Then by turn remove some files and write new files, always very
// close to max avaible bytes.
// Note the below test is not able to run in big configuration because it
// creates a lot of small files thus we reach EFFS_FSFULL 'out of inodes'
int case_ffull(int p0, int p1)
{
int error, i, bytes_free, file_size, max_write_size = 1000;
char myname[] = "/ffs/bxxx/";
p0 = (p0 == 0 ? 100 : p0); // Default 100 loops
if (p1 == 0 || p1 > 999)
p1 = 3; // Default run in 3 blocks
error = tffs_preformat(0xDEAD);
expect(error, EFFS_OK);
sprintf(myname, "/ffs/b%d", p1);
error = tffs_format(myname, 0x2BAD);
expect(error, EFFS_OK);
tffs_mkdir("/rand");
expect(error, EFFS_OK);
tw(tr(TR_FUNC, TrTest, "Fill it with files until it fails\n"));
ttw(ttr(TTrTest, "Fill it with files until it fails" NL));
// We have to avoid too many small files or else do we reach objects_max
ffs_query(Q_BYTES_FREE, &bytes_free);
max_write_size = bytes_free / fs.objects_max * 2.5;
do {
error = make_random_file("/rand", max_write_size, 0);
} while (error >= 0 );
tw(tr(TR_FUNC, TrTest, "Fill done (%d)\n" ,error));
ttw(ttr(TTrTest, "Fill done (%d)" NL, error));
expect(error, EFFS_NOSPACE); // Now are we sure that it is full
tw(tr(TR_FUNC, TrTest, "Cleanup and fill again \n"));
for (i = 0; i < (1 + p0); i++) {
tw(tr(TR_FUNC, TrTestHigh, "Loop %d \n", i + 1));
ttw(ttr(TTrTest, "Loop %d" NL, i + 1));
tw(tr_bstat());
error = cleanup(max_write_size * 3);
tw(tr_bstat());
do {
ffs_query(Q_BYTES_FREE, &bytes_free);
// Saturate size
file_size = bytes_free > max_write_size ? max_write_size :bytes_free;
// Query BYTES_FREE don't count the below data use.
//file_size -= (FFS_FILENAME_MAX + 1 + dev.atomsize);
if (file_size < 0)
break;
error = make_random_file("/rand", file_size - (FFS_FILENAME_MAX+1), 0);
if (error == EFFS_FSFULL) { // Out of inodes
error = cleanup(max_write_size * 6);
// Create bigger files to avoid '-11', auto fit :-)
max_write_size *= 1.1; // Add 10%
tw(tr(TR_FUNC, TrTestHigh, "Out of inodes, write size: %d \n",
max_write_size));
continue;
}
expect_ok(error);
} while (file_size != bytes_free);
}
tw(tr(TR_FUNC, TrTest, "Test finish (%d) \n", error));
ttw(ttr(TTrTest, "Test finish (%d)" NL, error));
if (error >= 0)
return EFFS_OK;
return error;
}
int case_rivtype(int p0, int p1)
{
// Use the compiler to test if the types are correctly defined. We don't
// need to run this test just make a compilation.
T_FFS_OPEN_FLAGS flags = FFS_O_RDONLY;
T_FFS_SIZE size = 20;
T_FFS_RET error = -10;
T_FFS_WHENCE whence = FFS_SEEK_SET;
T_FFS_STAT stat;
T_FFS_DIR dir;
T_FFS_FD fd = FFS_FD_OFFSET;
T_RV_RETURN callback;
T_FFS_FILE_CNF confirm;
T_FFS_OBJECT_TYPE objt = OT_FILE;
// Use the defined variables to avoid the boring warning: unused
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -