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