diff options
Diffstat (limited to 'test/usb_sm_checks.c')
-rw-r--r-- | test/usb_sm_checks.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/test/usb_sm_checks.c b/test/usb_sm_checks.c new file mode 100644 index 0000000000..498d56e323 --- /dev/null +++ b/test/usb_sm_checks.c @@ -0,0 +1,254 @@ +/* Copyright 2019 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Test USB Type-C VPD and CTVPD module. + */ +#include "common.h" +#include "task.h" +#include "test_util.h" +#include "timer.h" +#include "usb_pd.h" +#include "usb_sm.h" +#include "usb_tc_sm.h" +#include "util.h" +#include "usb_pd_test_util.h" +#include "vpd_api.h" + +#ifdef CONFIG_USB_TYPEC_SM +extern const struct test_sm_data test_tc_sm_data[]; +extern const int test_tc_sm_data_size; +#else +const struct test_sm_data test_tc_sm_data[] = {}; +const int test_tc_sm_data_size; +#endif + +#ifdef CONFIG_USB_PRL_SM +extern const struct test_sm_data test_prl_sm_data[]; +extern const int test_prl_sm_data_size; +#else +const struct test_sm_data test_prl_sm_data[] = {}; +const int test_prl_sm_data_size; +#endif + +#ifdef CONFIG_USB_PE_SM +extern const struct test_sm_data test_pe_sm_data[]; +extern const int test_pe_sm_data_size; +#else +const struct test_sm_data test_pe_sm_data[] = {}; +const int test_pe_sm_data_size; +#endif + +test_static int test_no_parent_cycles(const struct test_sm_data * const sm_data) +{ + int i; + + for (i = 0; i < sm_data->size; ++i) { + int depth = 0; + usb_state_ptr current = &sm_data->base[i]; + + while (current != NULL && ++depth <= sm_data->size) + current = current->parent; + + if (depth > sm_data->size) + break; + } + + /* Ensure all states end, otherwise the ith state has a cycle. */ + TEST_EQ(i, sm_data->size, "%d"); + + return EC_SUCCESS; +} + +int test_tc_no_parent_cycles(void) +{ + int i; + + for (i = 0; i < test_tc_sm_data_size; ++i) { + const int rv = test_no_parent_cycles(&test_tc_sm_data[i]); + + if (rv) { + ccprintf("TC State machine %d has a cycle!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + +int test_prl_no_parent_cycles(void) +{ + int i; + + for (i = 0; i < test_prl_sm_data_size; ++i) { + const int rv = test_no_parent_cycles(&test_prl_sm_data[i]); + + if (rv) { + ccprintf("PRL State machine %d has a cycle!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + +int test_pe_no_parent_cycles(void) +{ + int i; + + for (i = 0; i < test_pe_sm_data_size; ++i) { + const int rv = test_no_parent_cycles(&test_pe_sm_data[i]); + + if (rv) { + ccprintf("PE State machine %d has a cycle!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + +static int test_no_empty_state(const struct test_sm_data * const sm_data) +{ + int i; + const struct usb_state empty = { 0 }; + + for (i = 0; i < sm_data->size; ++i) { + if (memcmp(&sm_data->base[i], &empty, sizeof(empty)) == 0) + break; + } + + /* Ensure all states had data, otherwise the ith state is empty. */ + TEST_EQ(i, sm_data->size, "%d"); + + return EC_SUCCESS; +} + +int test_tc_no_empty_state(void) +{ + int i; + + for (i = 0; i < test_tc_sm_data_size; ++i) { + const int rv = test_no_empty_state(&test_tc_sm_data[i]); + + if (rv) { + ccprintf("TC State machine %d has empty state!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + +int test_prl_no_empty_state(void) +{ + int i; + + for (i = 0; i < test_prl_sm_data_size; ++i) { + const int rv = test_no_empty_state(&test_prl_sm_data[i]); + + if (rv) { + ccprintf("PRL State machine %d has empty state!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + +int test_pe_no_empty_state(void) +{ + int i; + + for (i = 0; i < test_pe_sm_data_size; ++i) { + const int rv = test_no_empty_state(&test_pe_sm_data[i]); + + if (rv) { + ccprintf("PE State machine %d has empty state!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + +static volatile int state_printed; + +/* Override the implement version of print */ +__override void print_current_state(const int port) +{ + state_printed = 1; +} + +static int test_all_states_named(const struct test_sm_data * const sm_data) +{ + int i; + + for (i = 0; i < sm_data->size; ++i) { + usb_state_ptr current = &sm_data->base[i]; + + state_printed = 0; + + if (current->entry) + current->entry(0); + + if (state_printed) { + if (i >= sm_data->names_size || + sm_data->names[i] == NULL) { + ccprintf("State %d does not have a name!\n", i); + TEST_ASSERT(0); + } + } + } + + return EC_SUCCESS; +} + +int test_tc_all_states_named(void) +{ + int i; + + for (i = 0; i < test_tc_sm_data_size; ++i) { + const int rv = test_all_states_named(&test_tc_sm_data[i]); + + if (rv) { + ccprintf("TC State machine %d has empty name!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + +int test_prl_all_states_named(void) +{ + int i; + + for (i = 0; i < test_prl_sm_data_size; ++i) { + const int rv = test_all_states_named(&test_prl_sm_data[i]); + + if (rv) { + ccprintf("PRL State machine %d has empty name!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + +int test_pe_all_states_named(void) +{ + int i; + + for (i = 0; i < test_pe_sm_data_size; ++i) { + const int rv = test_all_states_named(&test_pe_sm_data[i]); + + if (rv) { + ccprintf("PE State machine %d has empty name!\n", i); + TEST_ASSERT(0); + } + } + + return EC_SUCCESS; +} + |