Skip to content

Commit ba6748f

Browse files
author
Amir Cohen
committed
Improve general Block Device tests
Fixing all rand issues, aligning erase addresses, moving prints to debug mode.
1 parent f1e664b commit ba6748f

File tree

1 file changed

+67
-104
lines changed
  • features/storage/TESTS/blockdevice/general_block_device

1 file changed

+67
-104
lines changed

features/storage/TESTS/blockdevice/general_block_device/main.cpp

Lines changed: 67 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <stdlib.h>
2727
#include "BufferedBlockDevice.h"
2828
#include "BlockDevice.h"
29+
#include <algorithm>
2930

3031
#if COMPONENT_SPIF
3132
#include "SPIFBlockDevice.h"
@@ -47,13 +48,27 @@
4748
#include "FlashIAPBlockDevice.h"
4849
#endif
4950

51+
// Debug available
52+
#ifndef MODE_DEBUG
53+
#define MODE_DEBUG 0
54+
#endif
55+
56+
#if MODE_DEBUG
57+
#define DEBUG_PRINTF(...) printf(__VA_ARGS__)
58+
#else
59+
#define DEBUG_PRINTF(...)
60+
#endif
61+
5062
using namespace utest::v1;
5163

5264
#define TEST_BLOCK_COUNT 10
5365
#define TEST_ERROR_MASK 16
5466
#define TEST_NUM_OF_THREADS 5
5567
#define TEST_THREAD_STACK_SIZE 1024
5668

69+
uint8_t num_of_sectors = TEST_NUM_OF_THREADS * TEST_BLOCK_COUNT;
70+
uint32_t sectors_addr[TEST_NUM_OF_THREADS * TEST_BLOCK_COUNT] = {0};
71+
5772
const struct {
5873
const char *name;
5974
bd_size_t (BlockDevice::*method)() const;
@@ -194,13 +209,9 @@ void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_si
194209
srand(block_seed++);
195210

196211
// Find a random block
197-
int threaded_rand_number = (rand() * TEST_NUM_OF_THREADS) + thread_num;
198-
bd_addr_t block = (threaded_rand_number * block_size) % block_device->size();
199-
200-
// Flashiap boards with inconsistent sector size will not align with random start addresses
201-
if (bd_arr[test_iteration] == flashiap) {
202-
block = 0;
203-
}
212+
bd_addr_t block = sectors_addr[thread_num];
213+
bd_size_t curr_block_size = block_device->get_erase_size(block);
214+
block_size = std::min(block_size, curr_block_size);
204215

205216
// Use next random number as temporary seed to keep
206217
// the address progressing in the pseudorandom sequence
@@ -212,14 +223,9 @@ void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_si
212223
write_block[i_ind] = 0xff & rand();
213224
}
214225
// Write, sync, and read the block
215-
utest_printf("test %0*llx:%llu...\n", addrwidth, block, block_size);
226+
DEBUG_PRINTF("test %0*llx:%llu...\n", addrwidth, block, curr_block_size);
216227

217-
// Thread test for flashiap write to the same sector, so all write/read/erase actions should be locked
218-
if (bd_arr[test_iteration] != flashiap) {
219-
_mutex->unlock();
220-
}
221-
222-
err = block_device->erase(block, block_size);
228+
err = block_device->erase(block, curr_block_size);
223229
TEST_ASSERT_EQUAL(0, err);
224230

225231
err = block_device->program(write_block, block, block_size);
@@ -228,10 +234,6 @@ void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_si
228234
err = block_device->read(read_block, block, block_size);
229235
TEST_ASSERT_EQUAL(0, err);
230236

231-
if (bd_arr[test_iteration] != flashiap) {
232-
_mutex->lock();
233-
}
234-
235237
// Check that the data was unmodified
236238
srand(seed);
237239
int val_rand;
@@ -253,11 +255,19 @@ void test_init_bd()
253255
utest_printf("\nTest Init block device.\n");
254256

255257
block_device = get_bd_instance(test_iteration);
256-
257258
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
258259

259260
int err = block_device->init();
260261
TEST_ASSERT_EQUAL(0, err);
262+
263+
bd_addr_t start_address = 0;
264+
uint8_t i = 0;
265+
for (; i < num_of_sectors && start_address < block_device->size(); i++) {
266+
sectors_addr[i] = start_address;
267+
DEBUG_PRINTF("start_address = 0x%llx, sector_size = %d\n", start_address, block_device->get_erase_size(start_address));
268+
start_address += block_device->get_erase_size(start_address);
269+
}
270+
num_of_sectors = i;
261271
}
262272

