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 | * | |
83e495d7 | 5 | * Copyright(c) 2021 Intel Corporation. |
d52bbf74 AS |
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> | |
e57cdff0 | 12 | #include <kunit/device.h> |
d52bbf74 AS |
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 | ||
d52bbf74 AS |
25 | static int snd_soc_tplg_test_init(struct kunit *test) |
26 | { | |
e57cdff0 | 27 | test_dev = kunit_device_register(test, "sound-soc-topology-test"); |
d52bbf74 AS |
28 | test_dev = get_device(test_dev); |
29 | if (!test_dev) | |
30 | return -ENODEV; | |
31 | ||
d52bbf74 AS |
32 | return 0; |
33 | } | |
34 | ||
35 | static void snd_soc_tplg_test_exit(struct kunit *test) | |
36 | { | |
37 | put_device(test_dev); | |
d52bbf74 AS |
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(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 | ||
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(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, | |
d52bbf74 AS |
101 | }; |
102 | ||
cec9128d AS |
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 header; | |
112 | struct snd_soc_tplg_manifest manifest; | |
113 | } __packed; | |
114 | ||
115 | static struct tplg_tmpl_001 tplg_tmpl_empty = { | |
116 | .header = { | |
be6be67e AS |
117 | .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), |
118 | .abi = cpu_to_le32(5), | |
cec9128d | 119 | .version = 0, |
be6be67e AS |
120 | .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST), |
121 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | |
cec9128d | 122 | .vendor_type = 0, |
be6be67e | 123 | .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), |
cec9128d | 124 | .index = 0, |
be6be67e | 125 | .count = cpu_to_le32(1), |
cec9128d AS |
126 | }, |
127 | ||
128 | .manifest = { | |
be6be67e | 129 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), |
cec9128d AS |
130 | /* rest of fields is 0 */ |
131 | }, | |
132 | }; | |
133 | ||
3ad8c8e9 AS |
134 | // Structural representation of topology containing SectionPCM |
135 | ||
136 | struct tplg_tmpl_002 { | |
137 | struct snd_soc_tplg_hdr header; | |
138 | struct snd_soc_tplg_manifest manifest; | |
139 | struct snd_soc_tplg_hdr pcm_header; | |
140 | struct snd_soc_tplg_pcm pcm; | |
141 | } __packed; | |
142 | ||
143 | static struct tplg_tmpl_002 tplg_tmpl_with_pcm = { | |
144 | .header = { | |
be6be67e AS |
145 | .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), |
146 | .abi = cpu_to_le32(5), | |
3ad8c8e9 | 147 | .version = 0, |
be6be67e AS |
148 | .type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST), |
149 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | |
3ad8c8e9 | 150 | .vendor_type = 0, |
be6be67e | 151 | .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), |
3ad8c8e9 | 152 | .index = 0, |
be6be67e | 153 | .count = cpu_to_le32(1), |
3ad8c8e9 AS |
154 | }, |
155 | .manifest = { | |
be6be67e AS |
156 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), |
157 | .pcm_elems = cpu_to_le32(1), | |
3ad8c8e9 AS |
158 | /* rest of fields is 0 */ |
159 | }, | |
160 | .pcm_header = { | |
be6be67e AS |
161 | .magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), |
162 | .abi = cpu_to_le32(5), | |
3ad8c8e9 | 163 | .version = 0, |
be6be67e AS |
164 | .type = cpu_to_le32(SND_SOC_TPLG_TYPE_PCM), |
165 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | |
3ad8c8e9 | 166 | .vendor_type = 0, |
be6be67e | 167 | .payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)), |
3ad8c8e9 | 168 | .index = 0, |
be6be67e | 169 | .count = cpu_to_le32(1), |
3ad8c8e9 AS |
170 | }, |
171 | .pcm = { | |
be6be67e | 172 | .size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)), |
3ad8c8e9 AS |
173 | .pcm_name = "KUNIT Audio", |
174 | .dai_name = "kunit-audio-dai", | |
175 | .pcm_id = 0, | |
176 | .dai_id = 0, | |
be6be67e AS |
177 | .playback = cpu_to_le32(1), |
178 | .capture = cpu_to_le32(1), | |
3ad8c8e9 AS |
179 | .compress = 0, |
180 | .stream = { | |
181 | [0] = { | |
be6be67e | 182 | .channels = cpu_to_le32(2), |
3ad8c8e9 AS |
183 | }, |
184 | [1] = { | |
be6be67e | 185 | .channels = cpu_to_le32(2), |
3ad8c8e9 AS |
186 | }, |
187 | }, | |
188 | .num_streams = 0, | |
189 | .caps = { | |
190 | [0] = { | |
191 | .name = "kunit-audio-playback", | |
be6be67e AS |
192 | .channels_min = cpu_to_le32(2), |
193 | .channels_max = cpu_to_le32(2), | |
3ad8c8e9 AS |
194 | }, |
195 | [1] = { | |
196 | .name = "kunit-audio-capture", | |
be6be67e AS |
197 | .channels_min = cpu_to_le32(2), |
198 | .channels_max = cpu_to_le32(2), | |
3ad8c8e9 AS |
199 | }, |
200 | }, | |
201 | .flag_mask = 0, | |
202 | .flags = 0, | |
203 | .priv = { 0 }, | |
204 | }, | |
205 | }; | |
206 | ||
d52bbf74 AS |
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, &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, | |
d52bbf74 AS |
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, 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 | ||
54694840 CN |
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; | |
d52bbf74 AS |
253 | |
254 | /* run test */ | |
255 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component_null_comp, test_dev); | |
260 | KUNIT_EXPECT_EQ(test, 0, ret); | |
261 | ||
262 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
263 | KUNIT_EXPECT_EQ(test, 0, ret); | |
264 | ||
265 | /* cleanup */ | |
1892a991 | 266 | snd_soc_unregister_card(&kunit_comp->card); |
d52bbf74 AS |
267 | snd_soc_unregister_component(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, 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 | ||
54694840 CN |
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; | |
d52bbf74 AS |
295 | |
296 | /* run test */ | |
297 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component, test_dev); | |
302 | KUNIT_EXPECT_EQ(test, 0, ret); | |
303 | ||
304 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
305 | KUNIT_EXPECT_EQ(test, 0, ret); | |
306 | ||
307 | /* cleanup */ | |
d5017d13 | 308 | snd_soc_unregister_card(&kunit_comp->card); |
d52bbf74 AS |
309 | |
310 | snd_soc_unregister_component(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(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, | |
d52bbf74 AS |
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, 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 | ||
54694840 CN |
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; | |
d52bbf74 AS |
357 | |
358 | /* run test */ | |
359 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component_null_fw, test_dev); | |
364 | KUNIT_EXPECT_EQ(test, 0, ret); | |
365 | ||
366 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
367 | KUNIT_EXPECT_EQ(test, 0, ret); | |
368 | ||
369 | /* cleanup */ | |
d5017d13 | 370 | snd_soc_unregister_card(&kunit_comp->card); |
d52bbf74 AS |
371 | |
372 | snd_soc_unregister_component(test_dev); | |
373 | } | |
374 | ||
cec9128d AS |
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, 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(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 | ||
54694840 CN |
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; | |
cec9128d AS |
405 | |
406 | /* run test */ | |
407 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component, test_dev); | |
412 | KUNIT_EXPECT_EQ(test, 0, ret); | |
413 | ||
414 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
415 | KUNIT_EXPECT_EQ(test, 0, ret); | |
416 | ||
417 | /* cleanup */ | |
d5017d13 | 418 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
419 | |
420 | snd_soc_unregister_component(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, 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(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 | */ | |
be6be67e | 449 | data->header.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC + 1); |
cec9128d AS |
450 | |
451 | kunit_comp->fw.data = (u8 *)data; | |
452 | kunit_comp->fw.size = size; | |
453 | ||
54694840 CN |
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; | |
cec9128d AS |
460 | |
461 | /* run test */ | |
462 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component, test_dev); | |
467 | KUNIT_EXPECT_EQ(test, 0, ret); | |
468 | ||
469 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
470 | KUNIT_EXPECT_EQ(test, 0, ret); | |
471 | ||
472 | /* cleanup */ | |
d5017d13 | 473 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
474 | |
475 | snd_soc_unregister_component(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, 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(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 | */ | |
be6be67e | 504 | data->header.abi = cpu_to_le32(SND_SOC_TPLG_ABI_VERSION + 1); |
cec9128d AS |
505 | |
506 | kunit_comp->fw.data = (u8 *)data; | |
507 | kunit_comp->fw.size = size; | |
508 | ||
54694840 CN |
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; | |
cec9128d AS |
515 | |
516 | /* run test */ | |
517 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component, test_dev); | |
522 | KUNIT_EXPECT_EQ(test, 0, ret); | |
523 | ||
524 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
525 | KUNIT_EXPECT_EQ(test, 0, ret); | |
526 | ||
527 | /* cleanup */ | |
d5017d13 | 528 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
529 | |
530 | snd_soc_unregister_component(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, 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(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 | */ | |
be6be67e | 559 | data->header.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr) + 1); |
cec9128d AS |
560 | |
561 | kunit_comp->fw.data = (u8 *)data; | |
562 | kunit_comp->fw.size = size; | |
563 | ||
54694840 CN |
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; | |
cec9128d AS |
570 | |
571 | /* run test */ | |
572 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component, test_dev); | |
577 | KUNIT_EXPECT_EQ(test, 0, ret); | |
578 | ||
579 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
580 | KUNIT_EXPECT_EQ(test, 0, ret); | |
581 | ||
582 | /* cleanup */ | |
d5017d13 | 583 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
584 | |
585 | snd_soc_unregister_component(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, 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(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 | ||
54694840 CN |
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; | |
cec9128d AS |
626 | |
627 | /* run test */ | |
628 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component, test_dev); | |
633 | KUNIT_EXPECT_EQ(test, 0, ret); | |
634 | ||
635 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
636 | KUNIT_EXPECT_EQ(test, 0, ret); | |
637 | ||
638 | /* cleanup */ | |
639 | snd_soc_unregister_component(test_dev); | |
640 | ||
d5017d13 | 641 | snd_soc_unregister_card(&kunit_comp->card); |
cec9128d AS |
642 | } |
643 | ||
3ad8c8e9 AS |
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, 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(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 | ||
54694840 CN |
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; | |
3ad8c8e9 AS |
674 | |
675 | /* run test */ | |
676 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component, test_dev); | |
681 | KUNIT_EXPECT_EQ(test, 0, ret); | |
682 | ||
683 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
684 | KUNIT_EXPECT_EQ(test, 0, ret); | |
685 | ||
686 | snd_soc_unregister_component(test_dev); | |
687 | ||
688 | /* cleanup */ | |
d5017d13 | 689 | snd_soc_unregister_card(&kunit_comp->card); |
3ad8c8e9 AS |
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, 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(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 | ||
54694840 CN |
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; | |
3ad8c8e9 AS |
724 | |
725 | /* run test */ | |
726 | ret = snd_soc_register_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(&kunit_comp->comp, &test_component, test_dev); | |
732 | KUNIT_EXPECT_EQ(test, 0, ret); | |
733 | ||
734 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
735 | KUNIT_EXPECT_EQ(test, 0, ret); | |
736 | ||
737 | snd_soc_unregister_component(test_dev); | |
738 | } | |
739 | ||
740 | /* cleanup */ | |
d5017d13 | 741 | snd_soc_unregister_card(&kunit_comp->card); |
3ad8c8e9 AS |
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, 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(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 | ||
54694840 CN |
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; | |
3ad8c8e9 AS |
776 | |
777 | /* run test */ | |
778 | ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | |
779 | KUNIT_EXPECT_EQ(test, 0, ret); | |
780 | ||
781 | ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | |
782 | KUNIT_EXPECT_EQ(test, 0, ret); | |
783 | ||
784 | for (i = 0; i < 100; i++) { | |
785 | ret = snd_soc_register_card(&kunit_comp->card); | |
786 | if (ret != 0 && ret != -EPROBE_DEFER) | |
787 | KUNIT_FAIL(test, "Failed to register card"); | |
788 | ||
d5017d13 | 789 | snd_soc_unregister_card(&kunit_comp->card); |
3ad8c8e9 AS |
790 | } |
791 | ||
792 | /* cleanup */ | |
793 | snd_soc_unregister_component(test_dev); | |
794 | } | |
795 | ||
d52bbf74 AS |
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), | |
cec9128d AS |
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), | |
3ad8c8e9 AS |
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), | |
d52bbf74 AS |
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 | ||
ea762d10 | 822 | MODULE_DESCRIPTION("ASoC Topology Kernel Unit Tests"); |
d52bbf74 | 823 | MODULE_LICENSE("GPL"); |