/* Copyright 2019 The ChromiumOS Authors * 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_pd_test_util.h" #include "usb_sm.h" #include "usb_tc_sm.h" #include "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 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 && (i >= sm_data->names_size || sm_data->names[i] == NULL)) { current->entry(0); if (state_printed) { 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; }