summaryrefslogtreecommitdiff
path: root/test/lightbar.c
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2014-08-19 19:01:29 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-08-20 22:42:15 +0000
commitf883354bbad138390142fdeaa554f55ee51551ef (patch)
tree22fcffeda103aae6bd5b81163baa5acf8fffd6cd /test/lightbar.c
parent1b52de3e3c73886784ea1216b34305919449bd24 (diff)
downloadchrome-ec-f883354bbad138390142fdeaa554f55ee51551ef.tar.gz
lightbar: correctly revert to the S0/S3/S5 patterns
This CL ensures that temporary "one-shot" sequences such as KONAMI, TEST, TAP, etc. will revert to the previous "normal" sequences even when interrupted by other one-shot sequences. This also adds a test for those cases. BUG=chrome-os-partner:29873 BRANCH=ToT TEST=manual make runtests Change-Id: Ie83908731acdf2f7c9108568a1ba047943175d26 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/213230
Diffstat (limited to 'test/lightbar.c')
-rw-r--r--test/lightbar.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/test/lightbar.c b/test/lightbar.c
new file mode 100644
index 0000000000..32473c9ccf
--- /dev/null
+++ b/test/lightbar.c
@@ -0,0 +1,294 @@
+/* Copyright 2014 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.
+ */
+
+#include "console.h"
+#include "ec_commands.h"
+#include "lightbar.h"
+#include "host_command.h"
+#include "test_util.h"
+#include "timer.h"
+#include "util.h"
+
+static int get_seq(void)
+{
+ int rv;
+ struct ec_params_lightbar params;
+ struct ec_response_lightbar resp;
+
+ /* Get the state */
+ memset(&resp, 0, sizeof(resp));
+ params.cmd = LIGHTBAR_CMD_GET_SEQ;
+ rv = test_send_host_command(EC_CMD_LIGHTBAR_CMD, 0,
+ &params, sizeof(params),
+ &resp, sizeof(resp));
+ if (rv != EC_RES_SUCCESS) {
+ ccprintf("%s:%s(): rv = %d\n", __FILE__, __func__, rv);
+ return -1;
+ }
+
+ return resp.get_seq.num;
+}
+
+static int set_seq(int s)
+{
+ int rv;
+ struct ec_params_lightbar params;
+ struct ec_response_lightbar resp;
+
+ /* Get the state */
+ memset(&resp, 0, sizeof(resp));
+ params.cmd = LIGHTBAR_CMD_SEQ;
+ params.seq.num = s;
+ rv = test_send_host_command(EC_CMD_LIGHTBAR_CMD, 0,
+ &params, sizeof(params),
+ &resp, sizeof(resp));
+ if (rv != EC_RES_SUCCESS) {
+ ccprintf("%s:%s(): rv = %d\n", __FILE__, __func__, rv);
+ return -1;
+ }
+
+ return EC_RES_SUCCESS;
+}
+
+static int test_double_oneshots(void)
+{
+ /* Start in S0 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S0) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+ /* Invoke the oneshot */
+ TEST_ASSERT(set_seq(LIGHTBAR_TEST) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_TEST);
+ /* Switch to a different oneshot while that one's running */
+ TEST_ASSERT(set_seq(LIGHTBAR_KONAMI) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_KONAMI);
+ /* Afterwards, it should go back to the original normal state */
+ msleep(30 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+
+ /* Same test, but with a bunch more oneshots. */
+ TEST_ASSERT(set_seq(LIGHTBAR_S0) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+ TEST_ASSERT(set_seq(LIGHTBAR_TEST) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_TEST);
+ TEST_ASSERT(set_seq(LIGHTBAR_KONAMI) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_KONAMI);
+ TEST_ASSERT(set_seq(LIGHTBAR_TAP) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_TAP);
+ TEST_ASSERT(set_seq(LIGHTBAR_PULSE) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_PULSE);
+ TEST_ASSERT(set_seq(LIGHTBAR_KONAMI) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_KONAMI);
+ /* It should still go back to the original normal state */
+ msleep(30 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+
+ /* But if the interruption is a normal state, that should stick. */
+ TEST_ASSERT(set_seq(LIGHTBAR_S0) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+ TEST_ASSERT(set_seq(LIGHTBAR_TEST) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_TEST);
+ TEST_ASSERT(set_seq(LIGHTBAR_KONAMI) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_KONAMI);
+ /* Here's a normal sequence */
+ TEST_ASSERT(set_seq(LIGHTBAR_S3) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S3);
+ /* And another one-shot */
+ TEST_ASSERT(set_seq(LIGHTBAR_TAP) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_TAP);
+ TEST_ASSERT(set_seq(LIGHTBAR_PULSE) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_PULSE);
+ TEST_ASSERT(set_seq(LIGHTBAR_KONAMI) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_KONAMI);
+ /* It should go back to the new normal sequence */
+ msleep(30 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S3);
+
+ return EC_SUCCESS;
+}
+
+static int test_oneshots_norm_msg(void)
+{
+ /* Revert to the next state when interrupted with a normal message. */
+ enum lightbar_sequence seqs[] = {
+ LIGHTBAR_PULSE,
+ LIGHTBAR_TEST,
+ LIGHTBAR_KONAMI,
+ LIGHTBAR_TAP,
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(seqs); i++) {
+ /* Start in S0 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S0) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ /* Invoke the oneshot */
+ TEST_ASSERT(set_seq(seqs[i]) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ /* Interrupt with S0S3 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S0S3) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ /* It should be back right away */
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0S3);
+ /* And transition on to the correct value */
+ msleep(30 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S3);
+ }
+
+ return EC_SUCCESS;
+}
+
+static int test_stop_timeout(void)
+{
+ int i;
+
+ for (i = 0; i < LIGHTBAR_NUM_SEQUENCES; i++) {
+ /* Start in S0 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S0) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ /* Tell it to stop */
+ TEST_ASSERT(set_seq(LIGHTBAR_STOP) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_STOP);
+ /* Try to interrupt it */
+ TEST_ASSERT(set_seq(i) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ /* What happened? */
+ if (i == LIGHTBAR_RUN ||
+ i == LIGHTBAR_S0S3 || i == LIGHTBAR_S3 ||
+ i == LIGHTBAR_S3S5 || i == LIGHTBAR_S5)
+ /* RUN or shutdown sequences should stop it */
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+ else
+ /* All other sequences should be ignored */
+ TEST_ASSERT(get_seq() == LIGHTBAR_STOP);
+
+ /* Let it RUN again for the next iteration */
+ TEST_ASSERT(set_seq(LIGHTBAR_RUN) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ }
+
+ TEST_ASSERT(set_seq(LIGHTBAR_S0) == EC_RES_SUCCESS);
+ return EC_SUCCESS;
+}
+
+static int test_oneshots_timeout(void)
+{
+ /* These should revert to the previous state after running */
+ enum lightbar_sequence seqs[] = {
+ LIGHTBAR_RUN,
+ LIGHTBAR_TEST,
+ LIGHTBAR_KONAMI,
+ LIGHTBAR_TAP,
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(seqs); i++) {
+ TEST_ASSERT(set_seq(LIGHTBAR_S0) == EC_RES_SUCCESS);
+ msleep(MSEC);
+ TEST_ASSERT(set_seq(seqs[i]) == EC_RES_SUCCESS);
+ /* Assume the oneshot sequence takes at least a second (except
+ * for LIGHTBAR_RUN, which returns immediately) */
+ if (seqs[i] != LIGHTBAR_RUN) {
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == seqs[i]);
+ }
+ msleep(30 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+ }
+
+ return EC_SUCCESS;
+}
+
+static int test_transition_states(void)
+{
+ /* S5S3 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S5S3) == EC_RES_SUCCESS);
+ msleep(10 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S3);
+
+ /* S3S0 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S3S0) == EC_RES_SUCCESS);
+ msleep(10 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+
+ /* S0S3 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S0S3) == EC_RES_SUCCESS);
+ msleep(10 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S3);
+
+ /* S3S5 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S3S5) == EC_RES_SUCCESS);
+ msleep(10 * MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S5);
+
+ return EC_SUCCESS;
+}
+
+static int test_stable_states(void)
+{
+ int i;
+
+ /* Wait for the lightbar task to initialize */
+ msleep(500);
+
+ /* It should come up in S5 */
+ TEST_ASSERT(get_seq() == LIGHTBAR_S5);
+
+ /* It should stay there */
+ for (i = 0; i < 30; i++) {
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S5);
+ }
+
+ /* S3 is sticky, too */
+ TEST_ASSERT(set_seq(LIGHTBAR_S3) == EC_RES_SUCCESS);
+ for (i = 0; i < 30; i++) {
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S3);
+ }
+
+ /* And S0 */
+ TEST_ASSERT(set_seq(LIGHTBAR_S0) == EC_RES_SUCCESS);
+ for (i = 0; i < 30; i++) {
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_S0);
+ }
+
+ /* PULSE is stable too, but nobody should care. Test it anyway. */
+ TEST_ASSERT(set_seq(LIGHTBAR_PULSE) == EC_RES_SUCCESS);
+ for (i = 0; i < 30; i++) {
+ msleep(MSEC);
+ TEST_ASSERT(get_seq() == LIGHTBAR_PULSE);
+ }
+
+ return EC_SUCCESS;
+}
+
+void run_test(void)
+{
+ RUN_TEST(test_stable_states);
+ RUN_TEST(test_transition_states);
+ RUN_TEST(test_oneshots_timeout);
+ RUN_TEST(test_stop_timeout);
+ RUN_TEST(test_oneshots_norm_msg);
+ RUN_TEST(test_double_oneshots);
+ test_print_result();
+}