diff --git a/src/classic/hfp_ag.h b/src/classic/hfp_ag.h index c5fcc1d9e..50d7eb8ca 100644 --- a/src/classic/hfp_ag.h +++ b/src/classic/hfp_ag.h @@ -359,6 +359,8 @@ void hfp_ag_report_extended_audio_gateway_error_result_code(hci_con_handle_t acl /* API_END */ +// testing +hfp_ag_indicator_t * hfp_ag_get_ag_indicators(hfp_connection_t * hfp_connection); #if defined __cplusplus } diff --git a/test/hfp/CMakeLists.txt b/test/hfp/CMakeLists.txt new file mode 100644 index 000000000..87f96108d --- /dev/null +++ b/test/hfp/CMakeLists.txt @@ -0,0 +1,91 @@ +cmake_minimum_required (VERSION 3.5) +project(test-hfp) + +# add libusb +find_path(LIBUSB_INCLUDE_DIR NAMES libusb.h PATH_SUFFIXES "include" "libusb" "libusb-1.0") +find_library(LIBUSB_LIBRARY NAMES usb-1.0 PATH_SUFFIXES "lib" "lib32" "lib64" "dylib") +get_filename_component(LIBUSB_LIBRARY_PATH ${LIBUSB_LIBRARY} DIRECTORY) +include_directories( ${LIBUSB_INCLUDE_DIR} ) +link_directories( ${LIBUSB_LIBRARY_PATH} ) +link_libraries( usb-1.0 ) + +# add CppUTest +include_directories("/usr/local/include") +link_directories("/usr/local/lib") +link_libraries( CppUTest ) +link_libraries( CppUTestExt ) + +include_directories(.) +include_directories(..) +include_directories(../../3rd-party/micro-ecc) +include_directories(../../3rd-party/bluedroid/decoder/include) +include_directories(../../3rd-party/bluedroid/encoder/include) +include_directories(../../3rd-party/md5) +include_directories(../../3rd-party/hxcmod-player) +include_directories(../../3rd-party/hxcmod-player/mod) +include_directories(../../3rd-party/rijndael) +include_directories(../../3rd-party/yxml) +include_directories(../../3rd-party/tinydir) +include_directories(../../src) +include_directories(../../chipset/zephyr) +include_directories(../../platform/posix) +include_directories(../../platform/embedded) +include_directories(../../port/libusb) + +file(GLOB SOURCES_SRC "../../src/*.c" "../../example/sco_demo_util.c") +file(GLOB SOURCES_BLE "../../src/ble/*.c") +file(GLOB SOURCES_GATT "../../src/ble/gatt-service/*.c") +file(GLOB SOURCES_CLASSIC "../../src/classic/*.c") +file(GLOB SOURCES_BLUEDROID "../../3rd-party/bluedroid/encoder/srce/*.c" "../../3rd-party/bluedroid/decoder/srce/*.c") +file(GLOB SOURCES_MD5 "../../3rd-party/md5/md5.c") +file(GLOB SOURCES_UECC "../../3rd-party/micro-ecc/uECC.c") +file(GLOB SOURCES_YXML "../../3rd-party/yxml/yxml.c") +file(GLOB SOURCES_HXCMOD "../../3rd-party/hxcmod-player/*.c" "../../3rd-party/hxcmod-player/mods/*.c") +file(GLOB SOURCES_RIJNDAEL "../../3rd-party/rijndael/rijndael.c") +file(GLOB SOURCES_POSIX "../../platform/posix/*.c") +file(GLOB SOURCES_LIBUSB "../../port/libusb/*.c" "../../platform/libusb/*.c") + +file(GLOB SOURCES_BLE_OFF "../../src/ble/le_device_db_memory.c") +list(REMOVE_ITEM SOURCES_BLE ${SOURCES_BLE_OFF}) + +file(GLOB SOURCES_POSIX_OFF "../../platform/posix/le_device_db_fs.c") +list(REMOVE_ITEM SOURCES_POSIX ${SOURCES_POSIX_OFF}) + +set(SOURCES + ${SOURCES_MD5} + ${SOURCES_YXML} + ${SOURCES_BLUEDROID} + ${SOURCES_POSIX} + ${SOURCES_RIJNDAEL} + ${SOURCES_LIBUSB} + ${SOURCES_SRC} + ${SOURCES_BLE} + ${SOURCES_GATT} + ${SOURCES_CLASSIC} + ${SOURCES_UECC} + ${SOURCES_HXCMOD} + ${SOURCES_ZEPHYR} +) +list(SORT SOURCES) + +set_source_files_properties(../../src/classic/hfp_ag.c PROPERTIES LANGUAGE CXX ) + +list(APPEND SOURCES mock.c test_sequences.c) + +# create static lib +add_library(btstack STATIC ${SOURCES}) + +# create targets for all examples +file(GLOB EXAMPLES_C "*.c") +list(SORT EXAMPLES_C) + +# create targets +foreach(EXAMPLE_FILE ${EXAMPLES_C}) + get_filename_component(EXAMPLE ${EXAMPLE_FILE} NAME_WE) + # Use C++ Compiler + set_source_files_properties(${EXAMPLE_FILE} PROPERTIES LANGUAGE CXX ) + set (SOURCE_FILES ${EXAMPLE_FILE}) + message("test/hfp tool: ${EXAMPLE}") + add_executable(${EXAMPLE} ${SOURCE_FILES} ) + target_link_libraries(${EXAMPLE} btstack) +endforeach(EXAMPLE_FILE) diff --git a/test/hfp/Makefile b/test/hfp/Makefile index d264c0877..b8f218c0f 100644 --- a/test/hfp/Makefile +++ b/test/hfp/Makefile @@ -52,10 +52,10 @@ CFLAGS = -g -Wall -Wmissing-prototypes -Wnarrowing # CFLAGS += -Werror CFLAGS += -I. -I../ -I${BTSTACK_ROOT}/src -I${BTSTACK_ROOT}/src/classic -I${POSIX_ROOT} -I${BTSTACK_ROOT}/include # CFLAGS += -D OCTAVE_OUTPUT -CFLAGS += -fprofile-arcs -ftest-coverage -fsanitize=address +# CFLAGS += -fprofile-arcs -ftest-coverage -fsanitize=address LDFLAGS_CPPUTEST += -lCppUTest -lCppUTestExt -EXAMPLES = hfp_ag_parser_test hfp_ag_client_test hfp_hf_parser_test hfp_hf_client_test cvsd_plc_test pklg_cvsd_test +EXAMPLES = hfp_at_parser_test hfp_ag_client_test hfp_hf_client_test cvsd_plc_test pklg_cvsd_test all: ${EXAMPLES} @@ -63,10 +63,7 @@ clean: rm -rf *.o $(EXAMPLES) $(CLIENT_EXAMPLES) *.dSYM *.wav results/* pklg/*.wav rm -f *.gcno *.gcda -hfp_ag_parser_test: ${COMMON_OBJ} hfp_gsm_model.o hfp_ag.o hfp.o hfp_ag_parser_test.c - ${CC} $^ ${CFLAGS} ${LDFLAGS_CPPUTEST} -o $@ - -hfp_hf_parser_test: ${COMMON_OBJ} hfp_hf.o hfp.o hfp_hf_parser_test.c +hfp_at_parser_test: ${COMMON_OBJ} hfp_gsm_model.o hfp_ag.o hfp.o hfp_at_parser_test.c ${CC} $^ ${CFLAGS} ${LDFLAGS_CPPUTEST} -o $@ hfp_hf_client_test: ${MOCK_OBJ} hfp_hf.o hfp.o hfp_hf_client_test.c @@ -83,9 +80,8 @@ pklg_cvsd_test: hci_dump.o btstack_util.o btstack_cvsd_plc.o wav_util.o pklg_cvs test: all mkdir -p results - ./hfp_ag_parser_test + ./hfp_at_parser_test ./hfp_ag_client_test - ./hfp_hf_parser_test ./hfp_hf_client_test ./cvsd_plc_test diff --git a/test/hfp/hfp_ag_parser_test.c b/test/hfp/hfp_ag_parser_test.c deleted file mode 100644 index 4b2a07280..000000000 --- a/test/hfp/hfp_ag_parser_test.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * 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 - * - */ - - -#include -#include -#include -#include - -#include "CppUTest/TestHarness.h" -#include "CppUTest/CommandLineTestRunner.h" - -#include "classic/hfp.h" -#include "classic/hfp_ag.h" - -void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree); - -hfp_ag_indicator_t * hfp_ag_get_ag_indicators(hfp_connection_t * hfp_connection); - -// static int hf_indicators_nr = 3; -// static hfp_generic_status_indicator_t hf_indicators[] = { -// {1, 1}, -// {2, 1}, -// {3, 1} -// }; - -static int hfp_ag_indicators_nr = 7; -static hfp_ag_indicator_t hfp_ag_indicators[] = { - // index, name, min range, max range, status, mandatory, enabled, status changed - {1, "service", 0, 1, 1, 0, 0, 0}, - {2, "call", 0, 1, 0, 1, 1, 0}, - {3, "callsetup", 0, 3, 0, 1, 1, 0}, - {4, "battchg", 0, 5, 3, 0, 0, 0}, - {5, "signal", 0, 5, 5, 0, 0, 0}, - {6, "roam", 0, 1, 0, 0, 0, 0}, - {7, "callheld", 0, 2, 0, 1, 1, 0} -}; - - -static hfp_connection_t context; - -TEST_GROUP(HFPParser){ - char packet[200]; - uint16_t pos; - - void setup(void){ - context.parser_state = HFP_PARSER_CMD_HEADER; - context.parser_item_index = 0; - context.line_size = 0; - memset(packet,0, sizeof(packet)); - } -}; - -TEST(HFPParser, HFP_AG_SUPPORTED_FEATURES){ - sprintf(packet, "\r\nAT%s=159\r\n", HFP_SUPPORTED_FEATURES); - //context.keep_separator = 0; - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - CHECK_EQUAL(HFP_CMD_SUPPORTED_FEATURES, context.command); - CHECK_EQUAL(159, context.remote_supported_features); -} - -TEST(HFPParser, HFP_AG_AVAILABLE_CODECS){ - sprintf(packet, "\r\nAT%s=0,1,2\r\n", HFP_AVAILABLE_CODECS); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - CHECK_EQUAL(HFP_CMD_AVAILABLE_CODECS, context.command); - CHECK_EQUAL(3, context.remote_codecs_nr); - for (pos = 0; pos < 3; pos++){ - CHECK_EQUAL(pos, context.remote_codecs[pos]); - } -} - - -TEST(HFPParser, HFP_AG_GENERIC_STATUS_INDICATOR){ - sprintf(packet, "\r\nAT%s=0,1,2,3,4\r\n", HFP_GENERIC_STATUS_INDICATOR); - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - - CHECK_EQUAL(context.command, HFP_CMD_LIST_GENERIC_STATUS_INDICATORS); - CHECK_EQUAL(5, context.generic_status_indicators_nr); - - for (pos = 0; pos < context.generic_status_indicators_nr; pos++){ - CHECK_EQUAL(pos, context.generic_status_indicators[pos].uuid); - } -} - - -TEST(HFPParser, HFP_AG_ENABLE_INDICATOR_STATUS_UPDATE){ - sprintf(packet, "\r\nAT%s=3,0,0,1\r\n", HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - CHECK_EQUAL(HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE, context.command); - CHECK_EQUAL(1, context.enable_status_update_for_ag_indicators); -} - - - -TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE){ - hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators); - context.ag_indicators_nr = hfp_ag_indicators_nr; - memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); - - for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - CHECK_EQUAL(hfp_ag_get_ag_indicators(&context)[pos].index, hfp_ag_indicators[pos].index); - CHECK_EQUAL(hfp_ag_get_ag_indicators(&context)[pos].enabled, hfp_ag_indicators[pos].enabled); - CHECK_EQUAL(context.ag_indicators[pos].index, hfp_ag_indicators[pos].index); - CHECK_EQUAL(context.ag_indicators[pos].enabled, hfp_ag_indicators[pos].enabled); - } - sprintf(packet, "\r\nAT%s=0,0,0,0,0,0,0\r\n", - HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - - CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); - - for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - if (hfp_ag_get_ag_indicators(&context)[pos].mandatory){ - CHECK_EQUAL(hfp_ag_get_ag_indicators(&context)[pos].enabled, 1); - CHECK_EQUAL(context.ag_indicators[pos].enabled, 1); - } else { - CHECK_EQUAL(hfp_ag_get_ag_indicators(&context)[pos].enabled, 0); - CHECK_EQUAL(context.ag_indicators[pos].enabled, 0); - } - } -} - -TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES3){ - hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators); - context.ag_indicators_nr = hfp_ag_indicators_nr; - memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); - - sprintf(packet, "\r\nAT%s=,1,,,,,1\r\n", - HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - - CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); - - for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - CHECK_EQUAL(hfp_ag_get_ag_indicators(&context)[pos].index, hfp_ag_indicators[pos].index); - CHECK_EQUAL(hfp_ag_get_ag_indicators(&context)[pos].enabled, hfp_ag_indicators[pos].enabled); - CHECK_EQUAL(context.ag_indicators[pos].index, hfp_ag_indicators[pos].index); - CHECK_EQUAL(context.ag_indicators[pos].enabled, hfp_ag_indicators[pos].enabled); - } -} - -TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES2){ - hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators); - context.ag_indicators_nr = hfp_ag_indicators_nr; - memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); - - sprintf(packet, "\r\nAT%s=1,,,1,1,1,\r\n", - HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - - CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); - - for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - CHECK_EQUAL(hfp_ag_get_ag_indicators(&context)[pos].enabled, 1); - CHECK_EQUAL(context.ag_indicators[pos].enabled, 1); - } -} - -TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES1){ - hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators); - context.ag_indicators_nr = hfp_ag_indicators_nr; - memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); - - sprintf(packet, "\r\nAT%s=1,,,1,1,1,\r\n", - HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - - CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); - - for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - CHECK_EQUAL(hfp_ag_get_ag_indicators(&context)[pos].enabled, 1); - CHECK_EQUAL(context.ag_indicators[pos].enabled, 1); - } -} - -TEST(HFPParser, HFP_AG_HF_QUERY_OPERATOR_SELECTION){ - context.network_operator.format = 0xff; - sprintf(packet, "\r\nAT%s=3,0\r\n", HFP_QUERY_OPERATOR_SELECTION); - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - CHECK_EQUAL(context.operator_name_changed, 0); - - CHECK_EQUAL(HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT, context.command); - - sprintf(packet, "\r\nAT%s?\r\n", HFP_QUERY_OPERATOR_SELECTION); - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - CHECK_EQUAL(context.operator_name_changed, 0); -} - -TEST(HFPParser, HFP_AG_EXTENDED_AUDIO_GATEWAY_ERROR){ - sprintf(packet, "\r\nAT%s=1\r\n", HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR); - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - - CHECK_EQUAL(context.command, HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR); - CHECK_EQUAL(context.enable_extended_audio_gateway_error_report, 1); -} - -TEST(HFPParser, HFP_AG_TRIGGER_CODEC_CONNECTION_SETUP){ - sprintf(packet, "\r\nAT%s\r\n", HFP_TRIGGER_CODEC_CONNECTION_SETUP); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - CHECK_EQUAL(context.command, HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP); -} - -TEST(HFPParser, HFP_AG_CONFIRM_COMMON_CODEC){ - int codec = 2; - sprintf(packet, "\r\nAT%s=%d\r\n", HFP_CONFIRM_COMMON_CODEC, codec); - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 0); - } - - CHECK_EQUAL(context.command, HFP_CMD_HF_CONFIRMED_CODEC); - CHECK_EQUAL(context.codec_confirmed, codec); -} - -int main (int argc, const char * argv[]){ - return CommandLineTestRunner::RunAllTests(argc, argv); -} diff --git a/test/hfp/hfp_at_parser_test.c b/test/hfp/hfp_at_parser_test.c new file mode 100644 index 000000000..d2a1b52d1 --- /dev/null +++ b/test/hfp/hfp_at_parser_test.c @@ -0,0 +1,510 @@ +/* + * 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 + * + */ + + +#include +#include +#include +#include + +#include "CppUTest/TestHarness.h" +#include "CppUTest/CommandLineTestRunner.h" + +#include "classic/hfp.h" +#include "classic/hfp_ag.h" + +void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree); + +static hfp_connection_t context; +static int hfp_ag_indicators_nr = 7; +static hfp_ag_indicator_t hfp_ag_indicators[] = { + // index, name, min range, max range, status, mandatory, enabled, status changed + {1, "service", 0, 1, 1, 0, 0, 0}, + {2, "call", 0, 1, 0, 1, 1, 0}, + {3, "callsetup", 0, 3, 0, 1, 1, 0}, + {4, "battchg", 0, 5, 3, 0, 0, 0}, + {5, "signal", 0, 5, 5, 0, 0, 0}, + {6, "roam", 0, 1, 0, 0, 0, 0}, + {7, "callheld", 0, 2, 0, 1, 1, 0} +}; +static uint8_t call_status_index = 2; +static uint8_t callsetup_status_index = 3; +static uint8_t callheld_status_index = 7; + + +static void parse_ag(const char * packet){ + for (uint16_t pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos], 0); + } +} + +static void parse_hf(const char * packet){ + for (uint16_t pos = 0; pos < strlen(packet); pos++){ + hfp_parse(&context, packet[pos], 1); + } +} + +TEST_GROUP(HFPParser){ + char packet[200]; + int pos; + int offset; + + void setup(void){ + context.parser_state = HFP_PARSER_CMD_HEADER; + context.parser_item_index = 0; + context.line_size = 0; + context.ag_indicators_nr = 0; + context.remote_codecs_nr = 0; + memset(packet,0, sizeof(packet)); + } +}; + +TEST(HFPParser, HFP_HF_OK){ + sprintf(packet, "\r\n%s\r\n", HFP_OK); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); +} + +TEST(HFPParser, HFP_HF_SUPPORTED_FEATURES){ + sprintf(packet, "\r\n%s:1007\r\n\r\nOK\r\n", HFP_SUPPORTED_FEATURES); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(1007, context.remote_supported_features); +} + +TEST(HFPParser, HFP_CMD_INDICATORS_QUERY){ + sprintf(packet, "\r\nAT%s?\r\n", HFP_INDICATOR); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS, context.command); +} + +TEST(HFPParser, HFP_CMD_INDICATORS_RETRIEVE){ + sprintf(packet, "\r\nAT%s=?\r\n", HFP_INDICATOR); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_RETRIEVE_AG_INDICATORS, context.command); +} + +TEST(HFPParser, HFP_HF_INDICATORS){ + offset = 0; + offset += snprintf(packet, sizeof(packet), "%s:", HFP_INDICATOR); + for (pos = 0; pos < hfp_ag_indicators_nr - 1; pos++){ + offset += snprintf(packet+offset, sizeof(packet)-offset, "(\"%s\", (%d, %d)),", hfp_ag_indicators[pos].name, hfp_ag_indicators[pos].min_range, hfp_ag_indicators[pos].max_range); + } + offset += snprintf(packet+offset, sizeof(packet)-offset, "(\"%s\", (%d, %d))\r\n\r\nOK\r\n", hfp_ag_indicators[pos].name, hfp_ag_indicators[pos].min_range, hfp_ag_indicators[pos].max_range); + context.state = HFP_W4_RETRIEVE_INDICATORS; + + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(hfp_ag_indicators_nr, context.ag_indicators_nr); + for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ + CHECK_EQUAL(hfp_ag_indicators[pos].index, context.ag_indicators[pos].index); + STRCMP_EQUAL(hfp_ag_indicators[pos].name, context.ag_indicators[pos].name); + CHECK_EQUAL(hfp_ag_indicators[pos].min_range, context.ag_indicators[pos].min_range); + CHECK_EQUAL(hfp_ag_indicators[pos].max_range, context.ag_indicators[pos].max_range); + } +} + +TEST(HFPParser, HFP_HF_INDICATOR_STATUS){ + // send status + offset = 0; + offset += snprintf(packet, sizeof(packet), "%s:", HFP_INDICATOR); + for (pos = 0; pos < hfp_ag_indicators_nr - 1; pos++){ + offset += snprintf(packet+offset, sizeof(packet)-offset, "%d,", hfp_ag_indicators[pos].status); + } + offset += snprintf(packet+offset, sizeof(packet)-offset, "%d\r\n\r\nOK\r\n", hfp_ag_indicators[pos].status); + + //context.command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS; + context.state = HFP_W4_RETRIEVE_INDICATORS_STATUS; + + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ + CHECK_EQUAL(hfp_ag_indicators[pos].status, context.ag_indicators[pos].status); + } +} + +TEST(HFPParser, HFP_HF_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES_TEST){ + sprintf(packet, "\r\nAT%s=?\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, context.command); +} + +TEST(HFPParser, HFP_HF_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES_SET){ + int action = 1; + int call_index = 2; + sprintf(packet, "\r\nAT%s=%u%u\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES, action, call_index); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_CALL_HOLD, context.command); + CHECK_EQUAL(action, context.ag_call_hold_action); + CHECK_EQUAL(call_index, context.call_index); +} + +TEST(HFPParser, HFP_HF_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES){ + sprintf(packet, "\r\n%s:(1,1x,2,2x,3)\r\n\r\nOK\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(5, context.remote_call_services_nr); + + STRCMP_EQUAL("1", (char*)context.remote_call_services[0].name); + STRCMP_EQUAL("1x", (char*)context.remote_call_services[1].name); + STRCMP_EQUAL("2", (char*)context.remote_call_services[2].name); + STRCMP_EQUAL("2x", (char*)context.remote_call_services[3].name); + STRCMP_EQUAL("3", (char*)context.remote_call_services[4].name); +} + +TEST(HFPParser, HFP_GENERIC_STATUS_INDICATOR_TEST){ + sprintf(packet, "\r\nAT%s=?\r\n", HFP_GENERIC_STATUS_INDICATOR); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS, context.command); +} + +TEST(HFPParser, HFP_GENERIC_STATUS_INDICATOR_SET){ + int param = 1; + sprintf(packet, "\r\nAT%s=%u\r\n", HFP_GENERIC_STATUS_INDICATOR, param); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_LIST_GENERIC_STATUS_INDICATORS, context.command); +} + +TEST(HFPParser, HFP_GENERIC_STATUS_INDICATOR_READ){ + sprintf(packet, "\r\nAT%s?\r\n", HFP_GENERIC_STATUS_INDICATOR); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE, context.command); +} + +TEST(HFPParser, HFP_HF_GENERIC_STATUS_INDICATOR_STATE){ + sprintf(packet, "\r\n%s:0,1\r\n\r\nOK\r\n", HFP_GENERIC_STATUS_INDICATOR); + // context.command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE; + context.state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS; + + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(1, context.generic_status_indicators[0].state); +} + +TEST(HFPParser, HFP_HF_AG_INDICATOR_STATUS_UPDATE){ + context.ag_indicators_nr = hfp_ag_indicators_nr; + memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); + + uint8_t index = 4; + uint8_t status = 5; + + sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status); + + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(status, context.ag_indicators[index - 1].status); +} + +TEST(HFPParser, HFP_HF_AG_QUERY_OPERATOR_SELECTION){ + sprintf(packet, "\r\n%s:1,0,\"sunrise\"\r\n\r\nOK\r\n", HFP_QUERY_OPERATOR_SELECTION); + + context.command = HFP_CMD_QUERY_OPERATOR_SELECTION_NAME; + + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(0, context.operator_name_changed); + STRCMP_EQUAL( "sunrise", context.network_operator.name); +} + +TEST(HFPParser, HFP_HF_ERROR){ + sprintf(packet, "\r\n%s\r\n", HFP_ERROR); + + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_ERROR, context.command); +} + +TEST(HFPParser, HFP_HF_EXTENDED_AUDIO_GATEWAY_ERROR){ + sprintf(packet, "\r\n%s:%d\r\n", HFP_EXTENDED_AUDIO_GATEWAY_ERROR, HFP_CME_ERROR_NO_NETWORK_SERVICE); + + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR, context.command); + CHECK_EQUAL(HFP_CME_ERROR_NO_NETWORK_SERVICE, context.extended_audio_gateway_error_value); +} + +TEST(HFPParser, HFP_HF_AG_INDICATOR_CALLS_STATUS_UPDATE){ + context.ag_indicators_nr = hfp_ag_indicators_nr; + memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); + uint8_t status = 1; + + // call status + uint8_t index = call_status_index; + sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(status, context.ag_indicators[index - 1].status); + + // callsetup status + index = callsetup_status_index; + sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(status, context.ag_indicators[index - 1].status); + + // callheld status + index = callheld_status_index; + sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_OK, context.command); + CHECK_EQUAL(status, context.ag_indicators[index - 1].status); +} + +TEST(HFPParser, HFP_LIST_CURRENT_CALLS_1){ + strcpy(packet, "\r\n+CLCC: 1,2,3,4,5,,129\r\n"); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_LIST_CURRENT_CALLS, context.command); + CHECK_EQUAL(1, context.clcc_idx); + CHECK_EQUAL(2, context.clcc_dir); + CHECK_EQUAL(3, context.clcc_status); + CHECK_EQUAL(4, context.clcc_mode); + CHECK_EQUAL(5, context.clcc_mpty); + STRCMP_EQUAL("", context.bnip_number); + CHECK_EQUAL(129, context.bnip_type); +} + +TEST(HFPParser, HFP_LIST_CURRENT_CALLS_2){ + strcpy(packet, "\r\n+CLCC: 1,2,3,4,5,"",129\r\n"); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_LIST_CURRENT_CALLS, context.command); + CHECK_EQUAL(1, context.clcc_idx); + CHECK_EQUAL(2, context.clcc_dir); + CHECK_EQUAL(3, context.clcc_status); + CHECK_EQUAL(4, context.clcc_mode); + CHECK_EQUAL(5, context.clcc_mpty); + STRCMP_EQUAL("", context.bnip_number); + CHECK_EQUAL(129, context.bnip_type); +} + +TEST(HFPParser, HFP_AG_SUPPORTED_FEATURES){ + sprintf(packet, "\r\nAT%s=159\r\n", HFP_SUPPORTED_FEATURES); + //context.keep_separator = 0; + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_SUPPORTED_FEATURES, context.command); + CHECK_EQUAL(159, context.remote_supported_features); +} + +TEST(HFPParser, HFP_AG_AVAILABLE_CODECS){ + sprintf(packet, "\r\nAT%s=0,1,2\r\n", HFP_AVAILABLE_CODECS); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_AVAILABLE_CODECS, context.command); + CHECK_EQUAL(3, context.remote_codecs_nr); + for (pos = 0; pos < 3; pos++){ + CHECK_EQUAL(pos, context.remote_codecs[pos]); + } +} + +TEST(HFPParser, HFP_AG_GENERIC_STATUS_INDICATOR){ + sprintf(packet, "\r\nAT%s=0,1,2,3,4\r\n", HFP_GENERIC_STATUS_INDICATOR); + parse_ag(packet); + CHECK_EQUAL(context.command, HFP_CMD_LIST_GENERIC_STATUS_INDICATORS); + CHECK_EQUAL(5, context.generic_status_indicators_nr); + + for (pos = 0; pos < context.generic_status_indicators_nr; pos++){ + CHECK_EQUAL(pos, context.generic_status_indicators[pos].uuid); + } +} + +TEST(HFPParser, HFP_AG_ENABLE_INDICATOR_STATUS_UPDATE){ + sprintf(packet, "\r\nAT%s=3,0,0,1\r\n", HFP_ENABLE_STATUS_UPDATE_FOR_AG_INDICATORS); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_ENABLE_INDICATOR_STATUS_UPDATE, context.command); + CHECK_EQUAL(1, context.enable_status_update_for_ag_indicators); +} + +TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE){ + hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators); + context.ag_indicators_nr = hfp_ag_indicators_nr; + memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); + + for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ + CHECK_EQUAL(hfp_ag_indicators[pos].index, hfp_ag_get_ag_indicators(&context)[pos].index ); + CHECK_EQUAL(hfp_ag_indicators[pos].enabled, hfp_ag_get_ag_indicators(&context)[pos].enabled); + CHECK_EQUAL(hfp_ag_indicators[pos].index, context.ag_indicators[pos].index); + CHECK_EQUAL(hfp_ag_indicators[pos].enabled, context.ag_indicators[pos].enabled); + } + sprintf(packet, "\r\nAT%s=0,0,0,0,0,0,0\r\n", + HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); + + for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ + if (hfp_ag_get_ag_indicators(&context)[pos].mandatory){ + CHECK_EQUAL(1, hfp_ag_get_ag_indicators(&context)[pos].enabled); + CHECK_EQUAL(1, context.ag_indicators[pos].enabled); + } else { + CHECK_EQUAL(0, hfp_ag_get_ag_indicators(&context)[pos].enabled); + CHECK_EQUAL(0, context.ag_indicators[pos].enabled); + } + } +} + +TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES3){ + hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators); + context.ag_indicators_nr = hfp_ag_indicators_nr; + memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); + + sprintf(packet, "\r\nAT%s=,1,,,,,1\r\n", + HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); + parse_ag(packet); + + CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); + + for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ + CHECK_EQUAL(hfp_ag_indicators[pos].index, hfp_ag_get_ag_indicators(&context)[pos].index ); + CHECK_EQUAL(hfp_ag_indicators[pos].enabled, hfp_ag_get_ag_indicators(&context)[pos].enabled); + CHECK_EQUAL(hfp_ag_indicators[pos].index, context.ag_indicators[pos].index ); + CHECK_EQUAL(hfp_ag_indicators[pos].enabled, context.ag_indicators[pos].enabled); + } +} + +TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES2){ + hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators); + context.ag_indicators_nr = hfp_ag_indicators_nr; + memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); + + sprintf(packet, "\r\nAT%s=1,,,1,1,1,\r\n", + HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); + parse_ag(packet); + + CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); + + for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ + CHECK_EQUAL(1,hfp_ag_get_ag_indicators(&context)[pos].enabled); + CHECK_EQUAL(1, context.ag_indicators[pos].enabled); + } +} + +TEST(HFPParser, HFP_AG_ENABLE_INDIVIDUAL_INDICATOR_STATUS_UPDATE_OPT_VALUES1){ + hfp_ag_init_ag_indicators(hfp_ag_indicators_nr, (hfp_ag_indicator_t *)&hfp_ag_indicators); + context.ag_indicators_nr = hfp_ag_indicators_nr; + memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); + + sprintf(packet, "\r\nAT%s=1,,,1,1,1,\r\n", + HFP_UPDATE_ENABLE_STATUS_FOR_INDIVIDUAL_AG_INDICATORS); + parse_ag(packet); + + CHECK_EQUAL(HFP_CMD_ENABLE_INDIVIDUAL_AG_INDICATOR_STATUS_UPDATE, context.command); + + for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ + CHECK_EQUAL(1, hfp_ag_get_ag_indicators(&context)[pos].enabled); + CHECK_EQUAL(1, context.ag_indicators[pos].enabled); + } +} + +TEST(HFPParser, HFP_AG_HF_QUERY_OPERATOR_SELECTION){ + context.network_operator.format = 0xff; + sprintf(packet, "\r\nAT%s=3,0\r\n", HFP_QUERY_OPERATOR_SELECTION); + + parse_ag(packet); + CHECK_EQUAL(0, context.operator_name_changed); + CHECK_EQUAL(HFP_CMD_QUERY_OPERATOR_SELECTION_NAME_FORMAT, context.command); + + sprintf(packet, "\r\nAT%s?\r\n", HFP_QUERY_OPERATOR_SELECTION); + + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_QUERY_OPERATOR_SELECTION_NAME, context.command); + CHECK_EQUAL(0, context.operator_name_changed); +} + +TEST(HFPParser, HFP_AG_EXTENDED_AUDIO_GATEWAY_ERROR){ + sprintf(packet, "\r\nAT%s=1\r\n", HFP_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR); + + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_ENABLE_EXTENDED_AUDIO_GATEWAY_ERROR, context.command ); + CHECK_EQUAL(1, context.enable_extended_audio_gateway_error_report); +} + +TEST(HFPParser, HFP_AG_TRIGGER_CODEC_CONNECTION_SETUP){ + sprintf(packet, "\r\nAT%s\r\n", HFP_TRIGGER_CODEC_CONNECTION_SETUP); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_TRIGGER_CODEC_CONNECTION_SETUP, context.command); +} + +TEST(HFPParser, HFP_AG_CONFIRM_COMMON_CODEC){ + int codec = 2; + sprintf(packet, "\r\nAT%s=%d\r\n", HFP_CONFIRM_COMMON_CODEC, codec); + + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_HF_CONFIRMED_CODEC, context.command ); + CHECK_EQUAL(codec, context.codec_confirmed); +} + +TEST(HFPParser, HFP_AG_DIAL){ + strcpy(packet, "\r\nATD00123456789;\r\n"); + + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_CALL_PHONE_NUMBER, context.command); + STRCMP_EQUAL("00123456789", (const char *) &context.line_buffer[3]); +} + +TEST(HFPParser, HFP_ANSWER_CALL){ + sprintf(packet, "\r\n%s\r\n", HFP_ANSWER_CALL); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_CALL_ANSWERED, context.command); +} + +TEST(HFPParser, HFP_CMD_RESPONSE_AND_HOLD_QUERY){ + sprintf(packet, "\r\nAT%s?\r\n", HFP_RESPONSE_AND_HOLD); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_RESPONSE_AND_HOLD_QUERY, context.command); +} + +TEST(HFPParser, HFP_CMD_RESPONSE_AND_HOLD_COMMAND){ + int param = 1; + sprintf(packet, "\r\nAT%s=%u\r\n", HFP_RESPONSE_AND_HOLD, param); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_RESPONSE_AND_HOLD_COMMAND, context.command); + CHECK_EQUAL(param, context.ag_response_and_hold_action); +} + +TEST(HFPParser, HFP_CMD_RESPONSE_AND_HOLD_STATUS){ + int status = 1; + sprintf(packet, "\r\n%s:%u\r\n", HFP_RESPONSE_AND_HOLD, status); + parse_hf(packet); + CHECK_EQUAL(HFP_CMD_RESPONSE_AND_HOLD_STATUS, context.command); +} + +TEST(HFPParser, HFP_CMD_ENABLE_CLIP){ + int param = 1; + sprintf(packet, "\r\nAT%s=%u\r\n", HFP_ENABLE_CLIP, param); + parse_ag(packet); + CHECK_EQUAL(HFP_CMD_ENABLE_CLIP, context.command); + CHECK_EQUAL(param, context.clip_enabled); +} + +int main (int argc, const char * argv[]){ + return CommandLineTestRunner::RunAllTests(argc, argv); +} diff --git a/test/hfp/hfp_hf_parser_test.c b/test/hfp/hfp_hf_parser_test.c deleted file mode 100644 index cbcc14743..000000000 --- a/test/hfp/hfp_hf_parser_test.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * 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 - * - */ - - -#include -#include -#include -#include - -#include "CppUTest/TestHarness.h" -#include "CppUTest/CommandLineTestRunner.h" - -#include "classic/hfp.h" - -void hfp_parse(hfp_connection_t * context, uint8_t byte, int isHandsFree); - -static hfp_connection_t context; -static int hfp_ag_indicators_nr = 7; -static hfp_ag_indicator_t hfp_ag_indicators[] = { - // index, name, min range, max range, status, mandatory, enabled, status changed - {1, "service", 0, 1, 1, 0, 0, 0}, - {2, "call", 0, 1, 0, 1, 1, 0}, - {3, "callsetup", 0, 3, 0, 1, 1, 0}, - {4, "battchg", 0, 5, 3, 0, 0, 0}, - {5, "signal", 0, 5, 5, 0, 0, 0}, - {6, "roam", 0, 1, 0, 0, 0, 0}, - {7, "callheld", 0, 2, 0, 1, 1, 0} -}; -static uint8_t call_status_index = 2; -static uint8_t callsetup_status_index = 3; -static uint8_t callheld_status_index = 7; - - -TEST_GROUP(HFPParser){ - char packet[200]; - int pos; - int offset; - - void setup(void){ - context.parser_state = HFP_PARSER_CMD_HEADER; - context.parser_item_index = 0; - context.line_size = 0; - context.ag_indicators_nr = 0; - context.remote_codecs_nr = 0; - memset(packet,0, sizeof(packet)); - } -}; - - -TEST(HFPParser, HFP_HF_OK){ - sprintf(packet, "\r\n%s\r\n", HFP_OK); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - CHECK_EQUAL(HFP_CMD_OK, context.command); -} - -TEST(HFPParser, HFP_HF_SUPPORTED_FEATURES){ - sprintf(packet, "\r\n%s:1007\r\n\r\nOK\r\n", HFP_SUPPORTED_FEATURES); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - CHECK_EQUAL(HFP_CMD_OK, context.command); - CHECK_EQUAL(1007, context.remote_supported_features); -} - - -TEST(HFPParser, HFP_HF_INDICATORS){ - offset = 0; - offset += snprintf(packet, sizeof(packet), "%s:", HFP_INDICATOR); - for (pos = 0; pos < hfp_ag_indicators_nr - 1; pos++){ - offset += snprintf(packet+offset, sizeof(packet)-offset, "\"%s\", (%d, %d),", hfp_ag_indicators[pos].name, hfp_ag_indicators[pos].min_range, hfp_ag_indicators[pos].max_range); - } - offset += snprintf(packet+offset, sizeof(packet)-offset, "\"%s\", (%d, %d)\r\n\r\nOK\r\n", hfp_ag_indicators[pos].name, hfp_ag_indicators[pos].min_range, hfp_ag_indicators[pos].max_range); - - //context.command = HFP_CMD_RETRIEVE_AG_INDICATORS; - context.state = HFP_W4_RETRIEVE_INDICATORS; - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - CHECK_EQUAL(HFP_CMD_OK, context.command); - CHECK_EQUAL(hfp_ag_indicators_nr, context.ag_indicators_nr); - for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - CHECK_EQUAL(hfp_ag_indicators[pos].index, context.ag_indicators[pos].index); - CHECK_EQUAL(0, strcmp(hfp_ag_indicators[pos].name, context.ag_indicators[pos].name)); - CHECK_EQUAL(hfp_ag_indicators[pos].min_range, context.ag_indicators[pos].min_range); - CHECK_EQUAL(hfp_ag_indicators[pos].max_range, context.ag_indicators[pos].max_range); - } -} - -TEST(HFPParser, HFP_HF_INDICATOR_STATUS){ - // send status - offset = 0; - offset += snprintf(packet, sizeof(packet), "%s:", HFP_INDICATOR); - for (pos = 0; pos < hfp_ag_indicators_nr - 1; pos++){ - offset += snprintf(packet+offset, sizeof(packet)-offset, "%d,", hfp_ag_indicators[pos].status); - } - offset += snprintf(packet+offset, sizeof(packet)-offset, "%d\r\n\r\nOK\r\n", hfp_ag_indicators[pos].status); - - //context.command = HFP_CMD_RETRIEVE_AG_INDICATORS_STATUS; - context.state = HFP_W4_RETRIEVE_INDICATORS_STATUS; - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - - CHECK_EQUAL(HFP_CMD_OK, context.command); - for (pos = 0; pos < hfp_ag_indicators_nr; pos++){ - CHECK_EQUAL(hfp_ag_indicators[pos].status, context.ag_indicators[pos].status); - } -} - - -TEST(HFPParser, HFP_HF_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES){ - sprintf(packet, "\r\n%s:(1,1x,2,2x,3)\r\n\r\nOK\r\n", HFP_SUPPORT_CALL_HOLD_AND_MULTIPARTY_SERVICES); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - CHECK_EQUAL(HFP_CMD_OK, context.command); - CHECK_EQUAL(5, context.remote_call_services_nr); - - CHECK_EQUAL(0, strcmp("1", (char*)context.remote_call_services[0].name)); - CHECK_EQUAL(0, strcmp("1x", (char*)context.remote_call_services[1].name)); - CHECK_EQUAL(0, strcmp("2", (char*)context.remote_call_services[2].name)); - CHECK_EQUAL(0, strcmp("2x", (char*)context.remote_call_services[3].name)); - CHECK_EQUAL(0, strcmp("3", (char*)context.remote_call_services[4].name)); -} - -// TEST(HFPParser, HFP_HF_GENERIC_STATUS_INDICATOR){ -// sprintf(packet, "\r\n%s:0,1,2,3,4\r\n\r\nOK\r\n", HFP_GENERIC_STATUS_INDICATOR); -// //context.command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS; -// context.state = HFP_W4_RETRIEVE_GENERIC_STATUS_INDICATORS; - -// for (pos = 0; pos < strlen(packet); pos++){ -// hfp_parse(&context, packet[pos], 1); -// } - -// CHECK_EQUAL(HFP_CMD_OK, context.command); -// CHECK_EQUAL(5, context.generic_status_indicators_nr); - -// for (pos = 0; pos < context.generic_status_indicators_nr; pos++){ -// CHECK_EQUAL(pos, context.generic_status_indicators[pos].uuid); -// } -// } - -TEST(HFPParser, HFP_HF_GENERIC_STATUS_INDICATOR_STATE){ - sprintf(packet, "\r\n%s:0,1\r\n\r\nOK\r\n", HFP_GENERIC_STATUS_INDICATOR); - // context.command = HFP_CMD_RETRIEVE_GENERIC_STATUS_INDICATORS_STATE; - context.state = HFP_W4_RETRIEVE_INITITAL_STATE_GENERIC_STATUS_INDICATORS; - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - - CHECK_EQUAL(HFP_CMD_OK, context.command); - CHECK_EQUAL(1, context.generic_status_indicators[0].state); -} - -TEST(HFPParser, HFP_HF_AG_INDICATOR_STATUS_UPDATE){ - context.ag_indicators_nr = hfp_ag_indicators_nr; - memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); - - uint8_t index = 4; - uint8_t status = 5; - - sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - - CHECK_EQUAL(HFP_CMD_OK, context.command); - CHECK_EQUAL(context.ag_indicators[index - 1].status, status); -} - -TEST(HFPParser, HFP_HF_AG_QUERY_OPERATOR_SELECTION){ - sprintf(packet, "\r\n%s:1,0,\"sunrise\"\r\n\r\nOK\r\n", HFP_QUERY_OPERATOR_SELECTION); - - context.command = HFP_CMD_QUERY_OPERATOR_SELECTION_NAME; - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - - CHECK_EQUAL(context.command, HFP_CMD_OK); - CHECK_EQUAL(context.operator_name_changed, 0); - CHECK_EQUAL( strcmp("sunrise", context.network_operator.name), 0); -} - -TEST(HFPParser, HFP_HF_ERROR){ - sprintf(packet, "\r\n%s\r\n", HFP_ERROR); - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - - CHECK_EQUAL(context.command, HFP_CMD_ERROR); -} - -TEST(HFPParser, HFP_HF_EXTENDED_AUDIO_GATEWAY_ERROR){ - sprintf(packet, "\r\n%s:%d\r\n", HFP_EXTENDED_AUDIO_GATEWAY_ERROR, HFP_CME_ERROR_NO_NETWORK_SERVICE); - - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - - CHECK_EQUAL(context.command, HFP_CMD_EXTENDED_AUDIO_GATEWAY_ERROR); - CHECK_EQUAL(context.extended_audio_gateway_error_value, HFP_CME_ERROR_NO_NETWORK_SERVICE); -} - - -TEST(HFPParser, HFP_HF_AG_INDICATOR_CALLS_STATUS_UPDATE){ - context.ag_indicators_nr = hfp_ag_indicators_nr; - memcpy(context.ag_indicators, hfp_ag_indicators, hfp_ag_indicators_nr * sizeof(hfp_ag_indicator_t)); - uint8_t status = 1; - - // call status - uint8_t index = call_status_index; - sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - CHECK_EQUAL(HFP_CMD_OK, context.command); - CHECK_EQUAL(context.ag_indicators[index - 1].status, status); - - // callsetup status - index = callsetup_status_index; - sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - CHECK_EQUAL(HFP_CMD_OK, context.command); - CHECK_EQUAL(context.ag_indicators[index - 1].status, status); - - // callheld status - index = callheld_status_index; - sprintf(packet, "\r\n%s:%d,%d\r\n\r\nOK\r\n", HFP_TRANSFER_AG_INDICATOR_STATUS, index, status); - for (pos = 0; pos < strlen(packet); pos++){ - hfp_parse(&context, packet[pos], 1); - } - CHECK_EQUAL(HFP_CMD_OK, context.command); - CHECK_EQUAL(context.ag_indicators[index - 1].status, status); -} - -int main (int argc, const char * argv[]){ - return CommandLineTestRunner::RunAllTests(argc, argv); -}