mirror of
https://github.com/google/pebble.git
synced 2025-03-21 19:31:20 +00:00
298 lines
8.6 KiB
C
298 lines
8.6 KiB
C
|
/*
|
||
|
* Copyright 2024 Google LLC
|
||
|
*
|
||
|
* Licensed 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 "clar.h"
|
||
|
#include "comm/ble/gap_le_advert.h"
|
||
|
#include "comm/ble/gap_le_task.h"
|
||
|
#include "comm/ble/gatt_client_subscriptions.h"
|
||
|
#include "comm/ble/kernel_le_client/kernel_le_client.h"
|
||
|
#include "comm/ble/kernel_le_client/test/test_definition.h"
|
||
|
#include "kernel/events.h"
|
||
|
#include "util/size.h"
|
||
|
|
||
|
// Stubs
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include "fake_system_task.h"
|
||
|
|
||
|
#include "stubs_logging.h"
|
||
|
#include "stubs_passert.h"
|
||
|
#include "stubs_pbl_malloc.h"
|
||
|
#include "stubs_rand_ptr.h"
|
||
|
#include "stubs_rtc.h"
|
||
|
|
||
|
void ams_create(void) {
|
||
|
}
|
||
|
|
||
|
void ams_destroy(void) {
|
||
|
}
|
||
|
|
||
|
void ancs_create(void) {
|
||
|
}
|
||
|
|
||
|
void ancs_destroy(void) {
|
||
|
}
|
||
|
|
||
|
void app_launch_handle_disconnection(void) {
|
||
|
}
|
||
|
|
||
|
BTBondingID bt_persistent_storage_get_ble_ancs_bonding(void) {
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
bool bt_persistent_storage_is_ble_ancs_bonding(BTBondingID bonding) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void gap_le_advert_unschedule_job_types(GAPLEAdvertisingJobTag *tag_types, size_t num_types) {
|
||
|
}
|
||
|
|
||
|
void gap_le_connect_cancel_all(GAPLEClient client) {
|
||
|
}
|
||
|
|
||
|
BTErrno gap_le_connect_cancel_by_bonding(BTBondingID bonding_id, GAPLEClient client) {
|
||
|
return BTErrnoOK;
|
||
|
}
|
||
|
|
||
|
BTErrno gap_le_connect_connect_by_bonding(BTBondingID bonding_id, bool auto_reconnect,
|
||
|
bool is_pairing_required, GAPLEClient client) {
|
||
|
return BTErrnoOK;
|
||
|
}
|
||
|
|
||
|
void gap_le_slave_reconnect_start(void) {
|
||
|
}
|
||
|
|
||
|
void gap_le_slave_reconnect_stop(void) {
|
||
|
}
|
||
|
|
||
|
BTErrno gatt_client_discovery_discover_all(const BTDeviceInternal *device) {
|
||
|
return BTErrnoOK;
|
||
|
}
|
||
|
|
||
|
uint16_t gatt_client_subscriptions_consume_notification(BLECharacteristic *characteristic_ref_out,
|
||
|
uint8_t *value_out,
|
||
|
uint16_t *value_length_in_out,
|
||
|
GAPLEClient client, bool *has_more_out) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
bool gatt_client_subscriptions_get_notification_header(GAPLEClient client,
|
||
|
GATTBufferedNotificationHeader *header_out) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void gatt_client_subscriptions_reschedule(GAPLEClient c) {
|
||
|
}
|
||
|
|
||
|
void launcher_task_add_callback(CallbackEventCallback callback, void *data) {
|
||
|
// Use fake_system_task as mock:
|
||
|
system_task_add_callback(callback, data);
|
||
|
}
|
||
|
|
||
|
void ppogatt_create(void) {
|
||
|
}
|
||
|
|
||
|
void ppogatt_destroy(void) {
|
||
|
}
|
||
|
|
||
|
void ppogatt_handle_buffer_empty(void) {
|
||
|
}
|
||
|
|
||
|
void bt_driver_reconnect_try_now(bool ignore_paused) {
|
||
|
}
|
||
|
|
||
|
void gatt_client_op_cleanup(GAPLEClient client) {
|
||
|
}
|
||
|
|
||
|
void ppogatt_reset_disconnect_counter(void) {
|
||
|
}
|
||
|
|
||
|
// Fakes & Helpers
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
static const BTDeviceInternal s_test_device = {
|
||
|
.address = (const BTDeviceAddress) {
|
||
|
.octets = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66},
|
||
|
},
|
||
|
};
|
||
|
|
||
|
typedef enum {
|
||
|
TestServiceInstanceComplete = 1,
|
||
|
TestServiceInstanceIncomplete = 2,
|
||
|
TestServiceInstanceUnsupported = 3,
|
||
|
} TestServiceInstance;
|
||
|
|
||
|
static BLEService s_service_handles[] = {
|
||
|
TestServiceInstanceComplete,
|
||
|
TestServiceInstanceIncomplete,
|
||
|
TestServiceInstanceUnsupported,
|
||
|
};
|
||
|
|
||
|
typedef enum {
|
||
|
TestCharacteristicInstanceCompleteOne = 11,
|
||
|
TestCharacteristicInstanceCompleteTwo = 12,
|
||
|
TestCharacteristicInstanceIncompleteOne = 21,
|
||
|
TestCharacteristicInstanceUnsupported = 33,
|
||
|
} TestCharacteristicInstance;
|
||
|
|
||
|
Uuid gatt_client_service_get_uuid(BLEService service_ref) {
|
||
|
switch (service_ref) {
|
||
|
case TestServiceInstanceComplete:
|
||
|
case TestServiceInstanceIncomplete:
|
||
|
return s_test_service_uuid;
|
||
|
|
||
|
case TestServiceInstanceUnsupported:
|
||
|
default:
|
||
|
return UUID_INVALID;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint8_t gatt_client_service_get_characteristics_matching_uuids(BLEService service_ref,
|
||
|
BLECharacteristic characteristics_out[],
|
||
|
const Uuid matching_characteristic_uuids[],
|
||
|
uint8_t num_characteristics) {
|
||
|
cl_assert_equal_i(num_characteristics, TestCharacteristicCount);
|
||
|
switch (service_ref) {
|
||
|
case TestServiceInstanceComplete:
|
||
|
characteristics_out[0] = TestCharacteristicInstanceCompleteOne;
|
||
|
characteristics_out[1] = TestCharacteristicInstanceCompleteTwo;
|
||
|
return 2;
|
||
|
case TestServiceInstanceIncomplete:
|
||
|
characteristics_out[0] = TestCharacteristicInstanceIncompleteOne;
|
||
|
return 1;
|
||
|
case TestCharacteristicInstanceUnsupported:
|
||
|
characteristics_out[0] = TestCharacteristicInstanceUnsupported;
|
||
|
return 1;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int s_read_responses_consumed_count;
|
||
|
void gatt_client_consume_read_response(uintptr_t object_ref,
|
||
|
uint8_t value_out[],
|
||
|
uint16_t value_length,
|
||
|
GAPLEClient client) {
|
||
|
++s_read_responses_consumed_count;
|
||
|
}
|
||
|
|
||
|
static int s_services_discovered_count;
|
||
|
void test_client_handle_service_discovered(BLECharacteristic *characteristics) {
|
||
|
++s_services_discovered_count;
|
||
|
}
|
||
|
|
||
|
void test_client_invalidate_all_references(void) {
|
||
|
|
||
|
}
|
||
|
|
||
|
void test_client_handle_service_removed(BLECharacteristic *characteristics,
|
||
|
uint8_t num_characteristics) {
|
||
|
|
||
|
}
|
||
|
|
||
|
static bool s_can_handle_characteristic;
|
||
|
bool test_client_can_handle_characteristic(BLECharacteristic characteristic) {
|
||
|
return s_can_handle_characteristic;
|
||
|
}
|
||
|
|
||
|
void test_client_handle_write_response(BLECharacteristic characteristic, BLEGATTError error) {
|
||
|
|
||
|
}
|
||
|
|
||
|
void test_client_handle_subscribe(BLECharacteristic characteristic,
|
||
|
BLESubscription subscription_type, BLEGATTError error) {
|
||
|
|
||
|
}
|
||
|
|
||
|
void test_client_handle_read_or_notification(BLECharacteristic characteristic, const uint8_t *value,
|
||
|
size_t value_length, BLEGATTError error) {
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
// Tests
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void test_kernel_le_client__initialize(void) {
|
||
|
s_services_discovered_count = 0;
|
||
|
s_read_responses_consumed_count = 0;
|
||
|
s_can_handle_characteristic = false;
|
||
|
kernel_le_client_init();
|
||
|
}
|
||
|
|
||
|
void test_kernel_le_client__cleanup(void) {
|
||
|
kernel_le_client_deinit();
|
||
|
fake_system_task_callbacks_cleanup();
|
||
|
}
|
||
|
|
||
|
void test_kernel_le_client__read_response_consumed_even_if_client_is_gone(void) {
|
||
|
// Simulate the client goes away:
|
||
|
s_can_handle_characteristic = false;
|
||
|
|
||
|
PebbleEvent e = (PebbleEvent) {
|
||
|
.type = PEBBLE_BLE_GATT_CLIENT_EVENT,
|
||
|
.bluetooth.le.gatt_client = {
|
||
|
.object_ref = TestCharacteristicInstanceCompleteOne,
|
||
|
.value_length = 1,
|
||
|
.gatt_error = BLEGATTErrorSuccess,
|
||
|
.subtype = PebbleBLEGATTClientEventTypeCharacteristicRead,
|
||
|
},
|
||
|
};
|
||
|
|
||
|
kernel_le_client_handle_event(&e);
|
||
|
|
||
|
cl_assert_equal_i(s_read_responses_consumed_count, 1);
|
||
|
|
||
|
// When value_length is zero, the read response should NOT be consumed:
|
||
|
e.bluetooth.le.gatt_client.value_length = 0;
|
||
|
s_read_responses_consumed_count = 0;
|
||
|
kernel_le_client_handle_event(&e);
|
||
|
|
||
|
cl_assert_equal_i(s_read_responses_consumed_count, 0);
|
||
|
}
|
||
|
|
||
|
void test_kernel_le_client__service_added(void) {
|
||
|
uint8_t num_services_added = ARRAY_LENGTH(s_service_handles);
|
||
|
PebbleBLEGATTClientServiceEventInfo *info =
|
||
|
kernel_malloc(sizeof(PebbleBLEGATTClientServiceEventInfo) +
|
||
|
(num_services_added * sizeof(BLEService)));
|
||
|
|
||
|
*info = (PebbleBLEGATTClientServiceEventInfo) {
|
||
|
.status = BTErrnoOK,
|
||
|
.type = PebbleServicesAdded,
|
||
|
.device = s_test_device,
|
||
|
};
|
||
|
info->services_added_data.num_services_added = num_services_added;
|
||
|
memcpy(info->services_added_data.services, s_service_handles, sizeof(s_service_handles));
|
||
|
|
||
|
PebbleEvent e = (PebbleEvent) {
|
||
|
.type = PEBBLE_BLE_GATT_CLIENT_EVENT,
|
||
|
.bluetooth.le.gatt_client_service = {
|
||
|
.info = info,
|
||
|
.subtype = PebbleBLEGATTClientEventTypeServiceChange,
|
||
|
},
|
||
|
};
|
||
|
|
||
|
kernel_le_client_handle_event(&e);
|
||
|
|
||
|
// Found one complete service instance:
|
||
|
cl_assert_equal_i(s_services_discovered_count, 1);
|
||
|
|
||
|
kernel_free(info);
|
||
|
}
|
||
|
|
||
|
// FIXME: PBL-27751: Improve test coverage of kernel_le_client.c
|