Skip to content

Commit 99ee443

Browse files
tlaudaMarcin Maka
authored andcommitted
cmocka: add unit tests for channel selector
Adds unit tests for channel selector component. Signed-off-by: Lech Betlej <lech.betlej@linux.intel.com>
1 parent 9f2fd0c commit 99ee443

4 files changed

Lines changed: 357 additions & 2 deletions

File tree

src/audio/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,6 @@ config COMP_SEL
6464
bool "Channel selector component"
6565
default y
6666
help
67-
Select for SRC component
67+
Select for SEL component
6868

6969
endmenu

test/cmocka/src/audio/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@ if(CONFIG_COMP_VOLUME)
99
endif()
1010
if(CONFIG_COMP_VOLUME)
1111
add_subdirectory(kpb)
12-
endif()
12+
endif()
13+
if(CONFIG_COMP_SEL)
14+
add_subdirectory(selector)
15+
endif()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
cmocka_test(selector_test
2+
selector_test.c
3+
)
4+
5+
target_include_directories(selector_test PRIVATE ${PROJECT_SOURCE_DIR}/src/audio)
6+
7+
# make small version of libaudio so we don't have to care
8+
# about unused missing references
9+
add_library(audio_for_selector STATIC
10+
${PROJECT_SOURCE_DIR}/src/audio/selector.c
11+
${PROJECT_SOURCE_DIR}/src/audio/selector_generic.c
12+
)
13+
14+
target_link_libraries(audio_for_selector PRIVATE sof_options)
15+
16+
target_link_libraries(selector_test PRIVATE audio_for_selector)
Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
/*
2+
* Copyright (c) 2019, Intel Corporation
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
* * Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* * Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
* * Neither the name of the Intel Corporation nor the
13+
* names of its contributors may be used to endorse or promote products
14+
* derived from this software without specific prior written permission.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*
28+
* Author: Lech Betlej <lech.betlej@linux.intel.com>
29+
*/
30+
31+
#include <stdarg.h>
32+
#include <stddef.h>
33+
#include <setjmp.h>
34+
#include <cmocka.h>
35+
#include <sof/audio/component.h>
36+
#include "selector.h"
37+
38+
39+
struct sel_test_state {
40+
struct comp_dev *dev;
41+
struct comp_buffer *sink;
42+
struct comp_buffer *source;
43+
void (*verify)(struct comp_dev *dev, struct comp_buffer *sink,
44+
struct comp_buffer *source);
45+
};
46+
47+
struct sel_test_parameters {
48+
uint32_t in_channels;
49+
uint32_t out_channels;
50+
uint32_t sel_channel;
51+
uint32_t frames;
52+
uint32_t buffer_size_ms;
53+
uint32_t source_format;
54+
uint32_t sink_format;
55+
void (*verify)(struct comp_dev *dev, struct comp_buffer *sink,
56+
struct comp_buffer *source);
57+
};
58+
59+
static int setup(void **state)
60+
{
61+
struct sel_test_parameters *parameters = *state;
62+
struct sel_test_state *sel_state;
63+
struct comp_data *cd;
64+
uint32_t size = 0;
65+
66+
/* allocate new state */
67+
sel_state = test_malloc(sizeof(*sel_state));
68+
69+
/* allocate and set new device */
70+
sel_state->dev = test_malloc(COMP_SIZE(struct sof_ipc_comp_volume));
71+
sel_state->dev->params.channels = parameters->in_channels;
72+
sel_state->dev->frames = parameters->frames;
73+
74+
/* allocate and set new data */
75+
cd = test_malloc(sizeof(*cd));
76+
comp_set_drvdata(sel_state->dev, cd);
77+
cd->source_format = parameters->source_format;
78+
cd->sink_format = parameters->sink_format;
79+
80+
/* prepare paramters that will be used by sel_get_processing_function */
81+
cd->in_channels_count = parameters->in_channels;
82+
cd->out_channels_count = parameters->out_channels;
83+
cd->sel_channel = parameters->sel_channel;
84+
85+
cd->sel_func = sel_get_processing_function(sel_state->dev);
86+
87+
/* allocate new sink buffer */
88+
sel_state->sink = test_malloc(sizeof(*sel_state->sink));
89+
sel_state->dev->params.frame_fmt = parameters->sink_format;
90+
size = parameters->frames * comp_frame_bytes(sel_state->dev);
91+
if(cd->out_channels_count == SEL_SINK_1CH){
92+
size = size / sel_state->dev->params.channels;
93+
}
94+
sel_state->sink->w_ptr = test_calloc(parameters->buffer_size_ms,
95+
size);
96+
sel_state->sink->size = parameters->buffer_size_ms * size;
97+
98+
/* allocate new source buffer */
99+
sel_state->source = test_malloc(sizeof(*sel_state->source));
100+
sel_state->dev->params.frame_fmt = parameters->source_format;
101+
size = parameters->frames * comp_frame_bytes(sel_state->dev);
102+
sel_state->source->r_ptr = test_calloc(parameters->buffer_size_ms,
103+
size);
104+
sel_state->source->size = parameters->buffer_size_ms * size;
105+
106+
/* assigns verification function */
107+
sel_state->verify = parameters->verify;
108+
109+
/* assign test state */
110+
*state = sel_state;
111+
112+
return 0;
113+
}
114+
115+
static int teardown(void **state)
116+
{
117+
struct sel_test_state *sel_state = *state;
118+
struct comp_data *cd = comp_get_drvdata(sel_state->dev);
119+
120+
/* free everything */
121+
test_free(cd);
122+
test_free(sel_state->dev);
123+
test_free(sel_state->sink->w_ptr);
124+
test_free(sel_state->sink);
125+
test_free(sel_state->source->r_ptr);
126+
test_free(sel_state->source);
127+
test_free(sel_state);
128+
129+
return 0;
130+
}
131+
132+
static void fill_source_s16(struct sel_test_state *sel_state)
133+
{
134+
int16_t *src = (int16_t *)sel_state->source->r_ptr;
135+
int i;
136+
137+
for (i = 0; i < sel_state->source->size / sizeof(int16_t); i++)
138+
src[i] = i;
139+
140+
}
141+
142+
static void fill_source_s32(struct sel_test_state *sel_state)
143+
{
144+
int32_t *src = (int32_t *)sel_state->source->r_ptr;
145+
int i;
146+
147+
for (i = 0; i < sel_state->source->size / sizeof(int32_t); i++)
148+
src[i] = i << 16;
149+
}
150+
151+
static void verify_s16le_Xch_to_1ch(struct comp_dev *dev, struct comp_buffer *sink,
152+
struct comp_buffer *source)
153+
{
154+
struct comp_data *cd = comp_get_drvdata(dev);
155+
const uint16_t *src = (uint16_t *)source->r_ptr;
156+
const uint16_t *dst = (uint16_t *)sink->w_ptr;
157+
uint32_t in_channels = cd->in_channels_count;
158+
uint32_t channel;
159+
uint32_t i;
160+
uint32_t j = 0;
161+
uint16_t source_in;
162+
uint16_t destination;
163+
164+
for (i = 0; i < source->size / sizeof(uint16_t); i += in_channels) {
165+
for (channel = 0; channel < in_channels; channel++) {
166+
if (channel == cd->sel_channel) {
167+
source_in = src[i + cd->sel_channel];
168+
destination = dst[j++];
169+
assert_int_equal(source_in, destination);
170+
}
171+
}
172+
}
173+
}
174+
175+
static void verify_s32le_Xch_to_1ch(struct comp_dev *dev, struct comp_buffer *sink,
176+
struct comp_buffer *source)
177+
{
178+
struct comp_data *cd = comp_get_drvdata(dev);
179+
const uint32_t *src = (uint32_t *)source->r_ptr;
180+
const uint32_t *dst = (uint32_t *)sink->w_ptr;
181+
uint32_t in_channels = cd->in_channels_count;
182+
uint32_t channel;
183+
uint32_t i;
184+
uint32_t j = 0;
185+
uint16_t source_in;
186+
uint16_t destination;
187+
188+
for (i = 0; i < source->size / sizeof(uint32_t); i += in_channels) {
189+
for (channel = 0; channel < in_channels; channel++) {
190+
if (channel == cd->sel_channel) {
191+
source_in = src[i + cd->sel_channel];
192+
destination = dst[j++];
193+
assert_int_equal(source_in, destination);
194+
}
195+
}
196+
}
197+
}
198+
199+
200+
static void verify_s16le_2ch_to_2ch(struct comp_dev *dev, struct comp_buffer *sink,
201+
struct comp_buffer *source)
202+
{
203+
struct comp_data *cd = comp_get_drvdata(dev);
204+
const uint16_t *src = (uint16_t *)source->r_ptr;
205+
const uint16_t *dst = (uint16_t *)sink->w_ptr;
206+
uint32_t channels = dev->params.channels;
207+
uint32_t channel;
208+
uint32_t i;
209+
double processed;
210+
211+
for (i = 0; i < sink->size / sizeof(uint16_t); i += channels) {
212+
for (channel = 0; channel < channels; channel++) {
213+
processed = src[i + channel];
214+
assert_int_equal(dst[i + channel], processed);
215+
}
216+
}
217+
}
218+
219+
static void verify_s16le_4ch_to_4ch(struct comp_dev *dev, struct comp_buffer *sink,
220+
struct comp_buffer *source)
221+
{
222+
struct comp_data *cd = comp_get_drvdata(dev);
223+
const uint16_t *src = (uint16_t *)source->r_ptr;
224+
const uint16_t *dst = (uint16_t *)sink->w_ptr;
225+
uint32_t channels = dev->params.channels;
226+
uint32_t channel;
227+
uint32_t i;
228+
double processed;
229+
230+
for (i = 0; i < sink->size / sizeof(uint16_t); i += channels) {
231+
for (channel = 0; channel < channels; channel++) {
232+
processed = src[i + channel];
233+
assert_int_equal(dst[i + channel], processed);
234+
}
235+
}
236+
}
237+
238+
static void verify_s32le_2ch_to_2ch(struct comp_dev *dev, struct comp_buffer *sink,
239+
struct comp_buffer *source)
240+
{
241+
struct comp_data *cd = comp_get_drvdata(dev);
242+
const uint32_t *src = (uint32_t *)source->r_ptr;
243+
const uint32_t *dst = (uint32_t *)sink->w_ptr;
244+
uint32_t channels = dev->params.channels;
245+
uint32_t channel;
246+
uint32_t i;
247+
uint32_t processed;
248+
249+
for (i = 0; i < sink->size / sizeof(uint32_t); i += channels) {
250+
for (channel = 0; channel < channels; channel++) {
251+
processed = src[i + channel];
252+
assert_int_equal(dst[i + channel], processed);
253+
}
254+
}
255+
}
256+
257+
static void verify_s32le_4ch_to_4ch(struct comp_dev *dev, struct comp_buffer *sink,
258+
struct comp_buffer *source)
259+
{
260+
struct comp_data *cd = comp_get_drvdata(dev);
261+
const uint32_t *src = (uint32_t *)source->r_ptr;
262+
const uint32_t *dst = (uint32_t *)sink->w_ptr;
263+
uint32_t channels = dev->params.channels;
264+
uint32_t channel;
265+
uint32_t i;
266+
uint32_t processed;
267+
268+
for (i = 0; i < sink->size / sizeof(uint32_t); i += channels) {
269+
for (channel = 0; channel < channels; channel++) {
270+
processed = src[i + channel];
271+
assert_int_equal(dst[i + channel], processed);
272+
}
273+
}
274+
}
275+
276+
static void test_audio_sel(void **state)
277+
{
278+
struct sel_test_state *sel_state = *state;
279+
struct comp_data *cd = comp_get_drvdata(sel_state->dev);
280+
281+
switch (cd->source_format) {
282+
case SOF_IPC_FRAME_S16_LE:
283+
fill_source_s16(sel_state);
284+
break;
285+
case SOF_IPC_FRAME_S24_4LE:
286+
case SOF_IPC_FRAME_S32_LE:
287+
case SOF_IPC_FRAME_FLOAT:
288+
fill_source_s32(sel_state);
289+
break;
290+
}
291+
292+
cd->sel_func(sel_state->dev, sel_state->sink, sel_state->source,
293+
sel_state->dev->frames);
294+
295+
sel_state->verify(sel_state->dev, sel_state->sink, sel_state->source);
296+
}
297+
298+
299+
static struct sel_test_parameters parameters[] = {
300+
{ 2, 1, 0, 16, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16le_Xch_to_1ch },
301+
{ 2, 1, 1, 16, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16le_Xch_to_1ch },
302+
{ 2, 1, 0, 48, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16le_Xch_to_1ch },
303+
{ 2, 1, 1, 48, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16le_Xch_to_1ch },
304+
{ 2, 2, 0, 48, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16le_2ch_to_2ch },
305+
{ 4, 4, 0, 48, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16le_4ch_to_4ch },
306+
{ 2, 1, 0, 48, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16le_Xch_to_1ch },
307+
{ 4, 1, 0, 48, 1, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, verify_s16le_Xch_to_1ch },
308+
309+
{ 2, 1, 0, 16, 1, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, verify_s32le_Xch_to_1ch },
310+
{ 2, 1, 1, 16, 1, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, verify_s32le_Xch_to_1ch },
311+
{ 2, 1, 0, 48, 1, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, verify_s32le_Xch_to_1ch },
312+
{ 2, 1, 1, 48, 1, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, verify_s32le_Xch_to_1ch },
313+
{ 2, 2, 0, 48, 1, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, verify_s32le_2ch_to_2ch },
314+
{ 4, 4, 0, 48, 1, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, verify_s32le_4ch_to_4ch },
315+
{ 2, 1, 0, 48, 1, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, verify_s32le_Xch_to_1ch },
316+
{ 4, 1, 0, 48, 1, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, verify_s32le_Xch_to_1ch },
317+
};
318+
319+
int main(void)
320+
{
321+
int i;
322+
323+
struct CMUnitTest tests[ARRAY_SIZE(parameters)];
324+
325+
for (i = 0; i < ARRAY_SIZE(parameters); i++) {
326+
tests[i].name = "test_audio_sel";
327+
tests[i].test_func = test_audio_sel;
328+
tests[i].setup_func = setup;
329+
tests[i].teardown_func = teardown;
330+
tests[i].initial_state = &parameters[i];
331+
}
332+
333+
cmocka_set_message_output(CM_OUTPUT_TAP);
334+
335+
return cmocka_run_group_tests(tests, NULL, NULL);
336+
}

0 commit comments

Comments
 (0)