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

214 lines
8.2 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/app_glance.h"
#include "drivers/rtc.h"
#include "kernel/pbl_malloc.h"
#include "process_management/app_install_manager.h"
#include "resource/resource_ids.auto.h"
#include "services/normal/app_glances/app_glance_service.h"
#include "services/normal/blob_db/app_glance_db.h"
#include "services/normal/blob_db/app_glance_db_private.h"
#include "services/normal/filesystem/pfs.h"
#include "util/uuid.h"
// Fakes
////////////////////////////////////////////////////////////////
#include "fake_settings_file.h"
// Stubs
////////////////////////////////////////////////////////////////
#include "stubs_app_cache.h"
#include "stubs_app_install_manager.h"
#include "stubs_events.h"
#include "stubs_event_service_client.h"
#include "stubs_logging.h"
#include "stubs_mutex.h"
#include "stubs_passert.h"
#include "stubs_pbl_malloc.h"
status_t pfs_remove(const char *name) {
fake_settings_file_reset();
return S_SUCCESS;
}
#define APP_GLANCE_TEST_UUID \
(UuidMake(0x3d, 0xc6, 0xb9, 0x4c, 0x4, 0x2, 0x48, 0xf4, \
0xbe, 0x14, 0x81, 0x17, 0xf1, 0xa, 0xa9, 0xc4))
// Setup
////////////////////////////////////////////////////////////////
void test_app_glance_service__initialize(void) {
fake_settings_file_reset();
app_glance_db_init();
app_glance_service_init();
}
void app_glance_db_deinit(void);
void test_app_glance_service__cleanup(void) {
app_glance_db_deinit();
}
static void prv_check_expected_slice_data(const AppGlanceSliceInternal *expected_slice_data,
time_t time) {
// Set the current time to the provided time
rtc_set_time(time);
AppGlanceSliceInternal slice_out;
if (expected_slice_data) {
// Request the current slice from the glance, expecting it to return true
cl_assert_equal_b(app_glance_service_get_current_slice(&APP_GLANCE_TEST_UUID, &slice_out),
true);
// Check that it matches the slice data we expect
cl_assert_equal_m(&slice_out, expected_slice_data, sizeof(AppGlanceSliceInternal));
} else {
// Check that requesting the current slice returns false
cl_assert_equal_b(app_glance_service_get_current_slice(&APP_GLANCE_TEST_UUID, &slice_out),
false);
}
}
void test_app_glance_service__get_current_slice_basic(void) {
AppGlanceSliceInternal slice_out;
// Requesting the current slice with a NULL UUID should return false
cl_assert_equal_b(app_glance_service_get_current_slice(NULL, &slice_out), false);
// Requesting the current slice with an invalid UUID should return false
cl_assert_equal_b(app_glance_service_get_current_slice(&UUID_INVALID, &slice_out), false);
// Requesting the current slice with a NULL slice_out argument should return false
cl_assert_equal_b(app_glance_service_get_current_slice(&APP_GLANCE_TEST_UUID, NULL), false);
// Insert a glance
const AppGlance glance = (AppGlance) {
.num_slices = 1,
.slices = {
{
.expiration_time = 1464734484, // (Tue, 31 May 2016 22:41:24 GMT)
.type = AppGlanceSliceType_IconAndSubtitle,
.icon_and_subtitle = {
.icon_resource_id = RESOURCE_ID_SETTINGS_ICON_AIRPLANE,
.template_string = "Test subtitle",
},
},
},
};
cl_assert_equal_i(app_glance_db_insert_glance(&APP_GLANCE_TEST_UUID, &glance), S_SUCCESS);
// This is the slice we expect to get when we request the current slice
// Note that we don't expect the pointer to the slice but rather the data behind the pointer
const AppGlanceSliceInternal *expected_slice_data = &glance.slices[0];
// Since there's only one slice in the glance, check that we get it 100 seconds before its
// expiration time
prv_check_expected_slice_data(expected_slice_data, expected_slice_data->expiration_time - 100);
// Check that we get back nothing for the current slice if we set the time to exactly when the
// only slice in the glance expires
prv_check_expected_slice_data(NULL, expected_slice_data->expiration_time);
}
void test_app_glance_service__get_current_slice_from_glance_with_multiple_unsorted_slices(void) {
// Insert a glance with multiple, unsorted slices
// Note that the expiration time for each of these are a minimum of 10 seconds apart
const AppGlance glance = (AppGlance) {
.num_slices = 2,
.slices = {
{
.expiration_time = 1464734504, // (Tue, 31 May 2016 22:41:44 GMT)
.type = AppGlanceSliceType_IconAndSubtitle,
.icon_and_subtitle = {
.icon_resource_id = RESOURCE_ID_SETTINGS_ICON_BLUETOOTH_ALT,
.template_string = "Test subtitle 2",
},
},
{
.expiration_time = 1464734484, // (Tue, 31 May 2016 22:41:24 GMT)
.type = AppGlanceSliceType_IconAndSubtitle,
.icon_and_subtitle = {
.icon_resource_id = RESOURCE_ID_SETTINGS_ICON_AIRPLANE,
.template_string = "Test subtitle 1",
},
},
},
};
cl_assert_equal_i(app_glance_db_insert_glance(&APP_GLANCE_TEST_UUID, &glance), S_SUCCESS);
// This is the slice we expect to get when we request the current slice
// Note that we don't expect the pointer to the slice but rather the data behind the pointer
const AppGlanceSliceInternal *expected_slice_data = &glance.slices[1];
// Set the current time to 5 seconds before the slice we expect to get back expires and check
// that we get it
prv_check_expected_slice_data(expected_slice_data, expected_slice_data->expiration_time - 5);
// Try again for the next slice that expires
expected_slice_data = &glance.slices[0];
prv_check_expected_slice_data(expected_slice_data, expected_slice_data->expiration_time - 5);
// Finally, check that after all slices have expired we get back nothing for the current slice
prv_check_expected_slice_data(NULL, expected_slice_data->expiration_time);
}
void test_app_glance_service__slice_with_no_expiration(void) {
// Insert a glance with multiple, unsorted slices
// Note that the expiration time for each of these are a minimum of 10 seconds apart
const AppGlance glance = (AppGlance) {
.num_slices = 2,
.slices = {
{
.expiration_time = APP_GLANCE_SLICE_NO_EXPIRATION,
.type = AppGlanceSliceType_IconAndSubtitle,
.icon_and_subtitle = {
.icon_resource_id = RESOURCE_ID_SETTINGS_ICON_AIRPLANE,
.template_string = "Test subtitle 2",
},
},
{
.expiration_time = 1464734504, // (Tue, 31 May 2016 22:41:44 GMT)
.type = AppGlanceSliceType_IconAndSubtitle,
.icon_and_subtitle = {
.icon_resource_id = RESOURCE_ID_SETTINGS_ICON_BLUETOOTH_ALT,
.template_string = "Test subtitle 1",
},
},
},
};
cl_assert_equal_i(app_glance_db_insert_glance(&APP_GLANCE_TEST_UUID, &glance), S_SUCCESS);
// We expect the slice with the defined expiration time when we request the current slice
// Note that we don't expect the pointer to the slice but rather the data behind the pointer
const AppGlanceSliceInternal *expiring_slice_data = &glance.slices[1];
// Set the current time to 5 seconds before the slice we expect to get back expires and check
// that we get it
prv_check_expected_slice_data(expiring_slice_data, expiring_slice_data->expiration_time - 5);
// Check that we get the slice that never expires 5 seconds after the expiring slice expires
const AppGlanceSliceInternal *no_expire_slice_data = &glance.slices[0];
prv_check_expected_slice_data(no_expire_slice_data, expiring_slice_data->expiration_time + 5);
// Check that going super far into the future still returns the slice with no expiration time
prv_check_expected_slice_data(no_expire_slice_data,
expiring_slice_data->expiration_time + 9999999);
}