/*
|
* Licensed to the Apache Software Foundation (ASF) under one
|
* or more contributor license agreements. See the NOTICE file
|
* distributed with this work for additional information
|
* regarding copyright ownership. The ASF licenses this file
|
* to you under the Apache License, Version 2.0 (the
|
* "License"); you may not use this file except in compliance
|
* with the License. You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing,
|
* software distributed under the License is distributed on an
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
* KIND, either express or implied. See the License for the
|
* specific language governing permissions and limitations
|
* under the License.
|
*/
|
|
#include <stddef.h>
|
#include <errno.h>
|
#include <string.h>
|
#include "testutil/testutil.h"
|
#include "host/ble_hs.h"
|
#include "ble_hs_test.h"
|
#include "ble_hs_test_util.h"
|
|
#define BHST_MAX_EVENTS 32
|
|
static struct ble_gap_event bhst_events[BHST_MAX_EVENTS];
|
static int bhst_num_events;
|
|
static struct ble_hs_stop_listener bhst_listener;
|
static struct os_sem bhst_sem;
|
|
static int
|
bhst_gap_event(struct ble_gap_event *event, void *arg)
|
{
|
TEST_ASSERT_FATAL(bhst_num_events < BHST_MAX_EVENTS);
|
|
bhst_events[bhst_num_events++] = *event;
|
return 0;
|
}
|
|
static void
|
bhst_stop_cb(int status, void *arg)
|
{
|
int rc;
|
|
rc = os_sem_release(&bhst_sem);
|
TEST_ASSERT_FATAL(rc == 0);
|
}
|
|
TEST_CASE_TASK(ble_hs_stop_test_new_procs)
|
{
|
static const struct ble_gap_disc_params disc_params;
|
static const struct ble_gap_adv_params adv_params;
|
|
static const ble_addr_t peer_addr = {
|
BLE_ADDR_PUBLIC,
|
{ 1, 2, 3, 4, 5, 6 }
|
};
|
|
int rc;
|
|
rc = os_sem_init(&bhst_sem, 0);
|
TEST_ASSERT_FATAL(rc == 0);
|
|
/* Stop the host and wait for the stop procedure to complete. */
|
ble_hs_test_util_hci_ack_set(
|
BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_ADV_ENABLE), 0);
|
|
rc = ble_hs_stop(&bhst_listener, bhst_stop_cb, NULL);
|
TEST_ASSERT_FATAL(rc == 0);
|
rc = os_sem_pend(&bhst_sem, OS_TIMEOUT_NEVER);
|
TEST_ASSERT_FATAL(rc == 0);
|
|
/*** Ensure all GAP procedures fail. */
|
|
/* Advertise. */
|
rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, &adv_params,
|
BLE_HS_FOREVER, bhst_gap_event, NULL,
|
0, 0);
|
TEST_ASSERT(rc == BLE_HS_EDISABLED);
|
|
/* Discover. */
|
rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
|
&disc_params, bhst_gap_event, NULL, 0, 0);
|
TEST_ASSERT(rc == BLE_HS_EDISABLED);
|
|
/* Connect. */
|
rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, &peer_addr,
|
BLE_HS_FOREVER, NULL,
|
bhst_gap_event, NULL, 0);
|
TEST_ASSERT(rc == BLE_HS_EDISABLED);
|
|
/*** Restart stack; ensure GAP procedures succeed. */
|
|
ble_hs_test_util_hci_ack_set_startup();
|
ble_hs_sched_start();
|
|
/* Advertise. */
|
rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, &adv_params,
|
BLE_HS_FOREVER, bhst_gap_event, NULL,
|
0, 0);
|
TEST_ASSERT(rc == 0);
|
|
rc = ble_hs_test_util_adv_stop(0);
|
TEST_ASSERT(rc == 0);
|
|
/* Discover. */
|
rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
|
&disc_params, bhst_gap_event, NULL, 0, 0);
|
TEST_ASSERT(rc == 0);
|
|
rc = ble_hs_test_util_disc_cancel(0);
|
TEST_ASSERT(rc == 0);
|
|
/* Connect. */
|
rc = ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, &peer_addr,
|
BLE_HS_FOREVER, NULL,
|
bhst_gap_event, NULL, 0);
|
TEST_ASSERT(rc == 0);
|
|
rc = ble_hs_test_util_conn_cancel(0);
|
TEST_ASSERT(rc == 0);
|
|
ble_hs_test_util_assert_mbufs_freed(NULL);
|
}
|
|
TEST_CASE_TASK(ble_hs_stop_test_cur_procs)
|
{
|
static const struct ble_gap_disc_params disc_params;
|
static const struct ble_gap_adv_params adv_params;
|
|
int rc;
|
|
rc = os_sem_init(&bhst_sem, 0);
|
TEST_ASSERT_FATAL(rc == 0);
|
|
/* Advertise. */
|
rc = ble_hs_test_util_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, &adv_params,
|
BLE_HS_FOREVER, bhst_gap_event, NULL,
|
0, 0);
|
TEST_ASSERT(rc == 0);
|
|
/* Discover. */
|
rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER,
|
&disc_params, bhst_gap_event, NULL, 0, 0);
|
TEST_ASSERT(rc == 0);
|
|
/* Preload the host with HCI acks for the cancel commands that will be sent
|
* automatically when the host stops.
|
*/
|
ble_hs_test_util_hci_ack_set(
|
BLE_HS_TEST_UTIL_LE_OPCODE(BLE_HCI_OCF_LE_SET_ADV_ENABLE),
|
0);
|
ble_hs_test_util_hci_ack_append(
|
ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
|
BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
|
0);
|
|
/* Stop the host and wait for the stop procedure to complete. */
|
bhst_num_events = 0;
|
rc = ble_hs_stop(&bhst_listener, bhst_stop_cb, NULL);
|
TEST_ASSERT_FATAL(rc == 0);
|
rc = os_sem_pend(&bhst_sem, OS_TIMEOUT_NEVER);
|
TEST_ASSERT_FATAL(rc == 0);
|
|
/* Ensure the GAP procedure cancellations were reported. */
|
TEST_ASSERT_FATAL(bhst_num_events == 2);
|
TEST_ASSERT(bhst_events[0].type == BLE_GAP_EVENT_ADV_COMPLETE);
|
TEST_ASSERT(bhst_events[0].adv_complete.reason == BLE_HS_EPREEMPTED);
|
TEST_ASSERT(bhst_events[1].type == BLE_GAP_EVENT_DISC_COMPLETE);
|
TEST_ASSERT(bhst_events[1].disc_complete.reason == BLE_HS_EPREEMPTED);
|
|
ble_hs_test_util_assert_mbufs_freed(NULL);
|
}
|
|
static void
|
bhst_pre_test(void *arg)
|
{
|
ble_hs_test_util_init_no_sysinit_no_start();
|
|
/* Preload the host with HCI acks for the startup sequence. */
|
ble_hs_test_util_hci_ack_set_startup();
|
}
|
|
TEST_SUITE(ble_hs_stop_test_suite)
|
{
|
tu_suite_set_pre_test_cb(bhst_pre_test, NULL);
|
|
ble_hs_stop_test_new_procs();
|
ble_hs_stop_test_cur_procs();
|
}
|
|
int
|
ble_stop_test_all(void)
|
{
|
ble_hs_stop_test_suite();
|
|
return tu_any_failed;
|
}
|