summaryrefslogtreecommitdiff
path: root/test/usb_sm_checks.c
diff options
context:
space:
mode:
authorJett Rink <jettrink@chromium.org>2019-08-07 12:49:34 -0600
committerCommit Bot <commit-bot@chromium.org>2019-08-20 16:05:47 +0000
commit7a07137ff8861509b5942a82de1c46b376c6057a (patch)
tree40ec190a005c76d7be409ac20367486270e7b848 /test/usb_sm_checks.c
parent72405bceb4f8234ad1dc4a64041c0037abd57a21 (diff)
downloadchrome-ec-7a07137ff8861509b5942a82de1c46b376c6057a.tar.gz
test: add sanity check for existing state machines
We want to ensure that our usb state machines - do not have any cycles - do not have any completely empty states - have names for every print statement if called These new unit tests allow us to have build-times checks for the above. BRANCH=none BUG=none TEST=tests pass. Made each test fail locally to ensure that tests were actually working. Change-Id: Idd2c4d69e83cf38c97278edd1727d86b52a85db9 Signed-off-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1744657 Commit-Queue: Denis Brockus <dbrockus@chromium.org> Reviewed-by: Denis Brockus <dbrockus@chromium.org>
Diffstat (limited to 'test/usb_sm_checks.c')
-rw-r--r--test/usb_sm_checks.c254
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;
+}
+