Skip to content

Commit e6c97c9

Browse files
committed
Improve test coverage for audio codec helpers
1 parent 07b59d7 commit e6c97c9

7 files changed

Lines changed: 338 additions & 34 deletions

File tree

src/codec-msbc.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* BlueALSA - codec-msbc.c
3-
* SPDX-FileCopyrightText: 2017-2025 BlueALSA developers
3+
* SPDX-FileCopyrightText: 2017-2026 BlueALSA developers
44
* SPDX-License-Identifier: MIT
55
*/
66

@@ -29,6 +29,22 @@
2929
* correct number of PCM samples - matching sample rate. */
3030
#define MSBC_DECODE_ERROR_PLC 1
3131

32+
/**
33+
* Reinitialize SBC audio codec for mSBC mode.
34+
*
35+
* This implementation overrides the function int the libsbc library. The
36+
* original one is buggy and the library maintainer seems not to care
37+
* about fixing it...
38+
*
39+
* @param sbc SBC structure which shall be reinitialized.
40+
* @param flags SBC initialization flags.
41+
* @return This function returns 0 on success or a negative error value
42+
* in case of SBC audio codec initialization failure. */
43+
int sbc_reinit_msbc(sbc_t * sbc, unsigned long flags) {
44+
sbc_finish(sbc);
45+
return sbc_init_msbc(sbc, flags);
46+
}
47+
3248
/**
3349
* Initialize mSBC codec structure.
3450
*

src/codec-sbc.c

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
/*
22
* BlueALSA - codec-sbc.c
3-
* SPDX-FileCopyrightText: 2016-2025 BlueALSA developers
3+
* SPDX-FileCopyrightText: 2016-2026 BlueALSA developers
44
* SPDX-License-Identifier: MIT
55
*/
66

77
#include "codec-sbc.h"
8-
/* IWYU pragma: no_include "config.h" */
8+
9+
#if HAVE_CONFIG_H
10+
# include <config.h>
11+
#endif
912

