diff options
author | Bill Richardson <wfrichar@chromium.org> | 2014-08-19 19:01:29 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-08-20 22:42:15 +0000 |
commit | f883354bbad138390142fdeaa554f55ee51551ef (patch) | |
tree | 22fcffeda103aae6bd5b81163baa5acf8fffd6cd /test/lightbar.c | |
parent | 1b52de3e3c73886784ea1216b34305919449bd24 (diff) | |
download | chrome-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.c | 294 |
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, + ¶ms, 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, + ¶ms, 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(); +} |