Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * Copyright (c) 2017-2020 Nordic Semiconductor ASA
 * Copyright (c) 2015 Runtime Inc
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <string.h>

#include "fcb_test.h"
#include <storage/flash_map.h>
#include <drivers/flash.h>
#include <device.h>

struct fcb test_fcb;
uint8_t fcb_test_erase_value;

/* Sectors for FCB are defined far from application code
 * area. This test suite is the non bootable application so 1. image slot is
 * suitable for it.
 */
struct flash_sector test_fcb_sector[] = {
	[0] = {
		.fs_off = 0,
		.fs_size = 0x4000, /* 16K */
	},
	[1] = {
		.fs_off = 0x4000,
		.fs_size = 0x4000
	},
	[2] = {
		.fs_off = 0x8000,
		.fs_size = 0x4000
	},
	[3] = {
		.fs_off = 0xc000,
		.fs_size = 0x4000
	}
};


void test_fcb_wipe(void)
{
	int i;
	int rc;
	const struct flash_area *fap;

	rc = flash_area_open(TEST_FCB_FLASH_AREA_ID, &fap);
	zassert_true(rc == 0, "flash area open call failure");

	for (i = 0; i < ARRAY_SIZE(test_fcb_sector); i++) {
		rc = flash_area_erase(fap, test_fcb_sector[i].fs_off,
				      test_fcb_sector[i].fs_size);
		zassert_true(rc == 0, "erase call failure");
	}
}

int fcb_test_empty_walk_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
{
	zassert_unreachable("fcb_test_empty_walk_cb");
	return 0;
}

uint8_t fcb_test_append_data(int msg_len, int off)
{
	return (msg_len ^ off);
}

int fcb_test_data_walk_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
{
	uint16_t len;
	uint8_t test_data[128];
	int rc;
	int i;
	int *var_cnt = (int *)arg;

	len = entry_ctx->loc.fe_data_len;

	zassert_true(len == *var_cnt, "");

	rc = flash_area_read(entry_ctx->fap,
			     FCB_ENTRY_FA_DATA_OFF(entry_ctx->loc),
			     test_data, len);
	zassert_true(rc == 0, "read call failure");

	for (i = 0; i < len; i++) {
		zassert_true(test_data[i] == fcb_test_append_data(len, i),
		"fcb_test_append_data redout misrepresentation");
	}
	(*var_cnt)++;
	return 0;
}

int fcb_test_cnt_elems_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
{
	struct append_arg *aa = (struct append_arg *)arg;
	int idx;

	idx = entry_ctx->loc.fe_sector - &test_fcb_sector[0];
	aa->elem_cnts[idx]++;
	return 0;
}

void fcb_tc_pretest(int sectors)
{
	struct fcb *fcb;
	int rc = 0;

	test_fcb_wipe();
	fcb = &test_fcb;
	(void)memset(fcb, 0, sizeof(*fcb));
	fcb->f_erase_value = fcb_test_erase_value;
	fcb->f_sector_cnt = sectors;
	fcb->f_sectors = test_fcb_sector; /* XXX */

	rc = 0;
	rc = fcb_init(TEST_FCB_FLASH_AREA_ID, fcb);
	if (rc != 0) {
		printf("%s rc == %xm, %d\n", __func__, rc, rc);
		zassert_true(rc == 0, "fbc initialization failure");
	}
}

void fcb_pretest_2_sectors(void)
{
	fcb_tc_pretest(2);
}

void fcb_pretest_4_sectors(void)
{
	fcb_tc_pretest(4);
}

void teardown_nothing(void)
{
}

/*
 * This actually is not a test; the function gets erase value from flash
 * parameters, of the flash device that is used by tests, and stores it in
 * global fcb_test_erase_value.
 */
void test_get_flash_erase_value(void)
{
	const struct flash_area *fa;
	const struct flash_parameters *fp;
	const struct device *dev;
	int rc = 0;

	rc = flash_area_open(TEST_FCB_FLASH_AREA_ID, &fa);
	zassert_equal(rc, 0, "Failed top open flash area");

	dev = device_get_binding(fa->fa_dev_name);
	flash_area_close(fa);

	zassert_true(dev != NULL, "Failed to obtain device");

	fp = flash_get_parameters(dev);
	zassert_true(fp != NULL, "Failed to get flash device parameters");

	fcb_test_erase_value = fp->erase_value;
}

void test_fcb_len(void);
void test_fcb_init(void);
void test_fcb_empty_walk(void);
void test_fcb_append(void);
void test_fcb_append_too_big(void);
void test_fcb_append_fill(void);
void test_fcb_reset(void);
void test_fcb_rotate(void);
void test_fcb_multi_scratch(void);
void test_fcb_last_of_n(void);

void test_main(void)
{
	ztest_test_suite(test_fcb,
			 ztest_unit_test(test_get_flash_erase_value),
			 ztest_unit_test_setup_teardown(test_fcb_len,
							fcb_pretest_2_sectors,
							teardown_nothing),
			 ztest_unit_test(test_fcb_init),
			 ztest_unit_test_setup_teardown(test_fcb_empty_walk,
							fcb_pretest_2_sectors,
							teardown_nothing),
			 ztest_unit_test_setup_teardown(test_fcb_append,
							fcb_pretest_2_sectors,
							teardown_nothing),
			 ztest_unit_test_setup_teardown(test_fcb_append_too_big,
							fcb_pretest_2_sectors,
							teardown_nothing),
			 ztest_unit_test_setup_teardown(test_fcb_append_fill,
							fcb_pretest_2_sectors,
							teardown_nothing),
			 ztest_unit_test_setup_teardown(test_fcb_rotate,
							fcb_pretest_2_sectors,
							teardown_nothing),
			 ztest_unit_test_setup_teardown(test_fcb_multi_scratch,
							fcb_pretest_4_sectors,
							teardown_nothing),
			 ztest_unit_test_setup_teardown(test_fcb_last_of_n,
							fcb_pretest_4_sectors,
							teardown_nothing),
			 /* Finally, run one that leaves behind a
			  * flash.bin file without any random content */
			 ztest_unit_test_setup_teardown(test_fcb_reset,
							fcb_pretest_2_sectors,
							teardown_nothing)
			 );

	ztest_run_test_suite(test_fcb);
}