/* * 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 "flash_region/flash_region.h" #include "syscall/syscall.h" #include "services/normal/wakeup.h" #include "services/common/event_service.h" #include "services/normal/filesystem/pfs.h" #include "services/normal/settings/settings_file.h" #include "process_management/app_install_manager.h" #include "util/attributes.h" #include "clar.h" // Fakes ////////////////////////////////////////////////////////// #include "fake_app_manager.h" #include "fake_new_timer.h" #include "fake_pbl_malloc.h" #include "fake_rtc.h" #include "fake_spi_flash.h" #include "fake_system_task.h" #include "fake_time.h" // Stubs ////////////////////////////////////////////////////////// #include "stubs_analytics.h" #include "stubs_events.h" #include "stubs_logging.h" #include "stubs_print.h" #include "stubs_serial.h" #include "stubs_passert.h" #include "stubs_sleep.h" #include "stubs_mutex.h" #include "stubs_hexdump.h" #include "stubs_pebble_process_md.h" #include "stubs_prompt.h" #include "stubs_rand_ptr.h" #include "stubs_task_watchdog.h" #include "stubs_compiled_with_legacy2_sdk.h" #include "stubs_memory_layout.h" #define SETTINGS_FILE_NAME "wakeup" #define SETTINGS_FILE_SIZE 2048 #define WAKEUP_REASON 0x1337 #define TIMESTAMP 1337 // Structures //////////////////////////////////// typedef struct PACKED { Uuid uuid; int32_t reason; bool repeating; uint16_t repeat_hours_missed; bool notify_if_missed; } WakeupEntryV1; typedef struct PACKED { Uuid uuid; int32_t reason; bool repeating; uint16_t repeat_hours_missed; bool notify_if_missed; time_t timestamp; bool utc; } WakeupEntryV2; // Globals //////////////////////////////////// static const Uuid app_uuid = (Uuid) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; static PebbleProcessMd s_test_app_md = { .uuid = (Uuid) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 } }; static AppInstallEntry s_app_install_entry = { .install_id = 1, }; static WakeupEntryV1 w_entry; // Local Stubs //////////////////////////////////// void event_service_init(PebbleEventType type, EventServiceAddSubscriberCallback start_cb, EventServiceRemoveSubscriberCallback stop_cb) { return; } void wakeup_popup_window(uint8_t missed_apps_count, uint8_t *missed_apps_banks) { return; } bool app_install_get_entry_from_install_id(const AppInstallId id, AppInstallEntry *entry) { *entry = s_app_install_entry; return true; } bool clock_is_timezone_set(void) { return false; } // Helpers //////////////////////////////////// void open_settings_file(SettingsFile *file) { cl_must_pass(settings_file_open(file, SETTINGS_FILE_NAME, SETTINGS_FILE_SIZE)); } void close_settings_file(SettingsFile *file) { settings_file_close(file); } // Tests //////////////////////////////////// void test_migrate_wakeup__initialize(void) { fake_spi_flash_init(0, 0x1000000); pfs_init(false); pfs_format(false); // Load pre-migration wakeup entry onto pfs SettingsFile file; const int32_t timestamp = TIMESTAMP; // Create the Migration Entry w_entry = (WakeupEntryV1) { .uuid = app_uuid, .reason = WAKEUP_REASON, .repeating = false, .repeat_hours_missed = 0, .notify_if_missed = true }; open_settings_file(&file); cl_must_pass(settings_file_set(&file, (uint8_t*)×tamp, sizeof(timestamp), (uint8_t*)&w_entry, sizeof(w_entry))); close_settings_file(&file); } void test_migrate_wakeup__test_migration_of_wakeup_entries(void) { SettingsFile file; WakeupId wakeup_id = TIMESTAMP; WakeupEntryV1 wakeup_entry_v1; open_settings_file(&file); cl_must_pass(settings_file_get(&file, (uint8_t*)&wakeup_id, sizeof(wakeup_id), (uint8_t*)&wakeup_entry_v1, sizeof(wakeup_entry_v1))); cl_assert_equal_i(wakeup_entry_v1.reason, WAKEUP_REASON); cl_assert_equal_i(wakeup_entry_v1.repeat_hours_missed, 0); cl_assert(!wakeup_entry_v1.repeating); cl_assert(wakeup_entry_v1.notify_if_missed); uuid_equal(&wakeup_entry_v1.uuid, &app_uuid); close_settings_file(&file); // Migrate the timezone and check that the new entry is correct and the second version // of a Wakeup Entry wakeup_init(); WakeupEntryV2 wakeup_entry_v2; open_settings_file(&file); cl_must_pass(settings_file_exists(&file, (uint8_t*)&wakeup_id, sizeof(wakeup_id))); cl_assert_equal_i(settings_file_get_len(&file, (uint8_t*)&wakeup_id, sizeof(wakeup_id)), sizeof(WakeupEntryV2)); cl_must_pass(settings_file_get(&file, (uint8_t*)&wakeup_id, sizeof(wakeup_id), (uint8_t*)&wakeup_entry_v2, sizeof(wakeup_entry_v2))); cl_assert_equal_i(wakeup_entry_v2.reason, wakeup_entry_v1.reason); cl_assert_equal_i(wakeup_entry_v2.repeat_hours_missed, wakeup_entry_v1.repeat_hours_missed); cl_assert_equal_i(wakeup_entry_v2.timestamp, (int32_t)TIMESTAMP); cl_assert(wakeup_entry_v2.utc == false); cl_assert(wakeup_entry_v2.repeating == wakeup_entry_v1.repeating); cl_assert(wakeup_entry_v2.notify_if_missed == wakeup_entry_v1.notify_if_missed); uuid_equal(&wakeup_entry_v2.uuid, &wakeup_entry_v2.uuid); close_settings_file(&file); }