263273
void test_random_program_read_erase()
@@ -289,22 +299,23 @@ void test_random_program_read_erase()
289299
goto end;
290300
}
291301

292-
for (int b = 0; b < TEST_BLOCK_COUNT; b++) {
293-
basic_erase_program_read_test(block_device, block_size, write_block, read_block, addrwidth, 0);
302+
for (int b = 0; b < std::min((uint8_t)TEST_BLOCK_COUNT, num_of_sectors); b++) {
303+
basic_erase_program_read_test(block_device, block_size, write_block, read_block, addrwidth, b);
294304
}
295305

296306
end:
297-
delete[] write_block;
298307
delete[] read_block;
308+
delete[] write_block;
299309
}
300310

301-
static void test_thread_job(void *block_device_ptr)
311+
static void test_thread_job()
302312
{
303313
static int thread_num = 0;
304314
_mutex->lock();
305-
int block_num = thread_num++;
315+
int block_num = thread_num++ % TEST_NUM_OF_THREADS;
306316
_mutex->unlock();
307-
BlockDevice *block_device = (BlockDevice *)block_device_ptr;
317+
318+
uint8_t sector_per_thread = (num_of_sectors / TEST_NUM_OF_THREADS);
308319

309320
bd_size_t block_size = block_device->get_erase_size();
310321
unsigned addrwidth = ceil(log(float(block_device->size() - 1)) / log(float(16))) + 1;
@@ -317,13 +328,13 @@ static void test_thread_job(void *block_device_ptr)
317328
goto end;
318329
}
319330

320-
for (int b = 0; b < TEST_BLOCK_COUNT; b++) {
321-
basic_erase_program_read_test(block_device, block_size, write_block, read_block, addrwidth, block_num);
331+
for (int b = 0; b < sector_per_thread; b++) {
332+
basic_erase_program_read_test(block_device, block_size, write_block, read_block, addrwidth, block_num * sector_per_thread + b);
322333
}
323334

324335
end:
325-
delete[] write_block;
326336
delete[] read_block;
337+
delete[] write_block;
327338
}
328339

329340
void test_multi_threads()
@@ -363,7 +374,7 @@ void test_multi_threads()
363374
}
364375
delete[] dummy;
365376

366-
threadStatus = bd_thread[i_ind]->start(callback(test_thread_job, (void *)block_device));
377+
threadStatus = bd_thread[i_ind]->start(callback(test_thread_job));
367378
if (threadStatus != 0) {
368379
utest_printf("Thread %d Start Failed!\n", i_ind + 1);
369380
break;
@@ -398,39 +409,29 @@ void test_erase_functionality()
398409

399410
// Check erase value
400411
int erase_value_int = block_device->get_erase_value();
401-
utest_printf("block_device->get_erase_value()=%d\n", erase_value_int);
402412
TEST_SKIP_UNLESS_MESSAGE(erase_value_int >= 0, "Erase not supported in this block device. Test skipped.");
403413

404414
// Assuming that get_erase_value() returns byte value as documentation mentions
405415
// "If get_erase_value() returns a non-negative byte value" for unknown case.
406416
TEST_ASSERT(erase_value_int <= 255);
407417
uint8_t erase_value = (uint8_t)erase_value_int;
408418

409-
// Determine data_buf_size
410-
bd_size_t erase_size = block_device->get_erase_size();
411-
TEST_ASSERT(erase_size > 0);
412-
bd_size_t data_buf_size = erase_size;
413-
414419
// Determine start_address
415-
bd_addr_t start_address = rand(); // low 32 bytes
416-
start_address += (uint64_t)rand() << 32; // high 32 bytes
417-
start_address %= block_device->size() - data_buf_size - erase_size; // fit all data + alignment reserve
418-
start_address += erase_size; // add alignment reserve
419-
start_address -= start_address % erase_size; // align with erase_block
420+
bd_addr_t start_address = sectors_addr[rand() % num_of_sectors];
420421
utest_printf("start_address=0x%016" PRIx64 "\n", start_address);
421422

422-
// Flashiap boards with inconsistent sector size will not align with random start addresses
423-
if (bd_arr[test_iteration] == flashiap) {
424-
start_address = 0;
425-
}
423+
// Determine data_buf_size
424+
bd_size_t erase_size = block_device->get_erase_size(start_address);
425+
TEST_ASSERT(erase_size > 0);
426+
bd_size_t data_buf_size = erase_size;
426427

427428
// Allocate buffer for write test data
428-
uint8_t *data_buf = (uint8_t *)malloc(data_buf_size);
429-
TEST_SKIP_UNLESS_MESSAGE(data_buf, "Not enough memory for test.\n");
429+
uint8_t *data_buf = new (std::nothrow) uint8_t[data_buf_size];
430+
TEST_SKIP_UNLESS_MESSAGE(data_buf != NULL, "Not enough memory for test");
430431

431432
// Allocate buffer for read test data
432-
uint8_t *out_data_buf = (uint8_t *)malloc(data_buf_size);
433-
TEST_SKIP_UNLESS_MESSAGE(out_data_buf, "Not enough memory for test.\n");
433+
uint8_t *out_data_buf = new (std::nothrow) uint8_t[data_buf_size];
434+
TEST_SKIP_UNLESS_MESSAGE(out_data_buf != NULL, "Not enough memory for test");
434435

435436
// First must Erase given memory region
436437
utest_printf("erasing given memory region\n");
@@ -476,8 +477,8 @@ void test_erase_functionality()
476477
TEST_ASSERT_EQUAL(erase_value, out_data_buf[i]);
477478
}
478479

