Linux Audio

Check our new training course

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