tests: Add device/i2c-test test case
Add unit test for src/device/i2c.c module. This patch is also used as an example for incorporating Cmocka mocking feature (-wrap linker flag). Signed-off-by: Jan Dabros <jsd@semihalf.com> Change-Id: I2eeb565aacc724ae3b9f5c76ef4b98ef695416d6 Reviewed-on: https://review.coreboot.org/c/coreboot/+/40539 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-by: Paul Fagerburg <pfagerburg@chromium.org>
This commit is contained in:
parent
2d0ee36913
commit
a67cc5f5e8
|
@ -0,0 +1,18 @@
|
|||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
|
||||
tests-y += i2c-test
|
||||
|
||||
i2c-test-srcs += tests/device/i2c-test.c
|
||||
i2c-test-srcs += src/device/i2c.c
|
||||
i2c-test-mocks += platform_i2c_transfer
|
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <limits.h>
|
||||
#include <cmocka.h>
|
||||
|
||||
#include <device/i2c_simple.h>
|
||||
|
||||
/* Simulate two i2c devices, both on bus 0, each with three uint8_t regs
|
||||
implemented. */
|
||||
typedef struct {
|
||||
uint8_t reg;
|
||||
uint8_t data;
|
||||
} i2c_ex_regs_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int bus;
|
||||
uint8_t slave;
|
||||
i2c_ex_regs_t regs[3];
|
||||
} i2c_ex_devs_t;
|
||||
|
||||
i2c_ex_devs_t i2c_ex_devs[] = {
|
||||
{.bus = 0, .slave = 0xA, .regs = {
|
||||
{.reg = 0x0, .data = 0xB},
|
||||
{.reg = 0x1, .data = 0x6},
|
||||
{.reg = 0x2, .data = 0xF},
|
||||
} },
|
||||
{.bus = 0, .slave = 0x3, .regs = {
|
||||
{.reg = 0x0, .data = 0xDE},
|
||||
{.reg = 0x1, .data = 0xAD},
|
||||
{.reg = 0x2, .data = 0xBE},
|
||||
} },
|
||||
};
|
||||
|
||||
int __wrap_platform_i2c_transfer(unsigned int bus, struct i2c_msg *segments,
|
||||
int count)
|
||||
{
|
||||
int i;
|
||||
int reg;
|
||||
struct i2c_msg *tmp = segments;
|
||||
i2c_ex_devs_t *i2c_dev = NULL;
|
||||
|
||||
check_expected(count);
|
||||
|
||||
for (i = 0; i < count; i++, segments++) {
|
||||
check_expected_ptr(segments->buf);
|
||||
check_expected(segments->flags);
|
||||
}
|
||||
|
||||
reg = tmp->buf[0];
|
||||
|
||||
/* Find object for requested device */
|
||||
for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++, i2c_dev++)
|
||||
if (i2c_ex_devs[i].slave == tmp->slave) {
|
||||
i2c_dev = &i2c_ex_devs[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (i2c_dev == NULL)
|
||||
return -1;
|
||||
|
||||
/* Write commands */
|
||||
if (tmp->len > 1) {
|
||||
i2c_dev->regs[reg].data = tmp->buf[1];
|
||||
};
|
||||
|
||||
/* Read commands */
|
||||
for (i = 0; i < count; i++, tmp++)
|
||||
if (tmp->flags & I2C_M_RD) {
|
||||
*(tmp->buf) = i2c_dev->regs[reg].data;
|
||||
};
|
||||
}
|
||||
|
||||
static void mock_expect_params_platform_i2c_transfer(void)
|
||||
{
|
||||
unsigned long int expected_flags[] = {0, I2C_M_RD, I2C_M_TEN,
|
||||
I2C_M_RECV_LEN, I2C_M_NOSTART};
|
||||
|
||||
/* Flags should always be only within supported range */
|
||||
expect_in_set_count(__wrap_platform_i2c_transfer, segments->flags,
|
||||
expected_flags, -1);
|
||||
|
||||
expect_not_value_count(__wrap_platform_i2c_transfer, segments->buf,
|
||||
NULL, -1);
|
||||
|
||||
expect_in_range_count(__wrap_platform_i2c_transfer, count, 1, INT_MAX,
|
||||
-1);
|
||||
}
|
||||
|
||||
#define MASK 0x3
|
||||
#define SHIFT 0x1
|
||||
|
||||
static void i2c_read_field_test(void **state)
|
||||
{
|
||||
int bus, slave, reg;
|
||||
int i, j;
|
||||
uint8_t buf;
|
||||
|
||||
mock_expect_params_platform_i2c_transfer();
|
||||
|
||||
/* Read particular bits in all registers in all devices, then compare
|
||||
with expected value. */
|
||||
for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
|
||||
for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
|
||||
i2c_read_field(i2c_ex_devs[i].bus,
|
||||
i2c_ex_devs[i].slave,
|
||||
i2c_ex_devs[i].regs[j].reg,
|
||||
&buf, MASK, SHIFT);
|
||||
assert_int_equal((i2c_ex_devs[i].regs[j].data &
|
||||
(MASK << SHIFT)) >> SHIFT, buf);
|
||||
};
|
||||
|
||||
/* Read whole registers */
|
||||
for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
|
||||
for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
|
||||
i2c_read_field(i2c_ex_devs[i].bus,
|
||||
i2c_ex_devs[i].slave,
|
||||
i2c_ex_devs[i].regs[j].reg,
|
||||
&buf, 0xFF, 0);
|
||||
assert_int_equal(i2c_ex_devs[i].regs[j].data, buf);
|
||||
};
|
||||
}
|
||||
|
||||
static void i2c_write_field_test(void **state)
|
||||
{
|
||||
int bus, slave, reg;
|
||||
int i, j;
|
||||
uint8_t buf, tmp;
|
||||
|
||||
mock_expect_params_platform_i2c_transfer();
|
||||
|
||||
/* Clear particular bits in all registers in all devices, then compare
|
||||
with expected value. */
|
||||
for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
|
||||
for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
|
||||
buf = 0x0;
|
||||
tmp = i2c_ex_devs[i].regs[j].data;
|
||||
i2c_write_field(i2c_ex_devs[i].bus,
|
||||
i2c_ex_devs[i].slave,
|
||||
i2c_ex_devs[i].regs[j].reg,
|
||||
buf, MASK, SHIFT);
|
||||
assert_int_equal(i2c_ex_devs[i].regs[j].data,
|
||||
(tmp & ~(MASK << SHIFT)) | (buf << SHIFT));
|
||||
};
|
||||
|
||||
/* Set all bits in all registers, this time verify using
|
||||
i2c_read_field() accessor. */
|
||||
for (i = 0; i < ARRAY_SIZE(i2c_ex_devs); i++)
|
||||
for (j = 0; j < ARRAY_SIZE(i2c_ex_devs[0].regs); j++) {
|
||||
i2c_write_field(i2c_ex_devs[i].bus,
|
||||
i2c_ex_devs[i].slave,
|
||||
i2c_ex_devs[i].regs[j].reg,
|
||||
0xFF, 0xFF, 0);
|
||||
i2c_read_field(i2c_ex_devs[i].bus,
|
||||
i2c_ex_devs[i].slave,
|
||||
i2c_ex_devs[i].regs[j].reg,
|
||||
&buf, 0xFF, 0);
|
||||
assert_int_equal(buf, 0xFF);
|
||||
};
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(i2c_read_field_test),
|
||||
cmocka_unit_test(i2c_write_field_test)
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
Loading…
Reference in New Issue