pebble/tests/fw/services/comm_session/test_session_remote_version.c
2025-01-27 11:38:16 -08:00

171 lines
5.8 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 "services/common/bluetooth/bluetooth_persistent_storage.h"
#include "services/common/comm_session/session_internal.h"
#include "services/common/comm_session/session_remote_os.h"
#include "services/common/comm_session/session_remote_version.h"
#include "util/net.h"
static CommSession s_session;
extern void session_remote_version_protocol_msg_callback(CommSession *session,
const uint8_t *data, size_t length);
// Fakes & Stubs
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "fake_pbl_malloc.h"
#include "fake_events.h"
#include "fake_new_timer.h"
#include "stubs_bt_lock.h"
#include "stubs_logging.h"
#include "stubs_mutex.h"
#include "stubs_passert.h"
#include "stubs_rtc.h"
void bt_driver_reconnect_notify_platform_bitfield(uint32_t p) {}
static bool s_session_is_system;
bool comm_session_is_system(CommSession *session) {
return s_session_is_system;
}
static bool s_session_is_valid;
bool comm_session_is_valid(const CommSession *session) {
return (session == &s_session) && s_session_is_valid;
}
static bool s_data_sent;
bool comm_session_send_data(CommSession *session, uint16_t endpoint_id,
const uint8_t* data, size_t length, uint32_t timeout_ms) {
// The request is just a single 0x00 byte to endpoint 0x11:
cl_assert_equal_i(endpoint_id, 0x11);
cl_assert_equal_i(length, 1);
cl_assert_equal_i(*data, 0x00 /* Command ID 'Request' */);
s_data_sent = true;
return true;
}
CommSessionCapability s_capability_flags;
void comm_session_set_capabilities(CommSession *session, CommSessionCapability capability_flags) {
cl_assert_equal_p(session, &s_session);
s_capability_flags = capability_flags;
}
BTBondingID bt_persistent_storage_store_bt_classic_pairing(BTDeviceAddress *address, SM128BitKey *link_key,
char *name, uint8_t *platform_bits) {
return 1;
}
// Helpers
////////////////////////////////////////////////////////////////////////////////////////////////////
static void (*s_launcher_task_callback)(void *data);
static void *s_launcher_task_callback_data;
void launcher_task_add_callback(void (*callback)(void *data), void *data) {
// Simple fake, can only handle one call
cl_assert_equal_p(s_launcher_task_callback, NULL);
s_launcher_task_callback = callback;
s_launcher_task_callback_data = data;
}
static void prv_process_and_assert_sent_request_data(bool expect_request_data_sent) {
s_data_sent = false;
s_launcher_task_callback(s_launcher_task_callback_data);
cl_assert_equal_b(s_data_sent, expect_request_data_sent);
}
static void prv_receive_v3_response(uint8_t major, uint8_t minor, uint8_t bugfix,
CommSessionCapability protocol_capabilities) {
union {
CommSessionCapability protocol_capabilities;
uint8_t byte[8]; // Little-endian!
} capabilities;
capabilities.protocol_capabilities = protocol_capabilities;
uint8_t response_data[] = {
0x01, // Command ID 'Response'
0x00, 0x00, 0x00, 0x00, // Deprecated library version
0x00, 0x00, 0x00, 0x00, // Deprecated capabilities
0x00, 0x00, 0x00, 0x00, // Platform (OS) bitfield
0x02, // Response version
major, minor, bugfix,
capabilities.byte[0],
capabilities.byte[1],
capabilities.byte[2],
capabilities.byte[3],
capabilities.byte[4],
capabilities.byte[5],
capabilities.byte[7],
};
session_remote_version_protocol_msg_callback(&s_session, response_data, sizeof(response_data));
}
// Tests
////////////////////////////////////////////////////////////////////////////////////////////////////
#define MAX_ATTEMPTS (3)
void test_session_remote_version__initialize(void) {
fake_event_init();
s_session = (CommSession) {};
s_data_sent = false;
s_session_is_valid = true;
s_session_is_system = true;
s_capability_flags = 0;
session_remote_version_start_requests(&s_session);
}
void test_session_remote_version__cleanup(void) {
s_launcher_task_callback = NULL;
s_launcher_task_callback_data = NULL;
fake_pbl_malloc_clear_tracking();
}
void test_session_remote_version__receive_invalid_msg(void) {
uint8_t invalid_msg = 0xff;
session_remote_version_protocol_msg_callback(&s_session, &invalid_msg, sizeof(invalid_msg));
cl_assert_equal_i(fake_event_get_count(), 0);
}
static const CommSessionCapability s_expected_capabilities =
(CommSessionAppMessage8kSupport |
CommSessionVoiceApiSupport);
void test_session_remote_version__system_session(void) {
s_session_is_system = true;
prv_receive_v3_response(3, 2, 1, s_expected_capabilities);
// Triggers PEBBLE_REMOTE_APP_INFO_EVENT:
cl_assert_equal_i(fake_event_get_count(), 1);
PebbleEvent e = fake_event_get_last();
cl_assert_equal_i(e.type, PEBBLE_REMOTE_APP_INFO_EVENT);
cl_assert_equal_i(s_capability_flags, s_expected_capabilities);
}
void test_session_remote_version__app_session(void) {
s_session_is_system = false;
prv_receive_v3_response(3, 2, 1, s_expected_capabilities);
// Triggers no event:
cl_assert_equal_i(fake_event_get_count(), 0);
cl_assert_equal_i(s_capability_flags, s_expected_capabilities);
}