479-
free(data_buf);
480-
free(out_data_buf);
480+
delete[] out_data_buf;
481+
delete[] data_buf;
481482
}
482483

483484
void test_contiguous_erase_write_read()
@@ -486,11 +487,6 @@ void test_contiguous_erase_write_read()
486487

487488
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
488489

489-
// Flashiap boards with inconsistent sector size will not align with random start addresses
490-
if (bd_arr[test_iteration] == flashiap) {
491-
return;
492-
}
493-
494490
// Test flow:
495491
// 1. Erase whole test area
496492
// - Tests contiguous erase
@@ -499,57 +495,30 @@ void test_contiguous_erase_write_read()
499495
// 3. Return step 2 for whole erase region
500496

501497
// Test parameters
502-
bd_size_t erase_size = block_device->get_erase_size();
503-
TEST_ASSERT(erase_size > 0);
504498
bd_size_t program_size = block_device->get_program_size();
505499
TEST_ASSERT(program_size > 0);
506-
utest_printf("erase_size=%" PRId64 "\n", erase_size);
507500
utest_printf("program_size=%" PRId64 "\n", program_size);
508501
utest_printf("block_device->size()=%" PRId64 "\n", block_device->size());
509502

510-
// Determine write/read buffer size
511-
// start write_read_buf_size from 1% block_device->size()
512-
bd_size_t write_read_buf_size = block_device->size() / 100; // 1%, 10k=100, 100k=1k, 1MB=10k, 32MB=32k
513-
// try to limit write_read_buf_size to 10k. If program_size*2 is larger than 10k, that will be used instead.
514-
if (write_read_buf_size > 10000) {
515-
write_read_buf_size = 10000;
516-
}
517-
// 2 program_size blocks is minimum for contiguous write/read test
518-
if (write_read_buf_size < program_size * 2) {
519-
write_read_buf_size = program_size * 2; // going over 10k
520-
}
521-
bd_size_t contiguous_write_read_blocks_per_region = write_read_buf_size /
522-
program_size; // 2 is minimum to test contiguous write
523-
write_read_buf_size = contiguous_write_read_blocks_per_region * program_size;
524-
utest_printf("contiguous_write_read_blocks_per_region=%" PRIu64 "\n", contiguous_write_read_blocks_per_region);
525-
utest_printf("write_read_buf_size=%" PRIu64 "\n", write_read_buf_size);
526-
527-
// Determine test region count
528-
int contiguous_write_read_regions = TEST_BLOCK_COUNT;
529-
utest_printf("contiguous_write_read_regions=%d\n", contiguous_write_read_regions);
530-
531-
// Determine whole erase size
532-
bd_size_t contiguous_erase_size = write_read_buf_size * contiguous_write_read_regions;
533-
contiguous_erase_size -= contiguous_erase_size % erase_size; // aligned to erase_size
534-
contiguous_erase_size += erase_size; // but larger than write/read size * regions
535-
utest_printf("contiguous_erase_size=%" PRIu64 "\n", contiguous_erase_size);
536-
537-
// Determine starting address
538-
bd_addr_t start_address = rand(); // low 32 bytes
539-
start_address += (uint64_t)rand() << 32; // high 32 bytes
540-
start_address %= block_device->size() - contiguous_erase_size - erase_size; // fit all data + alignment reserve
541-
start_address += erase_size; // add alignment reserve
542-
start_address -= start_address % erase_size; // align with erase_block
543-
bd_addr_t stop_address = start_address + write_read_buf_size * contiguous_write_read_regions;
503+
// Determine start_address & stop_address
504+
uint8_t sector_num = rand() % (num_of_sectors - 2);
505+
bd_addr_t start_address = sectors_addr[sector_num];
506+
bd_addr_t stop_address = sectors_addr[sector_num + 2];
544507
utest_printf("start_address=0x%016" PRIx64 "\n", start_address);
545508
utest_printf("stop_address=0x%016" PRIx64 "\n", stop_address);
546509

