ASoC: topology: KUnit: Add KUnit tests passing empty topology with variants to snd_soc_tplg_component_load

In order to ensure correct behaviour of topology API, add unit tests
exercising topology functionality.

Add "empty" topology template and tests for parsing it. Also adds few
variants with bad magic numbers.

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-5-amadeuszx.slawinski@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Amadeusz Sławiński 2021-01-20 16:28:45 +01:00 committed by Mark Brown
parent d52bbf747c
commit cec9128dfc
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -6,7 +6,6 @@
*/
#include <linux/firmware.h>
#include <linux/random.h>
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-topology.h>
@ -108,6 +107,37 @@ static const struct snd_soc_component_driver test_component = {
.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 */
},
};
/* ===== TEST CASES ========================================================= */
// TEST CASE
@ -282,12 +312,291 @@ static void snd_soc_tplg_test_load_with_null_fw(struct kunit *test)
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);
}
/* ===== 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),
{}
};