1
0
Fork 0
mirror of https://github.com/linux-usb-gadgets/libusbgx.git synced 2025-07-23 17:15:07 +03:00
libusbgx/tests/test.c
Pawel Szewczyk d17722045a libusbgx: tests: Add config attributes getting and setting test
Change-Id: I86e5263e11f3794aa1b999f02778dbf6ce32e572
Signed-off-by: Pawel Szewczyk <p.szewczyk@samsung.com>
[Update description]
Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
2015-12-22 21:45:35 +01:00

2286 lines
54 KiB
C

#include <usbg/usbg.h>
#include <stdio.h>
#include <stdarg.h>
#include <setjmp.h>
#include <cmocka.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <getopt.h>
#include <time.h>
#ifdef HAS_LIBCONFIG
#include <libconfig.h>
#endif
#include "usbg-test.h"
/**
* @file tests/test.c
*/
#define USBG_TEST(name, test, setup, teardown) \
{"setup "#test, setup, UNIT_TEST_FUNCTION_TYPE_SETUP}, \
{name, test, UNIT_TEST_FUNCTION_TYPE_TEST}, \
{"teardown "#test, teardown, UNIT_TEST_FUNCTION_TYPE_TEARDOWN}
#define FILLED_STR(len, c) \
{ [0 ... len - 2] = c, [len - 1] = '\0' }
static usbg_gadget_attrs min_gadget_attrs = {
.bcdUSB = 0x0000,
.bDeviceClass = 0x0,
.bDeviceSubClass = 0x0,
.bDeviceProtocol = 0x0,
.bMaxPacketSize0 = 0x0,
.idVendor = 0x0000,
.idProduct = 0x0000,
.bcdDevice = 0x0000
};
static usbg_gadget_attrs max_gadget_attrs = {
.bcdUSB = 0xffff,
.bDeviceClass = 0xff,
.bDeviceSubClass = 0xff,
.bDeviceProtocol = 0xff,
.bMaxPacketSize0 = 0xff,
.idVendor = 0xffff,
.idProduct = 0xffff,
.bcdDevice = 0xffff
};
/* PATH_MAX is limit for path length */
#define LONG_PATH_LEN PATH_MAX/2
static char long_path_str[] = FILLED_STR(LONG_PATH_LEN, 'x');
/* NAME_MAX is limit for filename length */
static char long_usbg_string[] = FILLED_STR(NAME_MAX, 'x');
static usbg_config_strs simple_config_strs= {
.configuration = "configuration string"
};
static usbg_config_attrs max_config_attrs = {
.bmAttributes = 0xff,
.bMaxPower = 0xff
};
static usbg_config_attrs min_config_attrs = {
.bmAttributes = 0x00,
.bMaxPower = 0x00
};
/**
* @brief Simplest udcs names
* @details Used to go through init when testing other things
*/
static char *simple_udcs[] = {
"UDC1",
"UDC2",
NULL
};
static char *long_udcs[] = {
long_usbg_string,
"UDC1",
NULL
};
/**
* @brief Simplest functions names
* @details Used to go through init when testing other things
*/
static struct test_function simple_funcs[] = {
{
.type = F_ECM,
.instance = "0"
}, {
.type = F_ACM,
.instance = "0"
},
TEST_FUNCTION_LIST_END
};
/**
* @brief All functions types
* @details When testing with this in state, check if all func types are
* processed correctly
*/
static struct test_function all_funcs[] = {
{
.type = F_SERIAL,
.instance = "serial_instance0"
}, {
.type = F_ACM,
.instance = "acm_instance0"
}, {
.type = F_OBEX,
.instance = "obex_instance0"
}, {
.type = F_ECM,
.instance = "ecm_instance0"
}, {
.type = F_SUBSET,
.instance = "subset_instance0"
}, {
.type = F_NCM,
.instance = "ncm_instance0"
}, {
.type = F_EEM,
.instance = "eem_instance0"
}, {
.type = F_RNDIS,
.instance = "rndis_instance0"
}, {
.type = F_PHONET,
.instance = "phonet_instance0"
}, {
.type = F_FFS,
.instance = "ffs_instance0"
},
TEST_FUNCTION_LIST_END
};
static struct test_function same_type_funcs[] = {
{
.type = F_SERIAL,
.instance = "0"
}, {
.type = F_SERIAL,
.instance = "1"
}, {
.type = F_SERIAL,
.instance = "2"
},
TEST_FUNCTION_LIST_END
};
/**
* @brief No functions at all
* @details Check if gadget with no functions (or config with no bindings)
* is processed correctly.
*/
static struct test_function no_funcs[] = {
TEST_FUNCTION_LIST_END
};
/**
* @brief Simple configs
* @details Used to pass through init when testing other things
*/
static struct test_config simple_confs[] = {
{
.label = "c",
.id = 1,
.bound_funcs = simple_funcs
},
TEST_CONFIG_LIST_END
};
/**
* @brief Configs bound to all avaible function types
*/
static struct test_config all_bindings_confs[] = {
{
.label = "c",
.id = 2,
.bound_funcs = no_funcs
}, {
.label = "c",
.id = 4,
.bound_funcs = all_funcs
},
TEST_CONFIG_LIST_END
};
/**
* @brief Simplest gadget
*/
static struct test_gadget simple_gadgets[] = {
{
.name = "g1",
.udc = "UDC1",
.configs = simple_confs,
.functions = simple_funcs
},
TEST_GADGET_LIST_END
};
/**
* @brief Gadgets with all avaible functions
*/
static struct test_gadget all_funcs_gadgets[] = {
{
.name = "all_funcs_gadget1",
.udc = "UDC1",
.configs = all_bindings_confs,
.functions = all_funcs
},
TEST_GADGET_LIST_END
};
static struct test_gadget long_udc_gadgets[] = {
{
.name = "long_udc_gadgets",
.udc = long_usbg_string,
.configs = simple_confs,
.functions = simple_funcs
},
TEST_GADGET_LIST_END
};
struct test_data {
struct test_state *state;
struct usbg_state *usbg_state;
};
struct test_gadget_strs_data {
struct test_state *state;
usbg_gadget_strs *strs;
};
/**
* @brief Simple state
*/
static struct test_state simple_state = {
.configfs_path = "config",
.gadgets = simple_gadgets,
.udcs = simple_udcs
};
/**
* @brief State with all functions avaible
*/
static struct test_state all_funcs_state = {
.configfs_path = "all_funcs_configfs",
.gadgets = all_funcs_gadgets,
.udcs = simple_udcs
};
static struct test_state long_path_state = {
.configfs_path = long_path_str,
.gadgets = simple_gadgets,
.udcs = simple_udcs
};
static struct test_state long_udc_state = {
.configfs_path = "simple_path",
.gadgets = long_udc_gadgets,
.udcs = long_udcs
};
static usbg_config_attrs *get_random_config_attrs()
{
usbg_config_attrs *ret;
ret = malloc(sizeof(*ret));
if (ret == NULL)
fail();
free_later(ret);
srand(time(NULL));
ret->bmAttributes = rand() % max_config_attrs.bmAttributes;
ret->bMaxPower = rand() % max_config_attrs.bMaxPower;
return ret;
}
static usbg_gadget_attrs *get_random_gadget_attrs()
{
usbg_gadget_attrs *ret;
ret = malloc(sizeof(*ret));
if (ret == NULL)
fail();
free_later(ret);
srand(time(NULL));
ret->bcdUSB = rand() % max_gadget_attrs.bcdUSB;
ret->bDeviceClass = rand() % max_gadget_attrs.bDeviceClass;
ret->bDeviceSubClass = rand() % max_gadget_attrs.bDeviceSubClass;
ret->bDeviceProtocol = rand() % max_gadget_attrs.bDeviceProtocol;
ret->bMaxPacketSize0 = rand() % max_gadget_attrs.bMaxPacketSize0;
ret->idVendor = rand() % max_gadget_attrs.idVendor;
ret->idProduct = rand() % max_gadget_attrs.idProduct;
ret->bcdDevice = rand() % max_gadget_attrs.bcdDevice;
return ret;
}
/**
* @brief Add given attributes to all configs in state
* @return Prepared state where configs has given attributes
*/
static void *prepare_state_with_config_attrs(struct test_state *state,
usbg_config_attrs *attrs)
{
struct test_gadget *tg;
struct test_config *tc;
for (tg = state->gadgets; tg->name; ++tg)
for (tc = tg->configs; tc->label; ++tc)
tc->attrs = attrs;
state = prepare_state(state);
return state;
}
static void setup_max_config_attrs_state(void **state)
{
*state = prepare_state_with_config_attrs(&simple_state, &max_config_attrs);
}
static void setup_min_config_attrs_state(void **state)
{
*state = prepare_state_with_config_attrs(&simple_state, &min_config_attrs);
}
static void setup_random_config_attrs_state(void **state)
{
*state = prepare_state_with_config_attrs(&simple_state, get_random_config_attrs());
}
static void setup_simple_config_strs_state(void **state)
{
struct test_gadget *tg;
struct test_config *tc;
for (tg = simple_state.gadgets; tg->name; ++tg)
for (tc = tg->configs; tc->label; ++tc)
tc->strs = &simple_config_strs;
*state = prepare_state(&simple_state);
}
/**
* @brief Prepare test_state with one gadget containing given function list
* @details For testing only functions. We put them in a gadget as simply
* as possible.
* @param[in] func Pointer to list of functions
* @return Pointer to test state with given functions
*/
static struct test_state *put_func_in_state(struct test_function *func)
{
struct test_state *st;
struct test_gadget *g;
struct test_config *c;
char **udcs;
st = calloc(1, sizeof(*st));
if (st == NULL)
fail();
free_later(st);
/* Do not need config */
c = calloc(1, sizeof(*c));
if (c == NULL)
fail();
free_later(c);
g = calloc(2, sizeof(*g));
if (g == NULL)
fail();
free_later(g);
udcs = calloc(2, sizeof(*udcs));
if (udcs == NULL)
fail();
free_later(udcs);
g[0].name = "g1";
g[0].udc = "UDC1";
g[0].configs = c;
g[0].functions = func;
g[0].writable = 1;
udcs[0] = "UDC1";
g[0].writable = 1;
st->configfs_path = "config";
st->gadgets = g;
st->udcs = udcs;
st->writable = 1;
st = prepare_state(st);
return st;
}
/**
* @brief Setup simple state with some gadgets, configs and functions
*/
static void setup_simple_state(void **state)
{
*state = prepare_state(&simple_state);
}
/**
* @brief Setup state with all avaible functions
*/
static void setup_all_funcs_state(void **state)
{
*state = prepare_state(&all_funcs_state);
}
/**
* @brief Setup state with few functions of the same type
*/
static void setup_same_type_funcs_state(void **state)
{
*state = put_func_in_state(same_type_funcs);
}
/**
* @brief Setup state with very long path name
*/
static void setup_long_path_state(void **state)
{
*state = prepare_state(&long_path_state);
}
/**
* @brief Setup state with long udc name
*/
static void setup_long_udc_state(void **state)
{
*state = prepare_state(&long_udc_state);
}
/**
* @brief Setup state with gadget strings of random length
* @param[out] state Pointer to pointer to test_gadget_strs_data structure
* with initialized state and strings
*/
static void setup_random_len_gadget_strs_data(void **state)
{
usbg_gadget_strs *strs;
struct test_gadget_strs_data *data;
/* will fill memory with zeros */
strs = calloc(1, sizeof(*strs));
if (strs == NULL)
fail();
free_later(strs);
data = malloc(sizeof(*data));
if (data == NULL)
fail();
free_later(data);
srand(time(NULL));
memset(strs->str_ser, 'x', rand() % USBG_MAX_STR_LENGTH);
memset(strs->str_mnf, 'x', rand() % USBG_MAX_STR_LENGTH);
memset(strs->str_prd, 'x', rand() % USBG_MAX_STR_LENGTH);
data->strs = strs;
data->state = prepare_state(&simple_state);
*state = data;
}
/**
* @brief Tests usbg_get_gadget function with given state
* @details Check if gadgets are returned correctly
*/
static void test_get_gadget(void **state)
{
usbg_gadget *g = NULL;
usbg_state *s = NULL;
struct test_state *st;
int i = 0;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
for (i = 0; st->gadgets[i].name; i++) {
g = usbg_get_gadget(s, st->gadgets[i].name);
assert_non_null(g);
assert_gadget_equal(g, &st->gadgets[i]);
}
}
/**
* @brief Tests usbg_get_gadget with non-existing gadget name
* @details Check if get_gadget will not find non-existing gadgets and
* will not cause crash.
*/
static void test_get_gadget_fail(void **state)
{
usbg_gadget *g = NULL;
usbg_state *s = NULL;
struct test_state *st;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
g = usbg_get_gadget(s, "non-existing-gadget");
assert_null(g);
}
/**
* @brief Tests usbg_get_first_gadget function
* @details Check if gadget returned by get_first_gadget is actually first one
*/
static void test_get_first_gadget(void **state)
{
usbg_gadget *g = NULL;
usbg_state *s = NULL;
struct test_state *st;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
g = usbg_get_first_gadget(s);
assert_non_null(g);
assert_gadget_equal(g, &st->gadgets[0]);
}
/**
* @brief Tests get_first_gadget with invalid arguments
*/
static void test_get_first_gadget_fail(void **state)
{
usbg_gadget *g;
g = usbg_get_first_gadget(NULL);
assert_null(g);
}
/**
* @brief Tests getting name of gadget
* @details Check if gadget name is returned correctly
*/
static void test_get_gadget_name(void **state)
{
usbg_gadget *g = NULL;
usbg_state *s = NULL;
struct test_state *st;
int i = 0;
const char *name;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
for (i = 0; st->gadgets[i].name; i++) {
g = usbg_get_gadget(s, st->gadgets[i].name);
assert_non_null(g);
name = usbg_get_gadget_name(g);
assert_string_equal(name, st->gadgets[i].name);
}
}
/**
* @brief Tests getting name length of gadget
* @details Check if returned name length is equal original
*/
static void test_get_gadget_name_len(void **state)
{
usbg_gadget *g = NULL;
usbg_state *s = NULL;
struct test_state *st;
int i = 0;
int len;
int expected;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
for (i = 0; st->gadgets[i].name; i++) {
g = usbg_get_gadget(s, st->gadgets[i].name);
assert_non_null(g);
expected = strlen(st->gadgets[i].name);
len = usbg_get_gadget_name_len(g);
assert_int_equal(len, expected);
}
}
/**
* @brief Tests getting name of gadget with invalid arguments
* @details Check if trying to get name of wrong (non-existing) gadget
* will not cause crash, but return NULL as expected.
*/
static void test_get_gadget_name_fail(void **state)
{
const char *name;
name = usbg_get_gadget_name(NULL);
assert_null(name);
}
/**
* @brief Tests copying gadget's name
* @details Check if copying gadget name copy actual name correctly
*/
static void test_cpy_gadget_name(void **state)
{
usbg_gadget *g = NULL;
usbg_state *s = NULL;
struct test_state *st;
int i = 0;
char name[USBG_MAX_NAME_LENGTH];
int ret;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
for (i = 0; st->gadgets[i].name; i++) {
g = usbg_get_gadget(s, st->gadgets[i].name);
assert_non_null(g);
ret = usbg_cpy_gadget_name(g, name, USBG_MAX_NAME_LENGTH);
assert_int_equal(ret, USBG_SUCCESS);
assert_string_equal(name, st->gadgets[i].name);
}
}
/**
* @brief Test copying gadet name with invalid arguments
* @details Check if trying to copy gadget name into non-existing buffer,
* or give invalid buffer length, or invalid gadget will be handled by library
* and return correct error codes
*/
static void test_cpy_gadget_name_fail(void **state)
{
usbg_gadget *g = NULL;
usbg_state *s = NULL;
struct test_state *st;
int i = 0;
char name[USBG_MAX_NAME_LENGTH];
int ret;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
for (i = 0; st->gadgets[i].name; i++) {
g = usbg_get_gadget(s, st->gadgets[i].name);
assert_non_null(g);
ret = usbg_cpy_gadget_name(g, name, 0);
assert_int_equal(ret, USBG_ERROR_INVALID_PARAM);
ret = usbg_cpy_gadget_name(g, NULL, USBG_MAX_NAME_LENGTH);
assert_int_equal(ret, USBG_ERROR_INVALID_PARAM);
}
ret = usbg_cpy_gadget_name(NULL, name, USBG_MAX_NAME_LENGTH);
assert_int_equal(ret, USBG_ERROR_INVALID_PARAM);
}
/**
* @brief Tests init by comparing test state and usbg state
* @details Check if usbg state after init match given state and
* if init returned success code
*/
static void test_init(void **state)
{
usbg_state *s = NULL;
struct test_state *st;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
assert_state_equal(s, st);
}
/**
* @brief Test getting function by name
* @param[in] state Pointer to pointer to correctly initialized test_state structure
*/
static void test_get_function(void **state)
{
for_each_test_function(state, assert_func_equal);
}
/**
* @brief Tests usbg_get_function with some non-existing functions
* @details Check if get function will return NULL, when invalid
* functions names and types are passed as arguments and will not cause crash.
* @param[in] state Pointer to pointer to correctly initialized test_state structure
*/
static void test_get_function_fail(void **state)
{
usbg_state *s = NULL;
usbg_gadget *g = NULL;
usbg_function *f = NULL;
struct test_state *st;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
g = usbg_get_first_gadget(s);
assert_non_null(g);
f = usbg_get_function(g, F_ACM, "non-existing-instance");
assert_null(f);
f = usbg_get_function(g, 9001, "0");
assert_null(f);
}
/**
* @brief Tests function type translation to string
* @param[in] state Pointer to pointer to correctly initialized test_state structure
* @details Check if get_function_type_str returns proper strings for all types.
*/
static void test_get_function_type_str(void **state)
{
struct {
usbg_function_type type;
const char *str;
} types[] = {
{F_SERIAL, "gser"},
{F_ACM, "acm"},
{F_OBEX, "obex"},
{F_ECM, "ecm"},
{F_SUBSET, "geth"},
{F_NCM, "ncm"},
{F_EEM, "eem"},
{F_RNDIS, "rndis"},
{F_PHONET, "phonet"},
{F_FFS, "ffs"}
};
const char *str;
int i;
for (i = 0; i < ARRAY_SIZE(types); i++) {
str = usbg_get_function_type_str(types[i].type);
assert_non_null(str);
assert_string_equal(str, types[i].str);
}
}
/**
* @brief Tests function type translation to string with unknown funcs
* @param[in] state Not used parameter
* @details Check if get_function_type_str returns NULL, when given
* function type is unknown.
*/
static void test_get_function_type_str_fail(void **state)
{
const char *str;
str = usbg_get_function_type_str(-1);
assert_null(str);
}
/**
* @brief Get instance of given function and check it
* @param[in] f Usbg function
* @param[in] tf Test function which should match f
*/
static void try_get_function_instance(usbg_function *f, struct test_function *tf)
{
const char *str;
str = usbg_get_function_instance(f);
assert_string_equal(str, tf->instance);
}
/**
* @brief Tests getting function instance from usbg_function structure
* @param[in] state Pointer to pointer to correctly initialized test_state structure
* @details Check if returned instance name is correct.
*/
static void test_get_function_instance(void **state)
{
for_each_test_function(state, try_get_function_instance);
}
/**
* @brief Cpy instance of given usbg function and check it
* @param[in] f Usbg function
* @param[in] tf Test function which should match f
*/
static void try_cpy_function_instance(usbg_function *f, struct test_function *tf)
{
char str[USBG_MAX_NAME_LENGTH];
int ret;
int small_len = 2;
ret = usbg_cpy_function_instance(f, str, USBG_MAX_NAME_LENGTH);
assert_int_equal(ret, USBG_SUCCESS);
assert_string_equal(str, tf->instance);
ret = usbg_cpy_function_instance(f, str, small_len);
assert_int_equal(ret, USBG_SUCCESS);
assert_memory_equal(str, tf->instance, small_len - 1);
assert_int_equal(str[small_len - 1], '\0');
}
/**
* @brief Tests copying function instance from usbg_function structure into buffer
* @param[in] state Pointer to pointer to correctly initialized state
* @details Check if buffer contains expected string
*/
static void test_cpy_function_instance(void **state)
{
for_each_test_function(state, try_cpy_function_instance);
}
/**
* @brief Get function type and check it
* @param[in] f Usbg function
* @param[in] tf Test function which should match f by type
*/
static void try_get_function_type(usbg_function *f, struct test_function *tf)
{
usbg_function_type type;
type = usbg_get_function_type(f);
assert_int_equal(type, tf->type);
}
/**
* @brief Tests getting function type
* @details Check if getting function type returns what was expected.
* State must be proper (init must end with success).
* @param[in] state Pointer to pointer to correctly initialized state
*/
static void test_get_function_type(void **state)
{
for_each_test_function(state, try_get_function_type);
}
/**
* @brief Check if function instance length is correct
* @param[in] f Usbg function
* @param[in] tf Test function which should match f
*/
static void try_get_function_instance_len(usbg_function *f, struct test_function *tf)
{
size_t len;
len = usbg_get_function_instance_len(f);
assert_int_equal(len, strlen(tf->instance));
}
/**
* @brief Tests getting length of function instance name
* @details Check if returned instance name length matches
* actual length of instance name
* @param[in] state Pointer to pointer to correctly initialized state
*/
static void test_get_function_instance_len(void **state)
{
for_each_test_function(state, try_get_function_instance_len);
}
/**
* @brief Tests getting configfs path from usbg state
* @param[in,out] state Pointer to pointer to correctly initialized test state.
* When finished, it contains pointer to usbg_state which should be cleaned.
*/
static void test_get_configfs_path(void **state)
{
usbg_state *s = NULL;
struct test_state *st;
const char *path;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
path = usbg_get_configfs_path(s);
assert_path_equal(path, st->configfs_path);
}
/**
* @brief Tests getting configfs path length from usbg state
* @param[in,out] state Pointer to pointer to correctly initialized test state.
* When finished, it contains pointer to usbg_state which should be cleaned.
*/
static void test_get_configfs_path_len(void **state)
{
usbg_state *s = NULL;
struct test_state *st;
int ret, len;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
ret = usbg_get_configfs_path_len(s);
len = strlen(st->configfs_path);
assert_int_equal(ret, len);
}
/**
* @brief Tests copying configfs path into buffer
* @param[in,out] state Pointer to pointer to correctly initialized test state.
* When finished, it contains pointer to usbg_state which should be cleaned.
*/
static void test_cpy_configfs_path(void **state)
{
usbg_state *s = NULL;
struct test_state *st;
char path[PATH_MAX];
int ret;
st = (struct test_state *)(*state);
*state = NULL;
init_with_state(st, &s);
*state = s;
ret = usbg_cpy_configfs_path(s, path, PATH_MAX);
assert_int_equal(ret, USBG_SUCCESS);
assert_path_equal(path, st->configfs_path);
}
/**
* @brief Tests getting config by name
* @param[in,out] state Pointer to pointer to correctly initialized test state.
* When finished, it contains pointer to usbg_state which should be cleaned.
*/
static void test_get_config(void **state)
{
for_each_test_config(state, assert_config_equal);
}
static void test_get_config_without_label(void **state)
{
usbg_state *s = NULL;
usbg_gadget *g = NULL;
usbg_config *c = NULL;
struct test_state *ts;
struct test_gadget *tg;
struct test_config *tc;
ts = (struct test_state *)(*state);
*state = NULL;
init_with_state(ts, &s);
*state = s;
for (tg = ts->gadgets; tg->name; tg++) {
g = usbg_get_gadget(s, tg->name);
assert_non_null(g);
for (tc = tg->configs; tc->label; tc++) {
c = usbg_get_config(g, tc->id, NULL);
assert_non_null(c);
assert_config_equal(c, tc);
}
}
}
/**
* @bried Tests getting non-existing config
* @param[in,out] state Pointer to pointer to correctly initialized test state.
* When finished, it contains pointer to usbg_state which should be cleaned.
*/
static void test_get_config_fail(void **state)
{
usbg_state *s = NULL;
usbg_gadget *g = NULL;
usbg_config *c = NULL;
struct test_state *ts;
struct test_gadget *tg;
ts = (struct test_state *)(*state);
*state = NULL;
init_with_state(ts, &s);
*state = s;
for (tg = ts->gadgets; tg->name; tg++) {
g = usbg_get_gadget(s, tg->name);
assert_non_null(g);
c = usbg_get_config(g, 0, "non-existing-config");
assert_null(c);
c = usbg_get_config(g, -9001, "c");
assert_null(c);
c = usbg_get_config(g, -9001, NULL);
assert_null(c);
}
}
/**
* @brief Get config label and check it
* @param[in] c Usbg config
* @param[in] tc Test config which should match c
*/
static void try_get_config_label(usbg_config *c, struct test_config *tc)
{
const char *label;
label = usbg_get_config_label(c);
assert_string_equal(label, tc->label);
}
/**
* @brief Tests getting config label
* @param[in,out] state Pointer to pointer to correctly initialized test state.
* When finished, it contains pointer to usbg_state which should be cleaned.
*/
static void test_get_config_label(void **state)
{
for_each_test_config(state, try_get_config_label);
}
/**
* @brief Check config id with test structure
* @param[in] c Usbg config
* @param[in] tc Test config which should match c
*/
static void try_get_config_id(usbg_config *c, struct test_config *tc)
{
int id;
id = usbg_get_config_id(c);
assert_int_equal(id, tc->id);
}
/**
* @brief Tests getting config id
* @param[in,out] state Pointer to pointer to correctly initialized test state.
* When finished, it contains pointer to usbg_state which should be cleaned.
*/
static void test_get_config_id(void **state)
{
for_each_test_config(state, try_get_config_id);
}
/**
* @brief Test getting given attributes from gadgets present in state
* @param[in] s Pointer to usbg state
* @param[in] ts Pointer to test state matching given usbg state
* @param[in] attrs Pointer to gadget attributes which should be put in
* virtual filesystem for writting by usbg
*/
static void try_get_gadget_attrs(usbg_state *s, struct test_state *ts,
usbg_gadget_attrs *attrs)
{
usbg_gadget *g = NULL;
usbg_gadget_attrs actual;
struct test_gadget *tg;
int ret;
for (tg = ts->gadgets; tg->name; tg++) {
g = usbg_get_gadget(s, tg->name);
assert_non_null(g);
push_gadget_attrs(tg, attrs);
ret = usbg_get_gadget_attrs(g, &actual);
assert_int_equal(ret, 0);
assert_gadget_attrs_equal(&actual, attrs);
}
}
/**
* @brief Tests getting gadget attributes
* @param[in] state Pointer to correctly initialized test_state structure
**/
static void test_get_gadget_attrs(void **state)
{
usbg_state *s = NULL;
struct test_state *ts;
ts = (struct test_state *)(*state);
*state = NULL;
init_with_state(ts, &s);
*state = s;
try_get_gadget_attrs(s, ts, &min_gadget_attrs);
try_get_gadget_attrs(s, ts, &max_gadget_attrs);
try_get_gadget_attrs(s, ts, get_random_gadget_attrs());
}
/**
* @brief Test setting given attributes on gadgets present in state
* @param[in] s Pointer to usbg state
* @param[in] ts Pointer to test state matching given usbg state
* @param[in] attrs Pointer to gadget attributes to be set
*/
static void try_set_gadget_attrs(usbg_state *s, struct test_state *ts,
usbg_gadget_attrs *attrs)
{
usbg_gadget *g = NULL;
struct test_gadget *tg;
int ret;
for (tg = ts->gadgets; tg->name; tg++) {
g = usbg_get_gadget(s, tg->name);
assert_non_null(g);
pull_gadget_attrs(tg, attrs);
ret = usbg_set_gadget_attrs(g, attrs);
assert_int_equal(ret, 0);
}
}
/**
* @brief Tests setting gadget attributes
* @param[in] state Pointer to correctly initialized test_state structure
**/
static void test_set_gadget_attrs(void **state)
{
usbg_state *s = NULL;
struct test_state *ts;
ts = (struct test_state *)(*state);
*state = NULL;
init_with_state(ts, &s);
*state = s;
try_set_gadget_attrs(s, ts, &min_gadget_attrs);
try_set_gadget_attrs(s, ts, &max_gadget_attrs);
try_set_gadget_attrs(s, ts, get_random_gadget_attrs());
}
/**
* @brief Test setting given attributes on gadgets present in state one by one,
* using functions specific for each attribute
* @param[in] s Pointer to usbg state
* @param[in] ts Pointer to test state matching given usbg state
* @param[in] attrs Pointer to gadget attributes to be set
*/
static void try_set_specific_gadget_attr(usbg_state *s, struct test_state *ts,
usbg_gadget_attrs *attrs)
{
usbg_gadget *g = NULL;
struct test_gadget *tg;
int ret;
int i;
int attr;
for (tg = ts->gadgets; tg->name; tg++) {
g = usbg_get_gadget(s, tg->name);
assert_non_null(g);
for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; i++) {
attr = get_gadget_attr(attrs, i);
pull_gadget_attribute(tg, i, attr);
usbg_set_gadget_attr(g, i, attr);
assert_int_equal(ret, 0);
}
}
}
/**
* @brief Tests setting gadget attributes one by one
* @param[in] state Pointer to correctly initialized test_state structure
**/
static void test_set_specific_gadget_attr(void **state)
{
usbg_state *s = NULL;
struct test_state *ts;
ts = (struct test_state *)(*state);
*state = NULL;
init_with_state(ts, &s);
*state = s;
try_set_specific_gadget_attr(s, ts, &min_gadget_attrs);
try_set_specific_gadget_attr(s, ts, &max_gadget_attrs);
try_set_specific_gadget_attr(s, ts, get_random_gadget_attrs());
}
/**
* @brief Tests getting udc from state
* @param[in] state Pointer to correctly initialized test_state structure
**/
void test_get_udc(void **state)
{
struct test_state *ts;
char **tu;
struct test_gadget *tg;
usbg_state *s = NULL;
usbg_udc *u = NULL;
usbg_gadget *g = NULL;
ts = (struct test_state *)(*state);
*state = NULL;
init_with_state(ts, &s);
*state = s;
for (tu = ts->udcs; *tu; tu++) {
u = usbg_get_udc(s, *tu);
assert_non_null(u);
assert_string_equal(*tu, u->name);
assert_int_equal(s, u->parent);
}
for (tg = ts->gadgets; tg->name; tg++) {
u = usbg_get_udc(s, tg->udc);
g = usbg_get_gadget(s, tg->name);
assert_int_equal(u->gadget, g);
}
}
static void test_get_gadget_attr_str(void **state)
{
struct {
usbg_gadget_attr attr;
const char *str;
} attrs[] = {
{BCD_USB, "bcdUSB"},
{B_DEVICE_CLASS, "bDeviceClass"},
{B_DEVICE_SUB_CLASS, "bDeviceSubClass"},
{B_DEVICE_PROTOCOL, "bDeviceProtocol"},
{B_MAX_PACKET_SIZE_0, "bMaxPacketSize0"},
{ID_VENDOR, "idVendor"},
{ID_PRODUCT, "idProduct"},
{BCD_DEVICE, "bcdDevice"},
};
const char *str;
int i, j;
for (i = 0; i < ARRAY_SIZE(attrs); i++) {
str = usbg_get_gadget_attr_str(attrs[i].attr);
assert_non_null(str);
assert_string_equal(str, attrs[i].str);
}
/* Check if iteration over values works */
for (i = USBG_GADGET_ATTR_MIN; i < USBG_GADGET_ATTR_MAX; ++i) {
str = usbg_get_gadget_attr_str(i);
assert_non_null(str);
for (j = 0; j < ARRAY_SIZE(attrs); ++j)
if (attrs[j].attr == i) {
assert_string_equal(str, attrs[j].str);
break;
}
assert_int_not_equal(j, ARRAY_SIZE(attrs));
}
}
static void test_get_gadget_attr_str_fail(void **state)
{
const char *str;
str = usbg_get_gadget_attr_str(USBG_GADGET_ATTR_MIN - 1);
assert_null(str);
str = usbg_get_gadget_attr_str(USBG_GADGET_ATTR_MAX);
assert_null(str);
}
/**
* @brief set gadget strings
* @details Also do it one by one
* @param[in] data Pointer to correctly initialized test_gadget_strs_data structure
*/
static void test_set_gadget_strs(void **data)
{
struct test_gadget_strs_data *ts;
struct test_gadget *tg;
usbg_state *s = NULL;
usbg_gadget *g = NULL;
int i;
int ret;
ts = (struct test_gadget_strs_data *)(*data);
*data = NULL;
init_with_state(ts->state, &s);
*data = s;
for (tg = ts->state->gadgets; tg->name; tg++) {
g = usbg_get_gadget(s, tg->name);
pull_gadget_strs(tg, LANG_US_ENG, ts->strs);
ret = usbg_set_gadget_strs(g, LANG_US_ENG, ts->strs);
assert_int_equal(ret, 0);
for (i = 0; i < GADGET_STR_MAX; i++)
pull_gadget_string(tg, LANG_US_ENG, i, get_gadget_str(ts->strs, i));
ret = usbg_set_gadget_serial_number(g, LANG_US_ENG, ts->strs->str_ser);
assert_int_equal(ret, 0);
ret = usbg_set_gadget_manufacturer(g, LANG_US_ENG, ts->strs->str_mnf);
assert_int_equal(ret, 0);
ret = usbg_set_gadget_product(g, LANG_US_ENG, ts->strs->str_prd);
assert_int_equal(ret, 0);
}
}
/**
* @brief get gadget strings
* @param[in] data Pointer to correctly initialized test_gadget_strs_data structure
*/
static void test_get_gadget_strs(void **data)
{
struct test_gadget_strs_data *ts;
struct test_gadget *tg;
usbg_state *s = NULL;
usbg_gadget *g = NULL;
usbg_gadget_strs strs;
ts = (struct test_gadget_strs_data *)(*data);
*data = NULL;
init_with_state(ts->state, &s);
*data = s;
for (tg = ts->state->gadgets; tg->name; tg++) {
g = usbg_get_gadget(s, tg->name);
push_gadget_strs(tg, LANG_US_ENG, ts->strs);
usbg_get_gadget_strs(g, LANG_US_ENG, &strs);
assert_gadget_strs_equal(&strs, ts->strs);
}
}
/**
* @brief Get binding target
* @details Check if given function is target of given binding
* @param[in] tb Test function
* @param[in] b Binding
*/
static void try_get_binding_target(struct test_binding *tb, usbg_binding *b)
{
usbg_function *f;
f = usbg_get_binding_target(b);
assert_non_null(f);
assert_func_equal(f, tb->target);
}
/**
* @brief Test get binding target
* @details Test all bindings present in given state
* @param[in, out] state Pointer to pointer to correctly initialized test state,
* will point to usbg state when finished.
*/
static void test_get_binding_target(void **state)
{
for_each_binding(state, try_get_binding_target);
}
/**
* @brief Get binding name
* @details Check if name of given binding is equal name of given function
* @param[in] tb Test function
* @param[in] b Binding
*/
static void try_get_binding_name(struct test_binding *tb, usbg_binding *b)
{
const char *s;
s = usbg_get_binding_name(b);
assert_non_null(s);
assert_string_equal(s, tb->name);
}
/**
* @brief Test get bindig name from all binding present in state
* @param[in, out] state Pointer to pointer to correctly initialized test state,
* will point to usbg state when finished.
*/
static void test_get_binding_name(void **state)
{
for_each_binding(state, try_get_binding_name);
}
/**
* @brief Get binding name length
* @param[in] tb Test function
* @param[in] b Binding
*/
static void try_get_binding_name_len(struct test_binding *tb, usbg_binding *b)
{
int n;
n = usbg_get_binding_name_len(b);
assert_int_equal(n, strlen(tb->name));
}
/**
* @brief Test get binding name length from all bindings present in state
* @param[in, out] state Pointer to pointer to correctly initialized test state,
* will point to usbg state when finished.
*/
static void test_get_binding_name_len(void **state)
{
for_each_binding(state, try_get_binding_name_len);
}
/**
* @brief Set config strings
* @param[in] c Config on which string should be set
* @param[in] tc Test config containing strings to be set
*/
static void try_set_config_strs(usbg_config *c, struct test_config *tc)
{
pull_config_strs(tc, LANG_US_ENG, tc->strs);
usbg_set_config_strs(c, LANG_US_ENG, tc->strs);
}
/**
* @brief Test setting strings
* @details Set strings in all configs present in state
* @param[in, out] state Pointer to pointer to correctly initialized test state,
* will point to usbg state when finished.
*/
static void test_set_config_strs(void **state)
{
for_each_test_config(state, try_set_config_strs);
}
/**
* @brief Set strings one by one on config
* @param[in] c Config on which string should be set
* @param[in] tc Test config containing strings to be set
*/
static void try_set_config_string(usbg_config *c, struct test_config *tc)
{
pull_config_string(tc, LANG_US_ENG, tc->strs->configuration);
usbg_set_config_string(c, LANG_US_ENG, tc->strs->configuration);
}
/**
* @brief Test setting strings one by one
* @details Set strings on all configs present in given state
* @param[in, out] state Pointer to pointer to correctly initialized test state,
* will point to usbg state when finished.
*/
static void test_set_config_string(void **state)
{
for_each_test_config(state, try_set_config_string);
}
/**
* @brief Get config strings
* @details Assume that given configs have the same strings
* @param[in] c Config from which strings should be get
* @param[in] tc Test config expected to have the same string as c
*/
static void try_get_config_strs(usbg_config *c, struct test_config *tc)
{
usbg_config_strs strs;
push_config_strs(tc, LANG_US_ENG, tc->strs);
usbg_get_config_strs(c, LANG_US_ENG, &strs);
assert_string_equal(tc->strs->configuration, strs.configuration);
}
/**
* @brief Test getting congig strings
* @details Get config strings on all configs present in given state
* @param[in, out] state Pointer to pointer to correctly initialized test state,
* will point to usbg state when finished.
*/
static void test_get_config_strs(void **state)
{
for_each_test_config(state, try_get_config_strs);
}
/**
* @brief Get config attributes
* @details Assume that attributes which will be returned are the same as
* given test state contains.
* @param[in] c Usbg config
* @param[in] tc Test config with set attributes
*/
static void try_get_config_attrs(usbg_config *c, struct test_config *tc)
{
usbg_config_attrs attrs;
push_config_attrs(tc, tc->attrs);
usbg_get_config_attrs(c, &attrs);
assert_config_attrs_equal(tc->attrs, &attrs);
}
/**
* @brief Test getting config attributes
* @details Get config attributes on all configfs in state
* @param[in, out] state Pointer to pointer to correctly initialized test state,
* will point to usbg state when finished.
*/
static void test_get_config_attrs(void **state)
{
for_each_test_config(state, try_get_config_attrs);
}
/**
* @brief Set config attributes in given config
* @param[in] c Usbg config
* @param[in] tc Test config with attributes which will be set
*/
static void try_set_config_attrs(usbg_config *c, struct test_config *tc)
{
pull_config_attrs(tc, tc->attrs);
usbg_set_config_attrs(c, tc->attrs);
}
/**
* @brief Test setting config attributes
* @details Set config attributes on all configs in state
* @param[in, out] state Pointer to pointer to correctly initialized test state,
* will point to usbg state when finished.
*/
static void test_set_config_attrs(void **state)
{
for_each_test_config(state, try_set_config_attrs);
}
/**
*
* @brief cleanup usbg state
*/
static void teardown_state(void **state)
{
usbg_state *s = NULL;
s = (usbg_state *)(*state);
if (s != NULL)
usbg_cleanup(s);
cleanup_stack();
}
/* Custom macro for defining test with given name and fixed teardown function */
#define USBG_TEST_TS(name, test, setup) \
USBG_TEST(name, test, setup, teardown_state)
/**
* @page usbg_tests Tests
* @brief This is list of test cases
* @tests_start
*/
#ifndef DOXYGEN
static UnitTest tests[] = {
#endif
/**
* @usbg_test
* @test_desc{test_init_simple,
* Check if init was successfull on simple configfs state,
* usbg_init}
*/
USBG_TEST_TS("test_init_simple",
test_init, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_init_all_funcs,
* Check if init was successfull when all avaible functions
* are present in configfs,
* usbg_init}
*/
USBG_TEST_TS("test_init_all_funcs",
test_init, setup_all_funcs_state),
/**
* @usbg_test
* @test_desc{test_init_long_path,
* Try to initialize libusbg with long configfs path,
* usbg_init}
*/
USBG_TEST_TS("test_init_long_path",
test_init, setup_long_path_state),
/**
* @usbg_test
* @test_desc{test_init_long_udc,
* Try to initialize libusbg with long udc name,
* usbg_init}
*/
USBG_TEST_TS("test_init_long_udc",
test_init, setup_long_udc_state),
/**
* @usbg_test
* @test_desc{test_get_gadget_simple,
* Check if simple gadget will be correcty returned,
* usbg_get_gadget}
*/
USBG_TEST_TS("test_get_gadget_simple",
test_get_gadget, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_gadget_fail_simple,
* Check if getting non-existing and wrong gadgets cause
* expected failure and error codes are correct,
* usbg_get_gadget}
*/
USBG_TEST_TS("test_get_gadget_fail_simple",
test_get_gadget_fail, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_first_gadget_simple,
* Check if gadget returned by get_first_gadget
* is actually first one,
* usbg_get_first_gadget}
*/
USBG_TEST_TS("test_get_first_gadget_simple",
test_get_first_gadget, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_first_gadget_fail,
* Check if getting first gadget from state returns NULL when
* invalid parameters are passed,
* usbg_get_first_gadget}
*/
unit_test(test_get_first_gadget_fail),
/**
* @usbg_test
* @test_desc{test_get_gadget_name_simple,
* Check if returned gadget name matches expected value,
* usbg_get_gadget_name}
*/
USBG_TEST_TS("test_get_gadget_name_simple",
test_get_gadget_name, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_gadget_name_len,
* Check if returned simple gadget name length matches expected value,
* usbg_get_gadget_name}
*/
USBG_TEST_TS("test_get_gadget_name_len_simple",
test_get_gadget_name_len, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_gadget_name_fail,
* Check if trying to get name of invalid gadget
* cause expected failure (name is null),
* usbg_get_gadget_name}
*/
unit_test(test_get_gadget_name_fail),
/**
* @usbg_test
* @test_desc{test_cpy_gadget_name_simple,
* Check if getting simple gadget name into buffer work as expected,
* usbg_cpy_gadget_name}
*/
USBG_TEST_TS("test_cpy_gadget_name_simple",
test_cpy_gadget_name, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_cpy_gadget_name_fail_simple,
* Check if writting gadget name into buffer fail when
* invalid parameters are passed,
* usbg_cpy_gadget_name}
*/
USBG_TEST_TS("test_cpy_gadget_name_fail_simple",
test_cpy_gadget_name_fail, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_function_simple,
* Check if function can be correctly get from simple state,
* usbg_get_function}
*/
USBG_TEST_TS("test_get_function_simple",
test_get_function, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_function_all_funcs,
* Check if getting function work on all function types,
* usbg_get_function}
*/
USBG_TEST_TS("test_get_function_all_funcs",
test_get_function, setup_all_funcs_state),
/**
* @usbg_test
* @test_desc{test_get_function_same_type_funcs,
* Check if having multiple functions with the same type does not
* cause failure
* usbg_get_function}
*/
USBG_TEST_TS("test_get_function_same_type_funcs",
test_get_function, setup_same_type_funcs_state),
/**
* @usbg_test
* @test_desc{test_get_function_fail_simple,
* Check if trying to get invalid function's name ends
* with expected error,
* usbg_get_function}
*/
USBG_TEST_TS("test_get_function_fail_simple",
test_get_function_fail, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_function_instance_simple,
* Check if getting simple instance returns what expected,
* usbg_get_function_instance}
*/
USBG_TEST_TS("test_get_function_instance_simple",
test_get_function_instance, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_cpy_function_instance_simple,
* Check if copying simple instance into buffer returns what expected,
* usbg_cpy_function_instance}
*/
USBG_TEST_TS("test_cpy_function_instance_simple",
test_cpy_function_instance, setup_all_funcs_state),
/**
* @usbg_test
* @test_desc{test_get_function_type_simple,
* Check if function type is returned correctly,
* usbg_get_function_type}
*/
USBG_TEST_TS("test_get_function_type_simple",
test_get_function_type, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_function_type_all_funcs,
* Check if all function types are returned correctly,
* usbg_get_function_type}
*/
USBG_TEST_TS("test_get_function_type_all_funcs",
test_get_function_type, setup_all_funcs_state),
/**
* @usbg_test
* @test_desc{test_get_function_instance_len_simple,
* Check if function instance length is returned correctly,
* usbg_get_function_instance_len}
*/
USBG_TEST_TS("test_get_function_instance_len_simple",
test_get_function_instance_len, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_function_type_str,
* Compare returned function types strings with expected values,
* usbg_get_function_type_str}
*/
unit_test(test_get_function_type_str),
/**
* @usbg_test
* @test_desc{test_get_function_type_str_fail,
* Try to get type string of unknown type,
* usbg_get_function_type_str}
*/
unit_test(test_get_function_type_str_fail),
/**
* @usbg_test
* @test_desc{test_get_configfs_path_simple,
* heck if simple configfs path was returned correctly,
* usbg_get_configfs_path}
*/
USBG_TEST_TS("test_get_configfs_path_simple",
test_get_configfs_path, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_configfs_path_len,
* Check if configfs path length is correctly calculated,
* usbg_get_configfs_path_len}
*/
USBG_TEST_TS("test_get_configfs_path_len_simple",
test_get_configfs_path_len, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_cpy_configfs_path_simple,
* Copy simple configfs path into buffer and compare with original,
* usbg_cpy_configfs_path}
*/
USBG_TEST_TS("test_cpy_configfs_path_simple",
test_cpy_configfs_path, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_config_simple,
* Check if returned simple config matches original one,
* usbg_get_config}
*/
USBG_TEST_TS("test_get_config_simple",
test_get_config, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_config_without_label_simple,
* Check if returned simple config matches original one,
* usbg_get_config}
*/
USBG_TEST_TS("test_get_config_without_label_simple",
test_get_config_without_label, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_config_fail,
* Check if trying to get non-existing or invalid config
* fails as expected,
* usbg_get_config}*/
USBG_TEST_TS("test_get_config_fail",
test_get_config_fail, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_config_label_simple,
* Check if returned simple config label matches original one,
* usbg_get_config_label}
*/
USBG_TEST_TS("test_get_config_label_simple",
test_get_config_label, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_config_id_simple,
* Check if returned simple config id matches original one,
* usbg_get_config_id}
*/
USBG_TEST_TS("test_get_config_id_simple",
test_get_config_id, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_gadget_attrs_simple,
* Get gadget attributes list and compare them with original,
* usbg_get_gadget_attrs}
*/
USBG_TEST_TS("test_get_gadget_attrs_simple",
test_get_gadget_attrs, setup_simple_state),
/**
* @usbg_tets
* @test_desc{test_set_gadget_attrs_simple,
* Set gadget attributes list\, check if everything is wrote
* as expected,
* usbg_set_gadget_attrs}
*/
USBG_TEST_TS("test_set_gadget_attrs_simple",
test_set_gadget_attrs, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_set_specific_gadget_attr_simple,
* Set gadget attributes one by one,
* usbg_set_gadget_attrs}
*/
USBG_TEST_TS("test_set_specific_gadget_attr_simple",
test_set_specific_gadget_attr, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_udc_simple,
* Get udc name from state,
* usbg_get_udc}
*/
USBG_TEST_TS("test_get_udc_simple",
test_get_udc, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_udc_long,
* Get udc name witch very long name,
* usbg_get_udc}
*/
USBG_TEST_TS("test_get_udc_long",
test_get_udc, setup_long_udc_state),
/**
* @usbg_test
* @test_desc{test_get_gadget_attr_str,
* Compare returned gadget attribute strings witch expected values
* usbg_get_gadget_attr_str}
*/
unit_test(test_get_gadget_attr_str),
/**
* @usbg_test
* @test_desc{test_get_gadget_attr_str_fail,
* Check returned gadget attribute strings for invalid arguments
* usbg_get_gadget_attr_str}
*/
unit_test(test_get_gadget_attr_str_fail),
/**
* @usbg_test
* @test_desc{test_set_gadget_strs_random,
* Set gadget strings of random length,
* usbg_set_gadget_strs}
*/
USBG_TEST_TS("test_set_gadget_strs_random",
test_set_gadget_strs, setup_random_len_gadget_strs_data),
/**
* @usbg_test
* @test_desc{test_get_gadget_strs_random,
* Get gadget strings,
* usbg_get_gadget_strs}
*/
USBG_TEST_TS("test_get_gadget_strs_random",
test_get_gadget_strs, setup_random_len_gadget_strs_data),
/**
* @usbg_test
* @test_desc{test_get_binding_target_simple,
* Get binding target,
* usbg_get_binding_target}
*/
USBG_TEST_TS("test_get_binding_target_simple",
test_get_binding_target, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_binding_name_simple,
* Get binding name,
* usbg_get_binding_name}
*/
USBG_TEST_TS("test_get_binding_name_simple",
test_get_binding_name, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_get_binding_name_len_simple,
* Get binding name length,
* usbg_get_binding_name_len}
*/
USBG_TEST_TS("test_get_binding_name_len_simple",
test_get_binding_name_len, setup_simple_state),
/**
* @usbg_test
* @test_desc{test_set_config_strs_simple,
* Set simple strings in set of configurations,
* usbg_set_config_strs}
*/
USBG_TEST_TS("test_set_config_strs_simple",
test_set_config_strs, setup_simple_config_strs_state),
/**
* @usbg_test
* @test_desc{test_set_config_string_simple,
* Set simple string in set of configurations,
* usbg_set_config_string}
*/
USBG_TEST_TS("test_set_config_string_simple",
test_set_config_string, setup_simple_config_strs_state),
/**
* @usbg_test
* @test_desc{test_get_config_strs_simple,
* Get simple strings from set of configurations,
* usbg_get_config_strs}
*/
USBG_TEST_TS("test_get_config_strs_simple",
test_get_config_strs, setup_simple_config_strs_state),
/**
* @usbg_test
* @test_desc{test_get_config_attrs_max,
* Get config attributes with max values,
* usbg_get_config_attrs}
*/
USBG_TEST_TS("test_get_config_attrs_max",
test_get_config_attrs, setup_max_config_attrs_state),
/**
* @usbg_test
* @test_desc{test_get_config_attrs_min,
* Get config attributes with minimum values,
* usbg_get_config_attrs}
*/
USBG_TEST_TS("test_get_config_attrs_min",
test_get_config_attrs, setup_min_config_attrs_state),
/**
* @usbg_test
* @test_desc{test_get_config_attrs_random,
* Get config attributes with random values,
* usbg_get_config_attrs}
*/
USBG_TEST_TS("test_get_config_attrs_random",
test_get_config_attrs, setup_random_config_attrs_state),
/**
* @usbg_test
* @test_desc{test_set_config_attrs_max,
* Set config attributes with max values,
* usbg_set_config_attrs}
*/
USBG_TEST_TS("test_set_config_attrs_max",
test_set_config_attrs, setup_max_config_attrs_state),
/**
* @usbg_test
* @test_desc{test_set_config_attrs_min,
* Set config attributes with minimum values,
* usbg_set_config_attrs}
*/
USBG_TEST_TS("test_set_config_attrs_min",
test_set_config_attrs, setup_min_config_attrs_state),
/**
* @usbg_test
* @test_desc{test_set_config_attrs_random,
* Set config attributes with random values,
* usbg_set_config_attrs}
*/
USBG_TEST_TS("test_set_config_attrs_random",
test_set_config_attrs, setup_random_config_attrs_state),
#ifndef DOXYGEN
};
#endif
/**
* @usbg_test
* @tests_end
*/
#define TESTS_TAG "tests"
/* for autotools compability */
#define SKIPPED_CODE 77
#ifdef HAS_LIBCONFIG
static int gen_test_config(FILE *output)
{
config_t cfg;
config_setting_t *root;
config_setting_t *tests_node, *node;
int i;
int ret = SKIPPED_CODE, cfg_ret = 0;
config_init(&cfg);
config_set_tab_width(&cfg, 4);
root = config_root_setting(&cfg);
tests_node = config_setting_add(root, TESTS_TAG, CONFIG_TYPE_LIST);
if (!tests_node) {
ret = -ENOMEM;
goto out;
}
for (i = 0; i < ARRAY_SIZE(tests); ++i) {
if (tests[i].function_type != UNIT_TEST_FUNCTION_TYPE_TEST)
continue;
node = config_setting_add(tests_node, NULL, CONFIG_TYPE_STRING);
if (!node) {
ret = -ENOMEM;
goto out;
}
cfg_ret = config_setting_set_string(node, tests[i].name);
if (cfg_ret != CONFIG_TRUE) {
ret = -EINVAL;
goto out;
}
}
config_write(&cfg, output);
out:
config_destroy(&cfg);
return ret;
}
#else
static int gen_test_config(FILE *output)
{
fprintf(stderr, "Libconfig is not supported\n");
return -ENOTSUP;
}
#endif /* HAS_LIBCONFIG */
static int lookup_test(const char *name)
{
int i;
for (i = 0; i < ARRAY_SIZE(tests); ++i)
if (tests[i].function_type == UNIT_TEST_FUNCTION_TYPE_TEST &&
!strcmp(name, tests[i].name))
return i;
return -1;
}
#ifdef HAS_LIBCONFIG
static int apply_test_config(FILE *input)
{
config_t cfg;
config_setting_t *root;
config_setting_t *tests_node, *node;
int i, count, ind;
int ret = 0, cfg_ret = 0;
const char *test_name;
char selected[ARRAY_SIZE(tests)];
for (i = 0; i < ARRAY_SIZE(selected); ++i)
selected[i] = 0;
config_init(&cfg);
cfg_ret = config_read(&cfg, input);
if (cfg_ret != CONFIG_TRUE) {
fprintf(stderr, "Wrong config format\n");
ret = -EINVAL;
goto out;
}
root = config_root_setting(&cfg);
tests_node = config_setting_get_member(root, TESTS_TAG);
if (!tests_node || !config_setting_is_list(tests_node)) {
fprintf(stderr, "Missing or incorrect tests list\n");
ret = -EINVAL;
goto out;
}
count = config_setting_length(tests_node);
for (i = 0; i < count; ++i) {
node = config_setting_get_elem(tests_node, i);
if (!node) {
ret = -EINVAL;
goto out;
}
test_name = config_setting_get_string(node);
if (!test_name) {
fprintf(stderr, "Incorrect tests list. Element %d\n", i);
ret = -EINVAL;
goto out;
}
ind = lookup_test(test_name);
if (ind < 0) {
fprintf(stderr, "Test %s not found.\n", test_name);
ret = -EINVAL;
goto out;
}
selected[ind] = 1;
}
/* Structures with NULL function are skipped by cmocka*/
for (i = 0; i < ARRAY_SIZE(selected); ++i) {
if (selected[i] ||
tests[i].function_type != UNIT_TEST_FUNCTION_TYPE_TEST)
continue;
if (i - 1 >= 0 && tests[i - 1].function_type ==
UNIT_TEST_FUNCTION_TYPE_SETUP)
tests[i - 1].function = NULL;
tests[i].function = NULL;
if (i + 1 < ARRAY_SIZE(tests) && tests[i + 1].function_type ==
UNIT_TEST_FUNCTION_TYPE_TEARDOWN)
tests[i + 1].function = NULL;
}
out:
config_destroy(&cfg);
return ret;
}
#else
static int apply_test_config(FILE *input)
{
fprintf(stderr, "Libconfig is not supported\n");
return -ENOTSUP;
}
#endif /* HAS_LIBCONFIG */
static void print_skipped_tests(FILE *stream)
{
int i = 0, nmb_skipped = 0;
for (i = 0; i < ARRAY_SIZE(tests); ++i) {
if (tests[i].function ||
tests[i].function_type != UNIT_TEST_FUNCTION_TYPE_TEST)
continue;
++nmb_skipped;
}
if (nmb_skipped == 0)
return;
fprintf(stream, "[==========] %d test(s) skipped.\n",
nmb_skipped);
for (i = 0; i < ARRAY_SIZE(tests); ++i) {
if (tests[i].function ||
tests[i].function_type != UNIT_TEST_FUNCTION_TYPE_TEST)
continue;
fprintf(stream, "[ SKIPPED ] %s\n", tests[i].name);
}
}
static void print_help()
{
fprintf(stderr,
"libusbgx test suit:\n"
" --generate-config - generates config to stdout and exit\n"
" --use-config - runs test suit using config from stdin\n"
" -h --help - print this message\n"
);
}
int main(int argc, char **argv)
{
enum {
GENERATE_CONFIG = 0x01,
USE_CONFIG = 0x02,
};
int options = 0;
int opt;
int ret = -EINVAL;
static struct option long_options[] = {
{"generate-config", no_argument, 0, 1},
{"use-config", no_argument, 0, 2},
{"help", no_argument, 0, 'h'},
{NULL, 0, 0, 0}
};
while (1) {
opt = getopt_long(argc, argv, "h", long_options, NULL);
if (opt < 0)
break;
switch (opt) {
case 1:
options |= GENERATE_CONFIG;
break;
case 2:
options |= USE_CONFIG;
break;
case 'h':
default:
print_help();
goto out;
}
}
if (optind < argc ||
((options & GENERATE_CONFIG) &&
(options & USE_CONFIG))) {
print_help();
goto out;
}
if (options & GENERATE_CONFIG) {
ret = gen_test_config(stdout);
goto out;
}
if (options & USE_CONFIG) {
ret = apply_test_config(stdin);
if (ret)
goto out;
}
ret = run_tests(tests);
print_skipped_tests(stderr);
out:
return ret;
}