diff options
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(); +} |