mirror of
https://github.com/google/pebble.git
synced 2025-03-28 05:47:46 +00:00
412 lines
12 KiB
C
412 lines
12 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 "kernel/events.h"
|
|
#include "services/normal/blob_db/pin_db.h"
|
|
#include "services/normal/timeline/calendar.h"
|
|
#include "services/normal/timeline/event.h"
|
|
#include "services/normal/timeline/timeline.h"
|
|
#include "system/logging.h"
|
|
|
|
#include "clar.h"
|
|
|
|
// Stubs
|
|
////////////////////////////////////////////////////////////////
|
|
#include "stubs_analytics.h"
|
|
#include "stubs_ancs.h"
|
|
#include "stubs_ancs_notifications.h"
|
|
#include "stubs_app_cache.h"
|
|
#include "stubs_app_install_manager.h"
|
|
#include "stubs_app_manager.h"
|
|
#include "stubs_blob_db.h"
|
|
#include "stubs_blob_db_sync.h"
|
|
#include "stubs_blob_db_sync_util.h"
|
|
#include "stubs_event_loop.h"
|
|
#include "stubs_event_service_client.h"
|
|
#include "stubs_hexdump.h"
|
|
#include "stubs_i18n.h"
|
|
#include "stubs_layout_layer.h"
|
|
#include "stubs_logging.h"
|
|
#include "stubs_modal_manager.h"
|
|
#include "stubs_mutex.h"
|
|
#include "stubs_notification_storage.h"
|
|
#include "stubs_notifications.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_phone_call_util.h"
|
|
#include "stubs_prompt.h"
|
|
#include "stubs_rand_ptr.h"
|
|
#include "stubs_regular_timer.h"
|
|
#include "stubs_reminder_db.h"
|
|
#include "stubs_session.h"
|
|
#include "stubs_sleep.h"
|
|
#include "stubs_system_task.h"
|
|
#include "stubs_task_watchdog.h"
|
|
#include "stubs_text_layer_flow.h"
|
|
#include "stubs_timeline.h"
|
|
#include "stubs_timeline_pin_window.h"
|
|
#include "stubs_window_stack.h"
|
|
|
|
// Fakes
|
|
////////////////////////////////////////////////////////////////
|
|
#include "fake_new_timer.h"
|
|
#include "fake_pbl_malloc.h"
|
|
#include "fake_pebble_tasks.h"
|
|
#include "fake_rtc.h"
|
|
#include "fake_spi_flash.h"
|
|
#include "fake_settings_file.h"
|
|
#include "fake_events.h"
|
|
|
|
bool calendar_layout_verify(bool existing_attributes[]) {
|
|
return true;
|
|
}
|
|
|
|
bool weather_layout_verify(bool existing_attributes[]) {
|
|
return true;
|
|
}
|
|
|
|
const TimelineEventImpl *timeline_peek_get_event_service(void) {
|
|
return NULL;
|
|
}
|
|
|
|
// Helpers
|
|
////////////////////////////////////////////////////////////////
|
|
static bool s_in_calendar_event = false;
|
|
|
|
static bool prv_get_calendar_ongoing(void) {
|
|
PebbleEvent event = fake_event_get_last();
|
|
if (event.type == PEBBLE_CALENDAR_EVENT) {
|
|
s_in_calendar_event = event.calendar.is_event_ongoing;
|
|
}
|
|
return s_in_calendar_event;
|
|
}
|
|
|
|
// Fake pins
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
static Attribute title_attr = {
|
|
.id = AttributeIdTitle,
|
|
.cstring = "title",
|
|
};
|
|
|
|
static TimelineItem item1 = {
|
|
.header = {
|
|
.id = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
.timestamp = 10*60,
|
|
.duration = 10,
|
|
.type = TimelineItemTypePin,
|
|
.all_day = false,
|
|
.layout = LayoutIdCalendar,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &title_attr,
|
|
},
|
|
};
|
|
|
|
static TimelineItem item2 = {
|
|
.header = {
|
|
.id = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
.timestamp = 15*60,
|
|
.duration = 20,
|
|
.type = TimelineItemTypePin,
|
|
.all_day = false,
|
|
.layout = LayoutIdCalendar,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &title_attr,
|
|
},
|
|
};
|
|
|
|
static TimelineItem item3 = {
|
|
.header = {
|
|
.id = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
.timestamp = 25*60,
|
|
.duration = 5,
|
|
.type = TimelineItemTypePin,
|
|
.all_day = false,
|
|
.layout = LayoutIdCalendar,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &title_attr,
|
|
},
|
|
};
|
|
|
|
static TimelineItem item4 = {
|
|
.header = {
|
|
.id = {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
.timestamp = 100*60,
|
|
.duration = 10,
|
|
.type = TimelineItemTypePin,
|
|
.all_day = false,
|
|
.layout = LayoutIdCalendar,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &title_attr,
|
|
},
|
|
};
|
|
|
|
// NOT A CALENDAR PIN
|
|
static TimelineItem item5 = {
|
|
.header = {
|
|
.id = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
.timestamp = 10*60,
|
|
.duration = 10,
|
|
.type = TimelineItemTypePin,
|
|
.all_day = false,
|
|
.layout = LayoutIdWeather,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &title_attr,
|
|
},
|
|
};
|
|
|
|
// ALL DAY PIN
|
|
static TimelineItem item6 = {
|
|
.header = {
|
|
.id = {0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
|
.timestamp = 100*60,
|
|
.duration = 10,
|
|
.type = TimelineItemTypePin,
|
|
.all_day = true,
|
|
.layout = LayoutIdCalendar,
|
|
},
|
|
.attr_list = {
|
|
.num_attributes = 1,
|
|
.attributes = &title_attr,
|
|
},
|
|
};
|
|
|
|
// Setup
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
void test_calendar__initialize(void) {
|
|
s_in_calendar_event = false;
|
|
rtc_set_time(0);
|
|
fake_event_init();
|
|
pin_db_init();
|
|
}
|
|
|
|
void test_calendar__cleanup(void) {
|
|
timeline_event_deinit();
|
|
stub_new_timer_cleanup();
|
|
fake_settings_file_reset();
|
|
}
|
|
|
|
// Tests
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
void test_calendar__no_events(void) {
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert_equal_i(timer_id, TIMER_INVALID_ID);
|
|
}
|
|
|
|
void test_calendar__init_with_future_event(void) {
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
|
|
cl_assert(timeline_add(&item1));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert_equal_i(fake_event_get_count(), 2);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert(timer_id != TIMER_INVALID_ID);
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(10*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
}
|
|
|
|
void test_calendar_handle__future_event_added_and_removed(void) {
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert_equal_i(timer_id, TIMER_INVALID_ID);
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
|
|
cl_assert(timeline_add(&item1));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert_equal_i(fake_event_get_count(), 2);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(10*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
|
|
cl_assert(timeline_remove(&item1.header.id));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert_equal_i(fake_event_get_count(), 3);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
}
|
|
|
|
void test_calendar__init_with_ongoing_event(void) {
|
|
cl_assert(timeline_add(&item1));
|
|
timeline_event_handle_blobdb_event();
|
|
rtc_set_time(15 * 60);
|
|
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert(timer_id != TIMER_INVALID_ID);
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(5*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
}
|
|
|
|
void test_calendar_handle__ongoing_event_added_and_removed(void) {
|
|
rtc_set_time(15 * 60);
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert_equal_i(timer_id, TIMER_INVALID_ID);
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
|
|
cl_assert(timeline_add(&item1));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert_equal_i(fake_event_get_count(), 2);
|
|
cl_assert(prv_get_calendar_ongoing());
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(5*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
|
|
cl_assert(timeline_remove(&item1.header.id));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert_equal_i(fake_event_get_count(), 3);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
}
|
|
|
|
void test_calendar__init_with_past_event(void) {
|
|
cl_assert(timeline_add(&item1));
|
|
timeline_event_handle_blobdb_event();
|
|
rtc_set_time(30 * 60);
|
|
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert_equal_i(timer_id, TIMER_INVALID_ID);
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
}
|
|
|
|
void test_calendar_handle__past_event_added_and_removed(void) {
|
|
rtc_set_time(30 * 60);
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert_equal_i(timer_id, TIMER_INVALID_ID);
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
|
|
cl_assert(timeline_add(&item1));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert_equal_i(fake_event_get_count(), 2);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
|
|
cl_assert(timeline_remove(&item1.header.id));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert_equal_i(fake_event_get_count(), 3);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
}
|
|
|
|
void test_calendar__timer_test(void) {
|
|
cl_assert(timeline_add(&item1));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert(timeline_add(&item2));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert(timeline_add(&item3));
|
|
timeline_event_handle_blobdb_event();
|
|
cl_assert(timeline_add(&item4));
|
|
timeline_event_handle_blobdb_event();
|
|
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert(timer_id != TIMER_INVALID_ID);
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(10*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
|
|
rtc_set_time(10 * 60);
|
|
cl_assert(stub_new_timer_fire(timer_id));
|
|
cl_assert_equal_i(fake_event_get_count(), 2);
|
|
cl_assert(prv_get_calendar_ongoing());
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(10*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
|
|
rtc_set_time(20 * 60);
|
|
cl_assert(stub_new_timer_fire(timer_id));
|
|
cl_assert_equal_i(fake_event_get_count(), 3);
|
|
cl_assert(prv_get_calendar_ongoing());
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(15*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
|
|
rtc_set_time(35 * 60);
|
|
cl_assert(stub_new_timer_fire(timer_id));
|
|
cl_assert_equal_i(fake_event_get_count(), 4);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(65*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
|
|
rtc_set_time(100 * 60);
|
|
cl_assert(stub_new_timer_fire(timer_id));
|
|
cl_assert_equal_i(fake_event_get_count(), 5);
|
|
cl_assert(prv_get_calendar_ongoing());
|
|
cl_assert(stub_new_timer_is_scheduled(timer_id));
|
|
cl_assert_equal_i(10*60, stub_new_timer_timeout(timer_id) / 1000);
|
|
|
|
rtc_set_time(110 * 60);
|
|
cl_assert(stub_new_timer_fire(timer_id));
|
|
cl_assert_equal_i(fake_event_get_count(), 6);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
}
|
|
|
|
void test_calendar__handle_non_calendar_pins(void) {
|
|
// Insert a random pin (non calendar event)
|
|
cl_assert(timeline_add(&item5));
|
|
timeline_event_handle_blobdb_event();
|
|
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert_equal_i(timer_id, TIMER_INVALID_ID);
|
|
}
|
|
|
|
void test_calendar__handle_all_day_pins(void) {
|
|
// Insert an all day pin
|
|
cl_assert(timeline_add(&item6));
|
|
timeline_event_handle_blobdb_event();
|
|
|
|
timeline_event_init();
|
|
cl_assert_equal_i(fake_event_get_count(), 1);
|
|
cl_assert(!prv_get_calendar_ongoing());
|
|
TimerID timer_id = stub_new_timer_get_next();
|
|
cl_assert(!stub_new_timer_is_scheduled(timer_id));
|
|
}
|