Skip to content

bd: Add randomness to block device test and more debug friendly output #3747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 97 additions & 44 deletions features/TESTS/filesystem/heap_block_device/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,71 +23,124 @@

using namespace utest::v1;

/* It is not possible to build a KL25Z image with IAR including the file system if
* stack tracking statistics are enabled. If this is the case, build dummy
* tests.
*/
#if ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED)
#define TEST_BLOCK_SIZE 512
#define TEST_BLOCK_DEVICE_SIZE 16*TEST_BLOCK_SIZE
#define TEST_BLOCK_COUNT 10
#define TEST_ERROR_MASK 16

const struct {
const char *name;
bd_size_t (BlockDevice::*method)() const;
} ATTRS[] = {
{"read size", &BlockDevice::get_read_size},
{"program size", &BlockDevice::get_program_size},
{"erase size", &BlockDevice::get_erase_size},
{"total size", &BlockDevice::size},
};

#define BLOCK_SIZE 512
#define HEAP_BLOCK_DEVICE_TEST_01 test_read_write
uint8_t write_block[BLOCK_SIZE];
uint8_t read_block[BLOCK_SIZE];

// Simple test which reads and writes a block
// Simple test that read/writes random set of blocks
void test_read_write() {
HeapBlockDevice bd(16*BLOCK_SIZE, BLOCK_SIZE);
HeapBlockDevice bd(TEST_BLOCK_DEVICE_SIZE, TEST_BLOCK_SIZE);

int err = bd.init();
TEST_ASSERT_EQUAL(0, err);

// Fill with random sequence
srand(1);
for (int i = 0; i < BLOCK_SIZE; i++) {
write_block[i] = 0xff & rand();
for (unsigned a = 0; a < sizeof(ATTRS)/sizeof(ATTRS[0]); a++) {
static const char *prefixes[] = {"", "k", "M", "G"};
for (int i = 3; i >= 0; i--) {
bd_size_t size = (bd.*ATTRS[a].method)();
if (size >= (1ULL << 10*i)) {
printf("%s: %llu%sbytes (%llubytes)\n",
ATTRS[a].name, size >> 10*i, prefixes[i], size);
break;
}
}
}

// Write, sync, and read the block
err = bd.program(write_block, 0, BLOCK_SIZE);
TEST_ASSERT_EQUAL(0, err);

err = bd.read(read_block, 0, BLOCK_SIZE);
TEST_ASSERT_EQUAL(0, err);

// Check that the data was unmodified
srand(1);
for (int i = 0; i < BLOCK_SIZE; i++) {
TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]);
bd_size_t block_size = bd.get_erase_size();
uint8_t *write_block = new uint8_t[block_size];
uint8_t *read_block = new uint8_t[block_size];
uint8_t *error_mask = new uint8_t[TEST_ERROR_MASK];
unsigned addrwidth = ceil(log(float(bd.size()-1)) / log(float(16)))+1;

for (int b = 0; b < TEST_BLOCK_COUNT; b++) {
// Find a random block
bd_addr_t block = (rand()*block_size) % bd.size();

// Use next random number as temporary seed to keep
// the address progressing in the pseudorandom sequence
unsigned seed = rand();

// Fill with random sequence
srand(seed);
for (bd_size_t i = 0; i < block_size; i++) {
write_block[i] = 0xff & rand();
}

// erase, program, and read the block
printf("test %0*llx:%llu...\n", addrwidth, block, block_size);

err = bd.erase(block, block_size);
TEST_ASSERT_EQUAL(0, err);

err = bd.program(write_block, block, block_size);
TEST_ASSERT_EQUAL(0, err);

printf("write %0*llx:%llu ", addrwidth, block, block_size);
for (int i = 0; i < 16; i++) {
printf("%02x", write_block[i]);
}
printf("...\n");

err = bd.read(read_block, block, block_size);
TEST_ASSERT_EQUAL(0, err);

printf("read %0*llx:%llu ", addrwidth, block, block_size);
for (int i = 0; i < 16; i++) {
printf("%02x", read_block[i]);
}
printf("...\n");

// Find error mask for debugging
memset(error_mask, 0, TEST_ERROR_MASK);
bd_size_t error_scale = block_size / (TEST_ERROR_MASK*8);

srand(seed);
for (bd_size_t i = 0; i < TEST_ERROR_MASK*8; i++) {
for (bd_size_t j = 0; j < error_scale; j++) {
if ((0xff & rand()) != read_block[i*error_scale + j]) {
error_mask[i/8] |= 1 << (i%8);
}
}
}

printf("error %0*llx:%llu ", addrwidth, block, block_size);
for (int i = 0; i < 16; i++) {
printf("%02x", error_mask[i]);
}
printf("\n");

// Check that the data was unmodified
srand(seed);
for (bd_size_t i = 0; i < block_size; i++) {
TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]);
}
}

