mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-09 12:04:15 +08:00
3ad8c8e9ef
In order to ensure correct behaviour of topology API, add unit tests exercising topology functionality. Add topology containing PCM template and tests for parsing it. Also adds test cases simulating modules reloads in case of separate drivers for card and component. Signed-off-by: Amadeusz Sławiński <amadeuszx.slawinski@linux.intel.com> Tested-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com> Link: https://lore.kernel.org/r/20210120152846.1703655-6-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
844 lines
24 KiB
C
844 lines
24 KiB
C
// 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,
|
|
.non_legacy_dai_naming = 1,
|
|
};
|
|
|
|
/* ===== 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 = SND_SOC_TPLG_MAGIC,
|
|
.abi = 5,
|
|
.version = 0,
|
|
.type = SND_SOC_TPLG_TYPE_MANIFEST,
|
|
.size = sizeof(struct snd_soc_tplg_hdr),
|
|
.vendor_type = 0,
|
|
.payload_size = sizeof(struct snd_soc_tplg_manifest),
|
|
.index = 0,
|
|
.count = 1,
|
|
},
|
|
|
|
.manifest = {
|
|
.size = 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 = SND_SOC_TPLG_MAGIC,
|
|
.abi = 5,
|
|
.version = 0,
|
|
.type = SND_SOC_TPLG_TYPE_MANIFEST,
|
|
.size = sizeof(struct snd_soc_tplg_hdr),
|
|
.vendor_type = 0,
|
|
.payload_size = sizeof(struct snd_soc_tplg_manifest),
|
|
.index = 0,
|
|
.count = 1,
|
|
},
|
|
.manifest = {
|
|
.size = sizeof(struct snd_soc_tplg_manifest),
|
|
.pcm_elems = 1,
|
|
/* rest of fields is 0 */
|
|
},
|
|
.pcm_header = {
|
|
.magic = SND_SOC_TPLG_MAGIC,
|
|
.abi = 5,
|
|
.version = 0,
|
|
.type = SND_SOC_TPLG_TYPE_PCM,
|
|
.size = sizeof(struct snd_soc_tplg_hdr),
|
|
.vendor_type = 0,
|
|
.payload_size = sizeof(struct snd_soc_tplg_pcm),
|
|
.index = 0,
|
|
.count = 1,
|
|
},
|
|
.pcm = {
|
|
.size = sizeof(struct snd_soc_tplg_pcm),
|
|
.pcm_name = "KUNIT Audio",
|
|
.dai_name = "kunit-audio-dai",
|
|
.pcm_id = 0,
|
|
.dai_id = 0,
|
|
.playback = 1,
|
|
.capture = 1,
|
|
.compress = 0,
|
|
.stream = {
|
|
[0] = {
|
|
.channels = 2,
|
|
},
|
|
[1] = {
|
|
.channels = 2,
|
|
},
|
|
},
|
|
.num_streams = 0,
|
|
.caps = {
|
|
[0] = {
|
|
.name = "kunit-audio-playback",
|
|
.channels_min = 2,
|
|
.channels_max = 2,
|
|
},
|
|
[1] = {
|
|
.name = "kunit-audio-capture",
|
|
.channels_min = 2,
|
|
.channels_max = 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,
|
|
.non_legacy_dai_naming = 1,
|
|
};
|
|
|
|
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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
|
|
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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
|
|
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,
|
|
.non_legacy_dai_naming = 1,
|
|
};
|
|
|
|
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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
|
|
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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
|
|
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 = 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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
|
|
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 = 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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
|
|
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 = 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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
|
|
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);
|
|
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
}
|
|
|
|
// 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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
}
|
|
|
|
// 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 */
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
}
|
|
|
|
// 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");
|
|
|
|
ret = snd_soc_unregister_card(&kunit_comp->card);
|
|
KUNIT_EXPECT_EQ(test, 0, ret);
|
|
}
|
|
|
|
/* 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");
|