mirror of
https://github.com/google/pebble.git
synced 2025-11-23 16:01:02 -05:00
Import of the watch repository from Pebble
This commit is contained in:
356
tests/fw/services/app_message/test_app_message_receiver.c
Normal file
356
tests/fw/services/app_message/test_app_message_receiver.c
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* 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/app_inbox.h"
|
||||
#include "applib/app_message/app_message_internal.h"
|
||||
#include "applib/app_message/app_message_receiver.h"
|
||||
#include "comm/bt_conn_mgr.h"
|
||||
#include "services/common/comm_session/session_receive_router.h"
|
||||
#include "kernel/events.h"
|
||||
#include "process_management/app_install_types.h"
|
||||
|
||||
extern const ReceiverImplementation g_app_message_receiver_implementation;
|
||||
|
||||
static const ReceiverImplementation *s_rcv_imp = &g_app_message_receiver_implementation;
|
||||
|
||||
#define MAX_HEADER_SIZE (sizeof(AppMessageHeader))
|
||||
#define BUFFER_SIZE (sizeof(AppMessagePush))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Fakes & Stubs
|
||||
|
||||
#include "fake_kernel_malloc.h"
|
||||
#include "fake_system_task.h"
|
||||
|
||||
#include "stubs_analytics.h"
|
||||
#include "stubs_logging.h"
|
||||
#include "stubs_mutex.h"
|
||||
#include "stubs_passert.h"
|
||||
#include "stubs_syscall_internal.h"
|
||||
|
||||
bool process_manager_send_event_to_process(PebbleTask task, PebbleEvent* e) {
|
||||
cl_assert_equal_i(PEBBLE_CALLBACK_EVENT, e->type);
|
||||
|
||||
// Use fake_system_task as mock implementation:
|
||||
system_task_add_callback(e->callback.callback, e->callback.data);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void prv_process_events(void) {
|
||||
fake_system_task_callbacks_invoke_pending();
|
||||
}
|
||||
|
||||
static AppInbox *s_app_message_inbox;
|
||||
AppInbox **app_state_get_app_message_inbox(void) {
|
||||
return &s_app_message_inbox;
|
||||
}
|
||||
|
||||
static bool s_communication_timestamp_updated;
|
||||
void app_install_mark_prioritized(AppInstallId install_id, bool can_expire) {
|
||||
s_communication_timestamp_updated = true;
|
||||
}
|
||||
|
||||
AppInstallId app_manager_get_current_app_id(void) {
|
||||
return INSTALL_ID_INVALID;
|
||||
}
|
||||
|
||||
static uint8_t s_app_message_pp_buffer[BUFFER_SIZE];
|
||||
static size_t s_app_message_pp_received_length;
|
||||
|
||||
void app_message_app_protocol_msg_callback(CommSession *session,
|
||||
const uint8_t* data, size_t length,
|
||||
AppInboxConsumerInfo *consumer_info) {
|
||||
cl_assert(length <= BUFFER_SIZE);
|
||||
memcpy(s_app_message_pp_buffer, data, length);
|
||||
s_app_message_pp_received_length = length;
|
||||
}
|
||||
|
||||
static void prv_protocol_msg_callback(CommSession *session,
|
||||
const uint8_t* data, size_t length) {
|
||||
app_message_app_protocol_msg_callback(session, data, length, NULL);
|
||||
}
|
||||
|
||||
void app_message_inbox_handle_dropped_messages(uint32_t num_drops) {
|
||||
}
|
||||
|
||||
void comm_session_set_responsiveness(CommSession *session, BtConsumer consumer,
|
||||
ResponseTimeState state, uint16_t max_period_secs) {
|
||||
}
|
||||
|
||||
static bool s_kernel_receiver_available;
|
||||
static Receiver *s_kernel_receiver;
|
||||
static bool s_kernel_receiver_is_receiving;
|
||||
static uint8_t s_kernel_receiver_buffer[MAX_HEADER_SIZE];
|
||||
static off_t s_kernel_receiver_buffer_idx;
|
||||
static bool s_kernel_receiver_finish_called;
|
||||
static bool s_kernel_receiver_cleanup_called;
|
||||
|
||||
static Receiver *prv_default_kernel_receiver_prepare(CommSession *session,
|
||||
const PebbleProtocolEndpoint *endpoint,
|
||||
size_t total_payload_size) {
|
||||
if (!s_kernel_receiver_available) {
|
||||
return NULL;
|
||||
}
|
||||
s_kernel_receiver_is_receiving = true;
|
||||
cl_assert_equal_p(endpoint->handler, app_message_app_protocol_system_nack_callback);
|
||||
cl_assert(total_payload_size <= MAX_HEADER_SIZE);
|
||||
return s_kernel_receiver;
|
||||
}
|
||||
|
||||
static void prv_default_kernel_receiver_write(Receiver *receiver,
|
||||
const uint8_t *data, size_t length) {
|
||||
cl_assert_equal_p(receiver, s_kernel_receiver);
|
||||
memcpy(s_kernel_receiver_buffer + s_kernel_receiver_buffer_idx, data, length);
|
||||
s_kernel_receiver_buffer_idx += length;
|
||||
cl_assert(s_kernel_receiver_buffer_idx <= MAX_HEADER_SIZE);
|
||||
}
|
||||
|
||||
static void prv_default_kernel_receiver_finish(Receiver *receiver) {
|
||||
cl_assert_equal_p(receiver, s_kernel_receiver);
|
||||
s_kernel_receiver_is_receiving = false;
|
||||
s_kernel_receiver_finish_called = true;
|
||||
}
|
||||
|
||||
static void prv_default_kernel_receiver_cleanup(Receiver *receiver) {
|
||||
cl_assert_equal_p(receiver, s_kernel_receiver);
|
||||
s_kernel_receiver_is_receiving = false;
|
||||
s_kernel_receiver_cleanup_called = true;
|
||||
}
|
||||
|
||||
const ReceiverImplementation g_default_kernel_receiver_implementation = {
|
||||
.prepare = prv_default_kernel_receiver_prepare,
|
||||
.write = prv_default_kernel_receiver_write,
|
||||
.finish = prv_default_kernel_receiver_finish,
|
||||
.cleanup = prv_default_kernel_receiver_cleanup,
|
||||
};
|
||||
|
||||
void app_message_app_protocol_system_nack_callback(CommSession *session,
|
||||
const uint8_t* data, size_t length) {
|
||||
}
|
||||
void test_dropped_handler(uint32_t num_dropped_messages) {}
|
||||
void test_message_handler(const uint8_t *data, size_t length,
|
||||
AppInboxConsumerInfo *consumer_info) {}
|
||||
void test_alt_message_handler(const uint8_t *data, size_t length,
|
||||
AppInboxConsumerInfo *consumer_info) {}
|
||||
void test_alt_dropped_handler(uint32_t num_dropped_messages) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tests
|
||||
|
||||
static CommSession *s_session = (CommSession *)0xaabbccdd;
|
||||
|
||||
void test_app_message_receiver__initialize(void) {
|
||||
s_kernel_receiver_available = true;
|
||||
s_kernel_receiver = (Receiver *)0xffaaffaa;
|
||||
s_kernel_receiver_is_receiving = false;
|
||||
s_kernel_receiver_finish_called = false;
|
||||
s_kernel_receiver_cleanup_called = false;
|
||||
s_kernel_receiver_buffer_idx = 0;
|
||||
memset(s_kernel_receiver_buffer, 0, sizeof(s_kernel_receiver_buffer));
|
||||
s_app_message_pp_received_length = 0;
|
||||
memset(s_app_message_pp_buffer, 0, sizeof(s_app_message_pp_buffer));
|
||||
fake_kernel_malloc_init();
|
||||
fake_kernel_malloc_enable_stats(true);
|
||||
s_communication_timestamp_updated = false;
|
||||
}
|
||||
|
||||
void test_app_message_receiver__cleanup(void) {
|
||||
fake_system_task_callbacks_cleanup();
|
||||
fake_kernel_malloc_deinit();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Forwarding to default system receiver to nack the message
|
||||
|
||||
static const AppMessagePush s_push = {
|
||||
.header = {
|
||||
.command = CMD_PUSH,
|
||||
.transaction_id = 0xa5,
|
||||
},
|
||||
};
|
||||
|
||||
static const PebbleProtocolEndpoint s_app_message_endpoint = (const PebbleProtocolEndpoint) {
|
||||
.endpoint_id = APP_MESSAGE_ENDPOINT_ID,
|
||||
.handler = prv_protocol_msg_callback,
|
||||
.access_mask = PebbleProtocolAccessAny,
|
||||
.receiver_imp = &g_app_message_receiver_implementation,
|
||||
.receiver_opt = NULL,
|
||||
};
|
||||
|
||||
void test_app_message_receiver__receive_push_but_inbox_not_opened(void) {
|
||||
Receiver *r = s_rcv_imp->prepare(s_session, &s_app_message_endpoint,
|
||||
sizeof(AppMessagePush));
|
||||
cl_assert(r != NULL);
|
||||
cl_assert_equal_b(true, s_kernel_receiver_is_receiving);
|
||||
|
||||
s_rcv_imp->write(r, (const uint8_t *)&s_push, sizeof(s_push));
|
||||
|
||||
// Expect only up to MAX_HEADER_SIZE bytes has been written:
|
||||
cl_assert_equal_i(s_kernel_receiver_buffer_idx, MAX_HEADER_SIZE);
|
||||
// Check that the header is received correctly:
|
||||
cl_assert_equal_m(s_kernel_receiver_buffer, &s_push, MAX_HEADER_SIZE);
|
||||
|
||||
s_rcv_imp->finish(r);
|
||||
prv_process_events();
|
||||
cl_assert_equal_b(false, s_kernel_receiver_is_receiving);
|
||||
cl_assert_equal_b(true, s_kernel_receiver_finish_called);
|
||||
}
|
||||
|
||||
void test_app_message_receiver__receive_push_but_inbox_not_opened_then_cleanup(void) {
|
||||
Receiver *r = s_rcv_imp->prepare(s_session, &s_app_message_endpoint,
|
||||
sizeof(AppMessagePush));
|
||||
s_rcv_imp->write(r, (const uint8_t *)&s_push, sizeof(s_push));
|
||||
|
||||
s_rcv_imp->cleanup(r);
|
||||
cl_assert_equal_b(false, s_kernel_receiver_is_receiving);
|
||||
cl_assert_equal_b(true, s_kernel_receiver_cleanup_called);
|
||||
}
|
||||
|
||||
void test_app_message_receiver__receive_push_but_inbox_not_opened_kernel_oom(void) {
|
||||
fake_kernel_malloc_set_largest_free_block(0);
|
||||
|
||||
Receiver *r = s_rcv_imp->prepare(s_session, &s_app_message_endpoint,
|
||||
sizeof(AppMessagePush));
|
||||
cl_assert_equal_p(r, NULL);
|
||||
cl_assert_equal_b(false, s_kernel_receiver_is_receiving);
|
||||
}
|
||||
|
||||
void test_app_message_receiver__receive_push_but_inbox_not_opened_no_kernel_receiver(void) {
|
||||
fake_kernel_malloc_mark();
|
||||
s_kernel_receiver_available = false;
|
||||
Receiver *r = s_rcv_imp->prepare(s_session, &s_app_message_endpoint,
|
||||
sizeof(AppMessagePush));
|
||||
cl_assert_equal_p(r, NULL);
|
||||
cl_assert_equal_b(false, s_kernel_receiver_is_receiving);
|
||||
fake_kernel_malloc_mark_assert_equal();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Normal flow: writing message to app message inbox
|
||||
|
||||
static Receiver *prv_create_inbox_prepare_and_write(void) {
|
||||
cl_assert_equal_b(true, app_message_receiver_open(sizeof(AppMessagePush)));
|
||||
Receiver *r = s_rcv_imp->prepare(s_session, &s_app_message_endpoint,
|
||||
sizeof(AppMessagePush));
|
||||
cl_assert(r != NULL);
|
||||
|
||||
s_rcv_imp->write(r, (const uint8_t *)&s_push, sizeof(s_push));
|
||||
return r;
|
||||
}
|
||||
|
||||
static void prv_destroy_inbox(void) {
|
||||
app_message_receiver_close();
|
||||
}
|
||||
|
||||
void test_app_message_receiver__receive_push(void) {
|
||||
Receiver *r = prv_create_inbox_prepare_and_write();
|
||||
|
||||
s_rcv_imp->finish(r);
|
||||
prv_process_events();
|
||||
cl_assert_equal_b(false, s_kernel_receiver_is_receiving);
|
||||
cl_assert_equal_b(false, s_kernel_receiver_finish_called);
|
||||
|
||||
cl_assert_equal_m(&s_push, s_app_message_pp_buffer, sizeof(s_push));
|
||||
cl_assert_equal_i(s_app_message_pp_received_length, sizeof(s_push));
|
||||
|
||||
cl_assert_equal_b(true, s_communication_timestamp_updated);
|
||||
|
||||
prv_destroy_inbox();
|
||||
}
|
||||
|
||||
void test_app_message_receiver__receive_push_then_cleanup(void) {
|
||||
Receiver *r = prv_create_inbox_prepare_and_write();
|
||||
|
||||
s_rcv_imp->cleanup(r);
|
||||
cl_assert_equal_b(false, s_kernel_receiver_is_receiving);
|
||||
cl_assert_equal_b(false, s_kernel_receiver_finish_called);
|
||||
|
||||
cl_assert_equal_i(s_app_message_pp_received_length, 0);
|
||||
|
||||
cl_assert_equal_b(true, s_communication_timestamp_updated);
|
||||
|
||||
prv_destroy_inbox();
|
||||
}
|
||||
|
||||
void test_app_message_receiver__receive_push_buffer_overflow(void) {
|
||||
cl_assert_equal_b(true, app_message_receiver_open(sizeof(AppMessagePush)));
|
||||
// Write an ACK, we should be able to fit one (N)ACK in addition to the Push message:
|
||||
AppMessageAck ack = {};
|
||||
Receiver *r = s_rcv_imp->prepare(s_session, &s_app_message_endpoint,
|
||||
sizeof(ack));
|
||||
cl_assert(r != NULL);
|
||||
s_rcv_imp->write(r, (const uint8_t *)&ack, sizeof(ack));
|
||||
s_rcv_imp->finish(r);
|
||||
|
||||
cl_assert_equal_b(false, s_kernel_receiver_finish_called);
|
||||
cl_assert_equal_b(true, s_kernel_receiver_cleanup_called);
|
||||
s_app_message_pp_received_length = 0;
|
||||
s_kernel_receiver_buffer_idx = 0;
|
||||
|
||||
// Write a Push:
|
||||
r = s_rcv_imp->prepare(s_session, &s_app_message_endpoint,
|
||||
sizeof(AppMessagePush));
|
||||
cl_assert(r != NULL);
|
||||
s_rcv_imp->write(r, (const uint8_t *)&s_push, sizeof(s_push));
|
||||
|
||||
// Write some more, doesn't fit in the buffer:
|
||||
s_rcv_imp->write(r, (const uint8_t *)&s_push, sizeof(s_push));
|
||||
s_rcv_imp->finish(r);
|
||||
|
||||
prv_process_events();
|
||||
|
||||
// Header fwd to default system receiver should have finished, so it can be nacked:
|
||||
cl_assert_equal_b(true, s_kernel_receiver_finish_called);
|
||||
|
||||
// Only Ack is received:
|
||||
cl_assert_equal_i(s_app_message_pp_received_length, sizeof(AppMessageAck));
|
||||
prv_destroy_inbox();
|
||||
}
|
||||
|
||||
// Covers race as described here: PBL-41464
|
||||
// 1. A part of a big app message is being received, causing it to get received in chunks.
|
||||
// It's not received completely yet.
|
||||
// 2. app_message_outbox_closed is called.
|
||||
// 3. app_message_outbox_open is called, resetting the receiver state.
|
||||
// 4. Next chunk comes in. We used to assert: the "writer" (receiver state) was not NULL.
|
||||
// Fix: just eat the message and fail the app message by letting the KernelReceiver NACK it.
|
||||
void test_app_message_receiver__receive_multi_chunk_push_while_open_close_toggle(void) {
|
||||
cl_assert_equal_b(true, app_message_receiver_open(sizeof(AppMessagePush)));
|
||||
|
||||
Receiver *r = s_rcv_imp->prepare(s_session, &s_app_message_endpoint,
|
||||
sizeof(AppMessagePush));
|
||||
cl_assert(r != NULL);
|
||||
|
||||
// Receive only first byte of the push message:
|
||||
s_rcv_imp->write(r, (const uint8_t *)&s_push, 1);
|
||||
|
||||
// Close app message and open again:
|
||||
app_message_receiver_close();
|
||||
cl_assert_equal_b(true, app_message_receiver_open(sizeof(AppMessagePush)));
|
||||
|
||||
// Receive the remainder of the push message:
|
||||
s_rcv_imp->write(r, ((const uint8_t *)&s_push) + 1, sizeof(s_push) - 1);
|
||||
s_rcv_imp->finish(r);
|
||||
|
||||
// Header fwd to default system receiver should have finished, so it can be nacked:
|
||||
prv_process_events();
|
||||
cl_assert_equal_b(false, s_kernel_receiver_is_receiving);
|
||||
cl_assert_equal_b(true, s_kernel_receiver_finish_called);
|
||||
|
||||
prv_destroy_inbox();
|
||||
}
|
||||
427
tests/fw/services/app_message/test_app_message_sender.c
Normal file
427
tests/fw/services/app_message/test_app_message_sender.c
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* 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 "applib/app_message/app_message_internal.h"
|
||||
#include "clar.h"
|
||||
#include "services/normal/app_message/app_message_sender.h"
|
||||
#include "services/common/comm_session/session_internal.h"
|
||||
#include "services/common/comm_session/protocol.h"
|
||||
#include "services/common/comm_session/session.h"
|
||||
#include "process_management/app_install_manager.h"
|
||||
#include "services/normal/app_outbox_service.h"
|
||||
#include "util/math.h"
|
||||
#include "util/net.h"
|
||||
|
||||
extern const SessionSendJobImpl s_app_message_send_job_impl;
|
||||
extern void comm_session_send_queue_cleanup(CommSession *session);
|
||||
|
||||
// Fakes & Stubs
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stubs_analytics.h"
|
||||
#include "stubs_bt_lock.h"
|
||||
#include "stubs_logging.h"
|
||||
#include "stubs_passert.h"
|
||||
#include "stubs_pbl_malloc.h"
|
||||
|
||||
static int s_app_install_timestamp_update_count;
|
||||
void app_install_mark_prioritized(AppInstallId install_id, bool can_expire) {
|
||||
++s_app_install_timestamp_update_count;
|
||||
}
|
||||
|
||||
AppInstallId app_manager_get_current_app_id(void) {
|
||||
return INSTALL_ID_INVALID;
|
||||
}
|
||||
|
||||
static PebbleProcessMd s_process_md;
|
||||
const PebbleProcessMd* app_manager_get_current_app_md(void) {
|
||||
return &s_process_md;
|
||||
}
|
||||
|
||||
static int s_consumed_count;
|
||||
static AppOutboxStatus s_last_status_code;
|
||||
void app_outbox_service_consume_message(AppOutboxMessage *message, AppOutboxStatus status) {
|
||||
s_last_status_code = status;
|
||||
++s_consumed_count;
|
||||
kernel_free(message);
|
||||
}
|
||||
|
||||
static AppOutboxMessageHandler s_outbox_message_handler;
|
||||
static size_t s_service_data_size;
|
||||
void app_outbox_service_register(AppOutboxServiceTag service_tag,
|
||||
AppOutboxMessageHandler message_handler,
|
||||
PebbleTask consumer_task,
|
||||
size_t service_data_size) {
|
||||
s_outbox_message_handler = message_handler;
|
||||
s_service_data_size = service_data_size;
|
||||
}
|
||||
|
||||
static bool s_is_message_cancelled;
|
||||
bool app_outbox_service_is_message_cancelled(AppOutboxMessage *message) {
|
||||
return s_is_message_cancelled;
|
||||
}
|
||||
|
||||
void app_outbox_service_cleanup_all_pending_messages(void) {
|
||||
s_is_message_cancelled = true;
|
||||
}
|
||||
|
||||
void comm_session_analytics_inc_bytes_sent(CommSession *session, uint16_t length) {
|
||||
}
|
||||
|
||||
static CommSession s_system_session;
|
||||
static CommSession *s_system_session_ptr;
|
||||
CommSession *comm_session_get_system_session(void) {
|
||||
return s_system_session_ptr;
|
||||
}
|
||||
|
||||
static CommSession s_app_session;
|
||||
static CommSession *s_app_session_ptr;
|
||||
CommSession *comm_session_get_current_app_session(void) {
|
||||
if (s_process_md.allow_js) {
|
||||
return comm_session_get_system_session();
|
||||
}
|
||||
return s_app_session_ptr;
|
||||
}
|
||||
|
||||
bool comm_session_is_valid(const CommSession *session) {
|
||||
if (!session) {
|
||||
return false;
|
||||
}
|
||||
return (session == comm_session_get_current_app_session() ||
|
||||
session == comm_session_get_system_session());
|
||||
}
|
||||
|
||||
static int s_send_next_count = 0;
|
||||
void comm_session_send_next(CommSession *session) {
|
||||
++s_send_next_count;
|
||||
}
|
||||
|
||||
void comm_session_set_responsiveness(CommSession *session, BtConsumer consumer,
|
||||
ResponseTimeState state, uint16_t max_period_secs) {
|
||||
}
|
||||
|
||||
void comm_session_sanitize_app_session(CommSession **session_in_out) {
|
||||
CommSession *permitted_session = comm_session_get_current_app_session();
|
||||
*session_in_out = ((!*session_in_out) ||
|
||||
(*session_in_out == permitted_session)) ? permitted_session : NULL;
|
||||
}
|
||||
|
||||
// Helpers
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void prv_send_outbox_raw_data(const uint8_t *data, size_t length) {
|
||||
AppOutboxMessage *outbox_message = kernel_zalloc(sizeof(AppOutboxMessage) + s_service_data_size);
|
||||
cl_assert(outbox_message);
|
||||
outbox_message->data = data;
|
||||
outbox_message->length = length;
|
||||
s_outbox_message_handler(outbox_message);
|
||||
}
|
||||
|
||||
static AppMessageAppOutboxData *prv_create_and_send_outbox_message(CommSession *session,
|
||||
uint16_t endpoint_id,
|
||||
const uint8_t *payload,
|
||||
size_t payload_length) {
|
||||
const size_t outbox_data_size = sizeof(AppMessageAppOutboxData) + payload_length;
|
||||
AppMessageAppOutboxData *outbox_data = app_malloc(outbox_data_size);
|
||||
cl_assert(outbox_data);
|
||||
outbox_data->session = session;
|
||||
outbox_data->endpoint_id = endpoint_id;
|
||||
memcpy(outbox_data->payload, payload, payload_length);
|
||||
prv_send_outbox_raw_data((const uint8_t *)outbox_data, outbox_data_size);
|
||||
return outbox_data;
|
||||
}
|
||||
|
||||
static void prv_process_send_queue(CommSession *session) {
|
||||
cl_assert(session);
|
||||
size_t length = comm_session_send_queue_get_length(session);
|
||||
if (length) {
|
||||
comm_session_send_queue_consume(session, length);
|
||||
}
|
||||
}
|
||||
|
||||
#define assert_consumed(expected_last_status, expected_consumed_count) \
|
||||
{ \
|
||||
cl_assert_equal_i(expected_last_status, s_last_status_code); \
|
||||
cl_assert_equal_i(expected_consumed_count, s_consumed_count); \
|
||||
}
|
||||
|
||||
#define assert_not_consumed() \
|
||||
cl_assert_equal_i(0, s_consumed_count);
|
||||
|
||||
// Tests
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DISALLOWED_ENDPOINT_ID (9000) // GetBytes
|
||||
#define ALLOWED_ENDPOINT_ID (APP_MESSAGE_ENDPOINT_ID)
|
||||
|
||||
static const uint8_t TEST_PAYLOAD[] = {0xaa, 0xbb, 0xcc, 0xdd};
|
||||
static uint8_t TEST_EXPECTED_PP_MSG[sizeof(PebbleProtocolHeader) + sizeof(TEST_PAYLOAD)];
|
||||
|
||||
void test_app_message_sender__initialize(void) {
|
||||
s_system_session_ptr = &s_system_session;
|
||||
s_app_session_ptr = &s_app_session;
|
||||
s_send_next_count = 0;
|
||||
|
||||
s_outbox_message_handler = NULL;
|
||||
s_service_data_size = 0;
|
||||
|
||||
s_is_message_cancelled = false;
|
||||
|
||||
s_last_status_code = AppOutboxStatusUserRangeEnd;
|
||||
s_consumed_count = 0;
|
||||
|
||||
s_app_install_timestamp_update_count = 0;
|
||||
|
||||
s_process_md.allow_js = false;
|
||||
|
||||
PebbleProtocolHeader *header = (PebbleProtocolHeader *)TEST_EXPECTED_PP_MSG;
|
||||
header->length = htons(sizeof(TEST_PAYLOAD));
|
||||
header->endpoint_id = htons(ALLOWED_ENDPOINT_ID);
|
||||
memcpy(TEST_EXPECTED_PP_MSG + sizeof(*header), TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
|
||||
app_message_sender_init();
|
||||
cl_assert(s_outbox_message_handler);
|
||||
}
|
||||
|
||||
void test_app_message_sender__cleanup(void) {
|
||||
// Flush out to avoid other tests failing:
|
||||
if (s_system_session_ptr) {
|
||||
prv_process_send_queue(s_system_session_ptr);
|
||||
}
|
||||
if (s_app_session_ptr) {
|
||||
prv_process_send_queue(s_app_session_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that exercise the sanity checking of the input from the app
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void test_app_message_sender__outbox_data_too_short(void) {
|
||||
// This is one byte too small, because the PP payload has to be at least one in length:
|
||||
AppMessageAppOutboxData data = {};
|
||||
prv_send_outbox_raw_data((const uint8_t *)&data, sizeof(data));
|
||||
assert_consumed(AppMessageSenderErrorDataTooShort, 1);
|
||||
}
|
||||
|
||||
void test_app_message_sender__disallowed_endpoint(void) {
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(s_system_session_ptr, DISALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
assert_consumed(AppMessageSenderErrorEndpointDisallowed, 1);
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__system_session_but_not_js_app(void) {
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(s_system_session_ptr, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
assert_consumed(AppMessageSenderErrorDisconnected, 1);
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__app_session_but_js_app(void) {
|
||||
s_process_md.allow_js = true;
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(s_app_session_ptr, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
assert_consumed(AppMessageSenderErrorDisconnected, 1);
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__no_sessions_connected(void) {
|
||||
s_system_session_ptr = NULL;
|
||||
s_app_session_ptr = NULL;
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(NULL /* auto-select */, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
assert_consumed(AppMessageSenderErrorDisconnected, 1);
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__auto_select_not_js_app(void) {
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(NULL /* auto-select */, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
prv_process_send_queue(s_system_session_ptr);
|
||||
assert_not_consumed();
|
||||
|
||||
prv_process_send_queue(s_app_session_ptr);
|
||||
assert_consumed(AppMessageSenderErrorSuccess, 1);
|
||||
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__auto_select_js_app(void) {
|
||||
s_process_md.allow_js = true;
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(NULL /* auto-select */, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
prv_process_send_queue(s_app_session_ptr);
|
||||
assert_not_consumed();
|
||||
|
||||
prv_process_send_queue(s_system_session_ptr);
|
||||
assert_consumed(AppMessageSenderErrorSuccess, 1);
|
||||
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__system_session_and_js_app(void) {
|
||||
s_process_md.allow_js = true;
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(s_system_session_ptr, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
assert_not_consumed();
|
||||
prv_process_send_queue(s_system_session_ptr);
|
||||
assert_consumed(AppMessageSenderErrorSuccess, 1);
|
||||
cl_assert_equal_i(s_app_install_timestamp_update_count, 1);
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
// Tests that exercise interface towards the Send Queue
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void test_app_message_sender__freed_but_not_sent_entirely(void) {
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(NULL /* auto-select */, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
size_t length = comm_session_send_queue_get_length(s_app_session_ptr);
|
||||
comm_session_send_queue_consume(s_app_session_ptr, length - 1);
|
||||
comm_session_send_queue_cleanup(s_app_session_ptr);
|
||||
assert_consumed(AppMessageSenderErrorDisconnected, 1);
|
||||
cl_assert_equal_i(s_app_install_timestamp_update_count, 0);
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__byte_by_byte_consume(void) {
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(NULL /* auto-select */, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
size_t length = comm_session_send_queue_get_length(s_app_session_ptr);
|
||||
cl_assert_equal_i(length, sizeof(PebbleProtocolHeader) + sizeof(TEST_PAYLOAD));
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
// Test the `length` implementation:
|
||||
cl_assert_equal_i(length - i, comm_session_send_queue_get_length(s_app_session_ptr));
|
||||
|
||||
// Test the `read_pointer` implementation:
|
||||
const uint8_t *read_pointer = NULL;
|
||||
size_t length_available = comm_session_send_queue_get_read_pointer(s_app_session_ptr,
|
||||
&read_pointer);
|
||||
cl_assert(read_pointer);
|
||||
cl_assert_equal_i(TEST_EXPECTED_PP_MSG[i], *read_pointer);
|
||||
// Expect that the header and payload will be non-contiguous:
|
||||
if (i < sizeof(PebbleProtocolHeader)) {
|
||||
cl_assert_equal_i(sizeof(PebbleProtocolHeader) - i, length_available);
|
||||
} else {
|
||||
cl_assert_equal_i(length - i, length_available);
|
||||
}
|
||||
|
||||
// Test the `copy` implementation:
|
||||
uint8_t byte_out = 0xff;
|
||||
cl_assert_equal_i(1, comm_session_send_queue_copy(s_app_session_ptr, 0 /* offset */,
|
||||
1 /* length */, &byte_out));
|
||||
cl_assert_equal_i(TEST_EXPECTED_PP_MSG[i], byte_out);
|
||||
|
||||
comm_session_send_queue_consume(s_app_session_ptr, 1 /* length */);
|
||||
}
|
||||
|
||||
assert_consumed(AppMessageSenderErrorSuccess, 1);
|
||||
cl_assert_equal_i(s_app_install_timestamp_update_count, 1);
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__byte_by_byte_copy_with_offset(void) {
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(NULL /* auto-select */, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
size_t length = comm_session_send_queue_get_length(s_app_session_ptr);
|
||||
cl_assert_equal_i(length, sizeof(PebbleProtocolHeader) + sizeof(TEST_PAYLOAD));
|
||||
|
||||
uint8_t bytes_out[length];
|
||||
memset(bytes_out, 0xff, length);
|
||||
|
||||
// Consume byte by byte:
|
||||
for (int c = 0; c < length; ++c) {
|
||||
// Shift offset byte by byte:
|
||||
for (int o = 0; o < (length - c); ++o) {
|
||||
size_t length_to_copy = (length - c - o);
|
||||
cl_assert_equal_i(length_to_copy, comm_session_send_queue_copy(s_app_session_ptr, o,
|
||||
length_to_copy, bytes_out));
|
||||
cl_assert_equal_i(0, memcmp(bytes_out, TEST_EXPECTED_PP_MSG + o + c, length_to_copy));
|
||||
}
|
||||
|
||||
comm_session_send_queue_consume(s_app_session_ptr, 1 /* length */);
|
||||
}
|
||||
|
||||
assert_consumed(AppMessageSenderErrorSuccess, 1);
|
||||
cl_assert_equal_i(s_app_install_timestamp_update_count, 1);
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
// Tests that deal with the edge case of app outbox messages getting cancelled,
|
||||
// because the app that provides the buffer for the payload is quit while they are in the
|
||||
// process of being sent out.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void prv_quit_app_after_pp_msg_byte(uint32_t num_bytes) {
|
||||
AppMessageAppOutboxData *outbox_data =
|
||||
prv_create_and_send_outbox_message(NULL /* auto-select */, ALLOWED_ENDPOINT_ID,
|
||||
TEST_PAYLOAD, sizeof(TEST_PAYLOAD));
|
||||
|
||||
size_t length = comm_session_send_queue_get_length(s_app_session_ptr);
|
||||
uint8_t bytes_out[length];
|
||||
memset(bytes_out, 0xff, length);
|
||||
|
||||
// Copy & consume one byte of the header -- note the header is 4 bytes total:
|
||||
size_t first_length = num_bytes;
|
||||
cl_assert_equal_i(first_length, comm_session_send_queue_copy(s_app_session_ptr, 0,
|
||||
first_length, bytes_out));
|
||||
comm_session_send_queue_consume(s_app_session_ptr, first_length);
|
||||
|
||||
// App quits with only one header byte consumed:
|
||||
app_outbox_service_cleanup_all_pending_messages();
|
||||
|
||||
// Copy & consume the rest:
|
||||
size_t second_length = (length - first_length);
|
||||
cl_assert_equal_i(second_length, comm_session_send_queue_copy(s_app_session_ptr, 0,
|
||||
second_length,
|
||||
bytes_out + first_length));
|
||||
comm_session_send_queue_consume(s_app_session_ptr, second_length);
|
||||
|
||||
// The message should be consumed now (to free the resources associated with it):
|
||||
assert_consumed(AppMessageSenderErrorSuccess, 1);
|
||||
|
||||
// Expect at least the PebbleProtocol header or more to be intact:
|
||||
size_t intact_size = MAX(num_bytes, sizeof(PebbleProtocolHeader));
|
||||
cl_assert_equal_m(bytes_out, TEST_EXPECTED_PP_MSG, intact_size);
|
||||
|
||||
// Expect the remainder to be filled with zeroes:
|
||||
for (int i = 0; i < (length - intact_size); ++i) {
|
||||
cl_assert_equal_i(bytes_out[intact_size + i], 0x00);
|
||||
}
|
||||
|
||||
app_free(outbox_data);
|
||||
}
|
||||
|
||||
void test_app_message_sender__cancelled_message_in_flight_header_and_payload_not_finished(void) {
|
||||
// Expect header to get sent out normally, then a payload with all zeroes
|
||||
prv_quit_app_after_pp_msg_byte(sizeof(PebbleProtocolHeader) - 1);
|
||||
}
|
||||
|
||||
void test_app_message_sender__cancelled_message_in_flight_payload_not_finished(void) {
|
||||
// Expect remainder payload to be all zeroes
|
||||
prv_quit_app_after_pp_msg_byte(sizeof(PebbleProtocolHeader) + 1);
|
||||
}
|
||||
185
tests/fw/services/app_message/test_app_session_capabilities.c
Normal file
185
tests/fw/services/app_message/test_app_session_capabilities.c
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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/app_session_capabilities.h"
|
||||
#include "services/common/comm_session/session.h"
|
||||
#include "process_management/pebble_process_md.h"
|
||||
#include "services/normal/settings/settings_file.h"
|
||||
#include "system/status_codes.h"
|
||||
|
||||
static const CommSessionCapability s_live_capabilities = (CommSessionInfiniteLogDumping);
|
||||
|
||||
// Fakes & Stubs
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static PebbleProcessMd s_app_md;
|
||||
const PebbleProcessMd* app_manager_get_current_app_md(void) {
|
||||
return &s_app_md;
|
||||
}
|
||||
|
||||
CommSessionCapability comm_session_get_capabilities(CommSession *session) {
|
||||
if (!session) {
|
||||
return 0;
|
||||
}
|
||||
return s_live_capabilities;
|
||||
}
|
||||
|
||||
static CommSession *s_app_session_ptr;
|
||||
CommSession *comm_session_get_current_app_session(void) {
|
||||
return s_app_session_ptr;
|
||||
}
|
||||
|
||||
static bool s_close_called;
|
||||
void settings_file_close(SettingsFile *file) {
|
||||
s_close_called = true;
|
||||
}
|
||||
|
||||
static status_t s_open_status;
|
||||
status_t settings_file_open(SettingsFile *file, const char *name,
|
||||
int max_used_space) {
|
||||
return s_open_status;
|
||||
}
|
||||
|
||||
static bool s_has_cache;
|
||||
static bool s_get_called;
|
||||
static uint64_t s_get_value;
|
||||
status_t settings_file_get(SettingsFile *file, const void *key, size_t key_len,
|
||||
void *val_out, size_t val_out_len) {
|
||||
s_get_called = true;
|
||||
if (!s_has_cache) {
|
||||
return E_DOES_NOT_EXIST;
|
||||
}
|
||||
*((uint64_t *)val_out) = s_get_value;
|
||||
return S_SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t s_set_value;
|
||||
status_t settings_file_set(SettingsFile *file, const void *key, size_t key_len,
|
||||
const void *val, size_t val_len) {
|
||||
cl_assert_equal_i(val_len, sizeof(uint64_t));
|
||||
s_set_value = *(uint64_t *)val;
|
||||
return S_SUCCESS;
|
||||
}
|
||||
|
||||
status_t settings_file_delete(SettingsFile *file,
|
||||
const void *key, size_t key_len) {
|
||||
return S_SUCCESS;
|
||||
}
|
||||
|
||||
status_t settings_file_rewrite(SettingsFile *file,
|
||||
SettingsFileRewriteCallback cb, void *context) {
|
||||
return S_SUCCESS;
|
||||
}
|
||||
|
||||
// Helpers
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// Tests
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static CommSession *s_fake_app_session = (CommSession *)~0;
|
||||
static uint64_t s_unwritten_value = ~0;
|
||||
|
||||
void test_app_session_capabilities__initialize(void) {
|
||||
s_app_session_ptr = NULL;
|
||||
s_close_called = false;
|
||||
s_get_called = false;
|
||||
s_open_status = S_SUCCESS;
|
||||
s_get_value = 0;
|
||||
s_set_value = s_unwritten_value;
|
||||
s_has_cache = false;
|
||||
s_app_md = (PebbleProcessMd){};
|
||||
}
|
||||
|
||||
void test_app_session_capabilities__cleanup(void) {
|
||||
|
||||
}
|
||||
|
||||
void test_app_session_capabilities__no_cache_file_and_not_connected(void) {
|
||||
s_open_status = E_ERROR;
|
||||
bool has_cap =
|
||||
comm_session_current_app_session_cache_has_capability(CommSessionInfiniteLogDumping);
|
||||
cl_assert_equal_b(false, has_cap);
|
||||
cl_assert_equal_b(false, s_get_called);
|
||||
cl_assert_equal_b(false, s_close_called);
|
||||
}
|
||||
|
||||
void test_app_session_capabilities__no_cache_file_but_connected(void) {
|
||||
s_open_status = E_ERROR;
|
||||
s_app_session_ptr = s_fake_app_session;
|
||||
bool has_cap =
|
||||
comm_session_current_app_session_cache_has_capability(CommSessionInfiniteLogDumping);
|
||||
cl_assert_equal_b(true, has_cap);
|
||||
cl_assert_equal_b(false, s_get_called);
|
||||
cl_assert_equal_b(false, s_close_called);
|
||||
}
|
||||
|
||||
void test_app_session_capabilities__cache_file_and_not_connected(void) {
|
||||
s_has_cache = true;
|
||||
s_get_value = CommSessionInfiniteLogDumping;
|
||||
bool has_cap =
|
||||
comm_session_current_app_session_cache_has_capability(CommSessionInfiniteLogDumping);
|
||||
cl_assert_equal_b(true, has_cap);
|
||||
cl_assert_equal_b(true, s_get_called);
|
||||
cl_assert_equal_b(true, s_close_called);
|
||||
}
|
||||
|
||||
void test_app_session_capabilities__cache_file_but_no_key_and_not_connected(void) {
|
||||
bool has_cap =
|
||||
comm_session_current_app_session_cache_has_capability(CommSessionInfiniteLogDumping);
|
||||
cl_assert_equal_b(false, has_cap);
|
||||
cl_assert_equal_b(true, s_get_called);
|
||||
cl_assert_equal_b(true, s_close_called);
|
||||
}
|
||||
|
||||
void test_app_session_capabilities__cache_file_and_connected_new_value(void) {
|
||||
s_has_cache = true;
|
||||
s_get_value = CommSessionExtendedNotificationService;
|
||||
s_app_session_ptr = s_fake_app_session;
|
||||
|
||||
bool has_cap_infinite_log_dumping =
|
||||
comm_session_current_app_session_cache_has_capability(CommSessionInfiniteLogDumping);
|
||||
cl_assert_equal_b(true, has_cap_infinite_log_dumping);
|
||||
|
||||
bool has_ext_notifications =
|
||||
comm_session_current_app_session_cache_has_capability(CommSessionExtendedNotificationService);
|
||||
cl_assert_equal_b(false, has_ext_notifications);
|
||||
|
||||
// Check that cache is re-written:
|
||||
cl_assert_equal_i(s_set_value, s_live_capabilities);
|
||||
|
||||
cl_assert_equal_b(true, s_get_called);
|
||||
cl_assert_equal_b(true, s_close_called);
|
||||
}
|
||||
|
||||
void test_app_session_capabilities__cache_file_and_connected_same_value(void) {
|
||||
s_has_cache = true;
|
||||
s_get_value = CommSessionInfiniteLogDumping;
|
||||
s_app_session_ptr = s_fake_app_session;
|
||||
|
||||
bool has_cap_infinite_log_dumping =
|
||||
comm_session_current_app_session_cache_has_capability(CommSessionInfiniteLogDumping);
|
||||
cl_assert_equal_b(true, has_cap_infinite_log_dumping);
|
||||
|
||||
// Check that cache is NOT re-written:
|
||||
cl_assert_equal_i(s_set_value, s_unwritten_value);
|
||||
|
||||
cl_assert_equal_b(true, s_get_called);
|
||||
cl_assert_equal_b(true, s_close_called);
|
||||
}
|
||||
31
tests/fw/services/app_message/wscript
Normal file
31
tests/fw/services/app_message/wscript
Normal file
@@ -0,0 +1,31 @@
|
||||
from waftools.pebble_test import clar
|
||||
|
||||
|
||||
def build(bld):
|
||||
clar(bld,
|
||||
sources_ant_glob=(
|
||||
"src/fw/applib/app_inbox.c "
|
||||
"src/fw/applib/app_message/app_message_receiver.c "
|
||||
"src/fw/services/normal/app_message/app_message_receiver.c "
|
||||
"src/fw/services/normal/app_inbox_service.c "
|
||||
),
|
||||
test_sources_ant_glob="test_app_message_receiver.c",
|
||||
override_includes=['applib_malloc'])
|
||||
|
||||
clar(bld,
|
||||
sources_ant_glob=(
|
||||
"src/fw/services/normal/app_message/app_message_sender.c "
|
||||
"src/fw/services/common/comm_session/session_send_queue.c "
|
||||
),
|
||||
test_sources_ant_glob="test_app_message_sender.c",
|
||||
override_includes=[])
|
||||
|
||||
clar(bld,
|
||||
sources_ant_glob=(
|
||||
"src/fw/services/normal/comm_session/app_session_capabilities.c "
|
||||
),
|
||||
test_sources_ant_glob="test_app_session_capabilities.c",
|
||||
override_includes=[])
|
||||
|
||||
|
||||
# vim:filetype=python
|
||||
Reference in New Issue
Block a user