Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kselftest/alsa: pcm-test: Report cards declared in config but missing

When parsing the configs, keep track of card configurations that match
the current system but haven't matched any card, and report those as
test failures as they represent that a card which was expected to be
present on the system is missing. This allows the configuration files to
not only be used to detect missing PCM devices (which is currently
possible) but also that the soundcard hasn't been registered at all.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Reviewed-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20230919152702.100617-1-nfraprado@collabora.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Nícolas F. R. A. Prado and committed by
Takashi Iwai
72f6a130 f9262fb1

+73 -47
+10
tools/testing/selftests/alsa/alsa-local.h
··· 24 24 void conf_get_string_array(snd_config_t *root, const char *key1, const char *key2, 25 25 const char **array, int array_size, const char *def); 26 26 27 + struct card_cfg_data { 28 + int card; 29 + snd_config_t *config; 30 + const char *filename; 31 + const char *config_id; 32 + struct card_cfg_data *next; 33 + }; 34 + 35 + extern struct card_cfg_data *conf_cards; 36 + 27 37 #endif /* __ALSA_LOCAL_H */
+53 -47
tools/testing/selftests/alsa/conf.c
··· 19 19 20 20 #define SYSFS_ROOT "/sys" 21 21 22 - struct card_data { 23 - int card; 24 - snd_config_t *config; 25 - const char *filename; 26 - struct card_data *next; 27 - }; 28 - 29 - static struct card_data *conf_cards; 22 + struct card_cfg_data *conf_cards; 30 23 31 24 static const char *alsa_config = 32 25 "ctl.hw {\n" ··· 90 97 return config; 91 98 } 92 99 93 - static struct card_data *conf_data_by_card(int card, bool msg) 100 + static struct card_cfg_data *conf_data_by_card(int card, bool msg) 94 101 { 95 - struct card_data *conf; 102 + struct card_cfg_data *conf; 96 103 97 104 for (conf = conf_cards; conf; conf = conf->next) { 98 105 if (conf->card == card) { ··· 222 229 return iter > 0; 223 230 } 224 231 225 - static bool test_filename1(int card, const char *filename, const char *sysfs_card_root) 232 + static void assign_card_config(int card, const char *sysfs_card_root) 226 233 { 227 - struct card_data *data, *data2; 228 - snd_config_t *config, *sysfs_config, *card_config, *sysfs_card_config, *node; 229 - snd_config_iterator_t i, next; 234 + struct card_cfg_data *data; 235 + snd_config_t *sysfs_card_config; 230 236 231 - config = conf_load_from_file(filename); 232 - if (snd_config_search(config, "sysfs", &sysfs_config) || 233 - snd_config_get_type(sysfs_config) != SND_CONFIG_TYPE_COMPOUND) 234 - ksft_exit_fail_msg("Missing global sysfs block in filename %s\n", filename); 235 - if (snd_config_search(config, "card", &card_config) || 236 - snd_config_get_type(card_config) != SND_CONFIG_TYPE_COMPOUND) 237 - ksft_exit_fail_msg("Missing global card block in filename %s\n", filename); 238 - if (!sysfs_match(SYSFS_ROOT, sysfs_config)) 239 - return false; 240 - snd_config_for_each(i, next, card_config) { 241 - node = snd_config_iterator_entry(i); 242 - if (snd_config_search(node, "sysfs", &sysfs_card_config) || 243 - snd_config_get_type(sysfs_card_config) != SND_CONFIG_TYPE_COMPOUND) 244 - ksft_exit_fail_msg("Missing card sysfs block in filename %s\n", filename); 237 + for (data = conf_cards; data; data = data->next) { 238 + snd_config_search(data->config, "sysfs", &sysfs_card_config); 245 239 if (!sysfs_match(sysfs_card_root, sysfs_card_config)) 246 240 continue; 247 - data = malloc(sizeof(*data)); 248 - if (!data) 249 - ksft_exit_fail_msg("Out of memory\n"); 250 - data2 = conf_data_by_card(card, false); 251 - if (data2) 252 - ksft_exit_fail_msg("Duplicate card '%s' <-> '%s'\n", filename, data2->filename); 241 + 253 242 data->card = card; 254 - data->filename = filename; 255 - data->config = node; 256 - data->next = conf_cards; 257 - conf_cards = data; 258 - return true; 243 + break; 259 244 } 260 - return false; 261 245 } 262 246 263 - static bool test_filename(const char *filename) 247 + static void assign_card_configs(void) 264 248 { 265 249 char fn[128]; 266 250 int card; 267 251 268 252 for (card = 0; card < 32; card++) { 269 253 snprintf(fn, sizeof(fn), "%s/class/sound/card%d", SYSFS_ROOT, card); 270 - if (access(fn, R_OK) == 0 && test_filename1(card, filename, fn)) 271 - return true; 254 + if (access(fn, R_OK) == 0) 255 + assign_card_config(card, fn); 272 256 } 273 - return false; 274 257 } 275 258 276 259 static int filename_filter(const struct dirent *dirent) ··· 265 296 return 0; 266 297 } 267 298 299 + static bool match_config(const char *filename) 300 + { 301 + struct card_cfg_data *data; 302 + snd_config_t *config, *sysfs_config, *card_config, *sysfs_card_config, *node; 303 + snd_config_iterator_t i, next; 304 + 305 + config = conf_load_from_file(filename); 306 + if (snd_config_search(config, "sysfs", &sysfs_config) || 307 + snd_config_get_type(sysfs_config) != SND_CONFIG_TYPE_COMPOUND) 308 + ksft_exit_fail_msg("Missing global sysfs block in filename %s\n", filename); 309 + if (snd_config_search(config, "card", &card_config) || 310 + snd_config_get_type(card_config) != SND_CONFIG_TYPE_COMPOUND) 311 + ksft_exit_fail_msg("Missing global card block in filename %s\n", filename); 312 + if (!sysfs_match(SYSFS_ROOT, sysfs_config)) 313 + return false; 314 + snd_config_for_each(i, next, card_config) { 315 + node = snd_config_iterator_entry(i); 316 + if (snd_config_search(node, "sysfs", &sysfs_card_config) || 317 + snd_config_get_type(sysfs_card_config) != SND_CONFIG_TYPE_COMPOUND) 318 + ksft_exit_fail_msg("Missing card sysfs block in filename %s\n", filename); 319 + 320 + data = malloc(sizeof(*data)); 321 + if (!data) 322 + ksft_exit_fail_msg("Out of memory\n"); 323 + data->filename = filename; 324 + data->config = node; 325 + data->card = -1; 326 + if (snd_config_get_id(node, &data->config_id)) 327 + ksft_exit_fail_msg("snd_config_get_id failed for card\n"); 328 + data->next = conf_cards; 329 + conf_cards = data; 330 + } 331 + return true; 332 + } 333 + 268 334 void conf_load(void) 269 335 { 270 336 const char *fn = "conf.d"; ··· 315 311 if (filename == NULL) 316 312 ksft_exit_fail_msg("Out of memory\n"); 317 313 sprintf(filename, "%s/%s", fn, namelist[j]->d_name); 318 - if (test_filename(filename)) 314 + if (match_config(filename)) 319 315 filename = NULL; 320 316 free(filename); 321 317 free(namelist[j]); 322 318 } 323 319 free(namelist); 320 + 321 + assign_card_configs(); 324 322 } 325 323 326 324 void conf_free(void) 327 325 { 328 - struct card_data *conf; 326 + struct card_cfg_data *conf; 329 327 330 328 while (conf_cards) { 331 329 conf = conf_cards; ··· 338 332 339 333 snd_config_t *conf_by_card(int card) 340 334 { 341 - struct card_data *conf; 335 + struct card_cfg_data *conf; 342 336 343 337 conf = conf_data_by_card(card, true); 344 338 if (conf)
+10
tools/testing/selftests/alsa/pcm-test.c
··· 566 566 int main(void) 567 567 { 568 568 struct card_data *card; 569 + struct card_cfg_data *conf; 569 570 struct pcm_data *pcm; 570 571 snd_config_t *global_config, *cfg; 571 572 int num_pcm_tests = 0, num_tests, num_std_pcm_tests; ··· 584 583 585 584 find_pcms(); 586 585 586 + for (conf = conf_cards; conf; conf = conf->next) 587 + if (conf->card < 0) 588 + num_missing++; 589 + 587 590 num_std_pcm_tests = conf_get_count(default_pcm_config, "test", NULL); 588 591 589 592 for (pcm = pcm_list; pcm != NULL; pcm = pcm->next) { ··· 602 597 } 603 598 604 599 ksft_set_plan(num_missing + num_pcm_tests); 600 + 601 + for (conf = conf_cards; conf; conf = conf->next) 602 + if (conf->card < 0) 603 + ksft_test_result_fail("test.missing.%s.%s\n", 604 + conf->filename, conf->config_id); 605 605 606 606 for (pcm = pcm_missing; pcm != NULL; pcm = pcm->next) { 607 607 ksft_test_result(false, "test.missing.%d.%d.%d.%s\n",