Commit | Line | Data |
---|---|---|
d52bbf74 AS |
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> | |
d52bbf74 AS |
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 | */ | |
22 | static struct device *test_dev; | |
23 | ||
24 | static struct device_driver test_drv = { | |
25 | .name = "sound-soc-topology-test-driver", | |
26 | }; | |
27 | ||
28 | static 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 | ||
40 | static 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 | */ | |
51 | struct 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 | ||
59 | static 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 | ||
72 | static 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 | */ | |
85 | SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); | |
86 | ||
87 | SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sound-soc-topology-test"))); | |
88 | ||
89 | static 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 | ||
103 | static const struct snd_soc_component_driver test_component = { | |
104 | .name = "sound-soc-topology-test", | |
105 | .probe = d_probe, | |
106 | .remove = d_remove, | |
d52bbf74 AS |
107 | }; |
108 | ||
cec9128d AS |
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 | ||
116 | struct tplg_tmpl_001 { | |
117 | struct snd_soc_tplg_hdr header; | |
118 | struct snd_soc_tplg_manifest manifest; | |
119 | } __packed; | |
120 | ||
121 | static struct tplg_tmpl_001 tplg_tmpl_empty = { | |
122 | .header = { | |
be6be67e AS |
123 | .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), |
124 | .abi = cpu_to_le32(5), | |
cec9128d | 125 | .version = 0, |
be6be67e AS |
126 | .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST), |
127 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | |
cec9128d | 128 | .vendor_type = 0, |
be6be67e | 129 | .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), |
cec9128d | 130 | .index = 0, |
be6be67e | 131 | .count = cpu_to_le32(1), |
cec9128d AS |
132 | }, |
133 | ||
134 | .manifest = { | |
be6be67e | 135 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), |
cec9128d AS |
136 | /* rest of fields is 0 */ |
137 | }, | |
138 | }; | |
139 | ||
3ad8c8e9 AS |
140 | // Structural representation of topology containing SectionPCM |
141 | ||
142 | struct 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 | ||
149 | static struct tplg_tmpl_002 tplg_tmpl_with_pcm = { | |
150 | .header = { | |
be6be67e AS |
151 | .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), |
152 | .abi = cpu_to_le32(5), | |
3ad8c8e9 | 153 | .version = 0, |
be6be67e AS |
154 | .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST), |
155 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | |
3ad8c8e9 | 156 | .vendor_type = 0, |
be6be67e | 157 | .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), |
3ad8c8e9 | 158 | .index = 0, |
be6be67e | 159 | .count = cpu_to_le32(1), |
3ad8c8e9 AS |
160 | }, |
161 | .manifest = { | |
be6be67e AS |
162 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), |
163 | .pcm_elems = cpu_to_le32(1), | |
3ad8c8e9 AS |
164 | /* rest of fields is 0 */ |
165 | }, | |
166 | .pcm_header = { | |
be6be67e AS |
167 | .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), |
168 | .abi = cpu_to_le32(5), | |
3ad8c8e9 | 169 | .version = 0, |
be6be67e AS |
170 | .type = cpu_to_le32(SND_SOC_TPLG_TYPE_PCM), |
171 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | |
3ad8c8e9 | 172 | .vendor_type = 0, |
be6be67e | 173 | .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)), |
3ad8c8e9 | 174 | .index = 0, |
be6be67e | 175 | .count = cpu_to_le32(1), |
3ad8c8e9 AS |
176 | }, |
177 | .pcm = { | |
be6be67e | 178 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)), |
3ad8c8e9 AS |
179 | .pcm_name = "KUNIT Audio", |
180 | .dai_name = "kunit-audio-dai", | |
181 | .pcm_id = 0, | |
182 | .dai_id = 0, | |
be6be67e AS |
183 | .playback = cpu_to_le32(1), |
184 | .capture = cpu_to_le32(1), | |
3ad8c8e9 AS |
185 | .compress = 0, |
186 | .stream = { | |
187 | [0] = { | |
be6be67e | 188 | .channels = cpu_to_le32(2), |
3ad8c8e9 AS |
189 | }, |
190 | [1] = { | |
be6be67e | 191 | .channels = cpu_to_le32(2), |
3ad8c8e9 AS |
192 | }, |
193 | }, | |
194 | .num_streams = 0, | |
195 | .caps = { | |
196 | [0] = { | |
197 | .name = "kunit-audio-playback", | |
be6be67e AS |
198 | .channels_min = cpu_to_le32(2), |
199 | .channels_max = cpu_to_le32(2), | |
3ad8c8e9 AS |
200 | }, |
201 | [1] = { | |
202 | .name = "kunit-audio-capture", | |
be6be67e AS |
203 | .channels_min = cpu_to_le32(2), |
204 | .channels_max = cpu_to_le32(2), | |
3ad8c8e9 AS |
205 | }, |
206 | }, | |
207 | .flag_mask = 0, | |
208 | .flags = 0, | |
209 | .priv = { 0 }, | |
210 | }, | |
211 | }; | |
212 | ||
d52bbf74 AS |
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 | */ | |
223 | static 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 | ||
237 | static const struct snd_soc_component_driver test_component_null_comp = { | |
238 | .name = "sound-soc-topology-test", | |
239 | .probe = d_probe_null_comp, | |
d52bbf74 AS |
240 | }; |
241 | ||
242 | static 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 */ | |
1892a991 | 272 | snd_soc_unregister_card(&kunit_comp->card); |
d52bbf74 AS |
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 | */ | |
284 | static 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 */ | |
d5017d13 | 314 | snd_soc_unregister_card(&kunit_comp->card); |
d52bbf74 AS |
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 | */ | |
327 | static 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 | ||
341 | static const struct snd_soc_component_driver test_component_null_fw = { | |
342 | .name = "sound-soc-topology-test", | |
343 | .probe = d_probe_null_fw, | |
d52bbf74 AS |
344 | }; |
345 | ||
346 | static 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 */ | |
d5017d13 | 376 | snd_soc_unregister_card(&kunit_comp->card); |
d52bbf74 AS |
377 | |
378 | snd_soc_unregister_component(test_dev); | |
379 | } | |
380 | ||
cec9128d AS |
381 | // TEST CASE |
382 | // Test passing "empty" topology file | |
383 | static 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 */ | |
d5017d13 | 424 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
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 | |
433 | static 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 | */ | |
be6be67e | 455 | data->header.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC + 1); |
cec9128d AS |
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 */ | |
d5017d13 | 479 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
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 | |
488 | static 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 | */ | |
be6be67e | 510 | data->header.abi = cpu_to_le32(SND_SOC_TPLG_ABI_VERSION + 1); |
cec9128d AS |
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 */ | |
d5017d13 | 534 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
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 | |
543 | static 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 | */ | |
be6be67e | 565 | data->header.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr) + 1); |
cec9128d AS |
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 */ | |
d5017d13 | 589 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
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 | |
598 | static 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 | ||
d5017d13 | 647 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
648 | } |
649 | ||
3ad8c8e9 AS |
650 | // TEST CASE |
651 | // Test passing topology file with PCM definition | |
652 | static 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 */ | |
d5017d13 | 695 | snd_soc_unregister_card(&kunit_comp->card); |
3ad8c8e9 AS |
696 | } |
697 | ||
698 | // TEST CASE | |
699 | // Test passing topology file with PCM definition | |
700 | // with component reload | |
701 | static 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 */ | |
d5017d13 | 747 | snd_soc_unregister_card(&kunit_comp->card); |
3ad8c8e9 AS |
748 | } |
749 | ||
750 | // TEST CASE | |
751 | // Test passing topology file with PCM definition | |
752 | // with card reload | |
753 | static 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 | ||
d5017d13 | 795 | snd_soc_unregister_card(&kunit_comp->card); |
3ad8c8e9 AS |
796 | } |
797 | ||
798 | /* cleanup */ | |
799 | snd_soc_unregister_component(test_dev); | |
800 | } | |
801 | ||
d52bbf74 AS |
802 | /* ===== KUNIT MODULE DEFINITIONS =========================================== */ |
803 | ||
804 | static 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), | |
cec9128d AS |
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), | |
3ad8c8e9 AS |
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), | |
d52bbf74 AS |
816 | {} |
817 | }; | |
818 | ||
819 | static 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 | ||
826 | kunit_test_suites(&snd_soc_tplg_test_suite); | |
827 | ||
828 | MODULE_LICENSE("GPL"); |