mirror of
https://github.com/google/pebble.git
synced 2025-03-23 12:12:19 +00:00
352 lines
13 KiB
C
352 lines
13 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 "pebble_asserts.h"
|
|
|
|
#include "applib/unobstructed_area_service.h"
|
|
|
|
// Stubs
|
|
/////////////////////
|
|
#include "stubs_app.h"
|
|
#include "stubs_app_manager.h"
|
|
#include "stubs_app_state.h"
|
|
#include "stubs_events.h"
|
|
#include "stubs_framebuffer.h"
|
|
#include "stubs_graphics.h"
|
|
#include "stubs_logging.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_pbl_malloc.h"
|
|
#include "stubs_pebble_tasks.h"
|
|
#include "stubs_process_manager.h"
|
|
#include "stubs_ui_window.h"
|
|
|
|
// Fakes
|
|
/////////////////////
|
|
#include "fake_event_service.h"
|
|
|
|
// Statics
|
|
/////////////////////
|
|
|
|
void *s_context_target;
|
|
|
|
typedef struct UnobstructedAreaTestData {
|
|
void *context;
|
|
int num_will_change_calls;
|
|
int num_change_calls;
|
|
int num_did_change_calls;
|
|
GRect last_will_change_final_area;
|
|
AnimationProgress last_change_progress;
|
|
} UnobstructedAreaTestData;
|
|
|
|
UnobstructedAreaTestData s_data;
|
|
|
|
static void prv_will_change(GRect final_area, void *context) {
|
|
s_data.last_will_change_final_area = final_area;
|
|
cl_assert_equal_p(context, s_data.context);
|
|
s_data.num_will_change_calls++;
|
|
}
|
|
|
|
static void prv_change(AnimationProgress progress, void *context) {
|
|
s_data.last_change_progress = progress;
|
|
cl_assert_equal_p(context, s_data.context);
|
|
s_data.num_change_calls++;
|
|
}
|
|
|
|
static void prv_did_change(void *context) {
|
|
cl_assert_equal_p(context, s_data.context);
|
|
s_data.num_did_change_calls++;
|
|
}
|
|
|
|
// Test boilerplate
|
|
/////////////////////
|
|
|
|
void test_unobstructed_area_service__initialize(void) {
|
|
s_data = (UnobstructedAreaTestData) {
|
|
.context = &s_context_target,
|
|
.last_change_progress = -1,
|
|
};
|
|
|
|
fake_event_service_init();
|
|
s_app_state_framebuffer = &(FrameBuffer) { .size = DISP_FRAME.size };
|
|
|
|
unobstructed_area_service_init(app_state_get_unobstructed_area_state(), DISP_ROWS);
|
|
}
|
|
|
|
void test_unobstructed_area_service__cleanup(void) {
|
|
app_unobstructed_area_service_unsubscribe();
|
|
unobstructed_area_service_deinit(app_state_get_unobstructed_area_state());
|
|
}
|
|
|
|
// Tests
|
|
//////////////////////
|
|
|
|
void test_unobstructed_area_service__subscribe(void) {
|
|
// Unsubscribing first should not crash
|
|
app_unobstructed_area_service_unsubscribe();
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.will_change);
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.change);
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.did_change);
|
|
|
|
// Subscribing should use the event service
|
|
UnobstructedAreaHandlers handlers = {
|
|
.will_change = prv_will_change,
|
|
.change = prv_change,
|
|
.did_change = prv_did_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.will_change, prv_will_change);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.change, prv_change);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.did_change, prv_did_change);
|
|
|
|
// Unsubscribing after subscription should cancel subscriptions
|
|
app_unobstructed_area_service_unsubscribe();
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.will_change);
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.change);
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.did_change);
|
|
|
|
// Unsubscribing again should not crash
|
|
app_unobstructed_area_service_unsubscribe();
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.will_change);
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.change);
|
|
cl_assert(!app_state_get_unobstructed_area_state()->handlers.did_change);
|
|
}
|
|
|
|
void test_unobstructed_area_service__will_change(void) {
|
|
UnobstructedAreaHandlers handlers = {
|
|
.will_change = prv_will_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.will_change, prv_will_change);
|
|
|
|
const GRect from_area = GRect(0, 0, DISP_COLS, 400);
|
|
const GRect to_area = GRect(0, 0, DISP_COLS, 200);
|
|
unobstructed_area_service_will_change(from_area.size.h, to_area.size.h);
|
|
fake_event_service_handle_last();
|
|
cl_assert_equal_i(s_data.num_will_change_calls, 1);
|
|
const GRect to_area_expected = GRect(0, 0, DISP_COLS, MIN(200, DISP_ROWS));
|
|
cl_assert_equal_grect(s_data.last_will_change_final_area, to_area_expected);
|
|
}
|
|
|
|
void test_unobstructed_area_service__will_change_twice(void) {
|
|
UnobstructedAreaHandlers handlers = {
|
|
.will_change = prv_will_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.will_change, prv_will_change);
|
|
|
|
const GRect from_area = GRect(0, 0, DISP_COLS, 400);
|
|
const GRect to_area = GRect(0, 0, DISP_COLS, 200);
|
|
unobstructed_area_service_will_change(from_area.size.h, to_area.size.h);
|
|
fake_event_service_handle_last();
|
|
|
|
unobstructed_area_service_will_change(from_area.size.h, to_area.size.h);
|
|
cl_assert_passert(fake_event_service_handle_last());
|
|
}
|
|
|
|
void test_unobstructed_area_service__change(void) {
|
|
UnobstructedAreaHandlers handlers = {
|
|
.change = prv_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.change, prv_change);
|
|
|
|
const GRect from_area = GRect(0, 0, DISP_COLS, 400);
|
|
const GRect to_area = GRect(0, 0, DISP_COLS, 200);
|
|
unobstructed_area_service_will_change(from_area.size.h, to_area.size.h);
|
|
fake_event_service_handle_last();
|
|
|
|
const GRect area = GRect(0, 0, DISP_COLS, 200);
|
|
const AnimationProgress progress = ANIMATION_NORMALIZED_MAX / 2;
|
|
unobstructed_area_service_change(area.size.h, to_area.size.h, progress);
|
|
fake_event_service_handle_last();
|
|
cl_assert_equal_i(s_data.num_change_calls, 1);
|
|
cl_assert_equal_i(s_data.last_change_progress, progress);
|
|
}
|
|
|
|
void test_unobstructed_area_service__change_after_subscribe(void) {
|
|
const GRect from_area = GRect(0, 0, DISP_COLS, 400);
|
|
const GRect to_area = GRect(0, 0, DISP_COLS, 200);
|
|
unobstructed_area_service_will_change(from_area.size.h, to_area.size.h);
|
|
|
|
UnobstructedAreaHandlers handlers = {
|
|
.will_change = prv_will_change,
|
|
.change = prv_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.change, prv_change);
|
|
|
|
const GRect area = GRect(0, 0, DISP_COLS, 200);
|
|
const AnimationProgress progress = ANIMATION_NORMALIZED_MAX / 2;
|
|
unobstructed_area_service_change(area.size.h, to_area.size.h, progress);
|
|
fake_event_service_handle_last();
|
|
cl_assert_equal_i(s_data.num_will_change_calls, 1);
|
|
cl_assert_equal_i(s_data.num_change_calls, 1);
|
|
cl_assert_equal_i(s_data.last_change_progress, progress);
|
|
}
|
|
|
|
void test_unobstructed_area_service__change_no_will(void) {
|
|
UnobstructedAreaHandlers handlers = {
|
|
.will_change = prv_will_change,
|
|
.change = prv_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.change, prv_change);
|
|
|
|
const GRect to_area = GRect(0, 0, DISP_COLS, 200);
|
|
const GRect area = GRect(0, 0, DISP_COLS, 200);
|
|
const AnimationProgress progress = ANIMATION_NORMALIZED_MAX / 2;
|
|
unobstructed_area_service_change(area.size.h, to_area.size.h, progress);
|
|
fake_event_service_handle_last();
|
|
cl_assert_equal_i(s_data.num_will_change_calls, 1);
|
|
cl_assert_equal_i(s_data.num_change_calls, 1);
|
|
cl_assert_equal_i(s_data.last_change_progress, progress);
|
|
}
|
|
|
|
void test_unobstructed_area_service__did_change(void) {
|
|
UnobstructedAreaHandlers handlers = {
|
|
.did_change = prv_did_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.did_change, prv_did_change);
|
|
|
|
const GRect from_area = GRect(0, 0, DISP_COLS, 400);
|
|
const GRect to_area = GRect(0, 0, DISP_COLS, 200);
|
|
unobstructed_area_service_will_change(from_area.size.h, to_area.size.h);
|
|
fake_event_service_handle_last();
|
|
|
|
unobstructed_area_service_did_change(to_area.size.h);
|
|
fake_event_service_handle_last();
|
|
cl_assert_equal_i(s_data.num_did_change_calls, 1);
|
|
}
|
|
|
|
void test_unobstructed_area_service__did_change_after_subscribe(void) {
|
|
const GRect from_area = GRect(0, 0, DISP_COLS, 400);
|
|
const GRect to_area = GRect(0, 0, DISP_COLS, 200);
|
|
unobstructed_area_service_will_change(from_area.size.h, to_area.size.h);
|
|
|
|
UnobstructedAreaHandlers handlers = {
|
|
.will_change = prv_will_change,
|
|
.did_change = prv_did_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.did_change, prv_did_change);
|
|
|
|
unobstructed_area_service_did_change(to_area.size.h);
|
|
fake_event_service_handle_last();
|
|
cl_assert_equal_i(s_data.num_will_change_calls, 1);
|
|
cl_assert_equal_i(s_data.num_did_change_calls, 1);
|
|
}
|
|
|
|
void test_unobstructed_area_service__did_change_no_will(void) {
|
|
UnobstructedAreaHandlers handlers = {
|
|
.will_change = prv_will_change,
|
|
.did_change = prv_did_change,
|
|
};
|
|
app_unobstructed_area_service_subscribe(handlers, s_data.context);
|
|
cl_assert(fake_event_service_get_info(PEBBLE_UNOBSTRUCTED_AREA_EVENT)->handler);
|
|
cl_assert_equal_p(app_state_get_unobstructed_area_state()->handlers.did_change, prv_did_change);
|
|
|
|
const GRect to_area = GRect(0, 0, DISP_COLS, 200);
|
|
unobstructed_area_service_did_change(to_area.size.h);
|
|
fake_event_service_handle_last();
|
|
cl_assert_equal_i(s_data.num_will_change_calls, 1);
|
|
cl_assert_equal_i(s_data.num_did_change_calls, 1);
|
|
}
|
|
|
|
void test_unobstructed_area_service__layer_no_clip(void) {
|
|
app_state_get_unobstructed_area_state()->area = GRect(0, 0, 400, 400);
|
|
|
|
Layer root_layer = {
|
|
.bounds = GRect(100, 100, 200, 200),
|
|
};
|
|
GRect unobstructed_bounds;
|
|
layer_get_unobstructed_bounds(&root_layer, &unobstructed_bounds);
|
|
cl_assert_equal_grect(unobstructed_bounds, root_layer.bounds);
|
|
}
|
|
|
|
void test_unobstructed_area_service__layer_clip_x_y(void) {
|
|
app_state_get_unobstructed_area_state()->area = GRect(0, 0, 400, 400);
|
|
|
|
Layer root_layer = {
|
|
.bounds = GRect(210, 220, 300, 300),
|
|
};
|
|
GRect unobstructed_bounds;
|
|
layer_get_unobstructed_bounds(&root_layer, &unobstructed_bounds);
|
|
cl_assert_equal_grect(unobstructed_bounds, GRect(210, 220, 190, 180));
|
|
}
|
|
|
|
void test_unobstructed_area_service__layer_clip_nx_ny(void) {
|
|
app_state_get_unobstructed_area_state()->area = GRect(0, 0, 400, 400);
|
|
|
|
Layer root_layer = {
|
|
.bounds = GRect(-110, -120, 300, 300),
|
|
};
|
|
GRect unobstructed_bounds;
|
|
layer_get_unobstructed_bounds(&root_layer, &unobstructed_bounds);
|
|
cl_assert_equal_grect(unobstructed_bounds, GRect(0, 0, 190, 180));
|
|
}
|
|
|
|
void test_unobstructed_area_service__nested_layer_no_clip(void) {
|
|
app_state_get_unobstructed_area_state()->area = GRect(0, 0, 400, 400);
|
|
|
|
Layer root_layer = {
|
|
.bounds = GRect(30, 30, 30, 30),
|
|
};
|
|
Layer layer = {
|
|
.bounds = GRect(20, 20, 20, 20),
|
|
};
|
|
layer_add_child(&root_layer, &layer);
|
|
GRect unobstructed_bounds;
|
|
layer_get_unobstructed_bounds(&layer, &unobstructed_bounds);
|
|
cl_assert_equal_grect(unobstructed_bounds, layer.bounds);
|
|
}
|
|
|
|
void test_unobstructed_area_service__nested_layer_clip_x_y(void) {
|
|
app_state_get_unobstructed_area_state()->area = GRect(0, 0, 400, 400);
|
|
Layer root_layer = {
|
|
.bounds = GRect(150, 120, 10, 10), // The size of the parent layer has no affect
|
|
};
|
|
Layer layer = {
|
|
.bounds = GRect(110, 130, 300, 200),
|
|
};
|
|
layer_add_child(&root_layer, &layer);
|
|
GRect unobstructed_bounds;
|
|
layer_get_unobstructed_bounds(&layer, &unobstructed_bounds);
|
|
cl_assert_equal_grect(unobstructed_bounds, GRect(110, 130, 140, 150));
|
|
}
|
|
|
|
void test_unobstructed_area_service__nested_layer_clip_nx_ny(void) {
|
|
app_state_get_unobstructed_area_state()->area = GRect(0, 0, 400, 400);
|
|
Layer root_layer = {
|
|
.bounds = GRect(-150, -120, 10, 10), // The size of the parent layer has no affect
|
|
};
|
|
Layer layer = {
|
|
.bounds = GRect(-110, -130, 300, 290),
|
|
};
|
|
layer_add_child(&root_layer, &layer);
|
|
GRect unobstructed_bounds;
|
|
layer_get_unobstructed_bounds(&layer, &unobstructed_bounds);
|
|
cl_assert_equal_grect(unobstructed_bounds, GRect(150, 120, 40, 40));
|
|
}
|