err = bd.deinit();
TEST_ASSERT_EQUAL(0, err);
}

#else /* ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */

#define HEAP_BLOCK_DEVICE_TEST_01 heap_block_device_test_dummy

/** @brief heap_block_device_test_dummy Dummy test case for testing when KL25Z being built with stack statistics enabled.
*
* @return success always
*/
static control_t heap_block_device_test_dummy()
{
printf("Null test\n");
return CaseNext;
}

#endif /* ! defined(__ICCARM__) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */

// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(10, "default_auto");
GREENTEA_SETUP(30, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}

Case cases[] = {
Case("Testing read write of a block", HEAP_BLOCK_DEVICE_TEST_01),
Case("Testing read write random blocks", test_read_write),
};

Specification specification(test_setup, cases);
Expand Down
38 changes: 10 additions & 28 deletions features/TESTS/filesystem/util_block_device/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,15 @@

using namespace utest::v1;

/* It is not possible to build a KL25Z image with IAR including the file system if
* stack tracking statistics are enabled. If this is the case, build dummy
* tests.
*/
#if ! defined(TOOLCHAIN_IAR) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED)

#define BLOCK_COUNT 16
#define BLOCK_SIZE 512
#define UTIL_BLOCK_DEVICE_TEST_01 test_slicing
#define UTIL_BLOCK_DEVICE_TEST_02 test_chaining
uint8_t write_block[BLOCK_SIZE];
uint8_t read_block[BLOCK_SIZE];


// Simple test which read/writes blocks on a sliced block device
void test_slicing() {
HeapBlockDevice bd(BLOCK_COUNT*BLOCK_SIZE, BLOCK_SIZE);
uint8_t *write_block = new uint8_t[BLOCK_SIZE];
uint8_t *read_block = new uint8_t[BLOCK_SIZE];

// Test with first slice of block device
SlicingBlockDevice slice1(&bd, 0, (BLOCK_COUNT/2)*BLOCK_SIZE);
Expand Down Expand Up @@ -123,6 +115,8 @@ void test_slicing() {
TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]);
}

delete[] write_block;
delete[] read_block;
err = slice2.deinit();
TEST_ASSERT_EQUAL(0, err);
}
Expand All @@ -131,6 +125,8 @@ void test_slicing() {
void test_chaining() {
HeapBlockDevice bd1((BLOCK_COUNT/2)*BLOCK_SIZE, BLOCK_SIZE);
HeapBlockDevice bd2((BLOCK_COUNT/2)*BLOCK_SIZE, BLOCK_SIZE);
uint8_t *write_block = new uint8_t[BLOCK_SIZE];
uint8_t *read_block = new uint8_t[BLOCK_SIZE];

// Test with chain of block device
BlockDevice *bds[] = {&bd1, &bd2};
Expand Down Expand Up @@ -174,26 +170,12 @@ void test_chaining() {
TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]);
}

delete[] write_block;
delete[] read_block;
err = chain.deinit();
TEST_ASSERT_EQUAL(0, err);
}

#else /* ! defined(TOOLCHAIN_IAR) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */

#define UTIL_BLOCK_DEVICE_TEST_01 util_block_device_test_dummy
#define UTIL_BLOCK_DEVICE_TEST_02 util_block_device_test_dummy

/** @brief util_block_device_test_dummy Dummy test case for testing when KL25Z being built with stack statistics enabled.
*
* @return success always
*/
static control_t util_block_device_test_dummy()
{
printf("Null test\n");
return CaseNext;
}

#endif /* ! defined(TOOLCHAIN_IAR) && ! defined(TARGET_KL25Z) && ! defined(MBED_STACK_STATS_ENABLED) */

// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) {
Expand All @@ -202,8 +184,8 @@ utest::v1::status_t test_setup(const size_t number_of_cases) {
}

Case cases[] = {
Case("Testing slicing of a block device", UTIL_BLOCK_DEVICE_TEST_01),
Case("Testing chaining of block devices", UTIL_BLOCK_DEVICE_TEST_02),
Case("Testing slicing of a block device", test_slicing),
Case("Testing chaining of block devices", test_chaining),
};

Specification specification(test_setup, cases);
Expand Down