forked from Imagelibrary/rtems
PR2040: libtests/flashdisk01: New test
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
ACLOCAL_AMFLAGS = -I ../aclocal
|
||||
|
||||
SUBDIRS = POSIX
|
||||
SUBDIRS += flashdisk01
|
||||
|
||||
SUBDIRS += bspcmdline01 cpuuse devfs01 devfs02 devfs03 devfs04 \
|
||||
deviceio01 devnullfatal01 dumpbuf01 gxx01 \
|
||||
|
||||
@@ -43,6 +43,7 @@ AM_CONDITIONAL(NETTESTS,test "$rtems_cv_RTEMS_NETWORKING" = "yes")
|
||||
|
||||
# Explicitly list all Makefiles here
|
||||
AC_CONFIG_FILES([Makefile
|
||||
flashdisk01/Makefile
|
||||
block01/Makefile
|
||||
block02/Makefile
|
||||
block03/Makefile
|
||||
|
||||
19
testsuites/libtests/flashdisk01/Makefile.am
Normal file
19
testsuites/libtests/flashdisk01/Makefile.am
Normal file
@@ -0,0 +1,19 @@
|
||||
rtems_tests_PROGRAMS = flashdisk01
|
||||
flashdisk01_SOURCES = init.c test-file-system.c
|
||||
|
||||
dist_rtems_tests_DATA = flashdisk01.scn flashdisk01.doc
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(top_srcdir)/../automake/compile.am
|
||||
include $(top_srcdir)/../automake/leaf.am
|
||||
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/../support/include
|
||||
|
||||
LINK_OBJS = $(flashdisk01_OBJECTS)
|
||||
LINK_LIBS = $(flashdisk01_LDLIBS)
|
||||
|
||||
flashdisk01$(EXEEXT): $(flashdisk01_OBJECTS) $(flashdisk01_DEPENDENCIES)
|
||||
@rm -f flashdisk01$(EXEEXT)
|
||||
$(make-exe)
|
||||
|
||||
include $(top_srcdir)/../automake/local.am
|
||||
11
testsuites/libtests/flashdisk01/flashdisk01.doc
Normal file
11
testsuites/libtests/flashdisk01/flashdisk01.doc
Normal file
@@ -0,0 +1,11 @@
|
||||
This file describes the directives and concepts tested by this test set.
|
||||
|
||||
test set name: flashdisk01
|
||||
|
||||
directives:
|
||||
|
||||
TBD
|
||||
|
||||
concepts:
|
||||
|
||||
TBD
|
||||
265
testsuites/libtests/flashdisk01/flashdisk01.scn
Normal file
265
testsuites/libtests/flashdisk01/flashdisk01.scn
Normal file
@@ -0,0 +1,265 @@
|
||||
*** TEST FLASHDISK 1 ***
|
||||
[00]: start
|
||||
[00]: mount: /dev/fdda -> /mnt
|
||||
[00]: init root: /mnt
|
||||
[00]: create dir: 1804928587
|
||||
[00]: create dir: 959030623
|
||||
[00]: create dir: 1903590565
|
||||
[00]: open file: file
|
||||
[00]: sleep: 700 ms
|
||||
[00]: close file
|
||||
[00]: sleep: 200 ms
|
||||
[00]: open dir: 959030623
|
||||
[00]: create dir: 838545539
|
||||
[00]: create file: 1594243340
|
||||
[00]: create file: 162216788
|
||||
[00]: create file: 1841205112
|
||||
[00]: sleep: 700 ms
|
||||
[00]: remove dir: 838545539
|
||||
[00]: create dir: 1143741253
|
||||
[00]: remove file: 1594243340
|
||||
[00]: sleep: 400 ms
|
||||
[00]: close dir
|
||||
[00]: sleep: 400 ms
|
||||
[00]: create file: 832100416
|
||||
[00]: open dir: 1903590565
|
||||
[00]: create file: 1401208270
|
||||
[00]: create dir: 2032315143
|
||||
[00]: create dir: 2026989069
|
||||
[00]: close dir
|
||||
[00]: open dir: 1804928587
|
||||
[00]: close dir
|
||||
[00]: open dir: 1804928587
|
||||
[00]: sleep: 100 ms
|
||||
[00]: create dir: 650320721
|
||||
[00]: sleep: 500 ms
|
||||
[00]: create dir: 1857409239
|
||||
[00]: create file: 2060801678
|
||||
[00]: create dir: 490998763
|
||||
[00]: create dir: 644928527
|
||||
[00]: create file: 1758287264
|
||||
[00]: close dir
|
||||
[00]: sleep: 500 ms
|
||||
[00]: open file: file
|
||||
[00]: read from file
|
||||
[00]: read from file
|
||||
[00]: read from file
|
||||
[00]: sleep: 700 ms
|
||||
[00]: read from file
|
||||
[00]: sleep: 200 ms
|
||||
[00]: sleep: 300 ms
|
||||
[00]: read from file
|
||||
[00]: append to file
|
||||
[00]: read from file
|
||||
[00]: close file
|
||||
[00]: remove dir: 1804928587
|
||||
[00]: create file: 2073894790
|
||||
[00]: sleep: 900 ms
|
||||
[00]: create dir: 472737403
|
||||
[00]: remove dir: 1903590565
|
||||
[00]: create dir: 689486081
|
||||
[00]: create dir: 373636079
|
||||
[00]: remove file: file
|
||||
[00]: create dir: 1506727461
|
||||
[00]: open dir: 959030623
|
||||
[00]: create dir: 1029668001
|
||||
[00]: remove file: 162216788
|
||||
[00]: close dir
|
||||
[00]: sleep: 400 ms
|
||||
[00]: open dir: 959030623
|
||||
[00]: remove file: 1841205112
|
||||
[00]: create file: 378843792
|
||||
[00]: sleep: 1000 ms
|
||||
[00]: create file: 1871951748
|
||||
[00]: open dir: 1143741253
|
||||
[00]: create file: 855915646
|
||||
[00]: sleep: 700 ms
|
||||
[00]: create file: 2008730550
|
||||
[00]: close dir
|
||||
[00]: create file: 1327563176
|
||||
[00]: remove dir: 1143741253
|
||||
[00]: create file: 1384249492
|
||||
[00]: close dir
|
||||
[00]: remove dir: 959030623
|
||||
[00]: open file: 832100416
|
||||
[00]: read from file
|
||||
[00]: sleep: 400 ms
|
||||
[00]: close file
|
||||
[00]: open file: 832100416
|
||||
[00]: close file
|
||||
[00]: create dir: 2025552021
|
||||
[00]: remove dir: 959030623
|
||||
[00]: create dir: 1178339711
|
||||
[00]: remove file: 832100416
|
||||
[00]: remove file: 2073894790
|
||||
[00]: open dir: 1506727461
|
||||
[00]: sleep: 700 ms
|
||||
[00]: close dir
|
||||
[00]: sleep: 300 ms
|
||||
[00]: open dir: 1506727461
|
||||
[00]: create dir: 1625748679
|
||||
[00]: close dir
|
||||
[00]: remove dir: 689486081
|
||||
[00]: remove dir: 959030623
|
||||
[00]: open dir: 959030623
|
||||
[00]: sleep: 1000 ms
|
||||
[00]: close dir
|
||||
[00]: sleep: 100 ms
|
||||
[00]: open dir: 959030623
|
||||
[00]: create dir: 1128727833
|
||||
[00]: create file: 1203746106
|
||||
[00]: open dir: 1128727833
|
||||
[00]: create dir: 58221889
|
||||
[00]: create file: 611814452
|
||||
[00]: create dir: 420219909
|
||||
[00]: close dir
|
||||
[00]: remove file: 1384249492
|
||||
[00]: close dir
|
||||
[00]: open dir: 959030623
|
||||
[00]: close dir
|
||||
[00]: sleep: 800 ms
|
||||
[00]: remove dir: 1506727461
|
||||
[00]: create file: 550820384
|
||||
[00]: create file: 833699694
|
||||
[00]: remove dir: 1506727461
|
||||
[00]: create dir: 861614531
|
||||
[00]: remove dir: 1506727461
|
||||
[00]: create dir: 846638047
|
||||
[00]: remove dir: 1506727461
|
||||
[00]: create dir: 1766470371
|
||||
[00]: remove dir: 959030623
|
||||
[00]: create file: 1969337196
|
||||
[00]: remove dir: 1506727461
|
||||
[00]: create file: 1937189238
|
||||
[00]: remove dir: 959030623
|
||||
[00]: create dir: 1615521955
|
||||
[00]: remove dir: 959030623
|
||||
[00]: sleep: 500 ms
|
||||
[00]: open dir: 1506727461
|
||||
[00]: create file: 926653184
|
||||
[00]: remove dir: 1625748679
|
||||
[00]: close dir
|
||||
[00]: create dir: 975747319
|
||||
[00]: open dir: 959030623
|
||||
[00]: open file: 1871951748
|
||||
[00]: sleep: 600 ms
|
||||
[00]: close file
|
||||
[00]: sleep: 800 ms
|
||||
[00]: remove file: 378843792
|
||||
[00]: open file: 1203746106
|
||||
[00]: read from file
|
||||
[00]: append to file
|
||||
[00]: sleep: 600 ms
|
||||
[00]: close file
|
||||
[00]: open file: 1871951748
|
||||
[00]: append to file
|
||||
[00]: close file
|
||||
[00]: remove file: 1871951748
|
||||
[00]: sleep: 400 ms
|
||||
[00]: create file: 1835979858
|
||||
[00]: open dir: 1128727833
|
||||
[00]: create dir: 862728993
|
||||
[00]: sleep: 700 ms
|
||||
[00]: remove dir: 862728993
|
||||
[00]: close dir
|
||||
[00]: close dir
|
||||
[00]: open dir: 975747319
|
||||
[00]: sleep: 400 ms
|
||||
[00]: create dir: 1840098529
|
||||
[00]: create file: 231405798
|
||||
[00]: remove dir: 1840098529
|
||||
[00]: close dir
|
||||
[00]: remove file: 550820384
|
||||
[00]: create file: 1020303340
|
||||
[00]: create dir: 895068705
|
||||
[00]: open dir: 975747319
|
||||
[00]: close dir
|
||||
[00]: open file: 1020303340
|
||||
[00]: read from file
|
||||
[00]: close file
|
||||
[00]: create dir: 1993404773
|
||||
[00]: remove file: 1020303340
|
||||
[00]: create dir: 2112395285
|
||||
[00]: create dir: 81202983
|
||||
[00]: remove dir: 975747319
|
||||
[00]: remove dir: 959030623
|
||||
[00]: create dir: 467069459
|
||||
[00]: open dir: 1506727461
|
||||
[00]: create file: 612609068
|
||||
[00]: create dir: 1793174441
|
||||
[00]: create file: 710808000
|
||||
[00]: sleep: 300 ms
|
||||
[00]: create file: 897370450
|
||||
[00]: create file: 1901152134
|
||||
[00]: sleep: 200 ms
|
||||
[00]: close dir
|
||||
[00]: open dir: 1506727461
|
||||
[00]: close dir
|
||||
[00]: sleep: 800 ms
|
||||
[00]: create file: 906254788
|
||||
[00]: remove dir: 467069459
|
||||
[00]: remove dir: 1506727461
|
||||
[00]: open dir: 895068705
|
||||
[00]: close dir
|
||||
[00]: create file: 1216543556
|
||||
[00]: create file: 37176518
|
||||
[00]: open dir: 2112395285
|
||||
[00]: close dir
|
||||
[00]: create dir: 659416143
|
||||
[00]: remove file: 37176518
|
||||
[00]: sleep: 500 ms
|
||||
[00]: remove dir: 895068705
|
||||
[00]: create dir: 1507289677
|
||||
[00]: open dir: 959030623
|
||||
[00]: create file: 1766335976
|
||||
[00]: close dir
|
||||
[00]: sleep: 400 ms
|
||||
[00]: open dir: 2112395285
|
||||
[00]: create dir: 1476817327
|
||||
[00]: close dir
|
||||
[00]: create dir: 1841667551
|
||||
[00]: remove dir: 2112395285
|
||||
[00]: open dir: 1507289677
|
||||
[00]: close dir
|
||||
[00]: create file: 1610238546
|
||||
[00]: create file: 220151308
|
||||
[00]: remove dir: 1507289677
|
||||
[00]: open file: 1216543556
|
||||
[00]: append to file
|
||||
[00]: append to file
|
||||
[00]: close file
|
||||
[00]: remove file: 1216543556
|
||||
[00]: open dir: 959030623
|
||||
[00]: sleep: 500 ms
|
||||
[00]: create file: 1508553554
|
||||
[00]: create file: 1742399670
|
||||
[00]: sleep: 100 ms
|
||||
[00]: close dir
|
||||
[00]: create dir: 2113094209
|
||||
[00]: remove dir: 959030623
|
||||
[00]: remove file: 1610238546
|
||||
[00]: create dir: 2146380029
|
||||
[00]: sleep: 700 ms
|
||||
[00]: create file: 1557834172
|
||||
[00]: remove dir: 2146380029
|
||||
[00]: finish
|
||||
fdisk:Flash Disk Driver Status : 2.0
|
||||
fdisk:Block count 124
|
||||
fdisk:Unavail blocks 32
|
||||
fdisk:Starvations 76
|
||||
fdisk:Available queue 2 (2)
|
||||
fdisk:Used queue 2 (2)
|
||||
fdisk:Erase queue 0 (0)
|
||||
fdisk:Failed queue 0 (0)
|
||||
fdisk:Queue total 4 of 4, ok
|
||||
fdisk:Device count 1
|
||||
fdisk: Device 0
|
||||
fdisk: Segment count 4
|
||||
fdisk: 0 A--- p: 31 a: 30/ 30 u: 0/ 0 e: 1/ 1 br:30
|
||||
fdisk: 1 A--- p: 31 a: 0/ 0 u: 0/ 0 e: 31/ 31 br:0
|
||||
fdisk: 2 -U-- p: 31 a: 31/ 31 u: 0/ 0 e: 0/ 0 br:31
|
||||
fdisk: 3 -U-- p: 31 a: 31/ 31 u: 0/ 0 e: 0/ 0 br:31
|
||||
fdisk:Used List:
|
||||
fdisk: 0 00:002 u: 0
|
||||
fdisk: 1 00:003 u: 0
|
||||
*** END OF TEST FLASHDISK 1 ***
|
||||
353
testsuites/libtests/flashdisk01/init.c
Normal file
353
testsuites/libtests/flashdisk01/init.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright (c) 2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "tmacros.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <rtems/flashdisk.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/blkdev.h>
|
||||
#include <rtems/rtems-rfs-format.h>
|
||||
|
||||
#include "test-file-system.h"
|
||||
|
||||
#define FLASHDISK_CONFIG_COUNT 1
|
||||
|
||||
#define FLASHDISK_DEVICE_COUNT 1
|
||||
|
||||
#define FLASHDISK_SEGMENT_COUNT 4
|
||||
|
||||
#define FLASHDISK_SEGMENT_SIZE (16 * 1024)
|
||||
|
||||
#define FLASHDISK_BLOCK_SIZE 512
|
||||
|
||||
#define FLASHDISK_BLOCKS_PER_SEGMENT \
|
||||
(FLASHDISK_SEGMENT_SIZE / FLASHDISK_BLOCK_SIZE)
|
||||
|
||||
#define FLASHDISK_SIZE \
|
||||
(FLASHDISK_SEGMENT_COUNT * FLASHDISK_SEGMENT_SIZE)
|
||||
|
||||
static const rtems_rfs_format_config rfs_config;
|
||||
|
||||
static const char device [] = "/dev/fdda";
|
||||
|
||||
static const char mnt [] = "/mnt";
|
||||
|
||||
static const char file [] = "/mnt/file";
|
||||
|
||||
static uint8_t flashdisk_data [FLASHDISK_SIZE];
|
||||
|
||||
static void flashdisk_print_status(const char *disk_path)
|
||||
{
|
||||
int rv;
|
||||
int fd = open(disk_path, O_RDWR);
|
||||
rtems_test_assert(fd >= 0);
|
||||
|
||||
rv = ioctl(fd, RTEMS_FDISK_IOCTL_PRINT_STATUS);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = close(fd);
|
||||
rtems_test_assert(rv == 0);
|
||||
}
|
||||
|
||||
static int test_rfs_mount_handler(
|
||||
const char *disk_path,
|
||||
const char *mount_path,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return mount_and_make_target_path(
|
||||
disk_path,
|
||||
mount_path,
|
||||
RTEMS_FILESYSTEM_TYPE_RFS,
|
||||
RTEMS_FILESYSTEM_READ_WRITE,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
static int test_rfs_format_handler(
|
||||
const char *disk_path,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
flashdisk_print_status(disk_path);
|
||||
|
||||
rtems_test_assert(0);
|
||||
|
||||
errno = EIO;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const test_file_system_handler test_rfs_handler = {
|
||||
.mount = test_rfs_mount_handler,
|
||||
.format = test_rfs_format_handler
|
||||
};
|
||||
|
||||
static void test(void)
|
||||
{
|
||||
int rv;
|
||||
const void *data = NULL;
|
||||
|
||||
rv = mkdir(mnt, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = rtems_rfs_format(device, &rfs_config);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = mount(
|
||||
device,
|
||||
mnt,
|
||||
RTEMS_FILESYSTEM_TYPE_RFS,
|
||||
RTEMS_FILESYSTEM_READ_WRITE,
|
||||
data
|
||||
);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = mknod(file, S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO, 0);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
rv = unmount(mnt);
|
||||
rtems_test_assert(rv == 0);
|
||||
|
||||
test_file_system_with_handler(
|
||||
0,
|
||||
device,
|
||||
mnt,
|
||||
&test_rfs_handler,
|
||||
NULL
|
||||
);
|
||||
|
||||
flashdisk_print_status(device);
|
||||
}
|
||||
|
||||
static void Init(rtems_task_argument arg)
|
||||
{
|
||||
puts("\n\n*** TEST FLASHDISK 1 ***");
|
||||
|
||||
test();
|
||||
|
||||
puts("*** END OF TEST FLASHDISK 1 ***");
|
||||
|
||||
rtems_test_exit(0);
|
||||
}
|
||||
|
||||
static void erase_device(void)
|
||||
{
|
||||
memset(&flashdisk_data [0], 0xff, FLASHDISK_SIZE);
|
||||
}
|
||||
|
||||
static rtems_device_driver flashdisk_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
erase_device();
|
||||
|
||||
return rtems_fdisk_initialize(major, minor, arg);
|
||||
}
|
||||
|
||||
static uint8_t *get_data_pointer(
|
||||
const rtems_fdisk_segment_desc *sd,
|
||||
uint32_t segment,
|
||||
uint32_t offset
|
||||
)
|
||||
{
|
||||
offset += sd->offset + (segment - sd->segment) * sd->size;
|
||||
|
||||
return &flashdisk_data [offset];
|
||||
}
|
||||
|
||||
static int flashdisk_read(
|
||||
const rtems_fdisk_segment_desc *sd,
|
||||
uint32_t device,
|
||||
uint32_t segment,
|
||||
uint32_t offset,
|
||||
void *buffer,
|
||||
uint32_t size
|
||||
)
|
||||
{
|
||||
int eno = 0;
|
||||
const uint8_t *data = get_data_pointer(sd, segment, offset);
|
||||
|
||||
memcpy(buffer, data, size);
|
||||
|
||||
return eno;
|
||||
}
|
||||
|
||||
static int flashdisk_write(
|
||||
const rtems_fdisk_segment_desc *sd,
|
||||
uint32_t device,
|
||||
uint32_t segment,
|
||||
uint32_t offset,
|
||||
const void *buffer,
|
||||
uint32_t size
|
||||
)
|
||||
{
|
||||
int eno = 0;
|
||||
uint8_t *data = get_data_pointer(sd, segment, offset);
|
||||
|
||||
memcpy(data, buffer, size);
|
||||
|
||||
return eno;
|
||||
}
|
||||
|
||||
static int flashdisk_blank(
|
||||
const rtems_fdisk_segment_desc *sd,
|
||||
uint32_t device,
|
||||
uint32_t segment,
|
||||
uint32_t offset,
|
||||
uint32_t size
|
||||
)
|
||||
{
|
||||
int eno = 0;
|
||||
const uint8_t *current = get_data_pointer(sd, segment, offset);
|
||||
const uint8_t *end = current + size;;
|
||||
|
||||
while (eno == 0 && current != end) {
|
||||
if (*current != 0xff) {
|
||||
eno = EIO;
|
||||
}
|
||||
++current;
|
||||
}
|
||||
|
||||
return eno;
|
||||
}
|
||||
|
||||
static int flashdisk_verify(
|
||||
const rtems_fdisk_segment_desc *sd,
|
||||
uint32_t device,
|
||||
uint32_t segment,
|
||||
uint32_t offset,
|
||||
const void *buffer,
|
||||
uint32_t size
|
||||
)
|
||||
{
|
||||
int eno = 0;
|
||||
uint8_t *data = get_data_pointer(sd, segment, offset);
|
||||
|
||||
if (memcmp(data, buffer, size) != 0) {
|
||||
eno = EIO;
|
||||
}
|
||||
|
||||
return eno;
|
||||
}
|
||||
|
||||
static int flashdisk_erase(
|
||||
const rtems_fdisk_segment_desc *sd,
|
||||
uint32_t device,
|
||||
uint32_t segment
|
||||
)
|
||||
{
|
||||
int eno = 0;
|
||||
uint8_t *data = get_data_pointer(sd, segment, 0);
|
||||
|
||||
memset(data, 0xff, sd->size);
|
||||
|
||||
return eno;
|
||||
}
|
||||
|
||||
static int flashdisk_erase_device(
|
||||
const rtems_fdisk_device_desc *sd,
|
||||
uint32_t device
|
||||
)
|
||||
{
|
||||
int eno = 0;
|
||||
|
||||
erase_device();
|
||||
|
||||
return eno;
|
||||
}
|
||||
|
||||
static const rtems_fdisk_segment_desc flashdisk_segment_desc = {
|
||||
.count = FLASHDISK_SEGMENT_COUNT,
|
||||
.segment = 0,
|
||||
.offset = 0,
|
||||
.size = FLASHDISK_SEGMENT_SIZE
|
||||
};
|
||||
|
||||
static const rtems_fdisk_driver_handlers flashdisk_ops = {
|
||||
.read = flashdisk_read,
|
||||
.write = flashdisk_write,
|
||||
.blank = flashdisk_blank,
|
||||
.verify = flashdisk_verify,
|
||||
.erase = flashdisk_erase,
|
||||
.erase_device = flashdisk_erase_device
|
||||
};
|
||||
|
||||
static const rtems_fdisk_device_desc flashdisk_device = {
|
||||
.segment_count = 1,
|
||||
.segments = &flashdisk_segment_desc,
|
||||
.flash_ops = &flashdisk_ops
|
||||
};
|
||||
|
||||
const rtems_flashdisk_config
|
||||
rtems_flashdisk_configuration [FLASHDISK_CONFIG_COUNT] = {
|
||||
{
|
||||
.block_size = FLASHDISK_BLOCK_SIZE,
|
||||
.device_count = FLASHDISK_DEVICE_COUNT,
|
||||
.devices = &flashdisk_device,
|
||||
.flags = RTEMS_FDISK_CHECK_PAGES
|
||||
| RTEMS_FDISK_BLANK_CHECK_BEFORE_WRITE,
|
||||
.unavail_blocks = FLASHDISK_BLOCKS_PER_SEGMENT,
|
||||
.compact_segs = 2,
|
||||
.avail_compact_segs = 1,
|
||||
.info_level = 0
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t rtems_flashdisk_configuration_size = FLASHDISK_CONFIG_COUNT;
|
||||
|
||||
#define FLASHDISK_DRIVER { \
|
||||
.initialization_entry = flashdisk_initialize, \
|
||||
.open_entry = rtems_blkdev_generic_open, \
|
||||
.close_entry = rtems_blkdev_generic_close, \
|
||||
.read_entry = rtems_blkdev_generic_read, \
|
||||
.write_entry = rtems_blkdev_generic_write, \
|
||||
.control_entry = rtems_blkdev_generic_ioctl \
|
||||
}
|
||||
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
|
||||
#define CONFIGURE_APPLICATION_EXTRA_DRIVERS FLASHDISK_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK
|
||||
|
||||
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 6
|
||||
|
||||
#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
|
||||
#define CONFIGURE_FILESYSTEM_RFS
|
||||
|
||||
#define CONFIGURE_MAXIMUM_TASKS 2
|
||||
#define CONFIGURE_MAXIMUM_SEMAPHORES 1
|
||||
|
||||
#define CONFIGURE_MINIMUM_TASK_STACK_SIZE (32 * 1024)
|
||||
|
||||
#define CONFIGURE_EXTRA_TASK_STACKS (8 * 1024)
|
||||
|
||||
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
|
||||
|
||||
#define CONFIGURE_INIT
|
||||
|
||||
#include <rtems/confdefs.h>
|
||||
832
testsuites/libtests/flashdisk01/test-file-system.c
Normal file
832
testsuites/libtests/flashdisk01/test-file-system.c
Normal file
@@ -0,0 +1,832 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <info@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include "test-file-system.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/endian.h>
|
||||
|
||||
#define ASSERT_SC(sc) assert((sc) == RTEMS_SUCCESSFUL)
|
||||
|
||||
#define BUFFER_SIZE (32 * 1024)
|
||||
|
||||
#define HEADER_SIZE 8
|
||||
|
||||
/**
|
||||
* @brief Test states.
|
||||
*
|
||||
* digraph {
|
||||
* INIT -> MOUNT;
|
||||
* MOUNT -> INIT_ROOT;
|
||||
* MOUNT -> FORMAT;
|
||||
* INIT_ROOT -> CHOOSE_DIR_ACTION
|
||||
* INIT_ROOT -> ERROR;
|
||||
* CHOOSE_DIR_ACTION -> DIR_OPEN;
|
||||
* CHOOSE_DIR_ACTION -> DIR_CLOSE;
|
||||
* CHOOSE_DIR_ACTION -> DIR_CREATE;
|
||||
* CHOOSE_DIR_ACTION -> DIR_DELETE;
|
||||
* CHOOSE_DIR_ACTION -> DIR_SLEEP;
|
||||
* DIR_OPEN -> CHOOSE_DIR_ACTION;
|
||||
* DIR_OPEN -> CHOOSE_FILE_ACTION;
|
||||
* DIR_OPEN -> ERROR;
|
||||
* DIR_CLOSE -> CHOOSE_DIR_ACTION;
|
||||
* DIR_CLOSE -> ERROR;
|
||||
* DIR_CREATE -> CHOOSE_DIR_ACTION;
|
||||
* DIR_CREATE -> DIR_DELETE;
|
||||
* DIR_CREATE -> ERROR;
|
||||
* DIR_DELETE -> CHOOSE_DIR_ACTION;
|
||||
* DIR_DELETE -> ERROR;
|
||||
* DIR_SLEEP -> CHOOSE_DIR_ACTION;
|
||||
* CHOOSE_FILE_ACTION -> FILE_CLOSE;
|
||||
* CHOOSE_FILE_ACTION -> FILE_APPEND;
|
||||
* CHOOSE_FILE_ACTION -> FILE_READ;
|
||||
* CHOOSE_FILE_ACTION -> FILE_SLEEP;
|
||||
* FILE_CLOSE -> CHOOSE_DIR_ACTION;
|
||||
* FILE_CLOSE -> ERROR;
|
||||
* FILE_APPEND -> CHOOSE_FILE_ACTION;
|
||||
* FILE_APPEND -> FILE_CLOSE_AND_UNLINK;
|
||||
* FILE_APPEND -> ERROR;
|
||||
* FILE_READ -> CHOOSE_FILE_ACTION;
|
||||
* FILE_READ -> ERROR;
|
||||
* FILE_SLEEP -> CHOOSE_FILE_ACTION;
|
||||
* FILE_CLOSE_AND_UNLINK -> CHOOSE_DIR_ACTION;
|
||||
* FILE_CLOSE_AND_UNLINK -> ERROR;
|
||||
* ERROR -> FORMAT;
|
||||
* FORMAT -> MOUNT;
|
||||
* FORMAT -> FINISH;
|
||||
* }
|
||||
*/
|
||||
typedef enum {
|
||||
CHOOSE_DIR_ACTION,
|
||||
CHOOSE_FILE_ACTION,
|
||||
DIR_CLOSE,
|
||||
DIR_CREATE,
|
||||
DIR_DELETE,
|
||||
DIR_OPEN,
|
||||
DIR_SLEEP,
|
||||
ERROR,
|
||||
FILE_APPEND,
|
||||
FILE_READ,
|
||||
FILE_CLOSE,
|
||||
FILE_SLEEP,
|
||||
FILE_CLOSE_AND_UNLINK,
|
||||
FINISH,
|
||||
FORMAT,
|
||||
INIT,
|
||||
INIT_ROOT,
|
||||
MOUNT
|
||||
} test_state;
|
||||
|
||||
typedef struct {
|
||||
DIR *dir;
|
||||
unsigned level;
|
||||
unsigned content_count;
|
||||
int fd;
|
||||
int eno;
|
||||
uint8_t buf [BUFFER_SIZE];
|
||||
char file_path [MAXPATHLEN];
|
||||
} fs_state;
|
||||
|
||||
static test_state do_format(
|
||||
unsigned index,
|
||||
fs_state *fs,
|
||||
const char *disk_path,
|
||||
const test_file_system_handler *handler,
|
||||
void *handler_arg
|
||||
)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
printf("[%02u]: format: %s\n", index, disk_path);
|
||||
|
||||
rv = (*handler->format)(disk_path, handler_arg);
|
||||
if (rv == 0) {
|
||||
return MOUNT;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
|
||||
return FINISH;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t simple_random(uint32_t v)
|
||||
{
|
||||
v *= 1664525;
|
||||
v += 1013904223;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static unsigned get_bucket_with_random(unsigned count, long random)
|
||||
{
|
||||
long unsigned unit = (1U << 31) / count;
|
||||
long unsigned bucket = (long unsigned) random / unit;
|
||||
|
||||
if (bucket != count) {
|
||||
return bucket;
|
||||
} else {
|
||||
return bucket - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned get_bucket(unsigned count)
|
||||
{
|
||||
return get_bucket_with_random(count, lrand48());
|
||||
}
|
||||
|
||||
static test_state do_choose_dir_action(void)
|
||||
{
|
||||
switch (get_bucket(8)) {
|
||||
case 0:
|
||||
case 1:
|
||||
return DIR_CLOSE;
|
||||
case 2:
|
||||
case 3:
|
||||
return DIR_CREATE;
|
||||
case 4:
|
||||
case 5:
|
||||
return DIR_OPEN;
|
||||
case 6:
|
||||
return DIR_DELETE;
|
||||
case 7:
|
||||
return DIR_SLEEP;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static test_state do_choose_file_action(void)
|
||||
{
|
||||
switch (get_bucket(4)) {
|
||||
case 0:
|
||||
return FILE_CLOSE;
|
||||
case 1:
|
||||
return FILE_SLEEP;
|
||||
case 2:
|
||||
return FILE_APPEND;
|
||||
case 3:
|
||||
return FILE_READ;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_normal_entry(const char *entry_name)
|
||||
{
|
||||
static const char *black_list [] = {
|
||||
".",
|
||||
"..",
|
||||
"lost+found"
|
||||
};
|
||||
size_t n = sizeof(black_list) / sizeof(black_list [0]);
|
||||
size_t i = 0;
|
||||
bool ok = true;
|
||||
|
||||
while (ok && i < n) {
|
||||
ok = ok && strcmp(entry_name, black_list [i]) != 0;
|
||||
++i;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool open_dir(fs_state *fs, const char *dir_path)
|
||||
{
|
||||
int rv = 0;
|
||||
bool change_dir = true;
|
||||
|
||||
if (dir_path == NULL) {
|
||||
if (fs->level > 1) {
|
||||
rv = chdir("..");
|
||||
if (rv != 0) {
|
||||
fs->eno = errno;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
--fs->level;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
dir_path = ".";
|
||||
change_dir = false;
|
||||
}
|
||||
|
||||
if (fs->dir != NULL) {
|
||||
rv = closedir(fs->dir);
|
||||
if (rv != 0) {
|
||||
fs->eno = errno;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fs->content_count = 0;
|
||||
fs->dir = opendir(dir_path);
|
||||
|
||||
if (fs->dir != NULL) {
|
||||
struct dirent *de = NULL;
|
||||
|
||||
rewinddir(fs->dir);
|
||||
while ((de = readdir(fs->dir)) != NULL) {
|
||||
if (is_normal_entry(de->d_name)) {
|
||||
++fs->content_count;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (change_dir) {
|
||||
rv = chdir(dir_path);
|
||||
if (rv != 0) {
|
||||
fs->eno = errno;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
++fs->level;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *get_dir_entry(fs_state *fs, bool *is_dir)
|
||||
{
|
||||
int rv = 0;
|
||||
char *entry_name = NULL;
|
||||
|
||||
if (fs->content_count > 0) {
|
||||
struct dirent *de = NULL;
|
||||
unsigned bucket = get_bucket(fs->content_count);
|
||||
unsigned i = 0;
|
||||
|
||||
rewinddir(fs->dir);
|
||||
while ((de = readdir(fs->dir)) != NULL) {
|
||||
if (is_normal_entry(de->d_name)) {
|
||||
if (i != bucket) {
|
||||
++i;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (de != NULL) {
|
||||
struct stat st;
|
||||
|
||||
rv = stat(de->d_name, &st);
|
||||
if (rv == 0) {
|
||||
*is_dir = S_ISDIR(st.st_mode);
|
||||
|
||||
entry_name = strdup(de->d_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entry_name;
|
||||
}
|
||||
|
||||
|
||||
static test_state do_init_root(unsigned index, fs_state *fs, const char *mount_path)
|
||||
{
|
||||
printf("[%02u]: init root: %s\n", index, mount_path);
|
||||
|
||||
if (open_dir(fs, mount_path)) {
|
||||
return CHOOSE_DIR_ACTION;
|
||||
} else {
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static test_state do_dir_close(unsigned index, fs_state *fs)
|
||||
{
|
||||
if (fs->level > 1) {
|
||||
printf("[%02u]: close dir\n", index);
|
||||
|
||||
if (open_dir(fs, NULL)) {
|
||||
return CHOOSE_DIR_ACTION;
|
||||
} else {
|
||||
return ERROR;
|
||||
}
|
||||
} else {
|
||||
return CHOOSE_DIR_ACTION;
|
||||
}
|
||||
}
|
||||
|
||||
static int open_file(fs_state *fs, const char *path, int flags, mode_t mode)
|
||||
{
|
||||
size_t n = strlcpy(fs->file_path, path, sizeof(fs->file_path));
|
||||
assert(n < sizeof(fs->file_path));
|
||||
|
||||
return open(fs->file_path, flags, mode);
|
||||
}
|
||||
|
||||
static test_state do_dir_create(unsigned index, fs_state *fs)
|
||||
{
|
||||
int rv = 0;
|
||||
test_state state = ERROR;
|
||||
long number = lrand48();
|
||||
char name [64];
|
||||
|
||||
snprintf(name, sizeof(name), "%li", number);
|
||||
|
||||
if ((number % 2) == 0) {
|
||||
printf("[%02u]: create file: %s\n", index, name);
|
||||
|
||||
rv = open_file(fs, name, O_RDONLY | O_CREAT, 0777);
|
||||
|
||||
if (rv >= 0) {
|
||||
rv = close(rv);
|
||||
|
||||
if (rv == 0) {
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
}
|
||||
} else if (errno == ENOSPC) {
|
||||
state = DIR_DELETE;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
}
|
||||
} else {
|
||||
printf("[%02u]: create dir: %s\n", index, name);
|
||||
|
||||
rv = mkdir(name, 0777);
|
||||
|
||||
if (rv == 0) {
|
||||
++fs->content_count;
|
||||
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
} else if (errno == EEXIST) {
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
} else if (errno == ENOSPC) {
|
||||
state = DIR_DELETE;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static test_state remove_node(unsigned index, fs_state *fs, const char *path, bool is_dir)
|
||||
{
|
||||
test_state state = ERROR;
|
||||
int rv = 0;
|
||||
|
||||
if (is_dir) {
|
||||
printf("[%02u]: remove dir: %s\n", index, path);
|
||||
|
||||
rv = rmdir(path);
|
||||
} else {
|
||||
printf("[%02u]: remove file: %s\n", index, path);
|
||||
|
||||
rv = unlink(path);
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
--fs->content_count;
|
||||
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
} else if (errno == ENOTEMPTY) {
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static test_state do_dir_delete(unsigned index, fs_state *fs)
|
||||
{
|
||||
test_state state = ERROR;
|
||||
|
||||
if (fs->content_count > 0) {
|
||||
bool is_dir = false;
|
||||
char *dir_entry_path = get_dir_entry(fs, &is_dir);
|
||||
|
||||
if (dir_entry_path != NULL) {
|
||||
state = remove_node(index, fs, dir_entry_path, is_dir);
|
||||
free(dir_entry_path);
|
||||
}
|
||||
} else {
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static test_state do_dir_open(unsigned index, fs_state *fs)
|
||||
{
|
||||
test_state state = ERROR;
|
||||
|
||||
if (fs->content_count > 0) {
|
||||
bool is_dir = false;
|
||||
char *dir_entry_path = get_dir_entry(fs, &is_dir);
|
||||
|
||||
if (dir_entry_path != NULL) {
|
||||
if (is_dir) {
|
||||
printf("[%02u]: open dir: %s\n", index, dir_entry_path);
|
||||
|
||||
if (open_dir(fs, dir_entry_path)) {
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
}
|
||||
} else {
|
||||
printf("[%02u]: open file: %s\n", index, dir_entry_path);
|
||||
|
||||
fs->fd = open_file(fs, dir_entry_path, O_RDWR, 0);
|
||||
|
||||
if (fs->fd >= 0) {
|
||||
state = CHOOSE_FILE_ACTION;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
}
|
||||
}
|
||||
|
||||
free(dir_entry_path);
|
||||
}
|
||||
} else {
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define VALUE_SHIFT_INIT 0
|
||||
#define VALUE_SHIFT_INC 8
|
||||
#else
|
||||
#define VALUE_SHIFT_INIT 24
|
||||
#define VALUE_SHIFT_INC -8
|
||||
#endif
|
||||
|
||||
static test_state do_file_read(unsigned index, fs_state *fs)
|
||||
{
|
||||
test_state state = ERROR;
|
||||
int fd = fs->fd;
|
||||
off_t pos = lseek(fd, 0, SEEK_SET);
|
||||
struct stat st;
|
||||
int rv = fstat(fd, &st);
|
||||
off_t file_size = st.st_size;
|
||||
|
||||
printf("[%02u]: read from file\n", index);
|
||||
|
||||
if (pos == 0 && rv == 0) {
|
||||
if (file_size >= HEADER_SIZE) {
|
||||
size_t remaining = (size_t) file_size;
|
||||
size_t header = HEADER_SIZE;
|
||||
size_t data = 0;
|
||||
uint32_t header_buf [2];
|
||||
uint8_t *header_pos = (uint8_t *) header_buf;
|
||||
uint32_t value = 0;
|
||||
unsigned value_shift = VALUE_SHIFT_INIT;
|
||||
|
||||
while (remaining > 0) {
|
||||
size_t buf_size = sizeof(fs->buf);
|
||||
size_t in = remaining < buf_size ? remaining : buf_size;
|
||||
ssize_t in_actual = 0;
|
||||
uint8_t *buf = fs->buf;
|
||||
|
||||
in_actual = read(fd, buf, in);
|
||||
if (in_actual > 0) {
|
||||
while (in_actual > 0) {
|
||||
if (header > 0) {
|
||||
size_t copy = header <= (size_t) in_actual ?
|
||||
header : (size_t) in_actual;
|
||||
|
||||
memcpy(header_pos, buf, copy);
|
||||
|
||||
in_actual -= (ssize_t) copy;
|
||||
remaining -= copy;
|
||||
buf += copy;
|
||||
header -= copy;
|
||||
header_pos += copy;
|
||||
|
||||
if (header == 0) {
|
||||
data = header_buf [0];
|
||||
value = header_buf [1];
|
||||
value_shift = VALUE_SHIFT_INIT;
|
||||
value = simple_random(value);
|
||||
}
|
||||
}
|
||||
|
||||
if (data > 0) {
|
||||
size_t compare = data <= (size_t) in_actual ?
|
||||
data : (size_t) in_actual;
|
||||
size_t c = 0;
|
||||
|
||||
for (c = 0; c < compare; ++c) {
|
||||
assert(buf [c] == (uint8_t) (value >> value_shift));
|
||||
value_shift = (value_shift + VALUE_SHIFT_INC) % 32;
|
||||
if (value_shift == VALUE_SHIFT_INIT) {
|
||||
value = simple_random(value);
|
||||
}
|
||||
}
|
||||
|
||||
in_actual -= (ssize_t) compare;
|
||||
remaining -= compare;
|
||||
buf += compare;
|
||||
data -= compare;
|
||||
|
||||
if (data == 0) {
|
||||
header = HEADER_SIZE;
|
||||
header_pos = (uint8_t *) header_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (in_actual == 0) {
|
||||
/* This is either a severe bug or a damaged file system */
|
||||
printf("[%02u]: error: invalid file size\n", index);
|
||||
remaining = 0;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
remaining = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining == 0) {
|
||||
state = CHOOSE_FILE_ACTION;
|
||||
}
|
||||
} else if (file_size == 0) {
|
||||
state = CHOOSE_FILE_ACTION;
|
||||
} else {
|
||||
printf("[%02u]: error: unexpected file size\n", index);
|
||||
}
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static test_state do_file_append(unsigned index, fs_state *fs)
|
||||
{
|
||||
test_state state = ERROR;
|
||||
int fd = fs->fd;
|
||||
off_t pos = lseek(fd, 0, SEEK_END);
|
||||
|
||||
printf("[%02u]: append to file\n", index);
|
||||
|
||||
if (pos != (off_t) -1) {
|
||||
size_t buf_size = sizeof(fs->buf);
|
||||
long random = lrand48();
|
||||
size_t out = get_bucket_with_random(buf_size, random) + 1;
|
||||
ssize_t out_actual = 0;
|
||||
uint8_t *buf = fs->buf;
|
||||
uint32_t value = (uint32_t) random;
|
||||
uint32_t *words = (uint32_t *) &buf [0];
|
||||
size_t word_count = 0;
|
||||
size_t w = 0;
|
||||
|
||||
/* Must be big enough for the header */
|
||||
out = out >= HEADER_SIZE ? out : HEADER_SIZE;
|
||||
|
||||
/*
|
||||
* In case out is not an integral multiple of four we will write a bit to
|
||||
* much. This does not hurt since the buffer is big enough.
|
||||
*/
|
||||
word_count = (out + 3) / 4;
|
||||
|
||||
/* The first word will contain the byte count with random data */
|
||||
words [0] = out - HEADER_SIZE;
|
||||
|
||||
for (w = 1; w < word_count; ++w) {
|
||||
words [w] = value;
|
||||
value = simple_random(value);
|
||||
}
|
||||
|
||||
out_actual = write(fd, buf, out);
|
||||
|
||||
if (out_actual == (ssize_t) out) {
|
||||
state = CHOOSE_FILE_ACTION;
|
||||
} else if (out_actual >= 0 || errno == ENOSPC) {
|
||||
state = FILE_CLOSE_AND_UNLINK;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
}
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static test_state do_file_close(unsigned index, fs_state *fs)
|
||||
{
|
||||
int rv = 0;
|
||||
test_state state = ERROR;
|
||||
|
||||
printf("[%02u]: close file\n", index);
|
||||
|
||||
rv = close(fs->fd);
|
||||
fs->fd = -1;
|
||||
|
||||
if (rv == 0) {
|
||||
state = CHOOSE_DIR_ACTION;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static test_state do_file_close_and_unlink(unsigned index, fs_state *fs)
|
||||
{
|
||||
test_state state = do_file_close(index, fs);
|
||||
|
||||
if (state != ERROR) {
|
||||
state = remove_node(index, fs, fs->file_path, false);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static test_state do_sleep(unsigned index, test_state state)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
rtems_interval ms = ((rtems_interval) get_bucket(10) + 1) * 100;
|
||||
rtems_interval interval = ms / rtems_configuration_get_milliseconds_per_tick();
|
||||
|
||||
printf("[%02u]: sleep: %" PRIu32 " ms\n", index, ms);
|
||||
|
||||
sc = rtems_task_wake_after(interval);
|
||||
ASSERT_SC(sc);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static test_state do_mount(
|
||||
unsigned index,
|
||||
fs_state *fs,
|
||||
const char *disk_path,
|
||||
const char *mount_path,
|
||||
const test_file_system_handler *handler,
|
||||
void *handler_arg
|
||||
)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
printf("[%02u]: mount: %s -> %s\n", index, disk_path, mount_path);
|
||||
|
||||
rv = (*handler->mount)(disk_path, mount_path, handler_arg);
|
||||
if (rv == 0) {
|
||||
return INIT_ROOT;
|
||||
} else {
|
||||
fs->eno = errno;
|
||||
|
||||
return FORMAT;
|
||||
}
|
||||
}
|
||||
|
||||
static test_state do_error(unsigned index, fs_state *fs, const char *mount_path)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if (fs->eno > 0) {
|
||||
printf("[%02u]: error: %s\n", index, strerror(fs->eno));
|
||||
} else {
|
||||
printf("[%02u]: error\n", index);
|
||||
}
|
||||
fs->eno = 0;
|
||||
|
||||
if (fs->fd >= 0) {
|
||||
close(fs->fd);
|
||||
fs->fd = -1;
|
||||
}
|
||||
|
||||
if (fs->dir != NULL) {
|
||||
closedir(fs->dir);
|
||||
fs->dir = NULL;
|
||||
}
|
||||
|
||||
chdir("/");
|
||||
fs->level = 0;
|
||||
|
||||
rv = unmount(mount_path);
|
||||
if (rv == 0) {
|
||||
return FORMAT;
|
||||
} else {
|
||||
return FINISH;
|
||||
}
|
||||
}
|
||||
|
||||
void test_file_system_with_handler(
|
||||
unsigned index,
|
||||
const char *disk_path,
|
||||
const char *mount_path,
|
||||
const test_file_system_handler *handler,
|
||||
void *handler_arg
|
||||
)
|
||||
{
|
||||
int counter = 0;
|
||||
test_state state = INIT;
|
||||
fs_state *fs = calloc(1, sizeof(*fs));
|
||||
|
||||
if (fs == NULL) {
|
||||
printf("[%02u]: not enough memory\n", index);
|
||||
return;
|
||||
}
|
||||
|
||||
fs->fd = -1;
|
||||
|
||||
printf("[%02u]: start\n", index);
|
||||
|
||||
while (state != FINISH && counter < 600) {
|
||||
switch (state) {
|
||||
case CHOOSE_DIR_ACTION:
|
||||
state = do_choose_dir_action();
|
||||
break;
|
||||
case CHOOSE_FILE_ACTION:
|
||||
state = do_choose_file_action();
|
||||
break;
|
||||
case DIR_CLOSE:
|
||||
state = do_dir_close(index, fs);
|
||||
break;
|
||||
case DIR_CREATE:
|
||||
state = do_dir_create(index, fs);
|
||||
break;
|
||||
case DIR_DELETE:
|
||||
state = do_dir_delete(index, fs);
|
||||
break;
|
||||
case DIR_OPEN:
|
||||
state = do_dir_open(index, fs);
|
||||
break;
|
||||
case DIR_SLEEP:
|
||||
state = do_sleep(index, CHOOSE_DIR_ACTION);
|
||||
break;
|
||||
case ERROR:
|
||||
state = do_error(index, fs, mount_path);
|
||||
break;
|
||||
case FILE_APPEND:
|
||||
state = do_file_append(index, fs);
|
||||
break;
|
||||
case FILE_READ:
|
||||
state = do_file_read(index, fs);
|
||||
break;
|
||||
case FILE_CLOSE:
|
||||
state = do_file_close(index, fs);
|
||||
break;
|
||||
case FILE_CLOSE_AND_UNLINK:
|
||||
state = do_file_close_and_unlink(index, fs);
|
||||
break;
|
||||
case FILE_SLEEP:
|
||||
state = do_sleep(index, CHOOSE_FILE_ACTION);
|
||||
break;
|
||||
case FORMAT:
|
||||
state = do_format(index, fs, disk_path, handler, handler_arg);
|
||||
break;
|
||||
case INIT:
|
||||
state = MOUNT;
|
||||
break;
|
||||
case INIT_ROOT:
|
||||
state = do_init_root(index, fs, mount_path);
|
||||
break;
|
||||
case MOUNT:
|
||||
state = do_mount(
|
||||
index,
|
||||
fs,
|
||||
disk_path,
|
||||
mount_path,
|
||||
handler,
|
||||
handler_arg
|
||||
);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
++counter;
|
||||
}
|
||||
|
||||
printf("[%02u]: finish\n", index);
|
||||
|
||||
free(fs);
|
||||
}
|
||||
52
testsuites/libtests/flashdisk01/test-file-system.h
Normal file
52
testsuites/libtests/flashdisk01/test-file-system.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2012 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <info@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef TEST_FILE_SYSTEM_H
|
||||
#define TEST_FILE_SYSTEM_H
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef int (*test_file_system_mount_handler)(
|
||||
const char *disk_path,
|
||||
const char *mount_path,
|
||||
void *arg
|
||||
);
|
||||
|
||||
typedef int (*test_file_system_format_handler)(
|
||||
const char *disk_path,
|
||||
void *arg
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
test_file_system_mount_handler mount;
|
||||
test_file_system_format_handler format;
|
||||
} test_file_system_handler;
|
||||
|
||||
void test_file_system_with_handler(
|
||||
unsigned index,
|
||||
const char *disk_path,
|
||||
const char *mount_path,
|
||||
const test_file_system_handler *handler,
|
||||
void *handler_arg
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* TEST_FILE_SYSTEM_H */
|
||||
Reference in New Issue
Block a user