mirror of
https://github.com/google/pebble.git
synced 2025-03-22 11:42:19 +00:00
198 lines
5.9 KiB
C
198 lines
5.9 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 "applib/rockyjs/rocky_res.h"
|
|
#include "services/common/comm_session/session.h"
|
|
#include "services/normal/app_fetch_endpoint.h"
|
|
#include "system/logging.h"
|
|
#include "util/attributes.h"
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
// Fakes
|
|
////////////////////////////////////
|
|
#include "fake_events.h"
|
|
#include "fake_new_timer.h"
|
|
#include "fake_pbl_malloc.h"
|
|
#include "fake_session.h"
|
|
#include "fake_system_task.h"
|
|
|
|
// Stubs
|
|
////////////////////////////////////
|
|
#include "stubs_app_cache.h"
|
|
#include "stubs_bt_lock.h"
|
|
#include "stubs_hexdump.h"
|
|
#include "stubs_logging.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_rand_ptr.h"
|
|
#include "stubs_queue.h"
|
|
|
|
typedef struct {} EventServiceInfo;
|
|
|
|
void app_event_service_subscribe(EventServiceInfo * service_info) {
|
|
return;
|
|
}
|
|
|
|
void put_bytes_cancel(void) {
|
|
}
|
|
|
|
void put_bytes_expect_init(uint32_t timeout_ms) {
|
|
}
|
|
|
|
void app_storage_delete_bank(uint32_t bank) {
|
|
}
|
|
|
|
const PebbleProcessMd *app_install_get_md(AppInstallId id, bool worker) {
|
|
return NULL;
|
|
}
|
|
|
|
void app_install_release_md(const PebbleProcessMd *md) {
|
|
}
|
|
|
|
RockyResourceValidation s_rocky_app_validate_resources__result;
|
|
RockyResourceValidation rocky_app_validate_resources(const PebbleProcessMd *md) {
|
|
return s_rocky_app_validate_resources__result;
|
|
}
|
|
|
|
typedef struct PACKED {
|
|
uint16_t length;
|
|
uint16_t endpoint_id;
|
|
} PebbleProtocolHeader;
|
|
|
|
enum {
|
|
APP_FETCH_INSTALL_COMMAND = 0x01,
|
|
} AppFetchCommand;
|
|
|
|
enum {
|
|
APP_FETCH_INSTALL_RESPONSE = 0x01,
|
|
} AppFetchResponse;
|
|
|
|
typedef struct AppFetchData {
|
|
CommSession *session;
|
|
size_t length;
|
|
uint8_t data[];
|
|
} AppFetchData;
|
|
|
|
typedef struct PACKED {
|
|
uint8_t command;
|
|
Uuid uuid;
|
|
uint32_t app_id;
|
|
} AppFetchRequest;
|
|
|
|
extern void app_fetch_protocol_msg_callback(CommSession *session, const uint8_t* data, size_t length);
|
|
|
|
static const uint16_t APP_FETCH_ENDPOINT_ID = 6001;
|
|
|
|
static const uint32_t app_id_1 = 42;
|
|
static const Uuid uuid_1 = {0x6b, 0xf6, 0x21, 0x5b, 0xc9, 0x7f, 0x40, 0x9e,
|
|
0x8c, 0x31, 0x4f, 0x55, 0x65, 0x72, 0x22, 0xb4};
|
|
|
|
Transport *s_transport;
|
|
|
|
/* Start of test */
|
|
|
|
void test_app_fetch_endpoint__initialize(void) {
|
|
fake_comm_session_init();
|
|
s_transport = fake_transport_create(TransportDestinationSystem, NULL, NULL);
|
|
fake_transport_set_connected(s_transport, true /* connected */);
|
|
}
|
|
|
|
void test_app_fetch_endpoint__cleanup(void) {
|
|
fake_transport_destroy(s_transport);
|
|
s_transport = NULL;
|
|
fake_comm_session_cleanup();
|
|
fake_system_task_callbacks_cleanup();
|
|
}
|
|
|
|
/*************************************
|
|
* Checking for valid INSERT command *
|
|
*************************************/
|
|
|
|
static const uint8_t s_app_fetch_success[] = {
|
|
// Message Header
|
|
0x01, // APP_FETCH_INSTALL_RESPONSE
|
|
0x01, // ACK: 0x01
|
|
};
|
|
|
|
static void prv_check_valid_app_fetch_request(uint16_t endpoint_id, const uint8_t* data,
|
|
unsigned int data_length) {
|
|
|
|
// AppFetchRequest request = *(AppFetchRequest *)data;
|
|
PBL_LOG(LOG_LEVEL_DEBUG, "sizeof: %lu length: %u", sizeof(AppFetchRequest), data_length);
|
|
AppFetchRequest request = *(AppFetchRequest *)data;
|
|
|
|
cl_assert_equal_i(endpoint_id, APP_FETCH_ENDPOINT_ID);
|
|
cl_assert_equal_i(request.command, APP_FETCH_INSTALL_COMMAND);
|
|
cl_assert_equal_i(request.app_id, app_id_1);
|
|
cl_assert_equal_b(true, uuid_equal(&request.uuid, &uuid_1));
|
|
|
|
// if anything is planning on being done relating to this ACK, then it will be done after this
|
|
app_fetch_protocol_msg_callback(comm_session_get_system_session(),
|
|
s_app_fetch_success, sizeof(s_app_fetch_success));
|
|
}
|
|
|
|
void test_app_fetch_endpoint__app_fetch_binaries(void) {
|
|
// set the function that will validate the data in the send buffer
|
|
fake_transport_set_sent_cb(s_transport, prv_check_valid_app_fetch_request);
|
|
|
|
// queue of system task to send an app_fetch request
|
|
app_fetch_binaries(&uuid_1, app_id_1, 0);
|
|
|
|
// process system task events
|
|
fake_system_task_callbacks_invoke_pending();
|
|
fake_comm_session_process_send_next();
|
|
|
|
// if anything is planning on being done relating to the ACK sent back from phone,
|
|
// then it should be checked here.
|
|
}
|
|
|
|
static void prv_fetch_complete_app() {
|
|
app_fetch_binaries(&uuid_1, app_id_1, false);
|
|
app_fetch_put_bytes_event_handler(&(PebblePutBytesEvent){
|
|
.type = PebblePutBytesEventTypeCleanup,
|
|
.object_type = ObjectAppResources,
|
|
.has_cookie = true,
|
|
});
|
|
fake_system_task_callbacks_invoke_pending();
|
|
app_fetch_put_bytes_event_handler(&(PebblePutBytesEvent){
|
|
.type = PebblePutBytesEventTypeCleanup,
|
|
.object_type = ObjectWatchApp,
|
|
.has_cookie = true,
|
|
});
|
|
fake_system_task_callbacks_invoke_pending();
|
|
}
|
|
|
|
void test_app_fetch_endpoint__no_incompatible_js(void) {
|
|
s_rocky_app_validate_resources__result = RockyResourceValidation_Valid;
|
|
prv_fetch_complete_app();
|
|
|
|
const PebbleEvent e = fake_event_get_last();
|
|
cl_assert_equal_i(PEBBLE_APP_FETCH_EVENT, e.type);
|
|
cl_assert_equal_i(AppFetchEventTypeFinish, e.app_fetch.type);
|
|
}
|
|
|
|
void test_app_fetch_endpoint__incompatible_js(void) {
|
|
s_rocky_app_validate_resources__result = RockyResourceValidation_Invalid;
|
|
prv_fetch_complete_app();
|
|
|
|
const PebbleEvent e = fake_event_get_last();
|
|
cl_assert_equal_i(PEBBLE_APP_FETCH_EVENT, e.type);
|
|
cl_assert_equal_i(AppFetchEventTypeError, e.app_fetch.type);
|
|
cl_assert_equal_i(AppFetchResultIncompatibleJSFailure, e.app_fetch.error_code);
|
|
}
|