| // SPDX-License-Identifier: GPL-2.0-only | 
 | /* | 
 |  * soc-topology-test.c  --  ALSA SoC Topology Kernel Unit Tests | 
 |  * | 
 |  * Copyright(c) 2021 Intel Corporation. | 
 |  */ | 
 |  | 
 | #include <linux/firmware.h> | 
 | #include <sound/core.h> | 
 | #include <sound/soc.h> | 
 | #include <sound/soc-topology.h> | 
 | #include <kunit/device.h> | 
 | #include <kunit/test.h> | 
 |  | 
 | /* ===== HELPER FUNCTIONS =================================================== */ | 
 |  | 
 | /* | 
 |  * snd_soc_component needs device to operate on (primarily for prints), create | 
 |  * fake one, as we don't register with PCI or anything else | 
 |  * device_driver name is used in some of the prints (fmt_single_name) so | 
 |  * we also mock up minimal one | 
 |  */ | 
 | static struct device *test_dev; | 
 |  | 
 | static int snd_soc_tplg_test_init(struct kunit *test) | 
 | { | 
 | 	test_dev = kunit_device_register(test, "sound-soc-topology-test"); | 
 | 	test_dev = get_device(test_dev); | 
 | 	if (!test_dev) | 
 | 		return -ENODEV; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static void snd_soc_tplg_test_exit(struct kunit *test) | 
 | { | 
 | 	put_device(test_dev); | 
 | } | 
 |  | 
 | /* | 
 |  * helper struct we use when registering component, as we load topology during | 
 |  * component probe, we need to pass struct kunit somehow to probe function, so | 
 |  * we can report test result | 
 |  */ | 
 | struct kunit_soc_component { | 
 | 	struct kunit *kunit; | 
 | 	int expect; /* what result we expect when loading topology */ | 
 | 	struct snd_soc_component comp; | 
 | 	struct snd_soc_card card; | 
 | 	struct firmware fw; | 
 | }; | 
 |  | 
 | static int d_probe(struct snd_soc_component *component) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp = | 
 | 			container_of(component, struct kunit_soc_component, comp); | 
 | 	int ret; | 
 |  | 
 | 	ret = snd_soc_tplg_component_load(component, NULL, &kunit_comp->fw); | 
 | 	KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret, | 
 | 			    "Failed topology load"); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static void d_remove(struct snd_soc_component *component) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp = | 
 | 			container_of(component, struct kunit_soc_component, comp); | 
 | 	int ret; | 
 |  | 
 | 	ret = snd_soc_tplg_component_remove(component); | 
 | 	KUNIT_EXPECT_EQ(kunit_comp->kunit, 0, ret); | 
 | } | 
 |  | 
 | /* | 
 |  * ASoC minimal boiler plate | 
 |  */ | 
 | SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); | 
 |  | 
 | SND_SOC_DAILINK_DEF(platform, DAILINK_COMP_ARRAY(COMP_PLATFORM("sound-soc-topology-test"))); | 
 |  | 
 | static struct snd_soc_dai_link kunit_dai_links[] = { | 
 | 	{ | 
 | 		.name = "KUNIT Audio Port", | 
 | 		.id = 0, | 
 | 		.stream_name = "Audio Playback/Capture", | 
 | 		.nonatomic = 1, | 
 | 		.dynamic = 1, | 
 | 		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, | 
 | 		.dpcm_playback = 1, | 
 | 		.dpcm_capture = 1, | 
 | 		SND_SOC_DAILINK_REG(dummy, dummy, platform), | 
 | 	}, | 
 | }; | 
 |  | 
 | static const struct snd_soc_component_driver test_component = { | 
 | 	.name = "sound-soc-topology-test", | 
 | 	.probe = d_probe, | 
 | 	.remove = d_remove, | 
 | }; | 
 |  | 
 | /* ===== TOPOLOGY TEMPLATES ================================================= */ | 
 |  | 
 | // Structural representation of topology which can be generated with: | 
 | // $ touch empty | 
 | // $ alsatplg -c empty -o empty.tplg | 
 | // $ xxd -i empty.tplg | 
 |  | 
 | struct tplg_tmpl_001 { | 
 | 	struct snd_soc_tplg_hdr header; | 
 | 	struct snd_soc_tplg_manifest manifest; | 
 | } __packed; | 
 |  | 
 | static struct tplg_tmpl_001 tplg_tmpl_empty = { | 
 | 	.header = { | 
 | 		.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), | 
 | 		.abi = cpu_to_le32(5), | 
 | 		.version = 0, | 
 | 		.type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST), | 
 | 		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | 
 | 		.vendor_type = 0, | 
 | 		.payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), | 
 | 		.index = 0, | 
 | 		.count = cpu_to_le32(1), | 
 | 	}, | 
 |  | 
 | 	.manifest = { | 
 | 		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), | 
 | 		/* rest of fields is 0 */ | 
 | 	}, | 
 | }; | 
 |  | 
 | // Structural representation of topology containing SectionPCM | 
 |  | 
 | struct tplg_tmpl_002 { | 
 | 	struct snd_soc_tplg_hdr header; | 
 | 	struct snd_soc_tplg_manifest manifest; | 
 | 	struct snd_soc_tplg_hdr pcm_header; | 
 | 	struct snd_soc_tplg_pcm pcm; | 
 | } __packed; | 
 |  | 
 | static struct tplg_tmpl_002 tplg_tmpl_with_pcm = { | 
 | 	.header = { | 
 | 		.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), | 
 | 		.abi = cpu_to_le32(5), | 
 | 		.version = 0, | 
 | 		.type = cpu_to_le32(SND_SOC_TPLG_TYPE_MANIFEST), | 
 | 		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | 
 | 		.vendor_type = 0, | 
 | 		.payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), | 
 | 		.index = 0, | 
 | 		.count = cpu_to_le32(1), | 
 | 	}, | 
 | 	.manifest = { | 
 | 		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_manifest)), | 
 | 		.pcm_elems = cpu_to_le32(1), | 
 | 		/* rest of fields is 0 */ | 
 | 	}, | 
 | 	.pcm_header = { | 
 | 		.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC), | 
 | 		.abi = cpu_to_le32(5), | 
 | 		.version = 0, | 
 | 		.type = cpu_to_le32(SND_SOC_TPLG_TYPE_PCM), | 
 | 		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr)), | 
 | 		.vendor_type = 0, | 
 | 		.payload_size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)), | 
 | 		.index = 0, | 
 | 		.count = cpu_to_le32(1), | 
 | 	}, | 
 | 	.pcm = { | 
 | 		.size = cpu_to_le32(sizeof(struct snd_soc_tplg_pcm)), | 
 | 		.pcm_name = "KUNIT Audio", | 
 | 		.dai_name = "kunit-audio-dai", | 
 | 		.pcm_id = 0, | 
 | 		.dai_id = 0, | 
 | 		.playback = cpu_to_le32(1), | 
 | 		.capture = cpu_to_le32(1), | 
 | 		.compress = 0, | 
 | 		.stream = { | 
 | 			[0] = { | 
 | 				.channels = cpu_to_le32(2), | 
 | 			}, | 
 | 			[1] = { | 
 | 				.channels = cpu_to_le32(2), | 
 | 			}, | 
 | 		}, | 
 | 		.num_streams = 0, | 
 | 		.caps = { | 
 | 			[0] = { | 
 | 				.name = "kunit-audio-playback", | 
 | 				.channels_min = cpu_to_le32(2), | 
 | 				.channels_max = cpu_to_le32(2), | 
 | 			}, | 
 | 			[1] = { | 
 | 				.name = "kunit-audio-capture", | 
 | 				.channels_min = cpu_to_le32(2), | 
 | 				.channels_max = cpu_to_le32(2), | 
 | 			}, | 
 | 		}, | 
 | 		.flag_mask = 0, | 
 | 		.flags = 0, | 
 | 		.priv = { 0 }, | 
 | 	}, | 
 | }; | 
 |  | 
 | /* ===== TEST CASES ========================================================= */ | 
 |  | 
 | // TEST CASE | 
 | // Test passing NULL component as parameter to snd_soc_tplg_component_load | 
 |  | 
 | /* | 
 |  * need to override generic probe function with one using NULL when calling | 
 |  * topology load during component initialization, we don't need .remove | 
 |  * handler as load should fail | 
 |  */ | 
 | static int d_probe_null_comp(struct snd_soc_component *component) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp = | 
 | 			container_of(component, struct kunit_soc_component, comp); | 
 | 	int ret; | 
 |  | 
 | 	/* instead of passing component pointer as first argument, pass NULL here */ | 
 | 	ret = snd_soc_tplg_component_load(NULL, NULL, &kunit_comp->fw); | 
 | 	KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret, | 
 | 			    "Failed topology load"); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct snd_soc_component_driver test_component_null_comp = { | 
 | 	.name = "sound-soc-topology-test", | 
 | 	.probe = d_probe_null_comp, | 
 | }; | 
 |  | 
 | static void snd_soc_tplg_test_load_with_null_comp(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = -EINVAL; /* expect failure */ | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_comp, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 | 	snd_soc_unregister_component(test_dev); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test passing NULL ops as parameter to snd_soc_tplg_component_load | 
 |  | 
 | /* | 
 |  * NULL ops is default case, we pass empty topology (fw), so we don't have | 
 |  * anything to parse and just do nothing, which results in return 0; from | 
 |  * calling soc_tplg_dapm_complete in soc_tplg_process_headers | 
 |  */ | 
 | static void snd_soc_tplg_test_load_with_null_ops(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = 0; /* expect success */ | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 |  | 
 | 	snd_soc_unregister_component(test_dev); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test passing NULL fw as parameter to snd_soc_tplg_component_load | 
 |  | 
 | /* | 
 |  * need to override generic probe function with one using NULL pointer to fw | 
 |  * when calling topology load during component initialization, we don't need | 
 |  * .remove handler as load should fail | 
 |  */ | 
 | static int d_probe_null_fw(struct snd_soc_component *component) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp = | 
 | 			container_of(component, struct kunit_soc_component, comp); | 
 | 	int ret; | 
 |  | 
 | 	/* instead of passing fw pointer as third argument, pass NULL here */ | 
 | 	ret = snd_soc_tplg_component_load(component, NULL, NULL); | 
 | 	KUNIT_EXPECT_EQ_MSG(kunit_comp->kunit, kunit_comp->expect, ret, | 
 | 			    "Failed topology load"); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct snd_soc_component_driver test_component_null_fw = { | 
 | 	.name = "sound-soc-topology-test", | 
 | 	.probe = d_probe_null_fw, | 
 | }; | 
 |  | 
 | static void snd_soc_tplg_test_load_with_null_fw(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = -EINVAL; /* expect failure */ | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component_null_fw, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 |  | 
 | 	snd_soc_unregister_component(test_dev); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test passing "empty" topology file | 
 | static void snd_soc_tplg_test_load_empty_tplg(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	struct tplg_tmpl_001 *data; | 
 | 	int size; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = 0; /* expect success */ | 
 |  | 
 | 	size = sizeof(tplg_tmpl_empty); | 
 | 	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); | 
 |  | 
 | 	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); | 
 |  | 
 | 	kunit_comp->fw.data = (u8 *)data; | 
 | 	kunit_comp->fw.size = size; | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 |  | 
 | 	snd_soc_unregister_component(test_dev); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test "empty" topology file, but with bad "magic" | 
 | // In theory we could loop through all possible bad values, but it takes too | 
 | // long, so just use SND_SOC_TPLG_MAGIC + 1 | 
 | static void snd_soc_tplg_test_load_empty_tplg_bad_magic(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	struct tplg_tmpl_001 *data; | 
 | 	int size; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = -EINVAL; /* expect failure */ | 
 |  | 
 | 	size = sizeof(tplg_tmpl_empty); | 
 | 	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); | 
 |  | 
 | 	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); | 
 | 	/* | 
 | 	 * override abi | 
 | 	 * any value != magic number is wrong | 
 | 	 */ | 
 | 	data->header.magic = cpu_to_le32(SND_SOC_TPLG_MAGIC + 1); | 
 |  | 
 | 	kunit_comp->fw.data = (u8 *)data; | 
 | 	kunit_comp->fw.size = size; | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 |  | 
 | 	snd_soc_unregister_component(test_dev); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test "empty" topology file, but with bad "abi" | 
 | // In theory we could loop through all possible bad values, but it takes too | 
 | // long, so just use SND_SOC_TPLG_ABI_VERSION + 1 | 
 | static void snd_soc_tplg_test_load_empty_tplg_bad_abi(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	struct tplg_tmpl_001 *data; | 
 | 	int size; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = -EINVAL; /* expect failure */ | 
 |  | 
 | 	size = sizeof(tplg_tmpl_empty); | 
 | 	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); | 
 |  | 
 | 	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); | 
 | 	/* | 
 | 	 * override abi | 
 | 	 * any value != accepted range is wrong | 
 | 	 */ | 
 | 	data->header.abi = cpu_to_le32(SND_SOC_TPLG_ABI_VERSION + 1); | 
 |  | 
 | 	kunit_comp->fw.data = (u8 *)data; | 
 | 	kunit_comp->fw.size = size; | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 |  | 
 | 	snd_soc_unregister_component(test_dev); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test "empty" topology file, but with bad "size" | 
 | // In theory we could loop through all possible bad values, but it takes too | 
 | // long, so just use sizeof(struct snd_soc_tplg_hdr) + 1 | 
 | static void snd_soc_tplg_test_load_empty_tplg_bad_size(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	struct tplg_tmpl_001 *data; | 
 | 	int size; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = -EINVAL; /* expect failure */ | 
 |  | 
 | 	size = sizeof(tplg_tmpl_empty); | 
 | 	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); | 
 |  | 
 | 	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); | 
 | 	/* | 
 | 	 * override size | 
 | 	 * any value != struct size is wrong | 
 | 	 */ | 
 | 	data->header.size = cpu_to_le32(sizeof(struct snd_soc_tplg_hdr) + 1); | 
 |  | 
 | 	kunit_comp->fw.data = (u8 *)data; | 
 | 	kunit_comp->fw.size = size; | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 |  | 
 | 	snd_soc_unregister_component(test_dev); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test "empty" topology file, but with bad "payload_size" | 
 | // In theory we could loop through all possible bad values, but it takes too | 
 | // long, so just use the known wrong one | 
 | static void snd_soc_tplg_test_load_empty_tplg_bad_payload_size(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	struct tplg_tmpl_001 *data; | 
 | 	int size; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = -EINVAL; /* expect failure */ | 
 |  | 
 | 	size = sizeof(tplg_tmpl_empty); | 
 | 	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); | 
 |  | 
 | 	memcpy(data, &tplg_tmpl_empty, sizeof(tplg_tmpl_empty)); | 
 | 	/* | 
 | 	 * override payload size | 
 | 	 * there is only explicit check for 0, so check with it, other values | 
 | 	 * are handled by just not reading behind EOF | 
 | 	 */ | 
 | 	data->header.payload_size = 0; | 
 |  | 
 | 	kunit_comp->fw.data = (u8 *)data; | 
 | 	kunit_comp->fw.size = size; | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_component(test_dev); | 
 |  | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test passing topology file with PCM definition | 
 | static void snd_soc_tplg_test_load_pcm_tplg(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	u8 *data; | 
 | 	int size; | 
 | 	int ret; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = 0; /* expect success */ | 
 |  | 
 | 	size = sizeof(tplg_tmpl_with_pcm); | 
 | 	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); | 
 |  | 
 | 	memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm)); | 
 |  | 
 | 	kunit_comp->fw.data = data; | 
 | 	kunit_comp->fw.size = size; | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	snd_soc_unregister_component(test_dev); | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test passing topology file with PCM definition | 
 | // with component reload | 
 | static void snd_soc_tplg_test_load_pcm_tplg_reload_comp(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	u8 *data; | 
 | 	int size; | 
 | 	int ret; | 
 | 	int i; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = 0; /* expect success */ | 
 |  | 
 | 	size = sizeof(tplg_tmpl_with_pcm); | 
 | 	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); | 
 |  | 
 | 	memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm)); | 
 |  | 
 | 	kunit_comp->fw.data = data; | 
 | 	kunit_comp->fw.size = size; | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_register_card(&kunit_comp->card); | 
 | 	if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 		KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 	for (i = 0; i < 100; i++) { | 
 | 		ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 		KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 		ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 		KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 		snd_soc_unregister_component(test_dev); | 
 | 	} | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_card(&kunit_comp->card); | 
 | } | 
 |  | 
 | // TEST CASE | 
 | // Test passing topology file with PCM definition | 
 | // with card reload | 
 | static void snd_soc_tplg_test_load_pcm_tplg_reload_card(struct kunit *test) | 
 | { | 
 | 	struct kunit_soc_component *kunit_comp; | 
 | 	u8 *data; | 
 | 	int size; | 
 | 	int ret; | 
 | 	int i; | 
 |  | 
 | 	/* prepare */ | 
 | 	kunit_comp = kunit_kzalloc(test, sizeof(*kunit_comp), GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(test, kunit_comp); | 
 | 	kunit_comp->kunit = test; | 
 | 	kunit_comp->expect = 0; /* expect success */ | 
 |  | 
 | 	size = sizeof(tplg_tmpl_with_pcm); | 
 | 	data = kunit_kzalloc(kunit_comp->kunit, size, GFP_KERNEL); | 
 | 	KUNIT_EXPECT_NOT_ERR_OR_NULL(kunit_comp->kunit, data); | 
 |  | 
 | 	memcpy(data, &tplg_tmpl_with_pcm, sizeof(tplg_tmpl_with_pcm)); | 
 |  | 
 | 	kunit_comp->fw.data = data; | 
 | 	kunit_comp->fw.size = size; | 
 |  | 
 | 	kunit_comp->card.dev = test_dev; | 
 | 	kunit_comp->card.name = "kunit-card"; | 
 | 	kunit_comp->card.owner = THIS_MODULE; | 
 | 	kunit_comp->card.dai_link = kunit_dai_links; | 
 | 	kunit_comp->card.num_links = ARRAY_SIZE(kunit_dai_links); | 
 | 	kunit_comp->card.fully_routed = true; | 
 |  | 
 | 	/* run test */ | 
 | 	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0); | 
 | 	KUNIT_EXPECT_EQ(test, 0, ret); | 
 |  | 
 | 	for (i = 0; i < 100; i++) { | 
 | 		ret = snd_soc_register_card(&kunit_comp->card); | 
 | 		if (ret != 0 && ret != -EPROBE_DEFER) | 
 | 			KUNIT_FAIL(test, "Failed to register card"); | 
 |  | 
 | 		snd_soc_unregister_card(&kunit_comp->card); | 
 | 	} | 
 |  | 
 | 	/* cleanup */ | 
 | 	snd_soc_unregister_component(test_dev); | 
 | } | 
 |  | 
 | /* ===== KUNIT MODULE DEFINITIONS =========================================== */ | 
 |  | 
 | static struct kunit_case snd_soc_tplg_test_cases[] = { | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_with_null_comp), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_with_null_ops), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_with_null_fw), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_magic), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_abi), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_size), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_empty_tplg_bad_payload_size), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_comp), | 
 | 	KUNIT_CASE(snd_soc_tplg_test_load_pcm_tplg_reload_card), | 
 | 	{} | 
 | }; | 
 |  | 
 | static struct kunit_suite snd_soc_tplg_test_suite = { | 
 | 	.name = "snd_soc_tplg_test", | 
 | 	.init = snd_soc_tplg_test_init, | 
 | 	.exit = snd_soc_tplg_test_exit, | 
 | 	.test_cases = snd_soc_tplg_test_cases, | 
 | }; | 
 |  | 
 | kunit_test_suites(&snd_soc_tplg_test_suite); | 
 |  | 
 | MODULE_DESCRIPTION("ASoC Topology Kernel Unit Tests"); | 
 | MODULE_LICENSE("GPL"); |