mirror of
https://github.com/google/pebble.git
synced 2025-03-23 20:21:55 +00:00
359 lines
15 KiB
C
359 lines
15 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 "process_management/app_install_manager.h"
|
|
#include "resource/resource_ids.auto.h"
|
|
#include "services/normal/timeline/timeline_resources.h"
|
|
#include "system/passert.h"
|
|
#include "util/struct.h"
|
|
|
|
// Stubs
|
|
/////////////////////////
|
|
|
|
#include "stubs_kino_reel.h"
|
|
#include "stubs_logging.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_pbl_malloc.h"
|
|
#include "stubs_resources.h"
|
|
#include "stubs_syscalls.h"
|
|
|
|
// Test Data
|
|
/////////////////////////
|
|
|
|
typedef enum TimelineResourceTestAppTimelineId {
|
|
// We start at 1 because TIMELINE_RESOURCE_INVALID = 0
|
|
TimelineResourceTestTimelineId_AlarmClock = 1,
|
|
TimelineResourceTestTimelineId_Basketball,
|
|
|
|
TimelineResourceTestTimelineIdCount
|
|
} TimelineResourceTestTimelineId;
|
|
|
|
static const uint32_t s_app_lut[TimelineResourceTestTimelineIdCount][TimelineResourceSizeCount] = {
|
|
[TIMELINE_RESOURCE_INVALID] = {
|
|
RESOURCE_ID_INVALID, RESOURCE_ID_INVALID, RESOURCE_ID_INVALID
|
|
},
|
|
[TimelineResourceTestTimelineId_AlarmClock] = {
|
|
RESOURCE_ID_ALARM_CLOCK_TINY, RESOURCE_ID_ALARM_CLOCK_SMALL, RESOURCE_ID_ALARM_CLOCK_LARGE
|
|
},
|
|
[TimelineResourceTestTimelineId_Basketball] = {
|
|
RESOURCE_ID_BASKETBALL_TINY, RESOURCE_ID_BASKETBALL_SMALL, RESOURCE_ID_BASKETBALL_LARGE
|
|
},
|
|
};
|
|
|
|
typedef struct TimelineResourceTestAppData {
|
|
AppInstallEntry install_entry;
|
|
const uint32_t (*resource_lut)[TimelineResourceSizeCount];
|
|
} TimelineResourceTestAppData;
|
|
|
|
typedef enum TimelineResourceTestAppId {
|
|
// We start from 1 because INSTALL_ID_INVALID = 0
|
|
TimelineResourceTestAppId_AppWithInvalidLUT = 1,
|
|
TimelineResourceTestAppId_AppWithInvalidSDKVersion,
|
|
TimelineResourceTestAppId_ValidApp,
|
|
|
|
TimelineResourceTestAppIdInvalid,
|
|
TimelineResourceTestAppIdCount = TimelineResourceTestAppIdInvalid - 1
|
|
} TimelineResourceTestAppId;
|
|
|
|
static const TimelineResourceTestAppData s_test_apps[TimelineResourceTestAppIdCount] = {
|
|
{
|
|
.install_entry = {
|
|
.install_id = TimelineResourceTestAppId_AppWithInvalidLUT,
|
|
.uuid = {0x3c, 0x6e, 0x2e, 0x1d, 0x61, 0x7d, 0x4d, 0x17,
|
|
0x97, 0xa1, 0xbc, 0x43, 0x2d, 0x87, 0x4c, 0xed},
|
|
.sdk_version = {TIMELINE_RESOURCE_PBW_SUPPORT_FIRST_SDK_VERSION_MAJOR,
|
|
TIMELINE_RESOURCE_PBW_SUPPORT_FIRST_SDK_VERSION_MINOR},
|
|
},
|
|
// No resource_lut specified because this app has an "invalid" lut
|
|
},
|
|
{
|
|
.install_entry = {
|
|
.install_id = TimelineResourceTestAppId_AppWithInvalidSDKVersion,
|
|
.uuid = {0x37, 0xe7, 0x64, 0x5e, 0xd, 0x6a, 0x41, 0xfe,
|
|
0xb8, 0x80, 0xea, 0x47, 0x5a, 0x5f, 0x34, 0x34},
|
|
// We set the SDK version to one earlier than the first version supporting timeline resources
|
|
.sdk_version = {TIMELINE_RESOURCE_PBW_SUPPORT_FIRST_SDK_VERSION_MAJOR,
|
|
TIMELINE_RESOURCE_PBW_SUPPORT_FIRST_SDK_VERSION_MINOR - 1},
|
|
},
|
|
.resource_lut = s_app_lut,
|
|
},
|
|
{
|
|
.install_entry = {
|
|
.install_id = TimelineResourceTestAppId_ValidApp,
|
|
.uuid = {0x9e, 0x95, 0x8b, 0xfe, 0xd, 0xbd, 0x4d, 0xf2,
|
|
0xbe, 0xbc, 0xf3, 0x77, 0x5d, 0x8d, 0x9f, 0x95},
|
|
.sdk_version = {TIMELINE_RESOURCE_PBW_SUPPORT_FIRST_SDK_VERSION_MAJOR,
|
|
TIMELINE_RESOURCE_PBW_SUPPORT_FIRST_SDK_VERSION_MINOR},
|
|
},
|
|
.resource_lut = s_app_lut,
|
|
},
|
|
};
|
|
|
|
static const TimelineResourceTestAppData *prv_get_data_for_app_with_id(AppInstallId install_id) {
|
|
for (int i = 0; i < TimelineResourceTestAppIdCount; i++) {
|
|
const TimelineResourceTestAppData *data = &s_test_apps[i];
|
|
if (data->install_entry.install_id == install_id) {
|
|
return data;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static const TimelineResourceTestAppData *prv_get_data_for_app_with_uuid(const Uuid *uuid) {
|
|
for (int i = 0; i < TimelineResourceTestAppIdCount; i++) {
|
|
const TimelineResourceTestAppData *data = &s_test_apps[i];
|
|
if (uuid_equal(uuid, &data->install_entry.uuid)) {
|
|
return data;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// Fakes
|
|
/////////////////////////
|
|
|
|
bool prv_validate_lut(ResAppNum res_app_num) {
|
|
// Just check if the .resource_lut pointer for the provided res_app_num is non-NULL
|
|
const TimelineResourceTestAppData *data = prv_get_data_for_app_with_id(res_app_num);
|
|
return data ? (data->resource_lut != NULL) : false;
|
|
}
|
|
|
|
uint32_t prv_get_app_resource_id(ResAppNum res_app_num, TimelineResourceId timeline_id,
|
|
TimelineResourceSize size) {
|
|
// Size must be valid
|
|
if (size >= TimelineResourceSizeCount) {
|
|
return RESOURCE_ID_INVALID;
|
|
}
|
|
|
|
// This only supports valid non-system apps
|
|
const TimelineResourceTestAppData *data = prv_get_data_for_app_with_id(res_app_num);
|
|
if (!data) {
|
|
return RESOURCE_ID_INVALID;
|
|
}
|
|
|
|
// The app must have a valid LUT
|
|
if (!data->resource_lut) {
|
|
return RESOURCE_ID_INVALID;
|
|
}
|
|
|
|
return data->resource_lut[timeline_id][size];
|
|
}
|
|
|
|
static bool s_is_app_published_resource_invalid;
|
|
|
|
bool prv_is_app_published_resource_valid(const AppResourceInfo *res_info) {
|
|
return !s_is_app_published_resource_invalid;
|
|
}
|
|
|
|
AppInstallId app_install_get_id_for_uuid(const Uuid *uuid) {
|
|
const TimelineResourceTestAppData *data = prv_get_data_for_app_with_uuid(uuid);
|
|
return NULL_SAFE_FIELD_ACCESS(data, install_entry.install_id, INSTALL_ID_INVALID);
|
|
}
|
|
|
|
bool app_install_get_entry_for_install_id(AppInstallId install_id, AppInstallEntry *entry) {
|
|
if (!entry) {
|
|
return false;
|
|
}
|
|
|
|
const TimelineResourceTestAppData *data = prv_get_data_for_app_with_id(install_id);
|
|
if (!data) {
|
|
return false;
|
|
}
|
|
*entry = data->install_entry;
|
|
return true;
|
|
}
|
|
|
|
ResAppNum app_install_get_app_icon_bank(const AppInstallEntry *entry) {
|
|
PBL_ASSERTN(entry);
|
|
if (uuid_equal(&entry->uuid, &(Uuid)UUID_SYSTEM)) {
|
|
return SYSTEM_APP;
|
|
} else {
|
|
return entry->install_id;
|
|
}
|
|
}
|
|
|
|
// Setup
|
|
/////////////////////////
|
|
|
|
void test_timeline_resources__initialize(void) {
|
|
s_is_app_published_resource_invalid = false;
|
|
}
|
|
|
|
// Tests
|
|
/////////////////////////
|
|
|
|
void test_timeline_resources__get_id_system(void) {
|
|
AppResourceInfo res_info;
|
|
|
|
// Calling the function with an invalid TimelineResourceId should return false
|
|
cl_assert(!timeline_resources_get_id_system(TIMELINE_RESOURCE_INVALID, TimelineResourceSizeTiny,
|
|
TimelineResourceTestAppId_ValidApp, &res_info));
|
|
|
|
// Calling the function with an invalid size should return false
|
|
cl_assert(!timeline_resources_get_id_system(
|
|
(TimelineResourceId)TimelineResourceTestTimelineId_AlarmClock, TimelineResourceSizeCount,
|
|
TimelineResourceTestAppId_ValidApp, &res_info));
|
|
|
|
// Calling the function with the ResAppNum of an app with an invalid LUT should return false
|
|
cl_assert(!timeline_resources_get_id_system(
|
|
(TimelineResourceId)TimelineResourceTestTimelineId_AlarmClock, TimelineResourceSizeTiny,
|
|
TimelineResourceTestAppId_AppWithInvalidLUT, &res_info));
|
|
|
|
// Calling the function for an invalid resource (e.g. dimensions too large) should return false
|
|
s_is_app_published_resource_invalid = true;
|
|
cl_assert(!timeline_resources_get_id_system(
|
|
(TimelineResourceId)TimelineResourceTestTimelineId_AlarmClock, TimelineResourceSizeTiny,
|
|
TimelineResourceTestAppId_ValidApp, &res_info));
|
|
s_is_app_published_resource_invalid = false;
|
|
|
|
// Calling the function with valid args should return true and set the correct values in res_info
|
|
cl_assert(timeline_resources_get_id_system(
|
|
(TimelineResourceId)TimelineResourceTestTimelineId_AlarmClock, TimelineResourceSizeTiny,
|
|
TimelineResourceTestAppId_ValidApp, &res_info));
|
|
cl_assert_equal_i(res_info.res_app_num, TimelineResourceTestAppId_ValidApp);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_ALARM_CLOCK_TINY);
|
|
|
|
// Calling the function with valid args should return true even if no AppResourceInfo is provided
|
|
cl_assert(timeline_resources_get_id_system(
|
|
(TimelineResourceId)TimelineResourceTestTimelineId_AlarmClock, TimelineResourceSizeTiny,
|
|
TimelineResourceTestAppId_ValidApp, NULL));
|
|
|
|
// Calling the function with a valid system TimelineResourceId should return true and set res_info
|
|
cl_assert(timeline_resources_get_id_system(TIMELINE_RESOURCE_AUDIO_CASSETTE,
|
|
TimelineResourceSizeSmall, SYSTEM_APP, &res_info));
|
|
cl_assert_equal_i(res_info.res_app_num, SYSTEM_APP);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_AUDIO_CASSETTE_SMALL);
|
|
// Even if the provided ResAppNum != SYSTEM_APP
|
|
cl_assert(timeline_resources_get_id_system(TIMELINE_RESOURCE_AUDIO_CASSETTE,
|
|
TimelineResourceSizeSmall, TIMELINE_RESOURCE_INVALID,
|
|
&res_info));
|
|
cl_assert_equal_i(res_info.res_app_num, SYSTEM_APP);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_AUDIO_CASSETTE_SMALL);
|
|
}
|
|
|
|
void test_timeline_resources__get_id(void) {
|
|
TimelineResourceInfo timeline_res_info;
|
|
AppResourceInfo res_info;
|
|
|
|
const TimelineResourceTestAppData *valid_app_data =
|
|
prv_get_data_for_app_with_id(TimelineResourceTestAppId_ValidApp);
|
|
PBL_ASSERTN(valid_app_data);
|
|
|
|
// Calling the function with an invalid TimelineResourceId should set res_info to the fallback
|
|
timeline_res_info = (TimelineResourceInfo) {
|
|
.app_id = &valid_app_data->install_entry.uuid,
|
|
.res_id = TIMELINE_RESOURCE_INVALID,
|
|
.fallback_id = TIMELINE_RESOURCE_BIRTHDAY_EVENT,
|
|
};
|
|
timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeLarge, &res_info);
|
|
cl_assert_equal_i(res_info.res_app_num, SYSTEM_APP);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_BIRTHDAY_EVENT_LARGE);
|
|
|
|
// Set the TimelineResourceInfo to valid values
|
|
timeline_res_info = (TimelineResourceInfo) {
|
|
.app_id = &valid_app_data->install_entry.uuid,
|
|
.res_id = (TimelineResourceId)TimelineResourceTestTimelineId_AlarmClock,
|
|
.fallback_id = TIMELINE_RESOURCE_BIRTHDAY_EVENT,
|
|
};
|
|
|
|
// Calling the function with an invalid size, no TimelineResourceInfo, or no AppResourceInfo
|
|
// should assert
|
|
cl_assert_passert(timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeCount,
|
|
&res_info));
|
|
cl_assert_passert(timeline_resources_get_id(NULL, TimelineResourceSizeTiny, &res_info));
|
|
cl_assert_passert(timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeTiny, NULL));
|
|
|
|
// Set the TimelineResourceInfo to have the UUID of an app with an invalid LUT
|
|
const TimelineResourceTestAppData *app_with_invalid_lut_data =
|
|
prv_get_data_for_app_with_id(TimelineResourceTestAppId_AppWithInvalidLUT);
|
|
PBL_ASSERTN(app_with_invalid_lut_data);
|
|
timeline_res_info = (TimelineResourceInfo) {
|
|
.app_id = &app_with_invalid_lut_data->install_entry.uuid,
|
|
.res_id = (TimelineResourceId)TimelineResourceTestTimelineId_AlarmClock,
|
|
.fallback_id = TIMELINE_RESOURCE_BIRTHDAY_EVENT,
|
|
};
|
|
|
|
// Calling the function with the UUID of an app with an invalid LUT should set res_info to the
|
|
// fallback
|
|
timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeLarge, &res_info);
|
|
cl_assert_equal_i(res_info.res_app_num, SYSTEM_APP);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_BIRTHDAY_EVENT_LARGE);
|
|
|
|
// Set the TimelineResourceInfo to valid values
|
|
timeline_res_info = (TimelineResourceInfo) {
|
|
.app_id = &valid_app_data->install_entry.uuid,
|
|
.res_id = (TimelineResourceId)TimelineResourceTestTimelineId_AlarmClock,
|
|
.fallback_id = TIMELINE_RESOURCE_BIRTHDAY_EVENT,
|
|
};
|
|
|
|
// Calling the function for an invalid resource (e.g. dimensions too large) should set res_info
|
|
// to the fallback
|
|
s_is_app_published_resource_invalid = true;
|
|
timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeLarge, &res_info);
|
|
cl_assert_equal_i(res_info.res_app_num, SYSTEM_APP);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_BIRTHDAY_EVENT_LARGE);
|
|
s_is_app_published_resource_invalid = false;
|
|
|
|
// Calling the function with valid args should return true and set the correct values in res_info
|
|
timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeLarge, &res_info);
|
|
cl_assert_equal_i(res_info.res_app_num, TimelineResourceTestAppId_ValidApp);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_ALARM_CLOCK_LARGE);
|
|
|
|
// Set the TimelineResourceInfo to have the UUID of an app with an unsupported SDK version
|
|
const TimelineResourceTestAppData *app_with_invalid_sdk_version =
|
|
prv_get_data_for_app_with_id(TimelineResourceTestAppId_AppWithInvalidSDKVersion);
|
|
PBL_ASSERTN(app_with_invalid_sdk_version);
|
|
timeline_res_info = (TimelineResourceInfo) {
|
|
.app_id = &app_with_invalid_sdk_version->install_entry.uuid,
|
|
.res_id = (TimelineResourceId)TimelineResourceTestTimelineId_Basketball,
|
|
.fallback_id = TIMELINE_RESOURCE_BIRTHDAY_EVENT,
|
|
};
|
|
|
|
// Calling the function with the UUID of an app with an unsupported SDK version should set
|
|
// res_info to the fallback
|
|
timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeTiny, &res_info);
|
|
cl_assert_equal_i(res_info.res_app_num, SYSTEM_APP);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_BIRTHDAY_EVENT_TINY);
|
|
|
|
// Set the TimelineResourceInfo to valid values but with a system TimelineResourceId requested
|
|
timeline_res_info = (TimelineResourceInfo) {
|
|
.app_id = &(Uuid)UUID_SYSTEM,
|
|
.res_id = TIMELINE_RESOURCE_HOTEL_RESERVATION,
|
|
.fallback_id = TIMELINE_RESOURCE_BIRTHDAY_EVENT,
|
|
};
|
|
|
|
// Calling the function with a valid system TimelineResourceId should set the correct values in
|
|
// res_info
|
|
timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeSmall, &res_info);
|
|
cl_assert_equal_i(res_info.res_app_num, SYSTEM_APP);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_HOTEL_RESERVATION_SMALL);
|
|
// Even if the provided app UUID != UUID_SYSTEM
|
|
timeline_res_info.app_id = &valid_app_data->install_entry.uuid;
|
|
timeline_resources_get_id(&timeline_res_info, TimelineResourceSizeSmall, &res_info);
|
|
cl_assert_equal_i(res_info.res_app_num, SYSTEM_APP);
|
|
cl_assert_equal_i(res_info.res_id, RESOURCE_ID_HOTEL_RESERVATION_SMALL);
|
|
}
|
|
|
|
void test_timeline_resources__is_system(void) {
|
|
// System TimelineResourceIds should return true
|
|
cl_assert(timeline_resources_is_system(TIMELINE_RESOURCE_AUDIO_CASSETTE));
|
|
|
|
// Others should return false
|
|
cl_assert(!timeline_resources_is_system(TIMELINE_RESOURCE_INVALID));
|
|
cl_assert(!timeline_resources_is_system(NUM_TIMELINE_RESOURCES));
|
|
}
|