mirror of
https://github.com/google/pebble.git
synced 2025-05-22 03:14:52 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
386
tests/fw/applib/test_app_smartstrap.c
Normal file
386
tests/fw/applib/test_app_smartstrap.c
Normal file
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
* 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/event_service_client.h"
|
||||
#include "services/normal/accessory/smartstrap_attribute.h"
|
||||
#include "kernel/pbl_malloc.h"
|
||||
|
||||
#include "fake_smartstrap_profiles.h"
|
||||
#include "fake_smartstrap_state.h"
|
||||
#include "fake_system_task.h"
|
||||
|
||||
#include "stubs_app_state.h"
|
||||
#include "stubs_logging.h"
|
||||
#include "stubs_mutex.h"
|
||||
#include "stubs_passert.h"
|
||||
#include "stubs_pbl_malloc.h"
|
||||
#include "stubs_serial.h"
|
||||
|
||||
#define NON_NULL_MBUF ((MBuf *)1)
|
||||
#define assert_result_ok(result) cl_assert(result == SmartstrapResultOk)
|
||||
#define assert_result_invalid(result) cl_assert(result == SmartstrapResultInvalidArgs)
|
||||
#define assert_result_busy(result) cl_assert(result == SmartstrapResultBusy)
|
||||
|
||||
typedef void (*EventServiceEventHandler)(PebbleEvent *e, void *context);
|
||||
typedef struct {
|
||||
bool active;
|
||||
SmartstrapAttribute *attribute;
|
||||
size_t length;
|
||||
} PendingInfo;
|
||||
|
||||
static EventServiceEventHandler s_event_handler;
|
||||
static PendingInfo s_pending_did_read;
|
||||
static PendingInfo s_pending_did_write;
|
||||
static PendingInfo s_pending_notified;
|
||||
|
||||
|
||||
// Stubs / fakes
|
||||
|
||||
void event_service_client_subscribe(EventServiceInfo *info) {
|
||||
cl_assert(info->type == PEBBLE_SMARTSTRAP_EVENT);
|
||||
s_event_handler = info->handler;
|
||||
}
|
||||
|
||||
void event_service_client_unsubscribe(EventServiceInfo *info) {
|
||||
cl_assert(info->type == PEBBLE_SMARTSTRAP_EVENT);
|
||||
s_event_handler = NULL;
|
||||
}
|
||||
|
||||
bool process_manager_send_event_to_process(PebbleTask task, PebbleEvent *e) {
|
||||
cl_assert(task == PebbleTask_App);
|
||||
cl_assert(e->type == PEBBLE_SMARTSTRAP_EVENT);
|
||||
cl_assert(s_event_handler);
|
||||
s_event_handler(e, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void smartstrap_cancel_send(void) {
|
||||
}
|
||||
|
||||
|
||||
// Helper functions
|
||||
static void prv_prepare_for_did_read(SmartstrapAttribute *attribute, uint16_t read_length) {
|
||||
cl_assert(!s_pending_did_read.active);
|
||||
s_pending_did_read = (PendingInfo) {
|
||||
.active = true,
|
||||
.attribute = attribute,
|
||||
.length = read_length
|
||||
};
|
||||
}
|
||||
|
||||
static void prv_did_read_handler(SmartstrapAttribute *attribute, SmartstrapResult result,
|
||||
const uint8_t *data, size_t length) {
|
||||
cl_assert(data == (uint8_t *)attribute);
|
||||
cl_assert(result == SmartstrapResultOk);
|
||||
cl_assert(s_pending_did_read.active);
|
||||
cl_assert(s_pending_did_read.attribute == attribute);
|
||||
cl_assert(s_pending_did_read.length == length);
|
||||
s_pending_did_read.active = false;
|
||||
}
|
||||
|
||||
static void prv_prepare_for_did_write(SmartstrapAttribute *attribute) {
|
||||
cl_assert(!s_pending_did_write.active);
|
||||
s_pending_did_write = (PendingInfo) {
|
||||
.active = true,
|
||||
.attribute = attribute
|
||||
};
|
||||
}
|
||||
|
||||
static void prv_did_write_handler(SmartstrapAttribute *attribute, SmartstrapResult result) {
|
||||
cl_assert(result == SmartstrapResultOk);
|
||||
cl_assert(s_pending_did_write.active);
|
||||
cl_assert(s_pending_did_write.attribute == attribute);
|
||||
s_pending_did_write.active = false;
|
||||
}
|
||||
|
||||
static void prv_prepare_for_notified(SmartstrapAttribute *attribute) {
|
||||
cl_assert(!s_pending_notified.active);
|
||||
s_pending_notified = (PendingInfo) {
|
||||
.active = true,
|
||||
.attribute = attribute
|
||||
};
|
||||
}
|
||||
|
||||
static void prv_notified_handler(SmartstrapAttribute *attribute) {
|
||||
cl_assert(s_pending_notified.active);
|
||||
cl_assert(s_pending_notified.attribute == attribute);
|
||||
s_pending_notified.active = false;
|
||||
}
|
||||
|
||||
|
||||
// Setup
|
||||
|
||||
void test_app_smartstrap__initialize(void) {
|
||||
smartstrap_attribute_init();
|
||||
app_smartstrap_subscribe((SmartstrapHandlers) {
|
||||
.did_read = prv_did_read_handler,
|
||||
.did_write = prv_did_write_handler,
|
||||
.notified = prv_notified_handler
|
||||
});
|
||||
}
|
||||
|
||||
void test_app_smartstrap__cleanup(void) {
|
||||
}
|
||||
|
||||
|
||||
// Tests
|
||||
|
||||
void test_app_smartstrap__invalid_args(void) {
|
||||
// create test attribute
|
||||
SmartstrapAttribute *attr = app_smartstrap_attribute_create(0x1111, 0x2222, 100);
|
||||
|
||||
// smartstrap_attribute_create()
|
||||
cl_assert(app_smartstrap_attribute_create(0x1111, 0x2222, 0) == NULL);
|
||||
|
||||
// smartstrap_attribute_destroy()
|
||||
app_smartstrap_attribute_destroy(NULL);
|
||||
|
||||
// smartstrap_attribute_get_*_id()
|
||||
cl_assert(app_smartstrap_attribute_get_service_id(NULL) == 0);
|
||||
cl_assert(app_smartstrap_attribute_get_attribute_id(NULL) == 0);
|
||||
|
||||
// smartstrap_attribute_begin_write()
|
||||
uint8_t *buffer;
|
||||
size_t buffer_len;
|
||||
assert_result_invalid(app_smartstrap_attribute_begin_write(NULL, NULL, NULL));
|
||||
assert_result_invalid(app_smartstrap_attribute_begin_write(NULL, &buffer, NULL));
|
||||
assert_result_invalid(app_smartstrap_attribute_begin_write(NULL, NULL, &buffer_len));
|
||||
assert_result_invalid(app_smartstrap_attribute_begin_write(NULL, &buffer, &buffer_len));
|
||||
assert_result_invalid(app_smartstrap_attribute_begin_write(attr, NULL, NULL));
|
||||
assert_result_invalid(app_smartstrap_attribute_begin_write(attr, &buffer, NULL));
|
||||
assert_result_invalid(app_smartstrap_attribute_begin_write(attr, NULL, &buffer_len));
|
||||
|
||||
// smartstrap_attribute_end_write()
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(NULL, 0, false));
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(NULL, 0, true));
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(NULL, 100, false));
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(NULL, 100, true));
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(attr, 0, false));
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(attr, 0, true));
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(attr, 100, false));
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(attr, 100, true));
|
||||
|
||||
// smartstrap_attribute_read()
|
||||
assert_result_invalid(app_smartstrap_attribute_read(NULL));
|
||||
|
||||
// destroy test attribute
|
||||
app_smartstrap_attribute_destroy(attr);
|
||||
}
|
||||
|
||||
void test_app_smartstrap__check_ids(void) {
|
||||
// craete an attribute
|
||||
SmartstrapAttribute *attr = app_smartstrap_attribute_create(0x1111, 0x2222, 100);
|
||||
cl_assert(attr != NULL);
|
||||
|
||||
// verify the ids
|
||||
cl_assert(app_smartstrap_attribute_get_service_id(attr) == 0x1111);
|
||||
cl_assert(app_smartstrap_attribute_get_attribute_id(attr) == 0x2222);
|
||||
|
||||
// destroy the attribute
|
||||
app_smartstrap_attribute_destroy(attr);
|
||||
|
||||
// verify that we can no longer get the ids
|
||||
cl_assert(app_smartstrap_attribute_get_service_id(attr) == 0);
|
||||
cl_assert(app_smartstrap_attribute_get_attribute_id(attr) == 0);
|
||||
}
|
||||
|
||||
void test_app_smartstrap__create_duplicate(void) {
|
||||
// create the attribute once
|
||||
SmartstrapAttribute *attr = app_smartstrap_attribute_create(0x1111, 0x2222, 100);
|
||||
cl_assert(attr != NULL);
|
||||
|
||||
// try to create it again
|
||||
SmartstrapAttribute *attr_dup = app_smartstrap_attribute_create(0x1111, 0x2222, 100);
|
||||
cl_assert(attr_dup == NULL);
|
||||
|
||||
// destroy the attribute
|
||||
app_smartstrap_attribute_destroy(attr);
|
||||
|
||||
// destroy again (shouldn't do anything bad)
|
||||
app_smartstrap_attribute_destroy(attr);
|
||||
}
|
||||
|
||||
void test_app_smartstrap__read(void) {
|
||||
// create the attribute
|
||||
SmartstrapAttribute *attr = app_smartstrap_attribute_create(0x1111, 0x2222, 100);
|
||||
|
||||
// start a read request
|
||||
stub_pebble_tasks_set_current(PebbleTask_App);
|
||||
assert_result_ok(app_smartstrap_attribute_read(attr));
|
||||
|
||||
// attempt to issue another read request
|
||||
assert_result_busy(app_smartstrap_attribute_read(attr));
|
||||
|
||||
// trigger the read request to be sent and expect a did_write handler call
|
||||
stub_pebble_tasks_set_current(PebbleTask_KernelBackground);
|
||||
prv_prepare_for_did_write(attr);
|
||||
cl_assert(smartstrap_attribute_send_pending());
|
||||
cl_assert(!s_pending_did_write.active);
|
||||
|
||||
// attempt to issue another read request (should report busy)
|
||||
assert_result_busy(app_smartstrap_attribute_read(attr));
|
||||
|
||||
// check that it was sent successfully
|
||||
SmartstrapRequest request = {
|
||||
.service_id = 0x1111,
|
||||
.attribute_id = 0x2222,
|
||||
.write_mbuf = NULL,
|
||||
.read_mbuf = NON_NULL_MBUF,
|
||||
.timeout_ms = SMARTSTRAP_TIMEOUT_DEFAULT
|
||||
};
|
||||
fake_smartstrap_profiles_check_request_params(&request);
|
||||
|
||||
// fake the response and expect a did_read handler call
|
||||
prv_prepare_for_did_read(attr, 10);
|
||||
smartstrap_attribute_send_event(SmartstrapDataReceivedEvent, SmartstrapProfileGenericService,
|
||||
SmartstrapResultOk, 0x1111, 0x2222, 10);
|
||||
cl_assert(!s_pending_did_read.active);
|
||||
|
||||
// destroy the attribute
|
||||
app_smartstrap_attribute_destroy(attr);
|
||||
}
|
||||
|
||||
void test_app_smartstrap__write(void) {
|
||||
// create the attribute
|
||||
SmartstrapAttribute *attr = app_smartstrap_attribute_create(0x1111, 0x2222, 100);
|
||||
|
||||
// start a write request
|
||||
stub_pebble_tasks_set_current(PebbleTask_App);
|
||||
uint8_t *write_buffer = NULL;
|
||||
size_t write_length = 0;
|
||||
assert_result_ok(app_smartstrap_attribute_begin_write(attr, &write_buffer, &write_length));
|
||||
cl_assert(write_buffer == (uint8_t *)attr);
|
||||
cl_assert(write_length == 100);
|
||||
|
||||
// attempt to start another write request
|
||||
assert_result_busy(app_smartstrap_attribute_read(attr));
|
||||
uint8_t *write_buffer2 = NULL;
|
||||
size_t write_length2 = 0;
|
||||
assert_result_busy(app_smartstrap_attribute_begin_write(attr, &write_buffer2, &write_length2));
|
||||
cl_assert(write_buffer2 == NULL);
|
||||
cl_assert(write_length2 == 0);
|
||||
|
||||
// end the write request without sending anything
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(attr, 0, false));
|
||||
|
||||
// start the write request again
|
||||
write_buffer = NULL;
|
||||
write_length = 0;
|
||||
assert_result_ok(app_smartstrap_attribute_begin_write(attr, &write_buffer, &write_length));
|
||||
cl_assert(write_buffer == (uint8_t *)attr);
|
||||
cl_assert(write_length == 100);
|
||||
|
||||
// end the write request
|
||||
assert_result_ok(app_smartstrap_attribute_end_write(attr, 100, false));
|
||||
|
||||
// trigger the write request to be sent
|
||||
stub_pebble_tasks_set_current(PebbleTask_KernelBackground);
|
||||
cl_assert(smartstrap_attribute_send_pending());
|
||||
|
||||
// check that it was sent successfully
|
||||
SmartstrapRequest request = {
|
||||
.service_id = 0x1111,
|
||||
.attribute_id = 0x2222,
|
||||
.write_mbuf = NON_NULL_MBUF,
|
||||
.read_mbuf = NULL,
|
||||
.timeout_ms = SMARTSTRAP_TIMEOUT_DEFAULT
|
||||
};
|
||||
|
||||
// fake the ACK and expect a did_write handler call
|
||||
fake_smartstrap_profiles_check_request_params(&request);
|
||||
prv_prepare_for_did_write(attr);
|
||||
smartstrap_attribute_send_event(SmartstrapDataReceivedEvent, SmartstrapProfileGenericService,
|
||||
SmartstrapResultOk, 0x1111, 0x2222, 100);
|
||||
cl_assert(!s_pending_did_write.active);
|
||||
|
||||
// destroy the attribute
|
||||
app_smartstrap_attribute_destroy(attr);
|
||||
}
|
||||
|
||||
void test_app_smartstrap__write_read(void) {
|
||||
// create the attribute
|
||||
SmartstrapAttribute *attr = app_smartstrap_attribute_create(0x1111, 0x2222, 100);
|
||||
|
||||
// start a write request
|
||||
stub_pebble_tasks_set_current(PebbleTask_App);
|
||||
uint8_t *write_buffer = NULL;
|
||||
size_t write_length = 0;
|
||||
assert_result_ok(app_smartstrap_attribute_begin_write(attr, &write_buffer, &write_length));
|
||||
cl_assert(write_buffer == (uint8_t *)attr);
|
||||
cl_assert(write_length == 100);
|
||||
|
||||
// end the write request without sending anything
|
||||
assert_result_invalid(app_smartstrap_attribute_end_write(attr, 0, true));
|
||||
|
||||
// start the write request again
|
||||
write_buffer = NULL;
|
||||
write_length = 0;
|
||||
assert_result_ok(app_smartstrap_attribute_begin_write(attr, &write_buffer, &write_length));
|
||||
cl_assert(write_buffer == (uint8_t *)attr);
|
||||
cl_assert(write_length == 100);
|
||||
|
||||
// end the write request with request_read=true
|
||||
assert_result_ok(app_smartstrap_attribute_end_write(attr, 100, true));
|
||||
|
||||
// trigger the write request to be sent and expect a did_write handler call
|
||||
stub_pebble_tasks_set_current(PebbleTask_KernelBackground);
|
||||
prv_prepare_for_did_write(attr);
|
||||
cl_assert(smartstrap_attribute_send_pending());
|
||||
cl_assert(!s_pending_did_write.active);
|
||||
|
||||
// check that it was sent successfully
|
||||
SmartstrapRequest request = {
|
||||
.service_id = 0x1111,
|
||||
.attribute_id = 0x2222,
|
||||
.write_mbuf = NON_NULL_MBUF,
|
||||
.read_mbuf = NON_NULL_MBUF,
|
||||
.timeout_ms = SMARTSTRAP_TIMEOUT_DEFAULT
|
||||
};
|
||||
|
||||
// fake the response and expect a did_write and a did_read handler call
|
||||
fake_smartstrap_profiles_check_request_params(&request);
|
||||
prv_prepare_for_did_read(attr, 100);
|
||||
smartstrap_attribute_send_event(SmartstrapDataReceivedEvent, SmartstrapProfileGenericService,
|
||||
SmartstrapResultOk, 0x1111, 0x2222, 100);
|
||||
cl_assert(!s_pending_did_read.active);
|
||||
|
||||
// destroy the attribute
|
||||
app_smartstrap_attribute_destroy(attr);
|
||||
}
|
||||
|
||||
void test_app_smartstrap__notify(void) {
|
||||
// create the attribute
|
||||
SmartstrapAttribute *attr = app_smartstrap_attribute_create(0x1111, 0x2222, 100);
|
||||
|
||||
// send a notification and expect a notified handler call
|
||||
prv_prepare_for_notified(attr);
|
||||
smartstrap_attribute_send_event(SmartstrapNotifyEvent, SmartstrapProfileGenericService,
|
||||
SmartstrapResultOk, 0x1111, 0x2222, 0);
|
||||
cl_assert(!s_pending_notified.active);
|
||||
|
||||
// send a notification for a non-created attribute which shouldn't cause a notified handler call
|
||||
smartstrap_attribute_send_event(SmartstrapNotifyEvent, SmartstrapProfileGenericService,
|
||||
SmartstrapResultOk, 0x1111, 0x3333, 0);
|
||||
|
||||
// destroy the attribute
|
||||
app_smartstrap_attribute_destroy(attr);
|
||||
|
||||
// send a notification for the destroyed attribute which shouldn't cause a notified handler call
|
||||
smartstrap_attribute_send_event(SmartstrapNotifyEvent, SmartstrapProfileGenericService,
|
||||
SmartstrapResultOk, 0x1111, 0x2222, 0);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue