Skip to content

tests-integration-fs-threaded: makes tests independent from each other #12668

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
Apr 9, 2020
Merged
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
138 changes: 108 additions & 30 deletions TESTS/integration/fs-threaded/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@
*/

#if !INTEGRATION_TESTS
#error [NOT_SUPPORTED] integration tests not enabled for this target
#error [NOT_SUPPORTED] integration tests not enabled
#elif !MBED_CONF_RTOS_PRESENT
#error [NOT_SUPPORTED] integration tests require RTOS
#else
#endif

#include "mbed.h"
#include "FATFileSystem.h"
#include "LittleFileSystem.h"
#include "utest/utest.h"
#include "unity/unity.h"
Expand Down Expand Up @@ -59,38 +58,38 @@ void led_thread()
#endif

BlockDevice *bd = BlockDevice::get_default_instance();
SlicingBlockDevice sd(bd, 0, MBED_CONF_APP_TESTS_FS_SIZE);
#if TEST_USE_FILESYSTEM == FS_FAT
FATFileSystem fs("sd");
#else
SlicingBlockDevice sbd(bd, 0, MBED_CONF_APP_TESTS_FS_SIZE);
LittleFileSystem fs("sd");
#endif

static control_t test_format(const size_t call_count)
{
int format_err = fs.format(&sd);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, format_err, "could not format block device");
constexpr char fname_prefix[] = "mbed-file-test-";
constexpr char fname_postfix[] = ".txt";

int mount_err = fs.mount(&sd);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, mount_err, "could not mount block device");
static uint32_t thread_counter = 0;

return CaseNext;
void print_memory_info()
{
#if defined MBED_HEAP_STATS_ENABLED && MBED_MEM_TRACING_ENABLED
// Grab the heap statistics
mbed_stats_heap_t heap_stats;
mbed_stats_heap_get(&heap_stats);
printf("Heap size: %lu / %lu bytes\r\n",
heap_stats.current_size,
heap_stats.reserved_size);
#endif
}

static uint32_t thread_counter = 0;

void file_fn(size_t *block_size)
{
uint32_t thread_id = core_util_atomic_incr_u32(&thread_counter, 1);
char filename[255] = { 0 };
snprintf(filename, 255, "mbed-file-test-%" PRIu32 ".txt", thread_id);
snprintf(filename, 255, "%s%" PRIu32 "%s", fname_prefix, thread_id, fname_postfix);
file_test_write(filename, 0, story, sizeof(story), *block_size);
file_test_read(filename, 0, story, sizeof(story), *block_size);
print_memory_info();
}

static control_t file_2_threads(const size_t call_count)
{
thread_counter = 0;
size_t block_size1 = 4;
size_t block_size2 = 256;

Expand All @@ -104,39 +103,119 @@ static control_t file_2_threads(const size_t call_count)
return CaseNext;
}

static control_t file_3_threads(const size_t call_count)
static control_t file_4_threads(const size_t call_count)
{
thread_counter = 0;
size_t block_size1 = 256;
size_t block_size2 = 1024;
size_t block_size3 = 4096;
size_t block_size1 = 4;
size_t block_size2 = 256;
size_t block_size3 = 1024;
size_t block_size4 = 4096;

Thread t1;
Thread t2;
Thread t3;
Thread t4;
t1.start(callback(file_fn, &block_size1));
t2.start(callback(file_fn, &block_size2));
t3.start(callback(file_fn, &block_size3));
t4.start(callback(file_fn, &block_size4));
t1.join();
t2.join();
t3.join();
t4.join();

return CaseNext;
}

static control_t file_5_threads(const size_t call_count)
{
size_t block_size1 = 4;
size_t block_size2 = 256;
size_t block_size3 = 1024;
size_t block_size4 = 4096;
size_t block_size5 = 4096;

Thread t1;
Thread t2;
Thread t3;
Thread t4;
Thread t5;
t1.start(callback(file_fn, &block_size1));
t2.start(callback(file_fn, &block_size2));
t3.start(callback(file_fn, &block_size3));
t4.start(callback(file_fn, &block_size4));
t5.start(callback(file_fn, &block_size5));
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();

return CaseNext;
}

utest::v1::status_t greentea_setup(const size_t number_of_cases)
utest::v1::status_t test_setup_handler(const size_t number_of_cases)
{
GREENTEA_SETUP(10 * 60, "default_auto");

/* Format only once per each test run */
int format_err = fs.format(&sbd);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, format_err, "could not format block device");

int mount_err = fs.mount(&sbd);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, mount_err, "could not mount block device");

return greentea_test_setup_handler(number_of_cases);
}

void test_teardown_handler(const size_t passed, const size_t failed, const failure_t failure)
{
int mount_err = fs.unmount();
TEST_ASSERT_EQUAL_INT_MESSAGE(0, mount_err, "could not unmount block device");

greentea_test_teardown_handler(passed, failed, failure);
}

utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case)
{
thread_counter = 0;

return greentea_case_setup_handler(source, index_of_case);
}

utest::v1::status_t case_teardown_handler(const Case *const source,
const size_t passed,
const size_t failed,
const failure_t reason)
{
char filename[255] = { 0 };

for (uint32_t idx = 1; idx <= thread_counter; idx++) {
snprintf(filename, 255, "%s%" PRIu32 "%s", fname_prefix, idx, fname_postfix);
int removal_err = fs.remove(filename);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, removal_err, "could not remove file");
}

return greentea_case_teardown_handler(source, passed, failed, reason);
}



Case cases[] = {
Case(TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE " format", test_format),
Case(TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE " 2 files, buff 4b/256b", file_2_threads),
Case(TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE " 3 files, buff 256b/1kb/4kb", file_3_threads),
Case(TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE " 2 files, block size 4B/256B",
case_setup_handler,
file_2_threads,
case_teardown_handler),
Case(TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE " 4 files, block size 4B/256B/1KiB/4KiB",
case_setup_handler,
file_4_threads,
case_teardown_handler),
Case(TEST_BLOCK_DEVICE_TYPE "+" TEST_FILESYSTEM_TYPE " 5 files, block size 4B/256B/1KiB/4KiB/4KiB",
case_setup_handler,
file_5_threads,
case_teardown_handler),
};

Specification specification(greentea_setup, cases);
Specification specification(test_setup_handler, cases, test_teardown_handler);

int main()
{
Expand All @@ -148,4 +227,3 @@ int main()

return !Harness::run(specification);
}
#endif // !INTEGRATION_TESTS