/* * Copyright (C) 2014 BlueKitchen GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * 4. Any redistribution, use, or modification is done solely for * personal benefit and not for any commercial purpose or for * monetary gain. * * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Please inquire about commercial licensing options at * contact@bluekitchen-gmbh.com * */ // ***************************************************************************** // // test calculation of sdp records created by various profiles // // ***************************************************************************** #include #include #include #include #include "CppUTest/TestHarness.h" #include "CppUTest/CommandLineTestRunner.h" #include "classic/avrcp_controller.h" #include "btstack_util.h" #include "bluetooth.h" #include "classic/device_id_server.h" #include "classic/avrcp_target.h" #include "classic/a2dp_source.h" #include "classic/a2dp_sink.h" #include "classic/hsp_hs.h" #include "classic/hsp_ag.h" #include "classic/hfp_hf.h" #include "classic/hfp_ag.h" #include "classic/hid_device.h" #include "classic/pan.h" #include "classic/spp_server.h" #include "classic/sdp_util.h" static uint8_t service_buffer[300]; static const char * test_string = "test"; static const uint16_t uint16_list_empty[] = { 0 }; static const uint16_t uint16_list_single_element[] = { 0x1234, 0 }; TEST_GROUP(SDPRecordBuilder){ void setup(void){ memset(service_buffer, 0, sizeof(service_buffer)); } }; // a2dp sink static const char * default_a2dp_sink_service_name = "BTstack A2DP Sink Service"; static const char * default_a2dp_sink_service_provider_name = "BTstack A2DP Sink Service Provider"; #define A2DP_SINK_RECORD_SIZE_MIN 84 static uint16_t a2dp_sink_record_size(const char * service_name, const char * service_provider_name){ int service_name_len = service_name ? strlen(service_name) : strlen(default_a2dp_sink_service_name); int service_provider_name_len = service_provider_name ? strlen(service_provider_name) : strlen(default_a2dp_sink_service_provider_name); return A2DP_SINK_RECORD_SIZE_MIN + service_name_len + service_provider_name_len; } TEST(SDPRecordBuilder, A2DP_SINK){ const char * service_name; const char * service_provider_name; int expected_len; service_name = ""; service_provider_name = ""; expected_len = a2dp_sink_record_size(service_name, service_provider_name); a2dp_sink_create_sdp_record(service_buffer, 0, 0, service_name, service_provider_name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // a2dp source static const char * default_a2dp_source_service_name = "BTstack A2DP Source Service"; static const char * default_a2dp_source_service_provider_name = "BTstack A2DP Source Service Provider"; #define A2DP_SOURCE_RECORD_SIZE_MIN 84 static uint16_t a2dp_source_record_size(const char * service_name, const char * service_provider_name){ int service_name_len = service_name ? strlen(service_name) : strlen(default_a2dp_source_service_name); int service_provider_name_len = service_provider_name ? strlen(service_provider_name) : strlen(default_a2dp_source_service_provider_name); return A2DP_SOURCE_RECORD_SIZE_MIN + service_name_len + service_provider_name_len; } TEST(SDPRecordBuilder, A2DP_SOURCE){ const char * service_name; const char * service_provider_name; int expected_len; service_name = ""; service_provider_name = ""; expected_len = a2dp_source_record_size(service_name, service_provider_name); a2dp_source_create_sdp_record(service_buffer, 0, 0, service_name, service_provider_name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); service_name = NULL; service_provider_name = ""; expected_len = a2dp_source_record_size(service_name, service_provider_name); a2dp_source_create_sdp_record(service_buffer, 0, 0, service_name, service_provider_name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); service_name = NULL; service_provider_name = NULL; expected_len = a2dp_source_record_size(service_name, service_provider_name); a2dp_source_create_sdp_record(service_buffer, 0, 0, service_name, service_provider_name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // avcrp target // static const char * default_avrcp_target_service_name = "BTstack AVRCP Target Service"; static const char * default_avrcp_target_service_provider_name = "BTstack AVRCP Target Service Provider"; #define AVRCP_TARGET_RECORD_SIZE_MIN 84 static uint16_t avrcp_target_record_size(int browsing, const char * service_name, const char * service_provider_name){ int service_name_len = service_name ? strlen(service_name) : strlen(default_avrcp_target_service_name); int service_provider_name_len = service_provider_name ? strlen(service_provider_name) : strlen(default_avrcp_target_service_provider_name); int browsing_len = browsing ? 27 : 0; return AVRCP_TARGET_RECORD_SIZE_MIN + service_name_len + service_provider_name_len + browsing_len; } TEST(SDPRecordBuilder, AVRCP_TARGET){ const char * service_name; const char * service_provider_name; int expected_len; int descriptor_size; int browsing ; browsing = 0; service_name = ""; service_provider_name = ""; descriptor_size = 0; expected_len = avrcp_target_record_size(browsing, service_name, service_provider_name); avrcp_target_create_sdp_record(service_buffer, 0, browsing, 0, service_name, service_provider_name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); browsing = 1; service_name = ""; service_provider_name = ""; descriptor_size = 0; expected_len = avrcp_target_record_size(browsing, service_name, service_provider_name); avrcp_target_create_sdp_record(service_buffer, 0, browsing, 0, service_name, service_provider_name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // avrcp controller // static const char * default_avrcp_controller_service_name = "BTstack AVRCP Controller Service"; static const char * default_avrcp_controller_service_provider_name = "BTstack AVRCP Controller Service Provider"; #define AVRCP_CONTROLLER_RECORD_SIZE_MIN 87 static uint16_t avrcp_controller_record_size(int browsing, const char * service_name, const char * service_provider_name){ int service_name_len = service_name ? strlen(service_name) : strlen(default_avrcp_controller_service_name); int service_provider_name_len = service_provider_name ? strlen(service_provider_name) : strlen(default_avrcp_controller_service_provider_name); int browsing_len = browsing ? 27 : 0; return AVRCP_CONTROLLER_RECORD_SIZE_MIN + service_name_len + service_provider_name_len + browsing_len; } TEST(SDPRecordBuilder, AVRCP_CONTROLLER){ const char * service_name; const char * service_provider_name; int expected_len; int descriptor_size; int browsing ; browsing = 0; service_name = ""; service_provider_name = ""; descriptor_size = 0; expected_len = avrcp_controller_record_size(browsing, service_name, service_provider_name); avrcp_controller_create_sdp_record(service_buffer, 0, browsing, 0, service_name, service_provider_name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); browsing = 1; service_name = ""; service_provider_name = ""; descriptor_size = 0; expected_len = avrcp_controller_record_size(browsing, service_name, service_provider_name); avrcp_controller_create_sdp_record(service_buffer, 0, browsing, 0, service_name, service_provider_name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // hid_device.h // #define HID_DEVICE_RECORD_SIZE_MIN 153 static uint16_t hid_device_record_size(uint16_t descriptor_size, const char * name){ return HID_DEVICE_RECORD_SIZE_MIN + descriptor_size + strlen(name); } TEST(SDPRecordBuilder, HID_DEVICE){ const char * name; int expected_len; int descriptor_size; name = ""; descriptor_size = 0; expected_len = hid_device_record_size(descriptor_size, name); hid_create_sdp_record(service_buffer, 0, 0, 0, 0, 0, 0, NULL, descriptor_size, name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // hfp_hf // #define HFP_HF_RECORD_SIZE_MIN 78 static uint16_t hfp_hf_record_size(const char * name){ return HFP_HF_RECORD_SIZE_MIN + strlen(name); } TEST(SDPRecordBuilder, HFP_HF){ const char * name; int expected_len; name = ""; expected_len = hfp_hf_record_size(name); hfp_hf_create_sdp_record(service_buffer, 0, 0, name, 0, 0); CHECK_EQUAL(de_get_len(service_buffer), expected_len); name =test_string; expected_len = hfp_hf_record_size(name); hfp_hf_create_sdp_record(service_buffer, 0, 0, name, 0, 0); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // hfp_ag // #define HFP_AG_RECORD_SIZE_MIN 83 static uint16_t hfp_ag_record_size(const char * name){ return HFP_AG_RECORD_SIZE_MIN + strlen(name); } TEST(SDPRecordBuilder, HFP_AG){ const char * name; int expected_len; name = ""; expected_len = hfp_ag_record_size(name); hfp_ag_create_sdp_record(service_buffer, 0, 0, name, 0, 0, 0); CHECK_EQUAL(de_get_len(service_buffer), expected_len); name =test_string; expected_len = hfp_ag_record_size(name); hfp_ag_create_sdp_record(service_buffer, 0, 0, name, 0, 0, 0); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // hsp_ag // #define HSP_AG_RECORD_SIZE_MIN 72 static uint16_t hsp_ag_record_size(const char * name){ return HSP_AG_RECORD_SIZE_MIN + strlen(name); } TEST(SDPRecordBuilder, HSP_AG){ const char * name; int expected_len; name = ""; expected_len = hsp_ag_record_size(name); hsp_ag_create_sdp_record(service_buffer, 0, 0, name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); name =test_string; expected_len = hsp_ag_record_size(name); hsp_ag_create_sdp_record(service_buffer, 0, 0, name); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // hsp_hs // #define HSP_HS_RECORD_SIZE_MIN 80 static uint16_t hsp_hs_record_size(const char * name){ return HSP_HS_RECORD_SIZE_MIN + strlen(name); } TEST(SDPRecordBuilder, HSP_HS){ const char * name; int expected_len; name = ""; expected_len = hsp_hs_record_size(name); hsp_hs_create_sdp_record(service_buffer, 0, 0, name, 0); CHECK_EQUAL(de_get_len(service_buffer), expected_len); name =test_string; expected_len = hsp_hs_record_size(name); hsp_hs_create_sdp_record(service_buffer, 0, 0, name, 0); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // device id // #define DEVICE_ID_RECORD_SIZE 64 static uint16_t device_id_record_size(void){ return DEVICE_ID_RECORD_SIZE; } TEST(SDPRecordBuilder, DeviceID){ int expected_len; expected_len = device_id_record_size(); device_id_create_sdp_record(service_buffer, 0, 0, 0, 0, 0); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // pan // #define PAN_RECORD_MIN_LEN 104 static const char default_panu_service_name[] = "Personal Ad-hoc User Service"; static const char default_panu_service_desc[] = "Personal Ad-hoc User Service"; static const char default_nap_service_name[] = "Network Access Point Service"; static const char default_nap_service_desc[] = "Personal Ad-hoc Network Service which provides access to a network"; static const char default_gn_service_name[] = "Group Ad-hoc Network Service"; static const char default_gn_service_desc[] = "Personal Group Ad-hoc Network Service"; // network_packet_types (X bytes x nr network packet types) // name. default name or name // ipv4 subnet, if yes + x // ipv6 subnet, if yes + x static uint16_t pan_sdp_record_size(uint16_t * network_packet_types, const char *name, const char *description, const char *IPv4Subnet, const char *IPv6Subnet, const char * default_name, const char * default_desc){ int num_network_packet_types; for (num_network_packet_types=0; network_packet_types && *network_packet_types; num_network_packet_types++, network_packet_types++); int name_len = name ? strlen(name) : strlen(default_name); int desc_len = description ? strlen(description) : strlen(default_desc); int ipv4_len = IPv4Subnet ? 5 + strlen(IPv4Subnet) : 0; int ipv6_len = IPv6Subnet ? 5 + strlen(IPv6Subnet) : 0; uint16_t res = PAN_RECORD_MIN_LEN + name_len + desc_len + ipv4_len + ipv6_len + num_network_packet_types * 3; // tyoe + uint16_t return res; } static uint16_t pan_panu_sdp_record_size(uint16_t * network_packet_types, const char *name, const char *description){ return pan_sdp_record_size(network_packet_types, name, description, NULL, NULL, default_panu_service_name, default_panu_service_desc); } static uint16_t pan_gn_sdp_record_size(uint16_t * network_packet_types, const char *name, const char *description, const char *IPv4Subnet, const char *IPv6Subnet){ return pan_sdp_record_size(network_packet_types, name, description, IPv4Subnet, IPv6Subnet, default_gn_service_name, default_gn_service_desc); } static uint16_t pan_nap_sdp_record_size(uint16_t * network_packet_types, const char *name, const char *description, const char *IPv4Subnet, const char *IPv6Subnet){ return pan_sdp_record_size(network_packet_types, name, description, IPv4Subnet, IPv6Subnet, default_nap_service_name, default_nap_service_desc) + 14; } TEST(SDPRecordBuilder, PANU){ int expected_len; const char * name; const char * desc; uint16_t * network_packet_types; // empty name name = ""; desc = ""; network_packet_types = NULL; expected_len = pan_panu_sdp_record_size(network_packet_types, name, desc); pan_create_panu_sdp_record(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE); CHECK_EQUAL(de_get_len(service_buffer), expected_len); // default name name = NULL; desc = NULL; network_packet_types = NULL; expected_len = pan_panu_sdp_record_size(network_packet_types, name, desc); pan_create_panu_sdp_record(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE); CHECK_EQUAL(de_get_len(service_buffer), expected_len); // empty list name = NULL; desc = NULL; network_packet_types = (uint16_t *) &uint16_list_empty; expected_len = pan_panu_sdp_record_size(network_packet_types, name, desc); pan_create_panu_sdp_record(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE); CHECK_EQUAL(de_get_len(service_buffer), expected_len); // single element name = NULL; desc = NULL; network_packet_types = (uint16_t *) &uint16_list_single_element; expected_len = pan_panu_sdp_record_size(network_packet_types, name, desc); pan_create_panu_sdp_record(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } TEST(SDPRecordBuilder, GN){ int expected_len; const char * name; const char * desc; uint16_t * network_packet_types; const char *IPv4Subnet; const char *IPv6Subnet; // empty name name = ""; desc = ""; network_packet_types = NULL; IPv4Subnet = NULL; IPv6Subnet = NULL; expected_len = pan_gn_sdp_record_size(network_packet_types, name, desc, IPv4Subnet, IPv6Subnet); pan_create_gn_sdp_service(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE, IPv4Subnet, IPv6Subnet); CHECK_EQUAL(de_get_len(service_buffer), expected_len); // test ipv4 param name = ""; desc = ""; network_packet_types = NULL; IPv4Subnet = NULL; IPv6Subnet = ""; expected_len = pan_gn_sdp_record_size(network_packet_types, name, desc, IPv4Subnet, IPv6Subnet); pan_create_gn_sdp_service(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE, IPv4Subnet, IPv6Subnet); CHECK_EQUAL(de_get_len(service_buffer), expected_len); // test ipv6 param name = ""; desc = ""; network_packet_types = NULL; IPv4Subnet = ""; IPv6Subnet = ""; expected_len = pan_gn_sdp_record_size(network_packet_types, name, desc, IPv4Subnet, IPv6Subnet); pan_create_gn_sdp_service(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE, IPv4Subnet, IPv6Subnet); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } TEST(SDPRecordBuilder, NAP){ int expected_len; const char * name; const char * desc; uint16_t * network_packet_types; const char *IPv4Subnet; const char *IPv6Subnet; // empty name name = ""; desc = ""; network_packet_types = NULL; IPv4Subnet = NULL; IPv6Subnet = NULL; expected_len = pan_nap_sdp_record_size(network_packet_types, name, desc, IPv4Subnet, IPv6Subnet); pan_create_nap_sdp_record(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE, PAN_NET_ACCESS_TYPE_PSTN, 0, IPv4Subnet, IPv6Subnet); CHECK_EQUAL(de_get_len(service_buffer), expected_len); // test ipv4 param name = ""; desc = ""; network_packet_types = NULL; IPv4Subnet = NULL; IPv6Subnet = ""; expected_len = pan_nap_sdp_record_size(network_packet_types, name, desc, IPv4Subnet, IPv6Subnet); pan_create_nap_sdp_record(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE, PAN_NET_ACCESS_TYPE_PSTN, 0, IPv4Subnet, IPv6Subnet); CHECK_EQUAL(de_get_len(service_buffer), expected_len); // test ipv6 param name = ""; desc = ""; network_packet_types = NULL; IPv4Subnet = ""; IPv6Subnet = ""; expected_len = pan_nap_sdp_record_size(network_packet_types, name, desc, IPv4Subnet, IPv6Subnet); pan_create_nap_sdp_record(service_buffer, 0, network_packet_types, name, desc, BNEP_SECURITY_NONE, PAN_NET_ACCESS_TYPE_PSTN, 0, IPv4Subnet, IPv6Subnet); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } // // SPP: Record + strlen(service_name) // #define SPP_RECORD_MIN_LEN 84 static uint16_t spp_sdp_record_size_for_service_name(const char * service_name){ return SPP_RECORD_MIN_LEN + strlen(service_name); } TEST(SDPRecordBuilder, SPP){ int expected_len = spp_sdp_record_size_for_service_name(test_string); spp_create_sdp_record(service_buffer, 0, 0, test_string); CHECK_EQUAL(de_get_len(service_buffer), expected_len); } int main (int argc, const char * argv[]){ return CommandLineTestRunner::RunAllTests(argc, argv); }