547-
// Allocate write/read buffer
548-
uint8_t *write_read_buf = (uint8_t *)malloc(write_read_buf_size);
549-
if (write_read_buf == NULL) {
550-
TEST_SKIP_MESSAGE("not enough memory for test");
510+
bd_size_t contiguous_erase_size = stop_address - start_address;
511+
TEST_ASSERT(contiguous_erase_size > 0);
512+
utest_printf("contiguous_erase_size=%d\n", contiguous_erase_size);
513+
514+
bd_size_t write_read_buf_size = program_size;
515+
if (contiguous_erase_size / program_size > 8 && contiguous_erase_size % (program_size * 8) == 0) {
516+
write_read_buf_size = program_size * 8;
551517
}
552-
utest_printf("write_read_buf_size=%" PRIu64 "\n", (uint64_t)write_read_buf_size);
518+
519+
// Allocate write/read buffer
520+
uint8_t *write_read_buf = new (std::nothrow) uint8_t[write_read_buf_size];
521+
TEST_SKIP_UNLESS_MESSAGE(contiguous_erase_size, "Not enough memory for test.\n");
553522

554523
// Must Erase the whole region first
555524
utest_printf("erasing memory, from 0x%" PRIx64 " of size 0x%" PRIx64 "\n", start_address, contiguous_erase_size);
@@ -562,7 +531,7 @@ void test_contiguous_erase_write_read()
562531
for (size_t i = 0; i < write_read_buf_size; i++) {
563532
write_read_buf[i] = (uint8_t)rand();
564533
}
565-
utest_printf("pre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64 "\n", start_address + offset,
534+
DEBUG_PRINTF("pre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64 "", start_address + offset,
566535
write_read_buf_size);
567536
err = block_device->program((const void *)write_read_buf, start_address + offset, write_read_buf_size);
568537
TEST_ASSERT_EQUAL(0, err);
@@ -576,29 +545,24 @@ void test_contiguous_erase_write_read()
576545
// Loop through all write/read regions
577546
int region = 0;
578547
for (; start_address < stop_address; start_address += write_read_buf_size) {
579-
utest_printf("\nregion #%d start_address=0x%016" PRIx64 "\n", region++, start_address);
580548

581549
// Generate test data
582550
unsigned int seed = rand();
583-
utest_printf("generating test data, seed=%u\n", seed);
584551
srand(seed);
585552
for (size_t i = 0; i < write_read_buf_size; i++) {
586553
write_read_buf[i] = (uint8_t)rand();
587554
}
588555

589556
// Write test data
590-
utest_printf("writing test data\n");
591557
err = block_device->program((const void *)write_read_buf, start_address, write_read_buf_size);
592558
TEST_ASSERT_EQUAL(0, err);
593559

594560
// Read test data
595561
memset(write_read_buf, 0, (size_t)write_read_buf_size);
596-
utest_printf("reading test data\n");
597562
err = block_device->read(write_read_buf, start_address, write_read_buf_size);
598563
TEST_ASSERT_EQUAL(0, err);
599564

600565
// Verify read data
601-
utest_printf("verifying test data\n");
602566
srand(seed);
603567
for (size_t i = 0; i < write_read_buf_size; i++) {
604568
uint8_t expected_value = (uint8_t)rand();
@@ -608,7 +572,6 @@ void test_contiguous_erase_write_read()
608572
}
609573
TEST_ASSERT_EQUAL(write_read_buf[i], expected_value);
610574
}
611-
utest_printf("verify OK\n");
612575
}
613576

614577
free(write_read_buf);

0 commit comments

Comments
 (0)