/* * 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/comm_session/session.h" #include "services/common/bluetooth/bluetooth_persistent_storage.h" #include "services/normal/blob_db/api.h" #include "services/normal/blob_db/endpoint.h" #include "services/normal/blob_db/sync.h" #include // Fakes //////////////////////////////////// #include "fake_system_task.h" // Stubs //////////////////////////////////// #include "stubs_analytics.h" #include "stubs_app_cache.h" #include "stubs_ios_notif_pref_db.h" #include "stubs_app_db.h" #include "stubs_contacts_db.h" #include "stubs_notif_db.h" #include "stubs_pin_db.h" #include "stubs_prefs_db.h" #include "stubs_reminder_db.h" #include "stubs_watch_app_prefs_db.h" #include "stubs_weather_db.h" #include "stubs_bt_lock.h" #include "stubs_evented_timer.h" #include "stubs_events.h" #include "stubs_hexdump.h" #include "stubs_logging.h" #include "stubs_passert.h" #include "stubs_pbl_malloc.h" #include "stubs_reminders.h" #include "stubs_regular_timer.h" CommSession *comm_session_get_system_session(void) { return (CommSession *)1 ; } void blob_db_set_accepting_messages(bool ehh) { } static const uint8_t *s_expected_msg; static bool did_sync_next = false; static bool did_sync_cancel = false; static bool did_sync_db = false; static uint8_t sendbuffer[100]; static int sendbuffer_length; static int sendbuffer_write_index; extern void blob_db2_protocol_msg_callback(CommSession *session, const uint8_t* data, size_t length); typedef void SendBuffer; SendBuffer *comm_session_send_buffer_begin_write(CommSession *session, uint16_t endpoint_id, size_t required_payload_length, uint32_t timeout_ms) { cl_assert(required_payload_length < 100); sendbuffer_length = required_payload_length; sendbuffer_write_index = 0; return (void*)(uintptr_t)1; } bool comm_session_send_buffer_write(SendBuffer *sb, const uint8_t *data, size_t length) { memcpy(&sendbuffer[sendbuffer_write_index], data, length); sendbuffer_write_index += length; return true; } void comm_session_send_buffer_end_write(SendBuffer *sb) { cl_assert(sendbuffer_length > 0); cl_assert_equal_m(sendbuffer, s_expected_msg, sendbuffer_length); } bool comm_session_send_data(CommSession *session, uint16_t endpoint_id, const uint8_t *data, size_t length, uint32_t timeout_ms) { cl_assert_equal_m(data, s_expected_msg, length); return true; } extern void prv_send_response(CommSession *session, uint8_t *response, uint8_t response_length) { cl_assert_equal_m(response, s_expected_msg, response_length); } static const BlobDBToken token = 0x22; extern BlobDBToken prv_new_token(void) { return token; } void blob_db_sync_next(BlobDBSyncSession *session) { did_sync_next = true; } void blob_db_sync_cancel(BlobDBSyncSession *session) { did_sync_cancel = true; } status_t blob_db_sync_db(BlobDBId db_id) { did_sync_db = true; return S_SUCCESS; } BlobDBSyncSession *blob_db_sync_get_session_for_token(BlobDBToken token) { // Don't return NULL return (BlobDBSyncSession *)1; } extern void blob_db2_set_accepting_messages(bool ehh); void test_blob_db2_endpoint__initialize(void) { blob_db2_set_accepting_messages(true); did_sync_next = false; did_sync_cancel = false; did_sync_db = false; sendbuffer_length = 0; sendbuffer_write_index = 0; memset(sendbuffer, 0, sizeof(sendbuffer)); } void test_blob_db2_endpoint__cleanup(void) { } static const uint8_t s_dirty_dbs_request[] = { BLOB_DB_COMMAND_DIRTY_DBS, // cmd 0x12, 0x34, // token }; static const uint8_t s_dirty_dbs_response[] = { BLOB_DB_COMMAND_DIRTY_DBS_RESPONSE, // cmd 0x12, 0x34, // token BLOB_DB_SUCCESS, // status 0x01, // num db_ids BlobDBIdiOSNotifPref // dirty db }; void test_blob_db2_endpoint__handle_dirty_dbs_request(void) { s_expected_msg = s_dirty_dbs_response; blob_db2_protocol_msg_callback(NULL, s_dirty_dbs_request, sizeof(s_dirty_dbs_request)); } static const uint8_t s_start_sync_request[] = { BLOB_DB_COMMAND_START_SYNC, // cmd 0x12, 0x34, // token BlobDBIdiOSNotifPref, // db id }; static const uint8_t s_start_sync_response[] = { BLOB_DB_COMMAND_START_SYNC_RESPONSE, // cmd 0x12, 0x34, // token BLOB_DB_SUCCESS, // status }; void test_blob_db2_endpoint__handle_start_sync_request(void) { s_expected_msg = s_start_sync_response; blob_db2_protocol_msg_callback(NULL, s_start_sync_request, sizeof(s_start_sync_request)); cl_assert(did_sync_db); } static const uint8_t s_start_write_response_success[] = { BLOB_DB_COMMAND_WRITE_RESPONSE, // cmd 0x12, 0x34, // token BLOB_DB_SUCCESS, // response }; static const uint8_t s_start_write_response_error[] = { BLOB_DB_COMMAND_WRITE_RESPONSE, // cmd 0x56, 0x78, // token BLOB_DB_GENERAL_FAILURE, // response }; void test_blob_db2_endpoint__handle_write_response(void) { blob_db2_protocol_msg_callback(NULL, s_start_write_response_success, sizeof(s_start_write_response_success)); cl_assert(did_sync_next); blob_db2_protocol_msg_callback(NULL, s_start_write_response_error, sizeof(s_start_write_response_error)); cl_assert(did_sync_cancel); } static const uint8_t s_start_writeback_response_success[] = { BLOB_DB_COMMAND_WRITEBACK_RESPONSE, // cmd 0x12, 0x34, // token BLOB_DB_SUCCESS, // response }; static const uint8_t s_start_writeback_response_error[] = { BLOB_DB_COMMAND_WRITEBACK_RESPONSE, // cmd 0x56, 0x78, // token BLOB_DB_GENERAL_FAILURE, // response }; void test_blob_db2_endpoint__handle_writeback_response(void) { blob_db2_protocol_msg_callback(NULL, s_start_writeback_response_success, sizeof(s_start_writeback_response_success)); cl_assert(did_sync_next); blob_db2_protocol_msg_callback(NULL, s_start_writeback_response_error, sizeof(s_start_writeback_response_error)); cl_assert(did_sync_cancel); } static const uint8_t s_sync_done_response[] = { BLOB_DB_COMMAND_SYNC_DONE_RESPONSE, // cmd 0x56, 0x78, // token BLOB_DB_SUCCESS, // response }; void test_blob_db2_endpoint__handle_sync_done_response(void) { blob_db2_protocol_msg_callback(NULL, s_sync_done_response, sizeof(s_sync_done_response)); // We currently don't do anything with this message } const uint8_t INVALID_CMD = 123; static const uint8_t s_invalid_cmd[] = { INVALID_CMD, // invalid cmd 0x56, 0x78, // token BLOB_DB_SUCCESS, // response }; static const uint8_t s_invalid_cmd_response[] = { INVALID_CMD | RESPONSE_MASK, // cmd 0x56, 0x78, // token BLOB_DB_INVALID_OPERATION, // status }; void test_blob_db2_endpoint__handle_unknown_cmd_id(void) { s_expected_msg = s_invalid_cmd_response; blob_db2_protocol_msg_callback(NULL, s_invalid_cmd, sizeof(s_invalid_cmd)); } static const uint8_t s_sync_done_message[] = { BLOB_DB_COMMAND_SYNC_DONE, // cmd 0x22, 0x00, // token BlobDBIdiOSNotifPref, // db id }; void test_blob_db2_endpoint__send_sync_done(void) { s_expected_msg = s_sync_done_message; blob_db_endpoint_send_sync_done(BlobDBIdiOSNotifPref); } static const time_t last_updated = 1; static const uint8_t key = 9; static const uint8_t val = 2; static const uint8_t s_writeback_message[] = { BLOB_DB_COMMAND_WRITEBACK, // cmd 0x22, 0x00, // token BlobDBIdiOSNotifPref, // db id 0x01, 0x00, 0x00, 0x00, // last updated 0x01, // key_len key, // key 0x01, 0x00, // val_len val, // val }; void test_blob_db2_endpoint__send_writeback(void) { s_expected_msg = s_writeback_message; blob_db_endpoint_send_writeback(BlobDBIdiOSNotifPref, last_updated, &key, 1, &val, 1); } static const uint8_t s_write_message[] = { BLOB_DB_COMMAND_WRITE, // cmd 0x22, 0x00, // token BlobDBIdiOSNotifPref, // db id 0x01, 0x00, 0x00, 0x00, // last updated 0x01, // key_len key, // key 0x01, 0x00, // val_len val, // val }; void test_blob_db2_endpoint__send_write(void) { s_expected_msg = s_write_message; blob_db_endpoint_send_write(BlobDBIdiOSNotifPref, last_updated, &key, 1, &val, 1); }