[PATCH] kselftest: alsa: Check for event generation when we write to controls
Shuah Khan
skhan at linuxfoundation.org
Tue Feb 1 17:18:52 CET 2022
Hi Mark,
On 2/1/22 8:15 AM, Mark Brown wrote:
> Add some coverage of event generation to mixer-test. Rather than doing a
> separate set of writes designed to trigger events we add a step to the
> existing write_and_verify() which checks to see if the value we read back
> from non-volatile controls matches the value before writing and that an
> event is or isn't generated as appropriate. The "tests" for events then
> simply check that no spurious or missing events were detected. This avoids
> needing further logic to generate appropriate values for each control type
> and maximises coverage.
>
> When checking for events we use a timeout of 0. This relies on the kernel
> generating any event prior to returning to userspace when setting a control.
> That is currently the case and it is difficult to see it changing, if it
> does the test will need to be updated. Using a delay of 0 means that we
> don't slow things down unduly when checking for no event or when events
> fail to be generated.
>
> We don't check behaviour for volatile controls since we can't tell what
> the behaviour is supposed to be for any given control.
>
> Signed-off-by: Mark Brown <broonie at kernel.org>
> ---
> tools/testing/selftests/alsa/mixer-test.c | 148 +++++++++++++++++++++-
> 1 file changed, 145 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/alsa/mixer-test.c b/tools/testing/selftests/alsa/mixer-test.c
> index 0e88f4f3d802..42cf3b724586 100644
> --- a/tools/testing/selftests/alsa/mixer-test.c
> +++ b/tools/testing/selftests/alsa/mixer-test.c
> @@ -3,7 +3,7 @@
> // kselftest for the ALSA mixer API
> //
> // Original author: Mark Brown <broonie at kernel.org>
> -// Copyright (c) 2021 Arm Limited
> +// Copyright (c) 2021-2 Arm Limited
>
> // This test will iterate over all cards detected in the system, exercising
> // every mixer control it can find. This may conflict with other system
> @@ -27,11 +27,12 @@
>
> #include "../kselftest.h"
>
> -#define TESTS_PER_CONTROL 4
> +#define TESTS_PER_CONTROL 6
>
> struct card_data {
> snd_ctl_t *handle;
> int card;
> + struct pollfd pollfd;
> int num_ctls;
> snd_ctl_elem_list_t *ctls;
> struct card_data *next;
> @@ -43,6 +44,8 @@ struct ctl_data {
> snd_ctl_elem_info_t *info;
> snd_ctl_elem_value_t *def_val;
> int elem;
> + int event_missing;
> + int event_spurious;
> struct card_data *card;
> struct ctl_data *next;
> };
> @@ -149,6 +152,7 @@ void find_controls(void)
> if (!ctl_data)
> ksft_exit_fail_msg("Out of memory\n");
>
> + memset(ctl_data, 0, sizeof(*ctl_data));
> ctl_data->card = card_data;
> ctl_data->elem = ctl;
> ctl_data->name = snd_ctl_elem_list_get_name(card_data->ctls,
> @@ -184,6 +188,26 @@ void find_controls(void)
> ctl_list = ctl_data;
> }
>
> + /* Set up for events */
> + err = snd_ctl_subscribe_events(card_data->handle, true);
> + if (err < 0) {
> + ksft_exit_fail_msg("snd_ctl_subscribe_events() failed for card %d: %d\n",
> + card, err);
> + }
> +
> + err = snd_ctl_poll_descriptors_count(card_data->handle);
> + if (err != 1) {
> + ksft_exit_fail_msg("Unexpected desciptor count %d for card %d\n",
> + err, card);
> + }
> +
> + err = snd_ctl_poll_descriptors(card_data->handle,
> + &card_data->pollfd, 1);
> + if (err != 1) {
> + ksft_exit_fail_msg("snd_ctl_poll_descriptors() failed for %d\n",
> + card, err);
> + }
> +
> next_card:
> if (snd_card_next(&card) < 0) {
> ksft_print_msg("snd_card_next");
> @@ -194,6 +218,73 @@ void find_controls(void)
> snd_config_delete(config);
> }
>
> +/*
> + * Block for up to timeout ms for an event, returns a negative value
> + * on error, 0 for no event and 1 for an event.
> + */
> +int wait_for_event(struct ctl_data *ctl, int timeout)
Let's make this static.
> +{
> + unsigned short revents;
> + snd_ctl_event_t *event;
> + int count, err;
> + unsigned int mask = 0;
> + unsigned int ev_id;
> +
> + snd_ctl_event_alloca(&event);
> +
> + do {
> + err = poll(&(ctl->card->pollfd), 1, timeout);
> + if (err < 0) {
> + ksft_print_msg("poll() failed for %s: %s (%d)\n",
> + ctl->name, strerror(errno), errno);
> + return -1;
> + }
> + /* Timeout */
> + if (err == 0)
> + return 0;
> +
> + err = snd_ctl_poll_descriptors_revents(ctl->card->handle,
> + &(ctl->card->pollfd),
> + 1, &revents);
> + if (err < 0) {
> + ksft_print_msg("snd_ctl_poll_desciptors_revents() failed for %s: %d\n",
> + ctl->name, err);
> + return err;
> + }
> + if (revents & POLLERR) {
> + ksft_print_msg("snd_ctl_poll_desciptors_revents() reported POLLERR for %s\n",
> + ctl->name);
> + return -1;
> + }
> + /* No read events */
> + if (!(revents & POLLIN)) {
> + ksft_print_msg("No POLLIN\n");
> + continue;
> + }
> +
> + err = snd_ctl_read(ctl->card->handle, event);
> + if (err < 0) {
> + ksft_print_msg("snd_ctl_read() failed for %s: %d\n",
> + ctl->name, err);
> + return err;
> + }
> +
> + if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM)
> + continue;
> +
> + /* The ID returned from the event is 1 less than numid */
> + mask = snd_ctl_event_elem_get_mask(event);
> + ev_id = snd_ctl_event_elem_get_numid(event);
> + if (ev_id != ctl->elem + 1) {
> + ksft_print_msg("Event for unexpected ctl %s\n",
> + snd_ctl_event_elem_get_name(event));
> + continue;
> + }
> + } while ((mask & SND_CTL_EVENT_MASK_VALUE) != SND_CTL_EVENT_MASK_VALUE);
> +
> + return 1;
> +}
> +
> bool ctl_value_index_valid(struct ctl_data *ctl, snd_ctl_elem_value_t *val,
> int index)
> {
> @@ -428,7 +519,8 @@ int write_and_verify(struct ctl_data *ctl,
> {
> int err, i;
> bool error_expected, mismatch_shown;
> - snd_ctl_elem_value_t *read_val, *w_val;
> + snd_ctl_elem_value_t *initial_val, *read_val, *w_val;
> + snd_ctl_elem_value_alloca(&initial_val);
> snd_ctl_elem_value_alloca(&read_val);
> snd_ctl_elem_value_alloca(&w_val);
>
> @@ -446,6 +538,18 @@ int write_and_verify(struct ctl_data *ctl,
> snd_ctl_elem_value_copy(expected_val, write_val);
> }
>
> + /* Store the value before we write */
> + if (snd_ctl_elem_info_is_readable(ctl->info)) {
> + snd_ctl_elem_value_set_id(initial_val, ctl->id);
> +
> + err = snd_ctl_elem_read(ctl->card->handle, initial_val);
> + if (err < 0) {
> + ksft_print_msg("snd_ctl_elem_read() failed: %s\n",
> + snd_strerror(err));
> + return err;
> + }
> + }
> +
> /*
> * Do the write, if we have an expected value ignore the error
> * and carry on to validate the expected value.
> @@ -470,6 +574,30 @@ int write_and_verify(struct ctl_data *ctl,
> return err;
> }
>
> + /*
> + * Check for an event if the value changed, or confirm that
> + * there was none if it didn't. We rely on the kernel
> + * generating the notification before it returns from the
> + * write, this is currently true, should that ever change this
> + * will most likely break and need updating.
> + */
> + if (!snd_ctl_elem_info_is_volatile(ctl->info)) {
> + err = wait_for_event(ctl, 0);
> + if (snd_ctl_elem_value_compare(initial_val, read_val)) {
> + if (err < 1) {
> + ksft_print_msg("No event generated for %s\n",
> + ctl->name);
> + ctl->event_missing++;
> + }
> + } else {
> + if (err != 0) {
> + ksft_print_msg("Spurious event generated for %s\n",
> + ctl->name);
> + ctl->event_spurious++;
> + }
> + }
> + }
> +
> /*
> * Use the libray to compare values, if there's a mismatch
> * carry on and try to provide a more useful diagnostic than
> @@ -898,6 +1026,18 @@ void test_ctl_write_invalid(struct ctl_data *ctl)
> ctl->card->card, ctl->elem);
> }
>
> +void test_ctl_event_missing(struct ctl_data *ctl)
Let's make this static.
> +{
> + ksft_test_result(!ctl->event_missing, "event_missing.%d.%d\n",
> + ctl->card->card, ctl->elem);
> +}
> +
> +void test_ctl_event_spurious(struct ctl_data *ctl)
Let's make this static.
> +{
> + ksft_test_result(!ctl->event_spurious, "event_spurious.%d.%d\n",
> + ctl->card->card, ctl->elem);
> +}
> +
> int main(void)
> {
> struct ctl_data *ctl;
> @@ -917,6 +1057,8 @@ int main(void)
> test_ctl_write_default(ctl);
> test_ctl_write_valid(ctl);
> test_ctl_write_invalid(ctl);
> + test_ctl_event_missing(ctl);
> + test_ctl_event_spurious(ctl);
> }
>
> ksft_exit_pass();
>
Otherwise looks good to me.
Reviewed-by: Shuah Khan <skhan at linuxfoundation.org>
thanks,
-- Shuah
More information about the Alsa-devel
mailing list