Skip to content

Commit

Permalink
Split unit testing and integration testing
Browse files Browse the repository at this point in the history
  • Loading branch information
oyama committed Jun 13, 2024
1 parent 1130e39 commit ba98909
Show file tree
Hide file tree
Showing 16 changed files with 2,710 additions and 199 deletions.
43 changes: 11 additions & 32 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,55 +1,34 @@
set(CMAKE_BUILD_TYPE Debug)

add_executable(tests
add_executable(unittests
main.c
test_blockdevice.c
test_filesystem.c
test_vfs.c
test_stdio.c
test_copy_between_different_filesystems.c
)
target_compile_options(tests PRIVATE -Werror -Wall -Wextra -Wnull-dereference)
target_link_libraries(tests PRIVATE
target_compile_options(unittests PRIVATE -Werror -Wall -Wextra -Wnull-dereference)
target_link_libraries(unittests PRIVATE
pico_stdlib
blockdevice_flash
blockdevice_heap
blockdevice_sd
blockdevice_loopback
filesystem_fat
filesystem_littlefs
filesystem_vfs
)
target_link_options(tests PRIVATE -Wl,--print-memory-usage)
pico_add_extra_outputs(tests)
pico_enable_stdio_usb(tests 1)
target_link_options(unittests PRIVATE -Wl,--print-memory-usage)
pico_add_extra_outputs(unittests)
pico_enable_stdio_usb(unittests 1)


add_executable(multicore multicore.c)
target_compile_options(multicore PRIVATE -Werror -Wall -Wextra -Wnull-dereference)
target_link_libraries(multicore PRIVATE
pico_stdlib
pico_multicore
blockdevice_flash
blockdevice_heap
blockdevice_sd
filesystem_fat
filesystem_littlefs
filesystem_vfs
)
target_link_options(multicore PRIVATE -Wl,--print-memory-usage)
pico_add_extra_outputs(multicore)
pico_enable_stdio_uart(multicore 1)
pico_enable_stdio_usb(multicore 0)
pico_set_binary_type(multicore copy_to_ram)
add_subdirectory(integration)
add_subdirectory(multicore)

find_program(OPENOCD openocd)
if(OPENOCD)
add_custom_target(run_tests
COMMAND ${OPENOCD} -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "program tests.elf verify reset exit"
DEPENDS tests
)
add_custom_target(run_multicore
COMMAND ${OPENOCD} -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "program multicore.elf verify reset exit"
DEPENDS multicore
add_custom_target(run_unittests
COMMAND ${OPENOCD} -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "program unittests.elf verify reset exit"
DEPENDS unittests
)
endif()
15 changes: 15 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Tests

The project has three tests:

1. unit tests `unittests` using heap memory
2. integration tests `integrate` using Raspberry Pi Pico hardware
3. `multicore` using multi-core

```bash
cd build
make unittests integration multicore
make run_unittests
make run_integration
make run_multicore
```
33 changes: 33 additions & 0 deletions tests/integration/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
set(CMAKE_BUILD_TYPE Debug)

add_executable(integration
main.c
test_blockdevice.c
test_filesystem.c
test_vfs.c
test_stdio.c
test_copy_between_different_filesystems.c
)
target_compile_options(integration PRIVATE -Werror -Wall -Wextra -Wnull-dereference)
target_link_libraries(integration PRIVATE
pico_stdlib
blockdevice_flash
blockdevice_heap
blockdevice_sd
blockdevice_loopback
filesystem_fat
filesystem_littlefs
filesystem_vfs
)
target_link_options(integration PRIVATE -Wl,--print-memory-usage)
pico_add_extra_outputs(integration)
pico_enable_stdio_usb(integration 1)


find_program(OPENOCD openocd)
if(OPENOCD)
add_custom_target(run_integration
COMMAND ${OPENOCD} -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "program integration.elf verify reset exit"
DEPENDS integration
)
endif()
26 changes: 26 additions & 0 deletions tests/integration/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <stdio.h>
#include <pico/stdlib.h>

#define COLOR_GREEN(format) ("\e[32m" format "\e[0m")

extern void test_blockdevice(void);
extern void test_filesystem(void);
extern void test_vfs(void);
extern void test_stdio(void);
extern void test_copy_between_different_filesystems(void);

int main(void) {
stdio_init_all();

printf("Start all tests\n");

test_blockdevice();
test_filesystem();
test_vfs();
test_stdio();
test_copy_between_different_filesystems();

printf(COLOR_GREEN("All tests are ok\n"));
while (1)
tight_loop_contents();
}
243 changes: 243 additions & 0 deletions tests/integration/test_blockdevice.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
#include <assert.h>
#include <hardware/clocks.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "blockdevice/flash.h"
#include "blockdevice/heap.h"
#include "blockdevice/loopback.h"
#include "blockdevice/sd.h"
#include "filesystem/fat.h"
#include "filesystem/vfs.h"

#define COLOR_GREEN(format) ("\e[32m" format "\e[0m")
#define FLASH_START_AT (0.5 * 1024 * 1024)
#define FLASH_LENGTH_ALL 0
#define HEAP_STORAGE_SIZE (512 * 128) // 64KB
#define LOOPBACK_STORAGE_SIZE 1024
#define LOOPBACK_BLOCK_SIZE 512

#include <ctype.h>
static void print_hex(const char *label, const void *buffer, size_t length) {
const uint8_t *buf = buffer;
printf("%s:\n", label);
size_t offset = 0;
for (size_t i = 0; i < length; ++i) {
if (i % 16 == 0)
printf("0x%04u%s", offset, (i % 512) == 0 ? ">" : " ");
if (isalnum(buf[i])) {
printf("'%c' ", buf[i]);
} else {
printf("0x%02x", buf[i]);
}
if (i % 16 == 15) {
printf("\n");
offset += 16;
} else {
printf(", ");
}
}
}

static void test_printf(const char *format, ...) {
va_list args;
va_start(args, format);
int n = vprintf(format, args);
va_end(args);

printf(" ");
for (size_t i = 0; i < 50 - (size_t)n; i++)
printf(".");
}

static void setup(blockdevice_t *device) {
(void)device;
}

static void cleanup(blockdevice_t *device) {
size_t length = device->size(device);
device->erase(device, 0, length);
}

static bool is_sd_card_connected(blockdevice_t *device) {
int err = device->deinit(device);
assert(err == BD_ERROR_OK);

err = device->init(device);
if (err == BD_ERROR_OK)
return true;
else if (err == -5005)
return false;
else
assert(err == BD_ERROR_OK);
return false;
}

static void test_api_init(blockdevice_t *device) {
test_printf("init");

// The init is done when the object is created.
int err = device->deinit(device);
assert(err == BD_ERROR_OK);

// Init for later testing
err = device->init(device);
assert(err == BD_ERROR_OK);

printf(COLOR_GREEN("ok\n"));
}

static void test_api_sync(blockdevice_t *device) {
test_printf("sync");

int err = device->sync(device);
assert(err == BD_ERROR_OK);

printf(COLOR_GREEN("ok\n"));
}

static void test_api_erase_program_read(blockdevice_t *device) {
test_printf("erase,program,read");

size_t addr = 0;
size_t length = device->erase_size;

// erase test block
int err = device->erase(device, addr, length);
assert(err == BD_ERROR_OK);

// program by random data
uint8_t *program_buffer = calloc(1, length);
srand(length);
for (size_t i = 0; i < length; i++)
program_buffer[i] = rand() & 0xFF;
err = device->program(device, program_buffer, addr, length);
assert(err == BD_ERROR_OK);

// read test block
uint8_t *read_buffer = calloc(1, length);
err = device->read(device, read_buffer, addr, length);
assert(err == BD_ERROR_OK);
assert(memcmp(program_buffer, read_buffer, length) == 0);

free(read_buffer);
free(program_buffer);

printf(COLOR_GREEN("ok\n"));
}

static void test_api_trim(blockdevice_t *device) {
test_printf("trim");

int err = device->trim(device, 0, 0);
assert(err == BD_ERROR_OK);

printf(COLOR_GREEN("ok\n"));
}

static void test_api_size(blockdevice_t *device) {
test_printf("size");

size_t length = device->size(device);
assert(length > 0);

printf(COLOR_GREEN("ok\n"));
}

static void test_api_attribute(blockdevice_t *device) {
test_printf("attribute");

assert(device->read_size > 0);
assert(device->erase_size > 0);
assert(device->program_size > 0);
assert(strlen(device->name) > 0);

assert(device->config != NULL);

printf(COLOR_GREEN("ok\n"));
}

void test_blockdevice(void) {
printf("Block device Onboard-Flash:\n");
blockdevice_t *flash = blockdevice_flash_create(FLASH_START_AT, FLASH_LENGTH_ALL);
assert(flash != NULL);
setup(flash);

test_api_init(flash);
test_api_erase_program_read(flash);
test_api_trim(flash);
test_api_sync(flash);
test_api_size(flash);
test_api_attribute(flash);

cleanup(flash);
blockdevice_flash_free(flash);

printf("Block device SPI SD card:\n");
blockdevice_t *sd = blockdevice_sd_create(spi0,
PICO_DEFAULT_SPI_TX_PIN,
PICO_DEFAULT_SPI_RX_PIN,
PICO_DEFAULT_SPI_SCK_PIN,
PICO_DEFAULT_SPI_CSN_PIN,
10 * MHZ,
false);
assert(sd != NULL);
if (is_sd_card_connected(sd)) {
setup(sd);

test_api_init(sd);
test_api_erase_program_read(sd);
test_api_trim(sd);
test_api_sync(sd);
test_api_size(sd);
test_api_attribute(sd);

cleanup(sd);
} else {
test_printf("init");
printf("skip, device not connected\n");
}
blockdevice_sd_free(sd);

printf("Block device Heap memory:\n");
blockdevice_t *heap = blockdevice_heap_create(HEAP_STORAGE_SIZE);
assert(heap != NULL);
setup(heap);

test_api_init(heap);
test_api_erase_program_read(heap);
test_api_trim(heap);
test_api_sync(heap);
test_api_size(heap);
test_api_attribute(heap);

cleanup(heap);
blockdevice_heap_free(heap);

printf("Block device Loopback:\n");
heap = blockdevice_heap_create(HEAP_STORAGE_SIZE);
assert(heap != NULL);
setup(heap);
filesystem_t *fat = filesystem_fat_create();
assert(fat != NULL);
fs_format(fat, heap);
fs_mount("/", fat, heap);
blockdevice_t *loopback = blockdevice_loopback_create("/loopback",
LOOPBACK_STORAGE_SIZE,
LOOPBACK_BLOCK_SIZE);
assert(loopback != NULL);

test_api_init(loopback);
test_api_erase_program_read(loopback);
test_api_trim(loopback);
test_api_sync(loopback);
test_api_size(loopback);
test_api_attribute(loopback);

cleanup(loopback);
blockdevice_loopback_free(loopback);
fs_unmount("/");
filesystem_fat_free(fat);
cleanup(heap);
blockdevice_heap_free(heap);
}
Loading

0 comments on commit ba98909

Please sign in to comment.