From cea733e4bd16389141892d269be2d57149250adc Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Tue, 26 Jun 2018 18:31:42 +0200 Subject: [PATCH] test: new sdp/sdp_record_builder calculates sdp record sizes based on provided param --- test/sdp/.gitignore | 1 + test/sdp/Makefile | 69 +++++ test/sdp/sdp_record_builder.c | 546 ++++++++++++++++++++++++++++++++++ 3 files changed, 616 insertions(+) create mode 100644 test/sdp/.gitignore create mode 100644 test/sdp/Makefile create mode 100644 test/sdp/sdp_record_builder.c diff --git a/test/sdp/.gitignore b/test/sdp/.gitignore new file mode 100644 index 000000000..cf2aaf1cc --- /dev/null +++ b/test/sdp/.gitignore @@ -0,0 +1 @@ +sdp_record_builder diff --git a/test/sdp/Makefile b/test/sdp/Makefile new file mode 100644 index 000000000..e59028495 --- /dev/null +++ b/test/sdp/Makefile @@ -0,0 +1,69 @@ +CC = g++ + +# Requirements: cpputest.github.io + +BTSTACK_ROOT = ../.. + +CFLAGS = -g -Wall \ + -I.. \ + -I${BTSTACK_ROOT}/src \ + +LDFLAGS += -lCppUTest -lCppUTestExt + +VPATH += ${BTSTACK_ROOT}/src +VPATH += ${BTSTACK_ROOT}/src/classic + +COMMON = \ + btstack_util.c \ + hci_dump.c \ + hci.c \ + hci_cmd.c \ + btstack_run_loop.c \ + rfcomm.c \ + ad_parser.c \ + sdp_client.c \ + sdp_client_rfcomm.c \ + l2cap.c \ + l2cap_signaling.c \ + btstack_linked_list.c \ + btstack_memory.c \ + btstack_memory_pool.c \ + device_id_server.c \ + avdtp.c \ + a2dp_source.c \ + a2dp_sink.c \ + avdtp.c \ + avdtp_util.c \ + avdtp_sink.c \ + avdtp_source.c \ + avdtp_acceptor.c \ + avdtp_initiator.c \ + avrcp.c \ + avrcp_controller.c \ + avrcp_target.c \ + hfp.c \ + hfp_gsm_model.c \ + hfp_ag.c \ + hfp_hf.c \ + hsp_hs.c \ + hsp_ag.c \ + hid_device.c \ + pan.c \ + sdp_util.c \ + spp_server.c \ + +COMMON_OBJ = $(COMMON:.c=.o) + +all: sdp_record_builder + +sdp_record_builder: ${COMMON_OBJ} sdp_record_builder.c + ${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@ + +test: all + ./sdp_record_builder + +clean: + rm -f sdp_record_builder + rm -f *.o + rm -rf *.dSYM + diff --git a/test/sdp/sdp_record_builder.c b/test/sdp/sdp_record_builder.c new file mode 100644 index 000000000..f5769c580 --- /dev/null +++ b/test/sdp/sdp_record_builder.c @@ -0,0 +1,546 @@ +/* + * 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); +}