1013
#include <errno.h>
1114
#include <stdbool.h>
@@ -25,7 +28,7 @@
2528
* @param conf A2DP SBC configuration.
2629
* @param quality Target quality level.
2730
* @return SBC bitpool value. */
28-
uint8_t sbc_a2dp_get_bitpool(const a2dp_sbc_t *conf, unsigned int quality) {
31+
uint8_t sbc_a2dp_get_bitpool(const a2dp_sbc_t * conf, unsigned int quality) {
2932

3033
static const uint8_t bitpool_mono_44100[] = {
3134
[SBC_QUALITY_LOW] = SBC_BITPOOL_LQ_MONO_44100,
@@ -206,20 +209,6 @@ int sbc_reinit_a2dp_faststream(sbc_t *sbc, unsigned long flags,
206209

207210
#endif
208211

209-
#if ENABLE_MSBC
210-
/**
211-
* Reinitialize SBC audio codec for mSBC mode.
212-
*
213-
* @param sbc SBC structure which shall be reinitialized.
214-
* @param flags SBC initialization flags.
215-
* @return This function returns 0 on success or a negative error value
216-
* in case of SBC audio codec initialization failure. */
217-
int sbc_reinit_msbc(sbc_t *sbc, unsigned long flags) {
218-
sbc_finish(sbc);
219-
return sbc_init_msbc(sbc, flags);
220-
}
221-
#endif
222-
223212
/**
224213
* Get string representation of the SBC encode/decode error.
225214
*

src/codec-sbc.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* BlueALSA - codec-sbc.h
3-
* SPDX-FileCopyrightText: 2016-2025 BlueALSA developers
3+
* SPDX-FileCopyrightText: 2016-2026 BlueALSA developers
44
* SPDX-License-Identifier: MIT
55
*/
66

@@ -35,10 +35,6 @@ int sbc_reinit_a2dp_faststream(sbc_t *sbc, unsigned long flags,
3535
const void *conf, size_t size, bool voice);
3636
#endif
3737

38-
#if ENABLE_MSBC
39-
int sbc_reinit_msbc(sbc_t *sbc, unsigned long flags);
40-
#endif
41-
4238
const char *sbc_strerror(int err);
4339

4440
#if DEBUG

test/Makefile.am

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ TESTS = \
1414
test-at \
1515
test-audio \
1616
test-ba \
17+
test-codec-sbc \
1718
test-dbus \
1819
test-h2 \
1920
test-io \
@@ -28,6 +29,7 @@ check_PROGRAMS = \
2829
test-at \
2930
test-audio \
3031
test-ba \
32+
test-codec-sbc \
3133
test-dbus \
3234
test-h2 \
3335
test-io \
@@ -40,6 +42,11 @@ TESTS += test-utils-aplay
4042
check_PROGRAMS += test-utils-aplay
4143
endif
4244

45+
if ENABLE_APTX_OR_APTX_HD
46+
TESTS += test-codec-aptx
47+
check_PROGRAMS += test-codec-aptx
48+
endif
49+
4350
if ENABLE_CTL
4451
TESTS += test-utils-ctl
4552
check_PROGRAMS += test-utils-ctl
@@ -56,8 +63,8 @@ check_PROGRAMS += test-alsa-midi test-bt-advertising test-bt-gatt test-ble-midi
5663
endif
5764

5865
if ENABLE_MSBC
59-
TESTS += test-msbc
60-
check_PROGRAMS += test-msbc
66+
TESTS += test-codec-msbc
67+
check_PROGRAMS += test-codec-msbc
6168
endif
6269

6370
if HAVE_SNDFILE

test/test-codec-aptx.c

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* test-codec-aptx.c
3+
* SPDX-FileCopyrightText: 2026 BlueALSA developers
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
7+
#if HAVE_CONFIG_H
8+
# include <config.h>
9+
#endif
10+
11+
#include <stdint.h>
12+
#include <stddef.h>
13+
14+
#include <check.h>
15+
16+
#include "codec-aptx.h"
17+
#include "shared/defs.h"
18+
19+
#include "inc/check.inc"
20+
21+
#if ENABLE_APTX
22+
CK_START_TEST(test_codec_aptx_encode) {
23+
24+
const int16_t pcm[8] = { 0, 10, 100, 1000, 1000, 100, 10, 0 };
25+
uint8_t out[8];
26+
size_t len;
27+
28+
HANDLE_APTX handle;
29+
ck_assert_ptr_nonnull(handle = aptxenc_init());
30+
31+
len = sizeof(out);
32+
/* Check too short input buffer. */
33+
ck_assert_int_eq(aptxenc_encode(handle, pcm, ARRAYSIZE(pcm) - 2, out, &len), -1);
34+
35+
len = 2;
36+
/* Check too short output buffer. */
37+
ck_assert_int_eq(aptxenc_encode(handle, pcm, ARRAYSIZE(pcm), out, &len), -1);
38+
39+
len = sizeof(out);
40+
/* Check proper encoding. */
41+
ck_assert_int_eq(aptxenc_encode(handle, pcm, ARRAYSIZE(pcm), out, &len), 8);
42+
const uint8_t expected[4] = { 0x4B, 0xBF, 0x4B, 0xBF };
43+
ck_assert_mem_eq(out, expected, sizeof(expected));
44+
ck_assert_int_eq(len, 4);
45+
46+
aptxenc_destroy(handle);
47+
48+
} CK_END_TEST
49+
#endif
50+
51+
#if ENABLE_APTX && HAVE_APTX_DECODE
52+
CK_START_TEST(test_codec_aptx_decode) {
53+
54+
const uint8_t enc[4] = { 0x4B, 0xBF, 0x4B, 0xBF };
55+
int16_t out[16];
56+
size_t samples;
57+
58+
HANDLE_APTX handle;
59+
ck_assert_ptr_nonnull(handle = aptxdec_init());
60+
61+
samples = sizeof(out);
62+
/* Check too short input buffer. */
63+
ck_assert_int_eq(aptxdec_decode(handle, enc, sizeof(enc) - 2, out, &samples), -1);
64+
65+
samples = 2;
66+
/* Check too short output buffer. */
67+
ck_assert_int_eq(aptxdec_decode(handle, enc, sizeof(enc), out, &samples), -1);
68+
69+
samples = sizeof(out);
70+
/* Check proper decoding. */
71+
ck_assert_int_eq(aptxdec_decode(handle, enc, sizeof(enc), out, &samples), 4);
72+
/* Initial sync-word decoding does not output any samples. */
73+
ck_assert_int_eq(samples, 0);
74+
75+
aptxdec_destroy(handle);
76+
77+
} CK_END_TEST
78+
#endif
79+
80+
#if ENABLE_APTX_HD
81+
CK_START_TEST(test_codec_aptx_hd_encode) {
82+
83+
const int32_t pcm[8] = { 0, 10, 100, 1000, 1000, 100, 10, 0 };
84+
uint8_t out[8];
85+
size_t len;
86+
87+
HANDLE_APTX handle;
88+
ck_assert_ptr_nonnull(handle = aptxhdenc_init());
89+
90+
len = sizeof(out);
91+
/* Check too short input buffer. */
92+
ck_assert_int_eq(aptxhdenc_encode(handle, pcm, ARRAYSIZE(pcm) - 2, out, &len), -1);
93+
94+
len = 2;
95+
/* Check too short output buffer. */
96+
ck_assert_int_eq(aptxhdenc_encode(handle, pcm, ARRAYSIZE(pcm), out, &len), -1);
97+
98+
len = sizeof(out);
99+
/* Check proper encoding. */
100+
ck_assert_int_eq(aptxhdenc_encode(handle, pcm, ARRAYSIZE(pcm), out, &len), 8);
101+
const uint8_t expected[6] = { 0x73, 0xBE, 0xFF, 0x73, 0xBE, 0xFF };
102+
ck_assert_mem_eq(out, expected, sizeof(expected));
103+
ck_assert_int_eq(len, 6);
104+
105+
aptxhdenc_destroy(handle);
106+
107+
} CK_END_TEST
108+
#endif
109+
110+
#if ENABLE_APTX_HD && HAVE_APTX_HD_DECODE
111+
CK_START_TEST(test_codec_aptx_hd_decode) {
112+
113+
const uint8_t enc[6] = { 0x73, 0xBE, 0xFF, 0x73, 0xBE, 0xFF };
114+
int32_t out[16];
115+
size_t samples;
116+
117+
HANDLE_APTX handle;
118+
ck_assert_ptr_nonnull(handle = aptxhddec_init());
119+
120+
samples = sizeof(out);
121+
/* Check too short input buffer. */
122+
ck_assert_int_eq(aptxhddec_decode(handle, enc, sizeof(enc) - 2, out, &samples), -1);
123+
124+
samples = 2;
125+
/* Check too short output buffer. */
126+
ck_assert_int_eq(aptxhddec_decode(handle, enc, sizeof(enc), out, &samples), -1);
127+
128+
samples = sizeof(out);
129+
/* Check proper decoding. */
130+
ck_assert_int_eq(aptxhddec_decode(handle, enc, sizeof(enc), out, &samples), 6);
131+
/* Initial sync-word decoding does not output any samples. */
132+
ck_assert_int_eq(samples, 0);
133+
134+
aptxhddec_destroy(handle);
135+
136+
} CK_END_TEST
137+
#endif
138+
139+
int main(void) {
140+
141+
Suite * s = suite_create(__FILE__);
142+
TCase * tc = tcase_create(__FILE__);
143+
SRunner * sr = srunner_create(s);
144+
145+
suite_add_tcase(s, tc);
146+
147+
#if ENABLE_APTX
148+
tcase_add_test(tc, test_codec_aptx_encode);
149+
#endif
150+
#if ENABLE_APTX && HAVE_APTX_DECODE
151+
tcase_add_test(tc, test_codec_aptx_decode);
152+
#endif
153+
#if ENABLE_APTX_HD
154+
tcase_add_test(tc, test_codec_aptx_hd_encode);
155+
#endif
156+
#if ENABLE_APTX_HD && HAVE_APTX_HD_DECODE
157+
tcase_add_test(tc, test_codec_aptx_hd_decode);
158+
#endif
159+
160+
srunner_run_all(sr, CK_ENV);
161+
int nf = srunner_ntests_failed(sr);
162+
srunner_free(sr);
163+
164+
return nf == 0 ? 0 : 1;
165+
}
Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
* test-msbc.c
3-
* SPDX-FileCopyrightText: 2016-2025 BlueALSA developers
2+
* test-codec-msbc.c
3+
* SPDX-FileCopyrightText: 2016-2026 BlueALSA developers
44
* SPDX-License-Identifier: MIT
55
*/
66

7+
#include <errno.h>
78
#include <stdbool.h>
89
#include <stdint.h>
910
#include <stdio.h>
@@ -36,6 +37,8 @@ CK_START_TEST(test_msbc_init) {
3637
ck_assert_int_eq(ffb_len_out(&msbc.pcm), 0);
3738

3839
msbc_finish(&msbc);
40+
/* Check that NULL can be passed safely. */
41+
msbc_finish(NULL);
3942

4043
} CK_END_TEST
4144

@@ -45,13 +48,17 @@ CK_START_TEST(test_msbc_encode_decode) {
4548
snd_pcm_sine_s16_2le(sine, 1, ARRAYSIZE(sine), 1.0 / 128, 0);
4649

4750
uint8_t data[sizeof(sine)];
48-
uint8_t *data_tail = data;
51+
uint8_t * data_tail = data;
4952

50-
struct esco_msbc msbc = { 0 };
53+
struct esco_msbc msbc = { .initialized = false };
5154
size_t len;
5255
size_t i;
5356
int rv;
5457

58+
/* Check calling encode/decode without initialization. */
59+
ck_assert_int_eq(msbc_encode(&msbc), -EINVAL);
60+
ck_assert_int_eq(msbc_decode(&msbc), -EINVAL);
61+
5562
msbc.initialized = false;
5663
ck_assert_int_eq(msbc_init(&msbc), 0);
5764
for (rv = 1, i = 0; rv > 0;) {
@@ -75,7 +82,7 @@ CK_START_TEST(test_msbc_encode_decode) {
7582
msbc_finish(&msbc);
7683

7784
int16_t pcm[sizeof(sine)];
78-
int16_t *pcm_tail = pcm;
85+
int16_t * pcm_tail = pcm;
7986

8087
msbc.initialized = false;
8188
ck_assert_int_eq(msbc_init(&msbc), 0);
@@ -110,7 +117,7 @@ CK_START_TEST(test_msbc_decode_plc) {
110117
ck_assert_int_eq(msbc_init(&msbc), 0);
111118

112119
uint8_t data[sizeof(sine)];
113-
uint8_t *data_tail = data;
120+
uint8_t * data_tail = data;
114121

115122
debug("Simulating eSCO packet loss events");
116123

@@ -177,17 +184,23 @@ CK_START_TEST(test_msbc_decode_plc) {
177184

178185
} CK_END_TEST
179186

187+
CK_START_TEST(test_msbc_stderr) {
188+
ck_assert_str_eq(msbc_strerror(0), "Success");
189+
ck_assert_str_eq(msbc_strerror(-EINVAL), "Invalid argument");
190+
} CK_END_TEST
191+
180192
int main(void) {
181193

182-
Suite *s = suite_create(__FILE__);
183-
TCase *tc = tcase_create(__FILE__);
184-
SRunner *sr = srunner_create(s);
194+
Suite * s = suite_create(__FILE__);
195+
TCase * tc = tcase_create(__FILE__);
196+
SRunner * sr = srunner_create(s);
185197

186198
suite_add_tcase(s, tc);
187199

188200
tcase_add_test(tc, test_msbc_init);
189201
tcase_add_test(tc, test_msbc_encode_decode);
190202
tcase_add_test(tc, test_msbc_decode_plc);
203+
tcase_add_test(tc, test_msbc_stderr);
191204

192205
srunner_run_all(sr, CK_ENV);
193206
int nf = srunner_ntests_failed(sr);

0 commit comments

Comments
 (0)