/* * 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_types.h" #include "process_management/pebble_process_info.h" #include "process_management/pebble_process_md.h" #include "services/normal/filesystem/pfs.h" #include "services/normal/blob_db/app_db.h" // Fixture //////////////////////////////////////////////////////////////// // Fakes //////////////////////////////////////////////////////////////// #include "fake_spi_flash.h" // Stubs //////////////////////////////////////////////////////////////// #include "stubs_analytics.h" #include "stubs_app_cache.h" #include "stubs_events.h" #include "stubs_hexdump.h" #include "stubs_logging.h" #include "stubs_mutex.h" #include "stubs_passert.h" #include "stubs_pbl_malloc.h" #include "stubs_pebble_tasks.h" #include "stubs_prompt.h" #include "stubs_rand_ptr.h" #include "stubs_sleep.h" #include "stubs_task_watchdog.h" void app_install_clear_app_db(void) { } void put_bytes_cancel(void) { } typedef void (*InstallCallbackDoneCallback)(void*); bool app_install_do_callbacks(InstallEventType event_type, AppInstallId install_id, Uuid *uuid, InstallCallbackDoneCallback done_callback, void* done_callback_data) { return true; } bool app_fetch_in_progress(void) { return false; } void app_fetch_cancel_from_system_task(void) { } extern AppInstallId app_db_check_next_unique_id(void); static const AppDBEntry app1 = { .name = "Application 1", .uuid = {0x6b, 0xf6, 0x21, 0x5b, 0xc9, 0x7f, 0x40, 0x9e, 0x8c, 0x31, 0x4f, 0x55, 0x65, 0x72, 0x22, 0xb4}, .app_version = { .major = 1, .minor = 1, }, .sdk_version = { .major = 1, .minor = 1, }, .info_flags = 0, .icon_resource_id = 0, }; static const AppDBEntry app2 = { .name = "Application 2", .uuid = {0x55, 0xcb, 0x7c, 0x75, 0x8a, 0x35, 0x44, 0x87, 0x90, 0xa4, 0x91, 0x3f, 0x1f, 0xa6, 0x76, 0x01}, .app_version = { .major = 1, .minor = 1, }, .sdk_version = { .major = 1, .minor = 1, }, .info_flags = 0, .icon_resource_id = 0, }; static const AppDBEntry app3 = { .name = "Application 3", .uuid = {0x7c, 0x65, 0x2e, 0xb9, 0x26, 0xd6, 0x44, 0x2c, 0x98, 0x68, 0xa4, 0x36, 0x79, 0x7d, 0xe2, 0x05}, .app_version = { .major = 1, .minor = 1, }, .sdk_version = { .major = 1, .minor = 1, }, .info_flags = 0, .icon_resource_id = 0, }; // Setup //////////////////////////////////////////////////////////////// void test_app_db__initialize(void) { fake_spi_flash_init(0, 0x1000000); pfs_init(false); app_db_init(); // add all three cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app1.uuid, sizeof(Uuid), (uint8_t*)&app1, sizeof(AppDBEntry))); cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app2.uuid, sizeof(Uuid), (uint8_t*)&app2, sizeof(AppDBEntry))); cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app3.uuid, sizeof(Uuid), (uint8_t*)&app3, sizeof(AppDBEntry))); } void test_app_db__cleanup(void) { //nada } // Tests //////////////////////////////////////////////////////////////// void test_app_db__basic_test(void) { // confirm all three are there cl_assert(app_db_get_len((uint8_t*)&app1.uuid, sizeof(Uuid)) > 0); cl_assert(app_db_get_len((uint8_t*)&app2.uuid, sizeof(Uuid)) > 0); cl_assert(app_db_get_len((uint8_t*)&app3.uuid, sizeof(Uuid)) > 0); // remove #1 and confirm it's deleted cl_assert_equal_i(S_SUCCESS, app_db_delete((uint8_t*)&app1.uuid, sizeof(Uuid))); cl_assert_equal_i(0, app_db_get_len((uint8_t*)&app1.uuid, sizeof(Uuid))); // add 1 back so it's clean cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app1.uuid, sizeof(Uuid), (uint8_t*)&app1, sizeof(AppDBEntry))); AppDBEntry temp; cl_assert_equal_i(S_SUCCESS, app_db_read((uint8_t*)&app1.uuid, sizeof(Uuid), (uint8_t*)&temp, sizeof(AppDBEntry))); cl_assert_equal_i(5, app_db_check_next_unique_id()); // check app 1 memset(&temp, 0, sizeof(AppDBEntry)); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_uuid(&app1.uuid, &temp)); cl_assert_equal_b(true, uuid_equal(&app1.uuid, &temp.uuid)); cl_assert_equal_i(0 , strncmp((char *)&app1.name, (char *)&temp.name, APP_NAME_SIZE_BYTES)); // check app 2 memset(&temp, 0, sizeof(AppDBEntry)); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_uuid(&app1.uuid, &temp)); cl_assert_equal_b(true, uuid_equal(&app1.uuid, &temp.uuid)); cl_assert_equal_i(0, strncmp((char *)&app1.name, (char *)&temp.name, APP_NAME_SIZE_BYTES)); // check app 3 memset(&temp, 0, sizeof(AppDBEntry)); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_uuid(&app3.uuid, &temp)); cl_assert_equal_b(true, uuid_equal(&app3.uuid, &temp.uuid)); cl_assert_equal_i(0, strncmp((char *)&app3.name, (char *)&temp.name, APP_NAME_SIZE_BYTES)); } void test_app_db__retrieve_app_db_entries_by_install_id(void) { AppDBEntry temp; // check app_db_get_install_id_for_uuid for app 1 memset(&temp, 0, sizeof(AppDBEntry)); AppInstallId app_one_id = app_db_get_install_id_for_uuid(&app1.uuid); cl_assert(app_one_id > 0); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_install_id(app_one_id, &temp)); cl_assert_equal_b(true, uuid_equal(&app1.uuid, &temp.uuid)); // check app_db_get_install_id_for_uuid for app 2 memset(&temp, 0, sizeof(AppDBEntry)); AppInstallId app_two_id = app_db_get_install_id_for_uuid(&app2.uuid); cl_assert(app_one_id > 0); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_install_id(app_two_id, &temp)); cl_assert_equal_b(true, uuid_equal(&app2.uuid, &temp.uuid)); // check app_db_get_install_id_for_uuid for app 3 memset(&temp, 0, sizeof(AppDBEntry)); AppInstallId app_three_id = app_db_get_install_id_for_uuid(&app3.uuid); cl_assert(app_one_id > 0); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_install_id(app_three_id, &temp)); cl_assert_equal_b(true, uuid_equal(&app3.uuid, &temp.uuid)); } void test_app_db__retrieve_app_db_entries_by_uuid(void) { AppDBEntry temp; // check app_db_get_install_id_for_uuid for app 1 memset(&temp, 0, sizeof(AppDBEntry)); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_uuid(&app1.uuid, &temp)); cl_assert_equal_b(true, uuid_equal(&app1.uuid, &temp.uuid)); // check app_db_get_install_id_for_uuid for app 2 memset(&temp, 0, sizeof(AppDBEntry)); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_uuid(&app2.uuid, &temp)); cl_assert_equal_b(true, uuid_equal(&app2.uuid, &temp.uuid)); // check app_db_get_install_id_for_uuid for app 3 memset(&temp, 0, sizeof(AppDBEntry)); cl_assert_equal_i(S_SUCCESS, app_db_get_app_entry_for_uuid(&app3.uuid, &temp)); cl_assert_equal_b(true, uuid_equal(&app3.uuid, &temp.uuid)); } void test_app_db__overwrite(void) { // add 3 of the same. Confirm that the entry was overwritten by checking next ID. cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app1.uuid, sizeof(Uuid), (uint8_t*)&app1, sizeof(AppDBEntry))); cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app1.uuid, sizeof(Uuid), (uint8_t*)&app1, sizeof(AppDBEntry))); cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app1.uuid, sizeof(Uuid), (uint8_t*)&app1, sizeof(AppDBEntry))); cl_assert(app_db_check_next_unique_id() == 4); // add two more duplicates of a different app. Confirm it only increments by 1. cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app2.uuid, sizeof(Uuid), (uint8_t*)&app2, sizeof(AppDBEntry))); cl_assert_equal_i(S_SUCCESS, app_db_insert((uint8_t*)&app2.uuid, sizeof(Uuid), (uint8_t*)&app2, sizeof(AppDBEntry))); cl_assert(app_db_check_next_unique_id() == 4); } void test_app_db__test_exists(void) { cl_assert_equal_b(false, app_db_exists_install_id(-1)); cl_assert_equal_b(false, app_db_exists_install_id(0)); cl_assert_equal_b(true, app_db_exists_install_id(1)); cl_assert_equal_b(true, app_db_exists_install_id(2)); cl_assert_equal_b(true, app_db_exists_install_id(3)); cl_assert_equal_b(false, app_db_exists_install_id(4)); } static const uint8_t some_data[] = {0x01, 0x02, 0x17, 0x54}; void prv_enumerate_entries(AppInstallId install_id, AppDBEntry *entry, void *data) { switch(install_id) { case 1: cl_assert_equal_m(&app1, entry, sizeof(AppDBEntry)); break; case 2: cl_assert_equal_m(&app2, entry, sizeof(AppDBEntry)); break; case 3: cl_assert_equal_m(&app3, entry, sizeof(AppDBEntry)); break; default: break; } cl_assert_equal_m((uint8_t *)some_data, (uint8_t *)data, sizeof(some_data)); } void test_app_db__enumerate(void) { app_db_enumerate_entries(prv_enumerate_entries, (void *)&some_data); }