blob: 526d5f5af9d14de5fe7602b47c3b19d69644d180 [file] [log] [blame]
/*
* 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;
}