1 /*
2 * Copyright 2020 HIMSA II K/S - www.himsa.com.
3 * Represented by EHIMA - www.ehima.com
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include "le_audio_types.h"
19
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include <vector>
24
25 #include "le_audio_utils.h"
26
27 namespace bluetooth::le_audio {
28 namespace types {
29
30 using ::testing::AllOf;
31 using ::testing::Contains;
32 using ::testing::ElementsAre;
33 using ::testing::ElementsAreArray;
34 using ::testing::Eq;
35 using ::testing::Pair;
36 using ::testing::SizeIs;
37
TEST(LeAudioLtvMapTest,test_serialization)38 TEST(LeAudioLtvMapTest, test_serialization) {
39 // clang-format off
40 const std::vector<uint8_t> ltv_test_vec{
41 0x02, 0x01, 0x0a,
42 0x03, 0x02, 0xaa, 0xbb,
43 0x04, 0x03, 0xde, 0xc0, 0xd0,
44 };
45
46 const std::vector<uint8_t> ltv_test_vec2{
47 0x04, 0x03, 0xde, 0xc0, 0xde,
48 0x05, 0x04, 0xc0, 0xde, 0xc0, 0xde,
49 };
50
51 const std::vector<uint8_t> ltv_test_vec_expected{
52 0x02, 0x01, 0x0a,
53 0x03, 0x02, 0xaa, 0xbb,
54 0x04, 0x03, 0xde, 0xc0, 0xde,
55 0x05, 0x04, 0xc0, 0xde, 0xc0, 0xde,
56 };
57 // clang-format on
58
59 // Parse
60 bool success;
61 LeAudioLtvMap ltv_map = LeAudioLtvMap::Parse(ltv_test_vec.data(), ltv_test_vec.size(), success);
62 auto hash_one = ltv_map.GetHash();
63 ASSERT_TRUE(success);
64 ASSERT_NE(hash_one, 0lu);
65 ASSERT_FALSE(ltv_map.IsEmpty());
66 ASSERT_EQ((size_t)3, ltv_map.Size());
67
68 ASSERT_TRUE(ltv_map.Find(0x03));
69 ASSERT_THAT(*(ltv_map.Find(0x03)), ElementsAre(0xde, 0xc0, 0xd0));
70
71 LeAudioLtvMap ltv_map2 =
72 LeAudioLtvMap::Parse(ltv_test_vec2.data(), ltv_test_vec2.size(), success);
73 auto hash_two = ltv_map2.GetHash();
74 ASSERT_TRUE(success);
75 ASSERT_NE(hash_two, 0lu);
76 ASSERT_FALSE(ltv_map2.IsEmpty());
77 ASSERT_EQ((size_t)2, ltv_map2.Size());
78 ASSERT_NE(hash_one, hash_two);
79
80 ltv_map.Append(ltv_map2);
81 ASSERT_NE(ltv_map.GetHash(), 0lu);
82 ASSERT_NE(ltv_map.GetHash(), hash_one);
83 ASSERT_NE(ltv_map.GetHash(), hash_two);
84 ASSERT_EQ((size_t)4, ltv_map.Size());
85
86 ASSERT_TRUE(ltv_map.Find(0x01));
87 ASSERT_THAT(*(ltv_map.Find(0x01)), ElementsAre(0x0a));
88 ASSERT_TRUE(ltv_map.Find(0x02));
89 ASSERT_THAT(*(ltv_map.Find(0x02)), ElementsAre(0xaa, 0xbb));
90 ASSERT_TRUE(ltv_map.Find(0x03));
91 ASSERT_THAT(*(ltv_map.Find(0x03)), ElementsAre(0xde, 0xc0, 0xde));
92 ASSERT_TRUE(ltv_map.Find(0x04));
93 ASSERT_THAT(*(ltv_map.Find(0x04)), ElementsAre(0xc0, 0xde, 0xc0, 0xde));
94
95 // RawPacket
96 std::vector<uint8_t> serialized(ltv_map.RawPacketSize());
97 ASSERT_TRUE(ltv_map.RawPacket(serialized.data()));
98 ASSERT_THAT(serialized, ElementsAreArray(ltv_test_vec_expected));
99 ASSERT_THAT(ltv_map2.RawPacket(), ElementsAreArray(ltv_test_vec2));
100 }
101
TEST(LeAudioLtvMapTest,test_serialization_macros)102 TEST(LeAudioLtvMapTest, test_serialization_macros) {
103 uint64_t value = 0x08090A0B0C0D0E0F;
104
105 auto u16vec = UINT16_TO_VEC_UINT8(value);
106 ASSERT_EQ(sizeof(uint16_t), u16vec.size());
107 ASSERT_EQ(0x0F, u16vec[0]);
108 ASSERT_EQ(0x0E, u16vec[1]);
109
110 auto u32vec = UINT32_TO_VEC_UINT8(value);
111 ASSERT_EQ(sizeof(uint32_t), u32vec.size());
112 ASSERT_EQ(0x0F, u32vec[0]);
113 ASSERT_EQ(0x0E, u32vec[1]);
114 ASSERT_EQ(0x0D, u32vec[2]);
115 ASSERT_EQ(0x0C, u32vec[3]);
116 }
117
TEST(LeAudioLtvMapTest,test_serialization_ltv_len_is_zero)118 TEST(LeAudioLtvMapTest, test_serialization_ltv_len_is_zero) {
119 // clang-format off
120 const std::vector<uint8_t> ltv_test_vec{
121 0x02, 0x01, 0x0a,
122 0x03, 0x02, 0xaa, 0xbb,
123 0x00, 0x00, 0x00, 0x00, 0x00, // ltv_len == 0
124 0x05, 0x04, 0xc0, 0xde, 0xc0, 0xde,
125 };
126 // clang-format on
127
128 // Parse
129 bool success;
130 LeAudioLtvMap ltv_map = LeAudioLtvMap::Parse(ltv_test_vec.data(), ltv_test_vec.size(), success);
131 ASSERT_TRUE(success);
132 ASSERT_FALSE(ltv_map.IsEmpty());
133 ASSERT_EQ((size_t)3, ltv_map.Size());
134
135 ASSERT_TRUE(ltv_map.Find(0x01));
136 ASSERT_THAT(*(ltv_map.Find(0x01)), ElementsAre(0x0a));
137 ASSERT_TRUE(ltv_map.Find(0x02));
138 ASSERT_THAT(*(ltv_map.Find(0x02)), ElementsAre(0xaa, 0xbb));
139 ASSERT_TRUE(ltv_map.Find(0x04));
140 ASSERT_THAT(*(ltv_map.Find(0x04)), ElementsAre(0xc0, 0xde, 0xc0, 0xde));
141
142 // RawPacket
143 std::vector<uint8_t> serialized(ltv_map.RawPacketSize());
144 ASSERT_TRUE(ltv_map.RawPacket(serialized.data()));
145 ASSERT_THAT(serialized, ElementsAre(0x02, 0x01, 0x0a, 0x03, 0x02, 0xaa, 0xbb, 0x05, 0x04, 0xc0,
146 0xde, 0xc0, 0xde));
147 }
148
TEST(LeAudioLtvMapTest,test_serialization_ltv_len_is_one)149 TEST(LeAudioLtvMapTest, test_serialization_ltv_len_is_one) {
150 // clang-format off
151 const std::vector<uint8_t> ltv_test_vec{
152 0x02, 0x01, 0x0a,
153 0x01, 0x02,
154 };
155 // clang-format on
156
157 // Parse
158 bool success;
159 LeAudioLtvMap ltv_map = LeAudioLtvMap::Parse(ltv_test_vec.data(), ltv_test_vec.size(), success);
160 ASSERT_TRUE(success);
161 ASSERT_FALSE(ltv_map.IsEmpty());
162 ASSERT_EQ((size_t)2, ltv_map.Size());
163
164 ASSERT_TRUE(ltv_map.Find(0x01));
165 ASSERT_THAT(*(ltv_map.Find(0x01)), ElementsAre(0x0a));
166 ASSERT_TRUE(ltv_map.Find(0x02));
167 ASSERT_THAT(*(ltv_map.Find(0x02)), SizeIs(0));
168
169 // RawPacket
170 std::vector<uint8_t> serialized(ltv_map.RawPacketSize());
171 ASSERT_TRUE(ltv_map.RawPacket(serialized.data()));
172 ASSERT_THAT(serialized, ElementsAreArray(ltv_test_vec));
173 }
174
TEST(LeAudioLtvMapTest,test_serialization_ltv_len_is_invalid)175 TEST(LeAudioLtvMapTest, test_serialization_ltv_len_is_invalid) {
176 // clang-format off
177 const std::vector<uint8_t> ltv_test_vec_1{
178 0x02, 0x01, 0x0a,
179 0x04, 0x02, 0xaa, 0xbb, // one byte missing
180 };
181 const std::vector<uint8_t> ltv_test_vec_2{
182 0x02, 0x01, 0x0a,
183 0x03, 0x02, 0xaa, 0xbb,
184 0x01,
185 };
186 const std::vector<uint8_t> ltv_test_vec_3{
187 0x02, 0x01, 0x0a,
188 0x03, 0x02, 0xaa, 0xbb,
189 0x02, 0x03,
190 };
191 // clang-format on
192
193 // Parse
194 bool success = true;
195 LeAudioLtvMap ltv_map;
196
197 ltv_map = LeAudioLtvMap::Parse(ltv_test_vec_1.data(), ltv_test_vec_1.size(), success);
198 ASSERT_FALSE(success);
199
200 ltv_map = LeAudioLtvMap::Parse(ltv_test_vec_2.data(), ltv_test_vec_2.size(), success);
201 ASSERT_FALSE(success);
202
203 ltv_map = LeAudioLtvMap::Parse(ltv_test_vec_3.data(), ltv_test_vec_3.size(), success);
204 ASSERT_FALSE(success);
205 }
206
TEST(LeAudioLtvMapTest,test_configuration_valid)207 TEST(LeAudioLtvMapTest, test_configuration_valid) {
208 // clang-format off
209 const std::vector<uint8_t> config_ltv_vec{
210 // SamplingFreq = 48000
211 0x02, 0x01, 0x08,
212 // FrameDuration = 10000us
213 0x02, 0x02, 0x01,
214 // AudioChannelAllocation = kLeAudioLocationFrontLeft | kLeAudioLocationFrontRight
215 0x05, 0x03, 0x03, 0x00, 0x00, 0x00,
216 // OctetsPerCodecFrame = 40
217 0x03, 0x04, 40, 0x00,
218 // Unknown type entry to ignore
219 0x05, 0x06, 0x11, 0x22, 0x33, 0x44,
220 // CodecFrameBlocksPerSdu = 1
221 0x02, 0x05, 1,
222 };
223 // clang-format on
224
225 // Parse
226 bool success = true;
227 LeAudioLtvMap ltv_map =
228 LeAudioLtvMap::Parse(config_ltv_vec.data(), config_ltv_vec.size(), success);
229 ASSERT_TRUE(success);
230
231 // Verify the codec configuration values
232 auto config = ltv_map.GetAsCoreCodecConfig();
233
234 // SamplingFreq = 48000
235 ASSERT_TRUE(config.sampling_frequency.has_value());
236 ASSERT_EQ(0x08, config.sampling_frequency.value());
237 ASSERT_EQ(48000u, config.GetSamplingFrequencyHz());
238
239 // FrameDuration = 10000us
240 ASSERT_TRUE(config.frame_duration.has_value());
241 ASSERT_EQ(0x01, config.frame_duration.value());
242 ASSERT_EQ(10000u, config.GetFrameDurationUs());
243
244 // AudioChannelAllocation = kLeAudioLocationFrontLeft | kLeAudioLocationFrontRight
245 ASSERT_TRUE(config.audio_channel_allocation.has_value());
246 ASSERT_EQ(0x00000003u, config.audio_channel_allocation.value());
247
248 // OctetsPerCodecFrame = 40
249 ASSERT_TRUE(config.octets_per_codec_frame.has_value());
250 ASSERT_EQ(0x0028u, config.octets_per_codec_frame.value());
251
252 // CodecFrameBlocksPerSdu = 1
253 ASSERT_TRUE(config.codec_frames_blocks_per_sdu.has_value());
254 ASSERT_EQ(0x01u, config.codec_frames_blocks_per_sdu.value());
255 }
256
TEST(LeAudioLtvMapTest,test_capabilities_valid)257 TEST(LeAudioLtvMapTest, test_capabilities_valid) {
258 // clang-format off
259 const std::vector<uint8_t> capabilities_ltv_vec{
260 // SupportedSamplingFrequencies = 96000 and 16000
261 0x03, 0x01,
262 (uint8_t)(codec_spec_caps::kLeAudioSamplingFreq16000Hz) |
263 (uint8_t)(codec_spec_caps::kLeAudioSamplingFreq96000Hz),
264 (uint8_t)(codec_spec_caps::kLeAudioSamplingFreq16000Hz >> 8) |
265 (uint8_t)(codec_spec_caps::kLeAudioSamplingFreq96000Hz >> 8),
266 // SupportedFrameDurations = 10ms, 7.5ms, 10ms preferred
267 0x02, 0x02, codec_spec_caps::kLeAudioCodecFrameDur7500us |
268 codec_spec_caps::kLeAudioCodecFrameDur10000us |
269 codec_spec_caps::kLeAudioCodecFrameDurPrefer10000us,
270 // SupportedAudioChannelCounts = 0b1 | 0b2 (one and two channels)
271 0x02, 0x03, 0b01 | 0b10,
272 // SupportedOctetsPerCodecFrame = min:40, max:80
273 0x05, 0x04, 40, 00, 80, 00,
274 // Unknown type entry to ignore
275 0x05, 0x06, 0x11, 0x22, 0x33, 0x44,
276 // SupportedMaxCodecFramesPerSdu = 2
277 0x02, 0x05, 0x02,
278 };
279 // clang-format on
280
281 // Parse
282 bool success = true;
283 LeAudioLtvMap ltv_map =
284 LeAudioLtvMap::Parse(capabilities_ltv_vec.data(), capabilities_ltv_vec.size(), success);
285 ASSERT_TRUE(success);
286
287 // Verify the codec capabilities values
288 auto caps = ltv_map.GetAsCoreCodecCapabilities();
289
290 // SupportedSamplingFrequencies = 96000 and 16000
291 ASSERT_TRUE(caps.HasSupportedSamplingFrequencies());
292 ASSERT_EQ(codec_spec_caps::kLeAudioSamplingFreq16000Hz |
293 codec_spec_caps::kLeAudioSamplingFreq96000Hz,
294 caps.supported_sampling_frequencies.value());
295 // Check config values against the capabilities
296 ASSERT_FALSE(
297 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq8000Hz));
298 ASSERT_FALSE(
299 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq11025Hz));
300 ASSERT_TRUE(
301 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq16000Hz));
302 ASSERT_FALSE(
303 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq22050Hz));
304 ASSERT_FALSE(
305 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq24000Hz));
306 ASSERT_FALSE(
307 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq32000Hz));
308 ASSERT_FALSE(
309 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq44100Hz));
310 ASSERT_FALSE(
311 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq48000Hz));
312 ASSERT_FALSE(
313 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq88200Hz));
314 ASSERT_TRUE(
315 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq96000Hz));
316 ASSERT_FALSE(
317 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq176400Hz));
318 ASSERT_FALSE(
319 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq192000Hz));
320 ASSERT_FALSE(
321 caps.IsSamplingFrequencyConfigSupported(codec_spec_conf::kLeAudioSamplingFreq384000Hz));
322
323 // SupportedFrameDurations = 10ms, 7.5ms, 10ms preferred
324 ASSERT_TRUE(caps.HasSupportedFrameDurations());
325 ASSERT_EQ(codec_spec_caps::kLeAudioCodecFrameDur7500us |
326 codec_spec_caps::kLeAudioCodecFrameDur10000us |
327 codec_spec_caps::kLeAudioCodecFrameDurPrefer10000us,
328 caps.supported_frame_durations.value());
329 // Check config values against the capabilities
330 ASSERT_TRUE(caps.IsFrameDurationConfigSupported(codec_spec_conf::kLeAudioCodecFrameDur7500us));
331 ASSERT_TRUE(caps.IsFrameDurationConfigSupported(codec_spec_conf::kLeAudioCodecFrameDur10000us));
332
333 // SupportedAudioChannelCounts = 0b1 | 0b2 (one and two channels)
334 ASSERT_TRUE(caps.HasSupportedAudioChannelCounts());
335 ASSERT_EQ(codec_spec_caps::kLeAudioCodecChannelCountSingleChannel |
336 codec_spec_caps::kLeAudioCodecChannelCountTwoChannel,
337 caps.supported_audio_channel_counts.value());
338 // Check config values against the capabilities
339 ASSERT_TRUE(caps.IsAudioChannelCountsSupported(1));
340 ASSERT_TRUE(caps.IsAudioChannelCountsSupported(2));
341 for (uint8_t i = 3; i < 8; ++i) {
342 ASSERT_FALSE(caps.IsAudioChannelCountsSupported(i));
343 }
344
345 // SupportedOctetsPerCodecFrame = min:40, max:80
346 ASSERT_TRUE(caps.HasSupportedOctetsPerCodecFrame());
347 ASSERT_EQ(codec_spec_caps::kLeAudioCodecFrameLen40,
348 caps.supported_min_octets_per_codec_frame.value());
349 ASSERT_EQ(codec_spec_caps::kLeAudioCodecFrameLen80,
350 caps.supported_max_octets_per_codec_frame.value());
351 // Check config values against the capabilities
352 ASSERT_FALSE(caps.IsOctetsPerCodecFrameConfigSupported(codec_spec_conf::kLeAudioCodecFrameLen30));
353 ASSERT_TRUE(caps.IsOctetsPerCodecFrameConfigSupported(codec_spec_conf::kLeAudioCodecFrameLen40));
354 // Supported since: 40(min) < 60 < 80(max)
355 ASSERT_TRUE(caps.IsOctetsPerCodecFrameConfigSupported(codec_spec_conf::kLeAudioCodecFrameLen60));
356 ASSERT_TRUE(caps.IsOctetsPerCodecFrameConfigSupported(codec_spec_conf::kLeAudioCodecFrameLen80));
357 ASSERT_FALSE(
358 caps.IsOctetsPerCodecFrameConfigSupported(codec_spec_conf::kLeAudioCodecFrameLen120));
359
360 // SupportedMaxCodecFramesPerSdu = 2
361 ASSERT_TRUE(caps.HasSupportedMaxCodecFramesPerSdu());
362 ASSERT_EQ(2, caps.supported_max_codec_frames_per_sdu.value());
363 // Check config values against the capabilities: {1,2} <= 2(max)
364 ASSERT_TRUE(caps.IsCodecFramesPerSduSupported(1));
365 ASSERT_TRUE(caps.IsCodecFramesPerSduSupported(2));
366 ASSERT_FALSE(caps.IsCodecFramesPerSduSupported(3));
367 }
368
TEST(LeAudioLtvMapTest,test_metadata_use_guard1)369 TEST(LeAudioLtvMapTest, test_metadata_use_guard1) {
370 auto default_context = (uint16_t)bluetooth::le_audio::types::LeAudioContextType::VOICEASSISTANTS;
371 static const std::vector<uint8_t> default_metadata = {
372 bluetooth::le_audio::types::kLeAudioMetadataStreamingAudioContextLen + 1,
373 bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
374 (uint8_t)(default_context & 0x00FF), (uint8_t)((default_context & 0xFF00) >> 8)};
375
376 // Parse
377 bool success = true;
378 LeAudioLtvMap ltv_map =
379 LeAudioLtvMap::Parse(default_metadata.data(), default_metadata.size(), success);
380 ASSERT_TRUE(success);
381
382 // Verify the codec capabilities values
383 auto metadata = ltv_map.GetAsLeAudioMetadata();
384
385 // Should fail when trying to reinterpret the LTV as configuration
386 EXPECT_DEATH(ltv_map.GetAsCoreCodecConfig(), "");
387 }
388
TEST(LeAudioLtvMapTest,test_metadata_use_guard2)389 TEST(LeAudioLtvMapTest, test_metadata_use_guard2) {
390 auto default_context = (uint16_t)bluetooth::le_audio::types::LeAudioContextType::VOICEASSISTANTS;
391 static const std::vector<uint8_t> default_metadata = {
392 bluetooth::le_audio::types::kLeAudioMetadataStreamingAudioContextLen + 1,
393 bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
394 (uint8_t)(default_context & 0x00FF), (uint8_t)((default_context & 0xFF00) >> 8)};
395
396 // Parse
397 bool success = true;
398 LeAudioLtvMap ltv_map =
399 LeAudioLtvMap::Parse(default_metadata.data(), default_metadata.size(), success);
400 ASSERT_TRUE(success);
401
402 // Verify the codec capabilities values
403 auto metadata = ltv_map.GetAsLeAudioMetadata();
404
405 // Should fail when trying to reinterpret the LTV as configuration
406 EXPECT_DEATH(ltv_map.GetAsCoreCodecCapabilities(), "");
407 }
408
PrepareMetadataLtv()409 static auto PrepareMetadataLtv() {
410 ::bluetooth::le_audio::types::LeAudioLtvMap metadata_ltvs;
411 // Prepare the metadata LTVs
412 metadata_ltvs
413 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypePreferredAudioContext,
414 (uint16_t)10)
415 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeStreamingAudioContext, (uint16_t)8)
416 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeProgramInfo,
417 std::string{"ProgramInfo"})
418 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeLanguage, std::string{"ice"})
419 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList,
420 std::vector<uint8_t>{1, 2, 3})
421 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeparentalRating, (uint8_t)0x01)
422 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeProgramInfoUri,
423 std::string{"ProgramInfoUri"})
424 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeAudioActiveState, false)
425 .Add(::bluetooth::le_audio::types::
426 kLeAudioMetadataTypeBroadcastAudioImmediateRenderingFlag,
427 true)
428 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeExtendedMetadata,
429 std::vector<uint8_t>{1, 2, 3})
430 .Add(::bluetooth::le_audio::types::kLeAudioMetadataTypeVendorSpecific,
431 std::vector<uint8_t>{1, 2, 3});
432 return metadata_ltvs;
433 }
434
TEST(LeAudioLtvMapTest,test_metadata_valid)435 TEST(LeAudioLtvMapTest, test_metadata_valid) {
436 // Prepare the reference LTV
437 auto metadata_ltv = PrepareMetadataLtv();
438 auto raw_metadata = metadata_ltv.RawPacket();
439
440 // Check the Parsing
441 bool success = true;
442 LeAudioLtvMap parsed_ltv_map =
443 LeAudioLtvMap::Parse(raw_metadata.data(), raw_metadata.size(), success);
444 ASSERT_TRUE(success);
445
446 // Verify the values
447 auto metadata = metadata_ltv.GetAsLeAudioMetadata();
448 auto parsed_metadata = parsed_ltv_map.GetAsLeAudioMetadata();
449 ASSERT_EQ(parsed_metadata.preferred_audio_context.value(),
450 metadata.preferred_audio_context.value());
451 ASSERT_EQ(parsed_metadata.program_info.value(), metadata.program_info.value());
452 ASSERT_TRUE(parsed_metadata.language.has_value());
453 ASSERT_TRUE(metadata.language.has_value());
454 ASSERT_EQ(parsed_metadata.language.value(), metadata.language.value());
455 ASSERT_EQ(parsed_metadata.ccid_list.value(), metadata.ccid_list.value());
456 ASSERT_EQ(parsed_metadata.parental_rating.value(), metadata.parental_rating.value());
457 ASSERT_EQ(parsed_metadata.program_info_uri.value(), metadata.program_info_uri.value());
458 ASSERT_EQ(parsed_metadata.audio_active_state.value(), metadata.audio_active_state.value());
459 ASSERT_EQ(parsed_metadata.broadcast_audio_immediate_rendering.value(),
460 metadata.broadcast_audio_immediate_rendering.value());
461 ASSERT_EQ(parsed_metadata.extended_metadata.value(), metadata.extended_metadata.value());
462 ASSERT_EQ(parsed_metadata.vendor_specific.value(), metadata.vendor_specific.value());
463 }
464
TEST(LeAudioLtvMapTest,test_adding_types)465 TEST(LeAudioLtvMapTest, test_adding_types) {
466 LeAudioLtvMap ltv_map;
467 ltv_map.Add(1, (uint8_t)127);
468 ltv_map.Add(2, (uint16_t)32767);
469 ltv_map.Add(3, (uint32_t)65535);
470 ltv_map.Add(4, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
471 ltv_map.Add(5, std::string("sample text"));
472 ltv_map.Add(6, true);
473
474 ASSERT_EQ(6lu, ltv_map.Size());
475
476 uint8_t u8;
477 auto pp = ltv_map.At(1).data();
478 STREAM_TO_UINT8(u8, pp);
479 ASSERT_EQ((uint8_t)127, u8);
480
481 uint16_t u16;
482 pp = ltv_map.At(2).data();
483 STREAM_TO_UINT16(u16, pp);
484 ASSERT_EQ((uint16_t)32767, u16);
485
486 uint32_t u32;
487 pp = ltv_map.At(3).data();
488 STREAM_TO_UINT32(u32, pp);
489 ASSERT_EQ((uint32_t)65535, u32);
490
491 ASSERT_EQ((std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9}), ltv_map.At(4));
492
493 ASSERT_EQ(std::string("sample text"), std::string(ltv_map.At(5).begin(), ltv_map.At(5).end()));
494
495 ASSERT_EQ(true, (bool)ltv_map.At(6).data()[0]);
496 }
497
TEST(LeAudioLtvMapTest,test_hash_sanity)498 TEST(LeAudioLtvMapTest, test_hash_sanity) {
499 LeAudioLtvMap ltv_map;
500 ASSERT_EQ(ltv_map.GetHash(), 0lu);
501
502 auto hash = ltv_map.GetHash();
503 ltv_map.Add(0, (uint8_t)127);
504 ltv_map.Add(1, (uint16_t)32767);
505 ltv_map.Add(2, (uint32_t)65535);
506 ltv_map.Add(3, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
507
508 ASSERT_NE(ltv_map.GetHash(), 0lu);
509 ASSERT_NE(ltv_map.GetHash(), hash);
510 ASSERT_EQ(ltv_map, ltv_map);
511
512 // Compare hashes of equal LTV maps, filled in a different order
513 LeAudioLtvMap ltv_map_two;
514 ltv_map_two.Add(3, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
515 ltv_map_two.Add(0, (uint8_t)127);
516 ltv_map_two.Add(2, (uint32_t)65535);
517 ltv_map_two.Add(1, (uint16_t)32767);
518 ASSERT_EQ(ltv_map, ltv_map_two);
519 }
520
TEST(LeAudioLtvMapTest,test_value_hash_sanity)521 TEST(LeAudioLtvMapTest, test_value_hash_sanity) {
522 LeAudioLtvMap ltv_map;
523
524 ltv_map.Add(1, (uint16_t)32767);
525 auto hash = ltv_map.GetHash();
526
527 // Same value but type size is different
528 hash = ltv_map.GetHash();
529 ltv_map.Add(1, (uint32_t)32767);
530 ASSERT_NE(ltv_map.GetHash(), hash);
531 }
532
TEST(LeAudioLtvMapTest,test_type_change_same_value)533 TEST(LeAudioLtvMapTest, test_type_change_same_value) {
534 LeAudioLtvMap ltv_map_one;
535 ltv_map_one.Add(1, (uint16_t)32767);
536
537 LeAudioLtvMap ltv_map_two;
538 // The same value but different type
539 ltv_map_two.Add(3, (uint16_t)32767);
540
541 ASSERT_NE(ltv_map_one.GetHash(), ltv_map_two.GetHash());
542 }
543
TEST(LeAudioLtvMapTest,test_add_changing_hash)544 TEST(LeAudioLtvMapTest, test_add_changing_hash) {
545 LeAudioLtvMap ltv_map;
546
547 auto hash = ltv_map.GetHash();
548 ltv_map.Add(0, (uint8_t)127);
549 ASSERT_NE(ltv_map.GetHash(), hash);
550
551 hash = ltv_map.GetHash();
552 ltv_map.Add(1, (uint16_t)32767);
553 ASSERT_NE(ltv_map.GetHash(), hash);
554
555 hash = ltv_map.GetHash();
556 ltv_map.Add(2, (uint32_t)65535);
557 ASSERT_NE(ltv_map.GetHash(), hash);
558
559 hash = ltv_map.GetHash();
560 ltv_map.Add(3, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
561 ASSERT_NE(ltv_map.GetHash(), hash);
562 }
563
TEST(LeAudioLtvMapTest,test_update_changing_hash)564 TEST(LeAudioLtvMapTest, test_update_changing_hash) {
565 LeAudioLtvMap ltv_map;
566
567 auto hash = ltv_map.GetHash();
568 ltv_map.Add(0, (uint8_t)127);
569 ASSERT_NE(ltv_map.GetHash(), hash);
570
571 hash = ltv_map.GetHash();
572 ltv_map.Add(0, (uint16_t)32767);
573 ASSERT_NE(ltv_map.GetHash(), hash);
574
575 hash = ltv_map.GetHash();
576 ltv_map.Add(0, (uint32_t)65535);
577 ASSERT_NE(ltv_map.GetHash(), hash);
578
579 hash = ltv_map.GetHash();
580 ltv_map.Add(0, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
581 ASSERT_NE(ltv_map.GetHash(), hash);
582 }
583
TEST(LeAudioLtvMapTest,test_update_same_not_changing_hash)584 TEST(LeAudioLtvMapTest, test_update_same_not_changing_hash) {
585 LeAudioLtvMap ltv_map;
586
587 auto hash = ltv_map.GetHash();
588 ltv_map.Add(0, (uint8_t)127);
589 ASSERT_NE(ltv_map.GetHash(), hash);
590
591 hash = ltv_map.GetHash();
592 ltv_map.Add(0, (uint8_t)127);
593 ASSERT_EQ(ltv_map.GetHash(), hash);
594 }
595
TEST(LeAudioLtvMapTest,test_remove_changing_hash)596 TEST(LeAudioLtvMapTest, test_remove_changing_hash) {
597 LeAudioLtvMap ltv_map;
598
599 auto hash = ltv_map.GetHash();
600 ltv_map.Add(0, (uint8_t)127);
601 ltv_map.Add(1, (uint16_t)32767);
602 ltv_map.Add(2, (uint32_t)65535);
603 ltv_map.Add(3, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
604
605 hash = ltv_map.GetHash();
606 ltv_map.Remove(0);
607 ASSERT_NE(ltv_map.GetHash(), hash);
608
609 hash = ltv_map.GetHash();
610 ltv_map.Remove(1);
611 ASSERT_NE(ltv_map.GetHash(), hash);
612
613 hash = ltv_map.GetHash();
614 ltv_map.Remove(2);
615 ASSERT_NE(ltv_map.GetHash(), hash);
616
617 hash = ltv_map.GetHash();
618 ltv_map.Remove(3);
619 ASSERT_NE(ltv_map.GetHash(), hash);
620 }
621
TEST(LeAudioLtvMapTest,test_clear_changing_hash)622 TEST(LeAudioLtvMapTest, test_clear_changing_hash) {
623 LeAudioLtvMap ltv_map;
624
625 auto hash = ltv_map.GetHash();
626 ltv_map.Add(0, (uint8_t)127);
627 ltv_map.Add(1, (uint16_t)32767);
628 ltv_map.Add(2, (uint32_t)65535);
629 ltv_map.Add(3, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
630
631 hash = ltv_map.GetHash();
632 ltv_map.Clear();
633 ASSERT_NE(ltv_map.GetHash(), hash);
634
635 // 2nd clear should not change it
636 hash = ltv_map.GetHash();
637 ltv_map.Clear();
638 ASSERT_EQ(ltv_map.GetHash(), hash);
639
640 // Check if empty maps have equal hash
641 LeAudioLtvMap empty_ltv_map;
642 ASSERT_EQ(empty_ltv_map, ltv_map);
643 }
644
TEST(LeAudioLtvMapTest,test_remove_all_changing_hash)645 TEST(LeAudioLtvMapTest, test_remove_all_changing_hash) {
646 LeAudioLtvMap ltv_map;
647
648 auto hash = ltv_map.GetHash();
649 ltv_map.Add(0, (uint8_t)127);
650 ltv_map.Add(1, (uint16_t)32767);
651 ltv_map.Add(2, (uint32_t)65535);
652 ltv_map.Add(3, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
653
654 LeAudioLtvMap ltv_map_1st_half;
655 ltv_map_1st_half.Add(1, (uint16_t)32767);
656 ltv_map_1st_half.Add(3, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
657
658 LeAudioLtvMap ltv_map_2nd_half;
659 ltv_map_2nd_half.Add(0, (uint8_t)127);
660 ltv_map_2nd_half.Add(2, (uint32_t)65535);
661
662 ASSERT_NE(ltv_map_1st_half, ltv_map_2nd_half);
663 ASSERT_NE(ltv_map, ltv_map_2nd_half);
664
665 hash = ltv_map.GetHash();
666 ltv_map.RemoveAllTypes(ltv_map_1st_half);
667 ASSERT_NE(hash, ltv_map.GetHash());
668
669 hash = ltv_map.GetHash();
670 ltv_map.RemoveAllTypes(ltv_map_2nd_half);
671 ASSERT_NE(hash, ltv_map.GetHash());
672
673 // Check if empty maps have equal hash
674 LeAudioLtvMap empty_ltv_map;
675 ASSERT_EQ(empty_ltv_map, ltv_map);
676 }
677
TEST(LeAudioLtvMapTest,test_intersection)678 TEST(LeAudioLtvMapTest, test_intersection) {
679 LeAudioLtvMap ltv_map_one;
680 ltv_map_one.Add(1, (uint16_t)32767);
681 ltv_map_one.Add(3, std::vector<uint8_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
682 ltv_map_one.Add(2, (uint32_t)65535);
683
684 LeAudioLtvMap ltv_map_two;
685 ltv_map_two.Add(0, (uint8_t)127);
686 // Not the type is the same but value differs
687 ltv_map_two.Add(1, (uint16_t)32766);
688 ltv_map_two.Add(2, (uint32_t)65535);
689
690 LeAudioLtvMap ltv_map_common;
691 ltv_map_common.Add(2, (uint32_t)65535);
692 ASSERT_NE(ltv_map_common.GetHash(), 0lu);
693
694 ASSERT_EQ(ltv_map_one.GetIntersection(ltv_map_two).GetHash(), ltv_map_common.GetHash());
695 ASSERT_EQ(ltv_map_two.GetIntersection(ltv_map_one), ltv_map_common);
696 }
697
698 constexpr types::LeAudioCodecId kLeAudioCodecIdVendor1 = {
699 .coding_format = types::kLeAudioCodingFormatVendorSpecific,
700 // Not a particular vendor - just some random numbers
701 .vendor_company_id = 0xC0,
702 .vendor_codec_id = 0xDE,
703 };
704
705 static const set_configurations::CodecConfigSetting vendor_16_2 = {
706 .id = kLeAudioCodecIdVendor1,
707 .params = types::LeAudioLtvMap({
708 LTV_ENTRY_SAMPLING_FREQUENCY(codec_spec_conf::kLeAudioSamplingFreq16000Hz),
709 LTV_ENTRY_FRAME_DURATION(codec_spec_conf::kLeAudioCodecFrameDur10000us),
710 LTV_ENTRY_AUDIO_CHANNEL_ALLOCATION(codec_spec_conf::kLeAudioLocationStereo),
711 LTV_ENTRY_OCTETS_PER_CODEC_FRAME(40),
712 }),
713 .vendor_params = {0x01, 0x02, 0x03, 0x04},
714 .channel_count_per_iso_stream = 1,
715 };
716
TEST(CodecConfigSettingTest,test_vendor_codec_type)717 TEST(CodecConfigSettingTest, test_vendor_codec_type) {
718 auto vendor_codec = vendor_16_2;
719 ASSERT_EQ(vendor_16_2, vendor_codec);
720 }
721
TEST(CodecSpecTest,test_sampling_frequency_transition)722 TEST(CodecSpecTest, test_sampling_frequency_transition) {
723 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
724 codec_spec_caps::SamplingFreqConfig2Capability(
725 codec_spec_conf::kLeAudioSamplingFreq8000Hz)),
726 codec_spec_conf::kLeAudioSamplingFreq8000Hz);
727 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
728 codec_spec_caps::SamplingFreqConfig2Capability(
729 codec_spec_conf::kLeAudioSamplingFreq11025Hz)),
730 codec_spec_conf::kLeAudioSamplingFreq11025Hz);
731 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
732 codec_spec_caps::SamplingFreqConfig2Capability(
733 codec_spec_conf::kLeAudioSamplingFreq16000Hz)),
734 codec_spec_conf::kLeAudioSamplingFreq16000Hz);
735 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
736 codec_spec_caps::SamplingFreqConfig2Capability(
737 codec_spec_conf::kLeAudioSamplingFreq22050Hz)),
738 codec_spec_conf::kLeAudioSamplingFreq22050Hz);
739 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
740 codec_spec_caps::SamplingFreqConfig2Capability(
741 codec_spec_conf::kLeAudioSamplingFreq24000Hz)),
742 codec_spec_conf::kLeAudioSamplingFreq24000Hz);
743 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
744 codec_spec_caps::SamplingFreqConfig2Capability(
745 codec_spec_conf::kLeAudioSamplingFreq32000Hz)),
746 codec_spec_conf::kLeAudioSamplingFreq32000Hz);
747 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
748 codec_spec_caps::SamplingFreqConfig2Capability(
749 codec_spec_conf::kLeAudioSamplingFreq44100Hz)),
750 codec_spec_conf::kLeAudioSamplingFreq44100Hz);
751 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
752 codec_spec_caps::SamplingFreqConfig2Capability(
753 codec_spec_conf::kLeAudioSamplingFreq48000Hz)),
754 codec_spec_conf::kLeAudioSamplingFreq48000Hz);
755 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
756 codec_spec_caps::SamplingFreqConfig2Capability(
757 codec_spec_conf::kLeAudioSamplingFreq88200Hz)),
758 codec_spec_conf::kLeAudioSamplingFreq88200Hz);
759 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
760 codec_spec_caps::SamplingFreqConfig2Capability(
761 codec_spec_conf::kLeAudioSamplingFreq96000Hz)),
762 codec_spec_conf::kLeAudioSamplingFreq96000Hz);
763 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
764 codec_spec_caps::SamplingFreqConfig2Capability(
765 codec_spec_conf::kLeAudioSamplingFreq176400Hz)),
766 codec_spec_conf::kLeAudioSamplingFreq176400Hz);
767 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
768 codec_spec_caps::SamplingFreqConfig2Capability(
769 codec_spec_conf::kLeAudioSamplingFreq192000Hz)),
770 codec_spec_conf::kLeAudioSamplingFreq192000Hz);
771 ASSERT_EQ(codec_spec_conf::SingleSamplingFreqCapability2Config(
772 codec_spec_caps::SamplingFreqConfig2Capability(
773 codec_spec_conf::kLeAudioSamplingFreq384000Hz)),
774 codec_spec_conf::kLeAudioSamplingFreq384000Hz);
775 }
776
TEST(CodecSpecTest,test_frame_duration_transition)777 TEST(CodecSpecTest, test_frame_duration_transition) {
778 ASSERT_EQ(codec_spec_conf::SingleFrameDurationCapability2Config(
779 codec_spec_caps::FrameDurationConfig2Capability(
780 codec_spec_conf::kLeAudioCodecFrameDur7500us)),
781 codec_spec_conf::kLeAudioCodecFrameDur7500us);
782 ASSERT_EQ(codec_spec_conf::SingleFrameDurationCapability2Config(
783 codec_spec_caps::FrameDurationConfig2Capability(
784 codec_spec_conf::kLeAudioCodecFrameDur10000us)),
785 codec_spec_conf::kLeAudioCodecFrameDur10000us);
786 }
787
TEST(CodecSpecTest,test_channel_count_transition)788 TEST(CodecSpecTest, test_channel_count_transition) {
789 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
790 codec_spec_conf::SingleChannelCountCapability2Config(
791 codec_spec_caps::kLeAudioCodecChannelCountNone)),
792 codec_spec_caps::kLeAudioCodecChannelCountNone);
793 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
794 codec_spec_conf::SingleChannelCountCapability2Config(
795 codec_spec_caps::kLeAudioCodecChannelCountSingleChannel)),
796 codec_spec_caps::kLeAudioCodecChannelCountSingleChannel);
797 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
798 codec_spec_conf::SingleChannelCountCapability2Config(
799 codec_spec_caps::kLeAudioCodecChannelCountTwoChannel)),
800 codec_spec_caps::kLeAudioCodecChannelCountTwoChannel);
801 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
802 codec_spec_conf::SingleChannelCountCapability2Config(
803 codec_spec_caps::kLeAudioCodecChannelCountThreeChannel)),
804 codec_spec_caps::kLeAudioCodecChannelCountThreeChannel);
805 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
806 codec_spec_conf::SingleChannelCountCapability2Config(
807 codec_spec_caps::kLeAudioCodecChannelCountFourChannel)),
808 codec_spec_caps::kLeAudioCodecChannelCountFourChannel);
809 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
810 codec_spec_conf::SingleChannelCountCapability2Config(
811 codec_spec_caps::kLeAudioCodecChannelCountFiveChannel)),
812 codec_spec_caps::kLeAudioCodecChannelCountFiveChannel);
813 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
814 codec_spec_conf::SingleChannelCountCapability2Config(
815 codec_spec_caps::kLeAudioCodecChannelCountSixChannel)),
816 codec_spec_caps::kLeAudioCodecChannelCountSixChannel);
817 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
818 codec_spec_conf::SingleChannelCountCapability2Config(
819 codec_spec_caps::kLeAudioCodecChannelCountSevenChannel)),
820 codec_spec_caps::kLeAudioCodecChannelCountSevenChannel);
821 ASSERT_EQ(codec_spec_caps::ChannelCountConfig2Capability(
822 codec_spec_conf::SingleChannelCountCapability2Config(
823 codec_spec_caps::kLeAudioCodecChannelCountEightChannel)),
824 codec_spec_caps::kLeAudioCodecChannelCountEightChannel);
825 }
826
TEST(CodecConfigTest,test_lc3_bits_per_sample)827 TEST(CodecConfigTest, test_lc3_bits_per_sample) {
828 set_configurations::CodecConfigSetting lc3_codec_config = {
829 .id = {.coding_format = types::kLeAudioCodingFormatLC3},
830 };
831 ASSERT_EQ(utils::translateToBtLeAudioCodecConfigBitPerSample(lc3_codec_config.GetBitsPerSample()),
832 LE_AUDIO_BITS_PER_SAMPLE_INDEX_16);
833 }
834
TEST(CodecConfigTest,test_invalid_codec_bits_per_sample)835 TEST(CodecConfigTest, test_invalid_codec_bits_per_sample) {
836 set_configurations::CodecConfigSetting invalid_codec_config = {
837 .id = {.coding_format = types::kLeAudioCodingFormatVendorSpecific}};
838 ASSERT_EQ(utils::translateToBtLeAudioCodecConfigBitPerSample(
839 invalid_codec_config.GetBitsPerSample()),
840 LE_AUDIO_BITS_PER_SAMPLE_INDEX_NONE);
841 }
842
843 } // namespace types
844 } // namespace bluetooth::le_audio
845