Loading...
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * soc-topology-test.c -- ALSA SoC Topology Kernel Unit Tests
4 *
5 * Copyright(c) 2021 Intel Corporation. All rights reserved.
6 */
7
8#include <linux/firmware.h>
9#include <sound/core.h>
10#include <sound/soc.h>
11#include <sound/soc-topology.h>
12#include <kunit/test.h>
13
14/* ===== HELPER FUNCTIONS =================================================== */
15
16/*
17 * snd_soc_component needs device to operate on (primarily for prints), create
18 * fake one, as we don't register with PCI or anything else
19 * device_driver name is used in some of the prints (fmt_single_name) so
20 * we also mock up minimal one
21 */
22static struct device *test_dev;
23
24static struct device_driver test_drv = {
25 .name = "sound-soc-topology-test-driver",
26};
27
28static int snd_soc_tplg_test_init(struct kunit *test)
29{
30 test_dev = root_device_register("sound-soc-topology-test");
31 test_dev = get_device(test_dev);
32 if (!test_dev)
33 return -ENODEV;
34
35 test_dev->driver = &test_drv;
36
37 return 0;
38}
39
40static void snd_soc_tplg_test_exit(struct kunit *test)
41{
42 put_device(test_dev);
43 root_device_unregister(test_dev);
44}
45
46/*
47 * helper struct we use when registering component, as we load topology during
48 * component probe, we need to pass struct kunit somehow to probe function, so
49 * we can report test result
50 */
51struct kunit_soc_component {
52 struct kunit *kunit;
53 int expect; /* what result we expect when loading topology */
54 struct snd_soc_component comp;
55 struct snd_soc_card card;
56 struct firmware fw;
57};
58
59static int d_probe(struct snd_soc_component *component)
60{
61 struct kunit_soc_component *kunit_comp =
62 container_of(component, struct kunit_soc_component, comp);
63 int ret;
64
65 ret = snd_soc_tplg_component_load(component, NULL, &kunit_comp->fw);
66 KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
67 "Failed topology load");
68
69 return 0;
70}
71
72static void d_remove(struct snd_soc_component *component)
73{
74 struct kunit_soc_component *kunit_comp =
75 container_of(component, struct kunit_soc_component, comp);
76 int ret;
77
78 ret = snd_soc_tplg_component_remove(component);
79 KUNIT_EXPECT_EQ(kunit_comp->kunit, 0, ret);
80}
81
82/*
83 * ASoC minimal boiler plate
84 */
85SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY()));
86
87SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sound-soc-topology-test")));
88
89static struct snd_soc_dai_link kunit_dai_links[] = {
90 {
91 .name = "KUNIT Audio Port",
92 .id = 0,
93 .stream_name = "Audio Playback/Capture",
94 .nonatomic = 1,
95 .dynamic = 1,
96 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
97 .dpcm_playback = 1,
98 .dpcm_capture = 1,
99 SND_SOC_DAILINK_REG(dummy, dummy, platform),
100 },
101};
102
103static const struct snd_soc_component_driver test_component = {
104 .name = "sound-soc-topology-test",
105 .probe = d_probe,
106 .remove = d_remove,
107};
108
109/* ===== TOPOLOGY TEMPLATES ================================================= */
110
111// Structural representation of topology which can be generated with:
112// $ touch empty
113// $ alsatplg -c empty -o empty.tplg
114// $ xxd -i empty.tplg
115
116struct tplg_tmpl_001 {
117 struct snd_soc_tplg_hdr header;
118 struct snd_soc_tplg_manifest manifest;
119} __packed;
120
121static struct tplg_tmpl_001 tplg_tmpl_empty = {
122 .header = {
123 .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
124 .abi = cpu_to_le32(5),
125 .version = 0,
126 .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST),
127 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
128 .vendor_type = 0,
129 .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
130 .index = 0,
131 .count = cpu_to_le32(1),
132 },
133
134 .manifest = {
135 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
136 /* rest of fields is 0 */
137 },
138};
139
140// Structural representation of topology containing SectionPCM
141
142struct tplg_tmpl_002 {
143 struct snd_soc_tplg_hdr header;
144 struct snd_soc_tplg_manifest manifest;
145 struct snd_soc_tplg_hdr pcm_header;
146 struct snd_soc_tplg_pcm pcm;
147} __packed;
148
149static struct tplg_tmpl_002 tplg_tmpl_with_pcm = {
150 .header = {
151 .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
152 .abi = cpu_to_le32(5),
153 .version = 0,
154 .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST),
155 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
156 .vendor_type = 0,
157 .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
158 .index = 0,
159 .count = cpu_to_le32(1),
160 },
161 .manifest = {
162 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
163 .pcm_elems = cpu_to_le32(1),
164 /* rest of fields is 0 */
165 },
166 .pcm_header = {
167 .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
168 .abi = cpu_to_le32(5),
169 .version = 0,
170 .type = cpu_to_le32(SND_SOC_TPLG_TYPE_PCM),
171 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
172 .vendor_type = 0,
173 .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)),
174 .index = 0,
175 .count = cpu_to_le32(1),
176 },
177 .pcm = {
178 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)),
179 .pcm_name = "KUNIT Audio",
180 .dai_name = "kunit-audio-dai",
181 .pcm_id = 0,
182 .dai_id = 0,
183 .playback = cpu_to_le32(1),
184 .capture = cpu_to_le32(1),
185 .compress = 0,
186 .stream = {
187 [0] = {
188 .channels = cpu_to_le32(2),
189 },
190 [1] = {
191 .channels = cpu_to_le32(2),
192 },
193 },
194 .num_streams = 0,
195 .caps = {
196 [0] = {
197 .name = "kunit-audio-playback",
198 .channels_min = cpu_to_le32(2),
199 .channels_max = cpu_to_le32(2),
200 },
201 [1] = {
202 .name = "kunit-audio-capture",
203 .channels_min = cpu_to_le32(2),
204 .channels_max = cpu_to_le32(2),
205 },
206 },
207 .flag_mask = 0,
208 .flags = 0,
209 .priv = { 0 },
210 },
211};
212
213/* ===== TEST CASES ========================================================= */
214
215// TEST CASE
216// Test passing NULL component as parameter to snd_soc_tplg_component_load
217
218/*
219 * need to override generic probe function with one using NULL when calling
220 * topology load during component initialization, we don't need .remove
221 * handler as load should fail
222 */
223static int d_probe_null_comp(struct snd_soc_component *component)
224{
225 struct kunit_soc_component *kunit_comp =
226 container_of(component, struct kunit_soc_component, comp);
227 int ret;
228
229 /* instead of passing component pointer as first argument, pass NULL here */
230 ret = snd_soc_tplg_component_load(NULL, NULL, &kunit_comp->fw);
231 KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
232 "Failed topology load");
233
234 return 0;
235}
236
237static const struct snd_soc_component_driver test_component_null_comp = {
238 .name = "sound-soc-topology-test",
239 .probe = d_probe_null_comp,
240};
241
242static void snd_soc_tplg_test_load_with_null_comp(struct kunit *test)
243{
244 struct kunit_soc_component *kunit_comp;
245 int ret;
246
247 /* prepare */
248 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
249 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
250 kunit_comp->kunit = test;
251 kunit_comp->expect = -EINVAL; /* expect failure */
252
253 kunit_comp->card.dev = test_dev,
254 kunit_comp->card.name = "kunit-card",
255 kunit_comp->card.owner = THIS_MODULE,
256 kunit_comp->card.dai_link = kunit_dai_links,
257 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
258 kunit_comp->card.fully_routed = true,
259
260 /* run test */
261 ret = snd_soc_register_card(&kunit_comp->card);
262 if (ret != 0 && ret != -EPROBE_DEFER)
263 KUNIT_FAIL(test, "Failed to register card");
264
265 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_comp, test_dev);
266 KUNIT_EXPECT_EQ(test, 0, ret);
267
268 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
269 KUNIT_EXPECT_EQ(test, 0, ret);
270
271 /* cleanup */
272 snd_soc_unregister_card(&kunit_comp->card);
273 snd_soc_unregister_component(test_dev);
274}
275
276// TEST CASE
277// Test passing NULL ops as parameter to snd_soc_tplg_component_load
278
279/*
280 * NULL ops is default case, we pass empty topology (fw), so we don't have
281 * anything to parse and just do nothing, which results in return 0; from
282 * calling soc_tplg_dapm_complete in soc_tplg_process_headers
283 */
284static void snd_soc_tplg_test_load_with_null_ops(struct kunit *test)
285{
286 struct kunit_soc_component *kunit_comp;
287 int ret;
288
289 /* prepare */
290 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
291 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
292 kunit_comp->kunit = test;
293 kunit_comp->expect = 0; /* expect success */
294
295 kunit_comp->card.dev = test_dev,
296 kunit_comp->card.name = "kunit-card",
297 kunit_comp->card.owner = THIS_MODULE,
298 kunit_comp->card.dai_link = kunit_dai_links,
299 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
300 kunit_comp->card.fully_routed = true,
301
302 /* run test */
303 ret = snd_soc_register_card(&kunit_comp->card);
304 if (ret != 0 && ret != -EPROBE_DEFER)
305 KUNIT_FAIL(test, "Failed to register card");
306
307 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
308 KUNIT_EXPECT_EQ(test, 0, ret);
309
310 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
311 KUNIT_EXPECT_EQ(test, 0, ret);
312
313 /* cleanup */
314 snd_soc_unregister_card(&kunit_comp->card);
315
316 snd_soc_unregister_component(test_dev);
317}
318
319// TEST CASE
320// Test passing NULL fw as parameter to snd_soc_tplg_component_load
321
322/*
323 * need to override generic probe function with one using NULL pointer to fw
324 * when calling topology load during component initialization, we don't need
325 * .remove handler as load should fail
326 */
327static int d_probe_null_fw(struct snd_soc_component *component)
328{
329 struct kunit_soc_component *kunit_comp =
330 container_of(component, struct kunit_soc_component, comp);
331 int ret;
332
333 /* instead of passing fw pointer as third argument, pass NULL here */
334 ret = snd_soc_tplg_component_load(component, NULL, NULL);
335 KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
336 "Failed topology load");
337
338 return 0;
339}
340
341static const struct snd_soc_component_driver test_component_null_fw = {
342 .name = "sound-soc-topology-test",
343 .probe = d_probe_null_fw,
344};
345
346static void snd_soc_tplg_test_load_with_null_fw(struct kunit *test)
347{
348 struct kunit_soc_component *kunit_comp;
349 int ret;
350
351 /* prepare */
352 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
353 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
354 kunit_comp->kunit = test;
355 kunit_comp->expect = -EINVAL; /* expect failure */
356
357 kunit_comp->card.dev = test_dev,
358 kunit_comp->card.name = "kunit-card",
359 kunit_comp->card.owner = THIS_MODULE,
360 kunit_comp->card.dai_link = kunit_dai_links,
361 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
362 kunit_comp->card.fully_routed = true,
363
364 /* run test */
365 ret = snd_soc_register_card(&kunit_comp->card);
366 if (ret != 0 && ret != -EPROBE_DEFER)
367 KUNIT_FAIL(test, "Failed to register card");
368
369 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_fw, test_dev);
370 KUNIT_EXPECT_EQ(test, 0, ret);
371
372 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
373 KUNIT_EXPECT_EQ(test, 0, ret);
374
375 /* cleanup */
376 snd_soc_unregister_card(&kunit_comp->card);
377
378 snd_soc_unregister_component(test_dev);
379}
380
381// TEST CASE
382// Test passing "empty" topology file
383static void snd_soc_tplg_test_load_empty_tplg(struct kunit *test)
384{
385 struct kunit_soc_component *kunit_comp;
386 struct tplg_tmpl_001 *data;
387 int size;
388 int ret;
389
390 /* prepare */
391 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
392 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
393 kunit_comp->kunit = test;
394 kunit_comp->expect = 0; /* expect success */
395
396 size = sizeof(tplg_tmpl_empty);
397 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
398 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
399
400 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
401
402 kunit_comp->fw.data = (u8 *)data;
403 kunit_comp->fw.size = size;
404
405 kunit_comp->card.dev = test_dev,
406 kunit_comp->card.name = "kunit-card",
407 kunit_comp->card.owner = THIS_MODULE,
408 kunit_comp->card.dai_link = kunit_dai_links,
409 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
410 kunit_comp->card.fully_routed = true,
411
412 /* run test */
413 ret = snd_soc_register_card(&kunit_comp->card);
414 if (ret != 0 && ret != -EPROBE_DEFER)
415 KUNIT_FAIL(test, "Failed to register card");
416
417 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
418 KUNIT_EXPECT_EQ(test, 0, ret);
419
420 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
421 KUNIT_EXPECT_EQ(test, 0, ret);
422
423 /* cleanup */
424 snd_soc_unregister_card(&kunit_comp->card);
425
426 snd_soc_unregister_component(test_dev);
427}
428
429// TEST CASE
430// Test "empty" topology file, but with bad "magic"
431// In theory we could loop through all possible bad values, but it takes too
432// long, so just use SND_SOC_TPLG_MAGIC + 1
433static void snd_soc_tplg_test_load_empty_tplg_bad_magic(struct kunit *test)
434{
435 struct kunit_soc_component *kunit_comp;
436 struct tplg_tmpl_001 *data;
437 int size;
438 int ret;
439
440 /* prepare */
441 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
442 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
443 kunit_comp->kunit = test;
444 kunit_comp->expect = -EINVAL; /* expect failure */
445
446 size = sizeof(tplg_tmpl_empty);
447 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
448 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
449
450 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
451 /*
452 * override abi
453 * any value != magic number is wrong
454 */
455 data->header.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC + 1);
456
457 kunit_comp->fw.data = (u8 *)data;
458 kunit_comp->fw.size = size;
459
460 kunit_comp->card.dev = test_dev,
461 kunit_comp->card.name = "kunit-card",
462 kunit_comp->card.owner = THIS_MODULE,
463 kunit_comp->card.dai_link = kunit_dai_links,
464 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
465 kunit_comp->card.fully_routed = true,
466
467 /* run test */
468 ret = snd_soc_register_card(&kunit_comp->card);
469 if (ret != 0 && ret != -EPROBE_DEFER)
470 KUNIT_FAIL(test, "Failed to register card");
471
472 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
473 KUNIT_EXPECT_EQ(test, 0, ret);
474
475 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
476 KUNIT_EXPECT_EQ(test, 0, ret);
477
478 /* cleanup */
479 snd_soc_unregister_card(&kunit_comp->card);
480
481 snd_soc_unregister_component(test_dev);
482}
483
484// TEST CASE
485// Test "empty" topology file, but with bad "abi"
486// In theory we could loop through all possible bad values, but it takes too
487// long, so just use SND_SOC_TPLG_ABI_VERSION + 1
488static void snd_soc_tplg_test_load_empty_tplg_bad_abi(struct kunit *test)
489{
490 struct kunit_soc_component *kunit_comp;
491 struct tplg_tmpl_001 *data;
492 int size;
493 int ret;
494
495 /* prepare */
496 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
497 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
498 kunit_comp->kunit = test;
499 kunit_comp->expect = -EINVAL; /* expect failure */
500
501 size = sizeof(tplg_tmpl_empty);
502 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
503 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
504
505 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
506 /*
507 * override abi
508 * any value != accepted range is wrong
509 */
510 data->header.abi = cpu_to_le32(SND_SOC_TPLG_ABI_VERSION + 1);
511
512 kunit_comp->fw.data = (u8 *)data;
513 kunit_comp->fw.size = size;
514
515 kunit_comp->card.dev = test_dev,
516 kunit_comp->card.name = "kunit-card",
517 kunit_comp->card.owner = THIS_MODULE,
518 kunit_comp->card.dai_link = kunit_dai_links,
519 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
520 kunit_comp->card.fully_routed = true,
521
522 /* run test */
523 ret = snd_soc_register_card(&kunit_comp->card);
524 if (ret != 0 && ret != -EPROBE_DEFER)
525 KUNIT_FAIL(test, "Failed to register card");
526
527 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
528 KUNIT_EXPECT_EQ(test, 0, ret);
529
530 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
531 KUNIT_EXPECT_EQ(test, 0, ret);
532
533 /* cleanup */
534 snd_soc_unregister_card(&kunit_comp->card);
535
536 snd_soc_unregister_component(test_dev);
537}
538
539// TEST CASE
540// Test "empty" topology file, but with bad "size"
541// In theory we could loop through all possible bad values, but it takes too
542// long, so just use sizeof(struct snd_soc_tplg_hdr) + 1
543static void snd_soc_tplg_test_load_empty_tplg_bad_size(struct kunit *test)
544{
545 struct kunit_soc_component *kunit_comp;
546 struct tplg_tmpl_001 *data;
547 int size;
548 int ret;
549
550 /* prepare */
551 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
552 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
553 kunit_comp->kunit = test;
554 kunit_comp->expect = -EINVAL; /* expect failure */
555
556 size = sizeof(tplg_tmpl_empty);
557 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
558 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
559
560 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
561 /*
562 * override size
563 * any value != struct size is wrong
564 */
565 data->header.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr) + 1);
566
567 kunit_comp->fw.data = (u8 *)data;
568 kunit_comp->fw.size = size;
569
570 kunit_comp->card.dev = test_dev,
571 kunit_comp->card.name = "kunit-card",
572 kunit_comp->card.owner = THIS_MODULE,
573 kunit_comp->card.dai_link = kunit_dai_links,
574 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
575 kunit_comp->card.fully_routed = true,
576
577 /* run test */
578 ret = snd_soc_register_card(&kunit_comp->card);
579 if (ret != 0 && ret != -EPROBE_DEFER)
580 KUNIT_FAIL(test, "Failed to register card");
581
582 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
583 KUNIT_EXPECT_EQ(test, 0, ret);
584
585 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
586 KUNIT_EXPECT_EQ(test, 0, ret);
587
588 /* cleanup */
589 snd_soc_unregister_card(&kunit_comp->card);
590
591 snd_soc_unregister_component(test_dev);
592}
593
594// TEST CASE
595// Test "empty" topology file, but with bad "payload_size"
596// In theory we could loop through all possible bad values, but it takes too
597// long, so just use the known wrong one
598static void snd_soc_tplg_test_load_empty_tplg_bad_payload_size(struct kunit *test)
599{
600 struct kunit_soc_component *kunit_comp;
601 struct tplg_tmpl_001 *data;
602 int size;
603 int ret;
604
605 /* prepare */
606 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
607 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
608 kunit_comp->kunit = test;
609 kunit_comp->expect = -EINVAL; /* expect failure */
610
611 size = sizeof(tplg_tmpl_empty);
612 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
613 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
614
615 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
616 /*
617 * override payload size
618 * there is only explicit check for 0, so check with it, other values
619 * are handled by just not reading behind EOF
620 */
621 data->header.payload_size = 0;
622
623 kunit_comp->fw.data = (u8 *)data;
624 kunit_comp->fw.size = size;
625
626 kunit_comp->card.dev = test_dev,
627 kunit_comp->card.name = "kunit-card",
628 kunit_comp->card.owner = THIS_MODULE,
629 kunit_comp->card.dai_link = kunit_dai_links,
630 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
631 kunit_comp->card.fully_routed = true,
632
633 /* run test */
634 ret = snd_soc_register_card(&kunit_comp->card);
635 if (ret != 0 && ret != -EPROBE_DEFER)
636 KUNIT_FAIL(test, "Failed to register card");
637
638 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
639 KUNIT_EXPECT_EQ(test, 0, ret);
640
641 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
642 KUNIT_EXPECT_EQ(test, 0, ret);
643
644 /* cleanup */
645 snd_soc_unregister_component(test_dev);
646
647 snd_soc_unregister_card(&kunit_comp->card);
648}
649
650// TEST CASE
651// Test passing topology file with PCM definition
652static void snd_soc_tplg_test_load_pcm_tplg(struct kunit *test)
653{
654 struct kunit_soc_component *kunit_comp;
655 u8 *data;
656 int size;
657 int ret;
658
659 /* prepare */
660 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
661 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
662 kunit_comp->kunit = test;
663 kunit_comp->expect = 0; /* expect success */
664
665 size = sizeof(tplg_tmpl_with_pcm);
666 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
667 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
668
669 memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
670
671 kunit_comp->fw.data = data;
672 kunit_comp->fw.size = size;
673
674 kunit_comp->card.dev = test_dev,
675 kunit_comp->card.name = "kunit-card",
676 kunit_comp->card.owner = THIS_MODULE,
677 kunit_comp->card.dai_link = kunit_dai_links,
678 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
679 kunit_comp->card.fully_routed = true,
680
681 /* run test */
682 ret = snd_soc_register_card(&kunit_comp->card);
683 if (ret != 0 && ret != -EPROBE_DEFER)
684 KUNIT_FAIL(test, "Failed to register card");
685
686 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
687 KUNIT_EXPECT_EQ(test, 0, ret);
688
689 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
690 KUNIT_EXPECT_EQ(test, 0, ret);
691
692 snd_soc_unregister_component(test_dev);
693
694 /* cleanup */
695 snd_soc_unregister_card(&kunit_comp->card);
696}
697
698// TEST CASE
699// Test passing topology file with PCM definition
700// with component reload
701static void snd_soc_tplg_test_load_pcm_tplg_reload_comp(struct kunit *test)
702{
703 struct kunit_soc_component *kunit_comp;
704 u8 *data;
705 int size;
706 int ret;
707 int i;
708
709 /* prepare */
710 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
711 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
712 kunit_comp->kunit = test;
713 kunit_comp->expect = 0; /* expect success */
714
715 size = sizeof(tplg_tmpl_with_pcm);
716 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
717 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
718
719 memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
720
721 kunit_comp->fw.data = data;
722 kunit_comp->fw.size = size;
723
724 kunit_comp->card.dev = test_dev,
725 kunit_comp->card.name = "kunit-card",
726 kunit_comp->card.owner = THIS_MODULE,
727 kunit_comp->card.dai_link = kunit_dai_links,
728 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
729 kunit_comp->card.fully_routed = true,
730
731 /* run test */
732 ret = snd_soc_register_card(&kunit_comp->card);
733 if (ret != 0 && ret != -EPROBE_DEFER)
734 KUNIT_FAIL(test, "Failed to register card");
735
736 for (i = 0; i < 100; i++) {
737 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
738 KUNIT_EXPECT_EQ(test, 0, ret);
739
740 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
741 KUNIT_EXPECT_EQ(test, 0, ret);
742
743 snd_soc_unregister_component(test_dev);
744 }
745
746 /* cleanup */
747 snd_soc_unregister_card(&kunit_comp->card);
748}
749
750// TEST CASE
751// Test passing topology file with PCM definition
752// with card reload
753static void snd_soc_tplg_test_load_pcm_tplg_reload_card(struct kunit *test)
754{
755 struct kunit_soc_component *kunit_comp;
756 u8 *data;
757 int size;
758 int ret;
759 int i;
760
761 /* prepare */
762 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
763 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
764 kunit_comp->kunit = test;
765 kunit_comp->expect = 0; /* expect success */
766
767 size = sizeof(tplg_tmpl_with_pcm);
768 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
769 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
770
771 memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
772
773 kunit_comp->fw.data = data;
774 kunit_comp->fw.size = size;
775
776 kunit_comp->card.dev = test_dev,
777 kunit_comp->card.name = "kunit-card",
778 kunit_comp->card.owner = THIS_MODULE,
779 kunit_comp->card.dai_link = kunit_dai_links,
780 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links),
781 kunit_comp->card.fully_routed = true,
782
783 /* run test */
784 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
785 KUNIT_EXPECT_EQ(test, 0, ret);
786
787 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
788 KUNIT_EXPECT_EQ(test, 0, ret);
789
790 for (i = 0; i < 100; i++) {
791 ret = snd_soc_register_card(&kunit_comp->card);
792 if (ret != 0 && ret != -EPROBE_DEFER)
793 KUNIT_FAIL(test, "Failed to register card");
794
795 snd_soc_unregister_card(&kunit_comp->card);
796 }
797
798 /* cleanup */
799 snd_soc_unregister_component(test_dev);
800}
801
802/* ===== KUNIT MODULE DEFINITIONS =========================================== */
803
804static struct kunit_case snd_soc_tplg_test_cases[] = {
805 KUNIT_CASE(snd_soc_tplg_test_load_with_null_comp),
806 KUNIT_CASE(snd_soc_tplg_test_load_with_null_ops),
807 KUNIT_CASE(snd_soc_tplg_test_load_with_null_fw),
808 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg),
809 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_magic),
810 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_abi),
811 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_size),
812 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_payload_size),
813 KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg),
814 KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_comp),
815 KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_card),
816 {}
817};
818
819static struct kunit_suite snd_soc_tplg_test_suite = {
820 .name = "snd_soc_tplg_test",
821 .init = snd_soc_tplg_test_init,
822 .exit = snd_soc_tplg_test_exit,
823 .test_cases = snd_soc_tplg_test_cases,
824};
825
826kunit_test_suites(&snd_soc_tplg_test_suite);
827
828MODULE_LICENSE("GPL");
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * soc-topology-test.c -- ALSA SoC Topology Kernel Unit Tests
4 *
5 * Copyright(c) 2021 Intel Corporation.
6 */
7
8#include <linux/firmware.h>
9#include <sound/core.h>
10#include <sound/soc.h>
11#include <sound/soc-topology.h>
12#include <kunit/device.h>
13#include <kunit/test.h>
14
15/* ===== HELPER FUNCTIONS =================================================== */
16
17/*
18 * snd_soc_component needs device to operate on (primarily for prints), create
19 * fake one, as we don't register with PCI or anything else
20 * device_driver name is used in some of the prints (fmt_single_name) so
21 * we also mock up minimal one
22 */
23static struct device *test_dev;
24
25static int snd_soc_tplg_test_init(struct kunit *test)
26{
27 test_dev = kunit_device_register(test, "sound-soc-topology-test");
28 test_dev = get_device(test_dev);
29 if (!test_dev)
30 return -ENODEV;
31
32 return 0;
33}
34
35static void snd_soc_tplg_test_exit(struct kunit *test)
36{
37 put_device(test_dev);
38}
39
40/*
41 * helper struct we use when registering component, as we load topology during
42 * component probe, we need to pass struct kunit somehow to probe function, so
43 * we can report test result
44 */
45struct kunit_soc_component {
46 struct kunit *kunit;
47 int expect; /* what result we expect when loading topology */
48 struct snd_soc_component comp;
49 struct snd_soc_card card;
50 struct firmware fw;
51};
52
53static int d_probe(struct snd_soc_component *component)
54{
55 struct kunit_soc_component *kunit_comp =
56 container_of(component, struct kunit_soc_component, comp);
57 int ret;
58
59 ret = snd_soc_tplg_component_load(component, NULL, &kunit_comp->fw);
60 KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
61 "Failed topology load");
62
63 return 0;
64}
65
66static void d_remove(struct snd_soc_component *component)
67{
68 struct kunit_soc_component *kunit_comp =
69 container_of(component, struct kunit_soc_component, comp);
70 int ret;
71
72 ret = snd_soc_tplg_component_remove(component);
73 KUNIT_EXPECT_EQ(kunit_comp->kunit, 0, ret);
74}
75
76/*
77 * ASoC minimal boiler plate
78 */
79SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY()));
80
81SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sound-soc-topology-test")));
82
83static struct snd_soc_dai_link kunit_dai_links[] = {
84 {
85 .name = "KUNIT Audio Port",
86 .id = 0,
87 .stream_name = "Audio Playback/Capture",
88 .nonatomic = 1,
89 .dynamic = 1,
90 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
91 SND_SOC_DAILINK_REG(dummy, dummy, platform),
92 },
93};
94
95static const struct snd_soc_component_driver test_component = {
96 .name = "sound-soc-topology-test",
97 .probe = d_probe,
98 .remove = d_remove,
99};
100
101/* ===== TOPOLOGY TEMPLATES ================================================= */
102
103// Structural representation of topology which can be generated with:
104// $ touch empty
105// $ alsatplg -c empty -o empty.tplg
106// $ xxd -i empty.tplg
107
108struct tplg_tmpl_001 {
109 struct snd_soc_tplg_hdr header;
110 struct snd_soc_tplg_manifest manifest;
111} __packed;
112
113static struct tplg_tmpl_001 tplg_tmpl_empty = {
114 .header = {
115 .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
116 .abi = cpu_to_le32(5),
117 .version = 0,
118 .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST),
119 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
120 .vendor_type = 0,
121 .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
122 .index = 0,
123 .count = cpu_to_le32(1),
124 },
125
126 .manifest = {
127 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
128 /* rest of fields is 0 */
129 },
130};
131
132// Structural representation of topology containing SectionPCM
133
134struct tplg_tmpl_002 {
135 struct snd_soc_tplg_hdr header;
136 struct snd_soc_tplg_manifest manifest;
137 struct snd_soc_tplg_hdr pcm_header;
138 struct snd_soc_tplg_pcm pcm;
139} __packed;
140
141static struct tplg_tmpl_002 tplg_tmpl_with_pcm = {
142 .header = {
143 .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
144 .abi = cpu_to_le32(5),
145 .version = 0,
146 .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST),
147 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
148 .vendor_type = 0,
149 .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
150 .index = 0,
151 .count = cpu_to_le32(1),
152 },
153 .manifest = {
154 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)),
155 .pcm_elems = cpu_to_le32(1),
156 /* rest of fields is 0 */
157 },
158 .pcm_header = {
159 .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC),
160 .abi = cpu_to_le32(5),
161 .version = 0,
162 .type = cpu_to_le32(SND_SOC_TPLG_TYPE_PCM),
163 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)),
164 .vendor_type = 0,
165 .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)),
166 .index = 0,
167 .count = cpu_to_le32(1),
168 },
169 .pcm = {
170 .size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)),
171 .pcm_name = "KUNIT Audio",
172 .dai_name = "kunit-audio-dai",
173 .pcm_id = 0,
174 .dai_id = 0,
175 .playback = cpu_to_le32(1),
176 .capture = cpu_to_le32(1),
177 .compress = 0,
178 .stream = {
179 [0] = {
180 .channels = cpu_to_le32(2),
181 },
182 [1] = {
183 .channels = cpu_to_le32(2),
184 },
185 },
186 .num_streams = 0,
187 .caps = {
188 [0] = {
189 .name = "kunit-audio-playback",
190 .channels_min = cpu_to_le32(2),
191 .channels_max = cpu_to_le32(2),
192 },
193 [1] = {
194 .name = "kunit-audio-capture",
195 .channels_min = cpu_to_le32(2),
196 .channels_max = cpu_to_le32(2),
197 },
198 },
199 .flag_mask = 0,
200 .flags = 0,
201 .priv = { 0 },
202 },
203};
204
205/* ===== TEST CASES ========================================================= */
206
207// TEST CASE
208// Test passing NULL component as parameter to snd_soc_tplg_component_load
209
210/*
211 * need to override generic probe function with one using NULL when calling
212 * topology load during component initialization, we don't need .remove
213 * handler as load should fail
214 */
215static int d_probe_null_comp(struct snd_soc_component *component)
216{
217 struct kunit_soc_component *kunit_comp =
218 container_of(component, struct kunit_soc_component, comp);
219 int ret;
220
221 /* instead of passing component pointer as first argument, pass NULL here */
222 ret = snd_soc_tplg_component_load(NULL, NULL, &kunit_comp->fw);
223 KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
224 "Failed topology load");
225
226 return 0;
227}
228
229static const struct snd_soc_component_driver test_component_null_comp = {
230 .name = "sound-soc-topology-test",
231 .probe = d_probe_null_comp,
232};
233
234static void snd_soc_tplg_test_load_with_null_comp(struct kunit *test)
235{
236 struct kunit_soc_component *kunit_comp;
237 int ret;
238
239 /* prepare */
240 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
241 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
242 kunit_comp->kunit = test;
243 kunit_comp->expect = -EINVAL; /* expect failure */
244
245 kunit_comp->card.dev = test_dev;
246 kunit_comp->card.name = "kunit-card";
247 kunit_comp->card.owner = THIS_MODULE;
248 kunit_comp->card.dai_link = kunit_dai_links;
249 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
250 kunit_comp->card.fully_routed = true;
251
252 /* run test */
253 ret = snd_soc_register_card(&kunit_comp->card);
254 if (ret != 0 && ret != -EPROBE_DEFER)
255 KUNIT_FAIL(test, "Failed to register card");
256
257 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_comp, test_dev);
258 KUNIT_EXPECT_EQ(test, 0, ret);
259
260 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
261 KUNIT_EXPECT_EQ(test, 0, ret);
262
263 /* cleanup */
264 snd_soc_unregister_card(&kunit_comp->card);
265 snd_soc_unregister_component(test_dev);
266}
267
268// TEST CASE
269// Test passing NULL ops as parameter to snd_soc_tplg_component_load
270
271/*
272 * NULL ops is default case, we pass empty topology (fw), so we don't have
273 * anything to parse and just do nothing, which results in return 0; from
274 * calling soc_tplg_dapm_complete in soc_tplg_process_headers
275 */
276static void snd_soc_tplg_test_load_with_null_ops(struct kunit *test)
277{
278 struct kunit_soc_component *kunit_comp;
279 int ret;
280
281 /* prepare */
282 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
283 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
284 kunit_comp->kunit = test;
285 kunit_comp->expect = 0; /* expect success */
286
287 kunit_comp->card.dev = test_dev;
288 kunit_comp->card.name = "kunit-card";
289 kunit_comp->card.owner = THIS_MODULE;
290 kunit_comp->card.dai_link = kunit_dai_links;
291 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
292 kunit_comp->card.fully_routed = true;
293
294 /* run test */
295 ret = snd_soc_register_card(&kunit_comp->card);
296 if (ret != 0 && ret != -EPROBE_DEFER)
297 KUNIT_FAIL(test, "Failed to register card");
298
299 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
300 KUNIT_EXPECT_EQ(test, 0, ret);
301
302 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
303 KUNIT_EXPECT_EQ(test, 0, ret);
304
305 /* cleanup */
306 snd_soc_unregister_card(&kunit_comp->card);
307
308 snd_soc_unregister_component(test_dev);
309}
310
311// TEST CASE
312// Test passing NULL fw as parameter to snd_soc_tplg_component_load
313
314/*
315 * need to override generic probe function with one using NULL pointer to fw
316 * when calling topology load during component initialization, we don't need
317 * .remove handler as load should fail
318 */
319static int d_probe_null_fw(struct snd_soc_component *component)
320{
321 struct kunit_soc_component *kunit_comp =
322 container_of(component, struct kunit_soc_component, comp);
323 int ret;
324
325 /* instead of passing fw pointer as third argument, pass NULL here */
326 ret = snd_soc_tplg_component_load(component, NULL, NULL);
327 KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret,
328 "Failed topology load");
329
330 return 0;
331}
332
333static const struct snd_soc_component_driver test_component_null_fw = {
334 .name = "sound-soc-topology-test",
335 .probe = d_probe_null_fw,
336};
337
338static void snd_soc_tplg_test_load_with_null_fw(struct kunit *test)
339{
340 struct kunit_soc_component *kunit_comp;
341 int ret;
342
343 /* prepare */
344 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
345 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
346 kunit_comp->kunit = test;
347 kunit_comp->expect = -EINVAL; /* expect failure */
348
349 kunit_comp->card.dev = test_dev;
350 kunit_comp->card.name = "kunit-card";
351 kunit_comp->card.owner = THIS_MODULE;
352 kunit_comp->card.dai_link = kunit_dai_links;
353 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
354 kunit_comp->card.fully_routed = true;
355
356 /* run test */
357 ret = snd_soc_register_card(&kunit_comp->card);
358 if (ret != 0 && ret != -EPROBE_DEFER)
359 KUNIT_FAIL(test, "Failed to register card");
360
361 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_fw, test_dev);
362 KUNIT_EXPECT_EQ(test, 0, ret);
363
364 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
365 KUNIT_EXPECT_EQ(test, 0, ret);
366
367 /* cleanup */
368 snd_soc_unregister_card(&kunit_comp->card);
369
370 snd_soc_unregister_component(test_dev);
371}
372
373// TEST CASE
374// Test passing "empty" topology file
375static void snd_soc_tplg_test_load_empty_tplg(struct kunit *test)
376{
377 struct kunit_soc_component *kunit_comp;
378 struct tplg_tmpl_001 *data;
379 int size;
380 int ret;
381
382 /* prepare */
383 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
384 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
385 kunit_comp->kunit = test;
386 kunit_comp->expect = 0; /* expect success */
387
388 size = sizeof(tplg_tmpl_empty);
389 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
390 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
391
392 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
393
394 kunit_comp->fw.data = (u8 *)data;
395 kunit_comp->fw.size = size;
396
397 kunit_comp->card.dev = test_dev;
398 kunit_comp->card.name = "kunit-card";
399 kunit_comp->card.owner = THIS_MODULE;
400 kunit_comp->card.dai_link = kunit_dai_links;
401 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
402 kunit_comp->card.fully_routed = true;
403
404 /* run test */
405 ret = snd_soc_register_card(&kunit_comp->card);
406 if (ret != 0 && ret != -EPROBE_DEFER)
407 KUNIT_FAIL(test, "Failed to register card");
408
409 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
410 KUNIT_EXPECT_EQ(test, 0, ret);
411
412 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
413 KUNIT_EXPECT_EQ(test, 0, ret);
414
415 /* cleanup */
416 snd_soc_unregister_card(&kunit_comp->card);
417
418 snd_soc_unregister_component(test_dev);
419}
420
421// TEST CASE
422// Test "empty" topology file, but with bad "magic"
423// In theory we could loop through all possible bad values, but it takes too
424// long, so just use SND_SOC_TPLG_MAGIC + 1
425static void snd_soc_tplg_test_load_empty_tplg_bad_magic(struct kunit *test)
426{
427 struct kunit_soc_component *kunit_comp;
428 struct tplg_tmpl_001 *data;
429 int size;
430 int ret;
431
432 /* prepare */
433 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
434 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
435 kunit_comp->kunit = test;
436 kunit_comp->expect = -EINVAL; /* expect failure */
437
438 size = sizeof(tplg_tmpl_empty);
439 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
440 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
441
442 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
443 /*
444 * override abi
445 * any value != magic number is wrong
446 */
447 data->header.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC + 1);
448
449 kunit_comp->fw.data = (u8 *)data;
450 kunit_comp->fw.size = size;
451
452 kunit_comp->card.dev = test_dev;
453 kunit_comp->card.name = "kunit-card";
454 kunit_comp->card.owner = THIS_MODULE;
455 kunit_comp->card.dai_link = kunit_dai_links;
456 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
457 kunit_comp->card.fully_routed = true;
458
459 /* run test */
460 ret = snd_soc_register_card(&kunit_comp->card);
461 if (ret != 0 && ret != -EPROBE_DEFER)
462 KUNIT_FAIL(test, "Failed to register card");
463
464 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
465 KUNIT_EXPECT_EQ(test, 0, ret);
466
467 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
468 KUNIT_EXPECT_EQ(test, 0, ret);
469
470 /* cleanup */
471 snd_soc_unregister_card(&kunit_comp->card);
472
473 snd_soc_unregister_component(test_dev);
474}
475
476// TEST CASE
477// Test "empty" topology file, but with bad "abi"
478// In theory we could loop through all possible bad values, but it takes too
479// long, so just use SND_SOC_TPLG_ABI_VERSION + 1
480static void snd_soc_tplg_test_load_empty_tplg_bad_abi(struct kunit *test)
481{
482 struct kunit_soc_component *kunit_comp;
483 struct tplg_tmpl_001 *data;
484 int size;
485 int ret;
486
487 /* prepare */
488 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
489 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
490 kunit_comp->kunit = test;
491 kunit_comp->expect = -EINVAL; /* expect failure */
492
493 size = sizeof(tplg_tmpl_empty);
494 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
495 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
496
497 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
498 /*
499 * override abi
500 * any value != accepted range is wrong
501 */
502 data->header.abi = cpu_to_le32(SND_SOC_TPLG_ABI_VERSION + 1);
503
504 kunit_comp->fw.data = (u8 *)data;
505 kunit_comp->fw.size = size;
506
507 kunit_comp->card.dev = test_dev;
508 kunit_comp->card.name = "kunit-card";
509 kunit_comp->card.owner = THIS_MODULE;
510 kunit_comp->card.dai_link = kunit_dai_links;
511 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
512 kunit_comp->card.fully_routed = true;
513
514 /* run test */
515 ret = snd_soc_register_card(&kunit_comp->card);
516 if (ret != 0 && ret != -EPROBE_DEFER)
517 KUNIT_FAIL(test, "Failed to register card");
518
519 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
520 KUNIT_EXPECT_EQ(test, 0, ret);
521
522 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
523 KUNIT_EXPECT_EQ(test, 0, ret);
524
525 /* cleanup */
526 snd_soc_unregister_card(&kunit_comp->card);
527
528 snd_soc_unregister_component(test_dev);
529}
530
531// TEST CASE
532// Test "empty" topology file, but with bad "size"
533// In theory we could loop through all possible bad values, but it takes too
534// long, so just use sizeof(struct snd_soc_tplg_hdr) + 1
535static void snd_soc_tplg_test_load_empty_tplg_bad_size(struct kunit *test)
536{
537 struct kunit_soc_component *kunit_comp;
538 struct tplg_tmpl_001 *data;
539 int size;
540 int ret;
541
542 /* prepare */
543 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
544 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
545 kunit_comp->kunit = test;
546 kunit_comp->expect = -EINVAL; /* expect failure */
547
548 size = sizeof(tplg_tmpl_empty);
549 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
550 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
551
552 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
553 /*
554 * override size
555 * any value != struct size is wrong
556 */
557 data->header.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr) + 1);
558
559 kunit_comp->fw.data = (u8 *)data;
560 kunit_comp->fw.size = size;
561
562 kunit_comp->card.dev = test_dev;
563 kunit_comp->card.name = "kunit-card";
564 kunit_comp->card.owner = THIS_MODULE;
565 kunit_comp->card.dai_link = kunit_dai_links;
566 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
567 kunit_comp->card.fully_routed = true;
568
569 /* run test */
570 ret = snd_soc_register_card(&kunit_comp->card);
571 if (ret != 0 && ret != -EPROBE_DEFER)
572 KUNIT_FAIL(test, "Failed to register card");
573
574 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
575 KUNIT_EXPECT_EQ(test, 0, ret);
576
577 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
578 KUNIT_EXPECT_EQ(test, 0, ret);
579
580 /* cleanup */
581 snd_soc_unregister_card(&kunit_comp->card);
582
583 snd_soc_unregister_component(test_dev);
584}
585
586// TEST CASE
587// Test "empty" topology file, but with bad "payload_size"
588// In theory we could loop through all possible bad values, but it takes too
589// long, so just use the known wrong one
590static void snd_soc_tplg_test_load_empty_tplg_bad_payload_size(struct kunit *test)
591{
592 struct kunit_soc_component *kunit_comp;
593 struct tplg_tmpl_001 *data;
594 int size;
595 int ret;
596
597 /* prepare */
598 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
599 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
600 kunit_comp->kunit = test;
601 kunit_comp->expect = -EINVAL; /* expect failure */
602
603 size = sizeof(tplg_tmpl_empty);
604 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
605 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
606
607 memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty));
608 /*
609 * override payload size
610 * there is only explicit check for 0, so check with it, other values
611 * are handled by just not reading behind EOF
612 */
613 data->header.payload_size = 0;
614
615 kunit_comp->fw.data = (u8 *)data;
616 kunit_comp->fw.size = size;
617
618 kunit_comp->card.dev = test_dev;
619 kunit_comp->card.name = "kunit-card";
620 kunit_comp->card.owner = THIS_MODULE;
621 kunit_comp->card.dai_link = kunit_dai_links;
622 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
623 kunit_comp->card.fully_routed = true;
624
625 /* run test */
626 ret = snd_soc_register_card(&kunit_comp->card);
627 if (ret != 0 && ret != -EPROBE_DEFER)
628 KUNIT_FAIL(test, "Failed to register card");
629
630 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
631 KUNIT_EXPECT_EQ(test, 0, ret);
632
633 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
634 KUNIT_EXPECT_EQ(test, 0, ret);
635
636 /* cleanup */
637 snd_soc_unregister_component(test_dev);
638
639 snd_soc_unregister_card(&kunit_comp->card);
640}
641
642// TEST CASE
643// Test passing topology file with PCM definition
644static void snd_soc_tplg_test_load_pcm_tplg(struct kunit *test)
645{
646 struct kunit_soc_component *kunit_comp;
647 u8 *data;
648 int size;
649 int ret;
650
651 /* prepare */
652 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
653 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
654 kunit_comp->kunit = test;
655 kunit_comp->expect = 0; /* expect success */
656
657 size = sizeof(tplg_tmpl_with_pcm);
658 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
659 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
660
661 memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
662
663 kunit_comp->fw.data = data;
664 kunit_comp->fw.size = size;
665
666 kunit_comp->card.dev = test_dev;
667 kunit_comp->card.name = "kunit-card";
668 kunit_comp->card.owner = THIS_MODULE;
669 kunit_comp->card.dai_link = kunit_dai_links;
670 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
671 kunit_comp->card.fully_routed = true;
672
673 /* run test */
674 ret = snd_soc_register_card(&kunit_comp->card);
675 if (ret != 0 && ret != -EPROBE_DEFER)
676 KUNIT_FAIL(test, "Failed to register card");
677
678 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
679 KUNIT_EXPECT_EQ(test, 0, ret);
680
681 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
682 KUNIT_EXPECT_EQ(test, 0, ret);
683
684 snd_soc_unregister_component(test_dev);
685
686 /* cleanup */
687 snd_soc_unregister_card(&kunit_comp->card);
688}
689
690// TEST CASE
691// Test passing topology file with PCM definition
692// with component reload
693static void snd_soc_tplg_test_load_pcm_tplg_reload_comp(struct kunit *test)
694{
695 struct kunit_soc_component *kunit_comp;
696 u8 *data;
697 int size;
698 int ret;
699 int i;
700
701 /* prepare */
702 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
703 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
704 kunit_comp->kunit = test;
705 kunit_comp->expect = 0; /* expect success */
706
707 size = sizeof(tplg_tmpl_with_pcm);
708 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
709 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
710
711 memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
712
713 kunit_comp->fw.data = data;
714 kunit_comp->fw.size = size;
715
716 kunit_comp->card.dev = test_dev;
717 kunit_comp->card.name = "kunit-card";
718 kunit_comp->card.owner = THIS_MODULE;
719 kunit_comp->card.dai_link = kunit_dai_links;
720 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
721 kunit_comp->card.fully_routed = true;
722
723 /* run test */
724 ret = snd_soc_register_card(&kunit_comp->card);
725 if (ret != 0 && ret != -EPROBE_DEFER)
726 KUNIT_FAIL(test, "Failed to register card");
727
728 for (i = 0; i < 100; i++) {
729 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
730 KUNIT_EXPECT_EQ(test, 0, ret);
731
732 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
733 KUNIT_EXPECT_EQ(test, 0, ret);
734
735 snd_soc_unregister_component(test_dev);
736 }
737
738 /* cleanup */
739 snd_soc_unregister_card(&kunit_comp->card);
740}
741
742// TEST CASE
743// Test passing topology file with PCM definition
744// with card reload
745static void snd_soc_tplg_test_load_pcm_tplg_reload_card(struct kunit *test)
746{
747 struct kunit_soc_component *kunit_comp;
748 u8 *data;
749 int size;
750 int ret;
751 int i;
752
753 /* prepare */
754 kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL);
755 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp);
756 kunit_comp->kunit = test;
757 kunit_comp->expect = 0; /* expect success */
758
759 size = sizeof(tplg_tmpl_with_pcm);
760 data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL);
761 KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data);
762
763 memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm));
764
765 kunit_comp->fw.data = data;
766 kunit_comp->fw.size = size;
767
768 kunit_comp->card.dev = test_dev;
769 kunit_comp->card.name = "kunit-card";
770 kunit_comp->card.owner = THIS_MODULE;
771 kunit_comp->card.dai_link = kunit_dai_links;
772 kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links);
773 kunit_comp->card.fully_routed = true;
774
775 /* run test */
776 ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
777 KUNIT_EXPECT_EQ(test, 0, ret);
778
779 ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
780 KUNIT_EXPECT_EQ(test, 0, ret);
781
782 for (i = 0; i < 100; i++) {
783 ret = snd_soc_register_card(&kunit_comp->card);
784 if (ret != 0 && ret != -EPROBE_DEFER)
785 KUNIT_FAIL(test, "Failed to register card");
786
787 snd_soc_unregister_card(&kunit_comp->card);
788 }
789
790 /* cleanup */
791 snd_soc_unregister_component(test_dev);
792}
793
794/* ===== KUNIT MODULE DEFINITIONS =========================================== */
795
796static struct kunit_case snd_soc_tplg_test_cases[] = {
797 KUNIT_CASE(snd_soc_tplg_test_load_with_null_comp),
798 KUNIT_CASE(snd_soc_tplg_test_load_with_null_ops),
799 KUNIT_CASE(snd_soc_tplg_test_load_with_null_fw),
800 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg),
801 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_magic),
802 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_abi),
803 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_size),
804 KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_payload_size),
805 KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg),
806 KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_comp),
807 KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_card),
808 {}
809};
810
811static struct kunit_suite snd_soc_tplg_test_suite = {
812 .name = "snd_soc_tplg_test",
813 .init = snd_soc_tplg_test_init,
814 .exit = snd_soc_tplg_test_exit,
815 .test_cases = snd_soc_tplg_test_cases,
816};
817
818kunit_test_suites(&snd_soc_tplg_test_suite);
819
820MODULE_DESCRIPTION("ASoC Topology Kernel Unit Tests");
821MODULE_LICENSE("GPL");