From 2e7d35d2a60339cfa54e26a07326bc75e1060bb3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Feb 2014 15:59:21 -0700 Subject: dm: Add basic tests Add some tests of driver model functionality. Coverage includes: - basic init - binding of drivers to devices using platform_data - automatic probing of devices when referenced - availability of platform data to devices - lifecycle from bind to probe to remove to unbind - renumbering within a uclass when devices are probed/removed - calling driver-defined operations - deactivation of drivers when removed - memory leak across creation and destruction of drivers/uclasses - uclass init/destroy methods - automatic probe/remove of children/parents when needed This function is enabled for sandbox, using CONFIG_DM_TEST. Signed-off-by: Simon Glass --- include/dm/test.h | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/dm/ut.h | 95 +++++++++++++++++++++++++++++++ 2 files changed, 262 insertions(+) create mode 100644 include/dm/test.h create mode 100644 include/dm/ut.h (limited to 'include/dm') diff --git a/include/dm/test.h b/include/dm/test.h new file mode 100644 index 0000000..eeaa2eb --- /dev/null +++ b/include/dm/test.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2013 Google, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __DM_TEST_H +#define __DM_TEST_H + +#include + +/** + * struct dm_test_cdata - configuration data for test instance + * + * @ping_add: Amonut to add each time we get a ping + * @base: Base address of this device + */ +struct dm_test_pdata { + int ping_add; + uint32_t base; +}; + +/** + * struct test_ops - Operations supported by the test device + * + * @ping: Ping operation + * @dev: Device to operate on + * @pingval: Value to ping the device with + * @pingret: Returns resulting value from driver + * @return 0 if OK, -ve on error + */ +struct test_ops { + int (*ping)(struct device *dev, int pingval, int *pingret); +}; + +/* Operations that our test driver supports */ +enum { + DM_TEST_OP_BIND = 0, + DM_TEST_OP_UNBIND, + DM_TEST_OP_PROBE, + DM_TEST_OP_REMOVE, + + /* For uclass */ + DM_TEST_OP_POST_BIND, + DM_TEST_OP_PRE_UNBIND, + DM_TEST_OP_POST_PROBE, + DM_TEST_OP_PRE_REMOVE, + DM_TEST_OP_INIT, + DM_TEST_OP_DESTROY, + + DM_TEST_OP_COUNT, +}; + +/* Test driver types */ +enum { + DM_TEST_TYPE_FIRST = 0, + DM_TEST_TYPE_SECOND, +}; + +/* The number added to the ping total on each probe */ +#define DM_TEST_START_TOTAL 5 + +/** + * struct dm_test_priv - private data for the test devices + */ +struct dm_test_priv { + int ping_total; + int op_count[DM_TEST_OP_COUNT]; +}; + +/** + * struct dm_test_perdev_class_priv - private per-device data for test uclass + */ +struct dm_test_uclass_perdev_priv { + int base_add; +}; + +/** + * struct dm_test_uclass_priv - private data for test uclass + */ +struct dm_test_uclass_priv { + int total_add; +}; + +/* + * Operation counts for the test driver, used to check that each method is + * called correctly + */ +extern int dm_testdrv_op_count[DM_TEST_OP_COUNT]; + +extern struct dm_test_state global_test_state; + +/* + * struct dm_test_state - Entire state of dm test system + * + * This is often abreviated to dms. + * + * @root: Root device + * @testdev: Test device + * @fail_count: Number of tests that failed + * @force_fail_alloc: Force all memory allocs to fail + * @skip_post_probe: Skip uclass post-probe processing + */ +struct dm_test_state { + struct device *root; + struct device *testdev; + int fail_count; + int force_fail_alloc; + int skip_post_probe; +}; + +/* Test flags for each test */ +enum { + DM_TESTF_SCAN_PDATA = 1 << 0, /* test needs platform data */ + DM_TESTF_PROBE_TEST = 1 << 1, /* probe test uclass */ + DM_TESTF_SCAN_FDT = 1 << 2, /* scan device tree */ +}; + +/** + * struct dm_test - Information about a driver model test + * + * @name: Name of test + * @func: Function to call to perform test + * @flags: Flags indicated pre-conditions for test + */ +struct dm_test { + const char *name; + int (*func)(struct dm_test_state *dms); + int flags; +}; + +/* Declare a new driver model test */ +#define DM_TEST(_name, _flags) \ + ll_entry_declare(struct dm_test, _name, dm_test) = { \ + .name = #_name, \ + .flags = _flags, \ + .func = _name, \ + } + +/* Declare ping methods for the drivers */ +int test_ping(struct device *dev, int pingval, int *pingret); +int testfdt_ping(struct device *dev, int pingval, int *pingret); + +/** + * dm_check_operations() - Check that we can perform ping operations + * + * This checks that the ping operations work as expected for a device + * + * @dms: Overall test state + * @dev: Device to test + * @base: Base address, used to check ping return value + * @priv: Pointer to private test information + * @return 0 if OK, -ve on error + */ +int dm_check_operations(struct dm_test_state *dms, struct device *dev, + uint32_t base, struct dm_test_priv *priv); + +/** + * dm_test_main() - Run all the tests + * + * This runs all available driver model tests + * + * @return 0 if OK, -ve on error + */ +int dm_test_main(void); + +#endif diff --git a/include/dm/ut.h b/include/dm/ut.h new file mode 100644 index 0000000..fa9eac0 --- /dev/null +++ b/include/dm/ut.h @@ -0,0 +1,95 @@ +/* + * Simple unit test library for driver model + * + * Copyright (c) 2013 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __DM_UT_H +#define __DM_UT_H + +struct dm_test_state; + +/** + * ut_fail() - Record failure of a unit test + * + * @dms: Test state + * @fname: Filename where the error occured + * @line: Line number where the error occured + * @func: Function name where the error occured + * @cond: The condition that failed + */ +void ut_fail(struct dm_test_state *dms, const char *fname, int line, + const char *func, const char *cond); + +/** + * ut_failf() - Record failure of a unit test + * + * @dms: Test state + * @fname: Filename where the error occured + * @line: Line number where the error occured + * @func: Function name where the error occured + * @cond: The condition that failed + * @fmt: printf() format string for the error, followed by args + */ +void ut_failf(struct dm_test_state *dms, const char *fname, int line, + const char *func, const char *cond, const char *fmt, ...) + __attribute__ ((format (__printf__, 6, 7))); + + +/* Assert that a condition is non-zero */ +#define ut_assert(cond) \ + if (!(cond)) { \ + ut_fail(dms, __FILE__, __LINE__, __func__, #cond); \ + return -1; \ + } + +/* Assert that a condition is non-zero, with printf() string */ +#define ut_assertf(cond, fmt, args...) \ + if (!(cond)) { \ + ut_failf(dms, __FILE__, __LINE__, __func__, #cond, \ + fmt, ##args); \ + return -1; \ + } + +/* Assert that two int expressions are equal */ +#define ut_asserteq(expr1, expr2) { \ + unsigned int val1 = (expr1), val2 = (expr2); \ + \ + if (val1 != val2) { \ + ut_failf(dms, __FILE__, __LINE__, __func__, \ + #expr1 " == " #expr2, \ + "Expected %d, got %d", val1, val2); \ + return -1; \ + } \ +} + +/* Assert that two string expressions are equal */ +#define ut_asserteq_str(expr1, expr2) { \ + const char *val1 = (expr1), *val2 = (expr2); \ + \ + if (strcmp(val1, val2)) { \ + ut_failf(dms, __FILE__, __LINE__, __func__, \ + #expr1 " = " #expr2, \ + "Expected \"%s\", got \"%s\"", val1, val2); \ + return -1; \ + } \ +} + +/* Assert that two pointers are equal */ +#define ut_asserteq_ptr(expr1, expr2) { \ + const void *val1 = (expr1), *val2 = (expr2); \ + \ + if (val1 != val2) { \ + ut_failf(dms, __FILE__, __LINE__, __func__, \ + #expr1 " = " #expr2, \ + "Expected %p, got %p", val1, val2); \ + return -1; \ + } \ +} + +/* Assert that an operation succeeds (returns 0) */ +#define ut_assertok(cond) ut_asserteq(0, cond) + +#endif -- cgit v1.1