| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * soc-topology-test.c -- ALSA SoC Topology Kernel Unit Tests |
| * |
| * Copyright(c) 2021 Intel Corporation. All rights reserved. |
| */ |
| |
| #include <linux/firmware.h> |
| #include <sound/core.h> |
| #include <sound/soc.h> |
| #include <sound/soc-topology.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 struct device_driver test_drv = { |
| .name = "sound-soc-topology-test-driver", |
| }; |
| |
| static int snd_soc_tplg_test_init(struct kunit *test) |
| { |
| test_dev = root_device_register("sound-soc-topology-test"); |
| test_dev = get_device(test_dev); |
| if (!test_dev) |
| return -ENODEV; |
| |
| test_dev->driver = &test_drv; |
| |
| return 0; |
| } |
| |
| static void snd_soc_tplg_test_exit(struct kunit *test) |
| { |
| put_device(test_dev); |
| root_device_unregister(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_LICENSE("GPL"); |