Merge series "Add KUNIT tests for ASoC topology" from Amadeusz Sławiński<amadeuszx.slawinski@linux.intel.com>:

This series adds unit tests for ASoC topology.

First fix problems found when developing and running test cases and
then add tests implementation.

Tests themselves are quite simple and just call
snd_soc_tplg_component_load() with various parameters and check the
result. Tests themselves are described in more detail in commits
adding them.

Goal is to expand the amount of test cases in following patches.

Prerequisity for this patchset are 2 patches which have already been
sent:
https://lore.kernel.org/alsa-devel/20210114163602.911205-1-amadeuszx.slawinski@linux.intel.com/T/#t

Description on how typical test case itself works:

In order to load topology we need to have 3 things:
card, codec component & platform component.

In typical test case we register card and platform component and bind
to dummy codec. There are of course execeptions, when we want to
test behaviour of topology API when component or card is missing.
Note that this is bit different from typical scenario (in SOF and skylake
drivers) where card is registered by machine driver and component by
platform driver, as we register both when setting up test.

If you check the test case most of them have similar architecture of:
1.
	/* run test */
	ret = snd_soc_register_card(&kunit_comp->card);
	if (ret != 0 && ret != -EPROBE_DEFER)
		KUNIT_FAIL(test, "Failed to register card");

2.
	ret = snd_soc_component_initialize(&kunit_comp->comp, &test_component, test_dev);
	KUNIT_EXPECT_EQ(test, 0, ret);

3.
	ret = snd_soc_add_component(&kunit_comp->comp, NULL, 0);
	KUNIT_EXPECT_EQ(test, 0, ret);

Ad. 1.
First we register card, which in most tests returns -EPROBE_DEFER
(from snd_soc_bind_card()), as platform component is not yet created.
I test for both 0 and -EPROBE_DEFER, as it makes it easier to reshuffle
this code around if needed and there is one test case which does it in
different order.

Ad. 2.
Then we initialize platform component with structure pointing at proper
probe function, which calls snd_soc_tplg_component_load() with test
parameters and checks expected result.

Ad. 3.
And then in follow up we call snd_soc_add_component() which creates
platform component for us and calls snd_soc_try_rebind_card() which
if everything is bound properly calls previously set probe function.

Amadeusz Sławiński (5):
  ASoC: topology: Properly unregister DAI on removal
  Revert "ASoC: soc-devres: add devm_snd_soc_register_dai()"
  ASoC: topology: KUnit: Add KUnit tests passing various arguments to
    snd_soc_tplg_component_load
  ASoC: topology: KUnit: Add KUnit tests passing empty topology with
    variants to snd_soc_tplg_component_load
  ASoC: topology: KUnit: Add KUnit tests passing topology with PCM to
    snd_soc_tplg_component_load

 include/sound/soc.h           |   4 -
 sound/soc/Kconfig             |  17 +
 sound/soc/Makefile            |   5 +
 sound/soc/soc-devres.c        |  37 --
 sound/soc/soc-topology-test.c | 843 ++++++++++++++++++++++++++++++++++
 sound/soc/soc-topology.c      |   9 +-
 6 files changed, 870 insertions(+), 45 deletions(-)
 create mode 100644 sound/soc/soc-topology-test.c

--
2.25.1
This commit is contained in:
Mark Brown 2021-01-21 18:13:24 +00:00
commit 1e924131e9
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
3 changed files with 865 additions and 0 deletions

View file

@ -37,6 +37,23 @@ config SND_SOC_COMPRESS
config SND_SOC_TOPOLOGY
bool
config SND_SOC_TOPOLOGY_KUNIT_TESTS
tristate "KUnit tests for SoC topology"
depends on KUNIT
depends on SND_SOC_TOPOLOGY
default KUNIT_ALL_TESTS
help
If you want to perform tests on ALSA SoC topology support say Y here.
This builds a module which can be later manually loaded to run KUNIT
test cases against soc-topology.c API. This should be primarily used
by developers to test their changes to ASoC.
Do note that it creates fake playback devices which do not interact
well with userspace. When running tests one may want to disable
userspace applications such as pulseaudio, to prevent unnecessary
problems.
config SND_SOC_ACPI
tristate

View file

@ -7,6 +7,11 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY),)
snd-soc-core-objs += soc-topology.o
endif
ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS),)
# snd-soc-test-objs := soc-topology-test.o
obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS) := soc-topology-test.o
endif
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
endif

View file

@ -0,0 +1,843 @@
// 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");