Route app thread orchestration through app core
This commit is contained in:
@@ -565,6 +565,16 @@ add_test(NAME pp_app_core_app_frame_tests COMMAND pp_app_core_app_frame_tests)
|
||||
set_tests_properties(pp_app_core_app_frame_tests PROPERTIES
|
||||
LABELS "app;desktop-fast;fuzz")
|
||||
|
||||
add_executable(pp_app_core_app_thread_tests
|
||||
app_core/app_thread_tests.cpp)
|
||||
target_link_libraries(pp_app_core_app_thread_tests PRIVATE
|
||||
pp_app_core
|
||||
pp_test_harness)
|
||||
|
||||
add_test(NAME pp_app_core_app_thread_tests COMMAND pp_app_core_app_thread_tests)
|
||||
set_tests_properties(pp_app_core_app_thread_tests PROPERTIES
|
||||
LABELS "app;desktop-fast;fuzz")
|
||||
|
||||
add_executable(pp_app_core_app_input_tests
|
||||
app_core/app_input_tests.cpp)
|
||||
target_link_libraries(pp_app_core_app_input_tests PRIVATE
|
||||
@@ -1012,6 +1022,31 @@ if(TARGET pano_cli)
|
||||
WILL_FAIL TRUE
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-frame\".*\"message\":\"resize dimensions")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_thread_dispatch_smoke
|
||||
COMMAND pano_cli plan-app-thread --kind dispatch --unique --queued-tasks 2 --wait)
|
||||
set_tests_properties(pano_cli_plan_app_thread_dispatch_smoke PROPERTIES
|
||||
LABELS "app;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-thread\".*\"kind\":\"dispatch\".*\"queueTask\":true.*\"removeMatchingUniqueTask\":true.*\"notifyWorker\":true.*\"waitForCompletion\":true")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_thread_ui_loop_smoke
|
||||
COMMAND pano_cli plan-app-thread --kind ui-loop --dt 0.25 --frame-accumulator 0.5 --fps-accumulator 0.9 --reload-accumulator 0.9 --rendered-frames 7 --live-reload)
|
||||
set_tests_properties(pano_cli_plan_app_thread_ui_loop_smoke PROPERTIES
|
||||
LABELS "app;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-thread\".*\"kind\":\"ui-loop\".*\"frameAccumulator\":0.75.*\"fpsAccumulator\":0.*\"reportRenderedFrames\":true.*\"reportedFrameCount\":7.*\"checkLiveAssetReload\":true")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_thread_stop_smoke
|
||||
COMMAND pano_cli plan-app-thread --kind stop --not-joinable)
|
||||
set_tests_properties(pano_cli_plan_app_thread_stop_smoke PROPERTIES
|
||||
LABELS "app;integration;desktop-fast"
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-thread\".*\"kind\":\"stop\".*\"markNotRunning\":true.*\"notifyWorker\":true.*\"joinThread\":false")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_thread_rejects_bad_timer
|
||||
COMMAND pano_cli plan-app-thread --kind ui-loop --bad-timer)
|
||||
set_tests_properties(pano_cli_plan_app_thread_rejects_bad_timer PROPERTIES
|
||||
LABELS "app;integration;desktop-fast;fuzz"
|
||||
WILL_FAIL TRUE
|
||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-app-thread\".*\"message\":\"UI loop timer values")
|
||||
|
||||
add_test(NAME pano_cli_plan_app_input_pointer_smoke
|
||||
COMMAND pano_cli plan-app-input --kind pointer --x 100 --y 50 --zoom 2)
|
||||
set_tests_properties(pano_cli_plan_app_input_pointer_smoke PROPERTIES
|
||||
|
||||
134
tests/app_core/app_thread_tests.cpp
Normal file
134
tests/app_core/app_thread_tests.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "app_core/app_thread.h"
|
||||
#include "test_harness.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace {
|
||||
|
||||
void task_dispatch_executes_immediately_on_target_thread(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_task_dispatch(true, true, 3, true, true, true);
|
||||
|
||||
PP_EXPECT(harness, plan.execute_immediately);
|
||||
PP_EXPECT(harness, !plan.queue_task);
|
||||
PP_EXPECT(harness, !plan.remove_matching_unique_task);
|
||||
PP_EXPECT(harness, !plan.notify_worker);
|
||||
PP_EXPECT(harness, !plan.wait_for_completion);
|
||||
PP_EXPECT(harness, plan.request_redraw);
|
||||
}
|
||||
|
||||
void task_dispatch_queues_unique_work_and_waits_for_running_worker(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_task_dispatch(false, true, 2, true, true, false);
|
||||
|
||||
PP_EXPECT(harness, !plan.execute_immediately);
|
||||
PP_EXPECT(harness, plan.queue_task);
|
||||
PP_EXPECT(harness, plan.remove_matching_unique_task);
|
||||
PP_EXPECT(harness, plan.notify_worker);
|
||||
PP_EXPECT(harness, plan.wait_for_completion);
|
||||
PP_EXPECT(harness, !plan.request_redraw);
|
||||
}
|
||||
|
||||
void task_dispatch_does_not_wait_for_stopped_worker(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_task_dispatch(false, false, 0, false, true, false);
|
||||
|
||||
PP_EXPECT(harness, plan.queue_task);
|
||||
PP_EXPECT(harness, plan.notify_worker);
|
||||
PP_EXPECT(harness, !plan.wait_for_completion);
|
||||
}
|
||||
|
||||
void render_queue_drain_wraps_non_empty_work_in_context(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto empty = pp::app::plan_app_render_queue_drain(0);
|
||||
const auto work = pp::app::plan_app_render_queue_drain(4);
|
||||
|
||||
PP_EXPECT(harness, empty.mark_running);
|
||||
PP_EXPECT(harness, !empty.drain_tasks);
|
||||
PP_EXPECT(harness, !empty.wrap_in_render_context);
|
||||
PP_EXPECT(harness, work.mark_running);
|
||||
PP_EXPECT(harness, work.drain_tasks);
|
||||
PP_EXPECT(harness, work.wrap_in_render_context);
|
||||
PP_EXPECT(harness, work.task_count == 4U);
|
||||
}
|
||||
|
||||
void ui_thread_tick_runs_tasks_and_schedules_redraw(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_ui_thread_tick(3, true);
|
||||
|
||||
PP_EXPECT(harness, plan.mark_running);
|
||||
PP_EXPECT(harness, plan.execute_tasks);
|
||||
PP_EXPECT(harness, plan.tick_app);
|
||||
PP_EXPECT(harness, plan.update_before_render);
|
||||
PP_EXPECT(harness, plan.enqueue_render_frame);
|
||||
PP_EXPECT(harness, plan.task_count == 3U);
|
||||
}
|
||||
|
||||
void ui_loop_timers_report_fps_and_reload_on_threshold(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto plan = pp::app::plan_app_ui_loop_timers(0.25F, 0.5F, 0.9F, 0.9F, 7, true);
|
||||
|
||||
PP_EXPECT(harness, plan);
|
||||
if (plan) {
|
||||
PP_EXPECT(harness, plan.value().update_platform_frame);
|
||||
PP_EXPECT(harness, plan.value().frame_accumulator == 0.75F);
|
||||
PP_EXPECT(harness, plan.value().fps_accumulator == 0.0F);
|
||||
PP_EXPECT(harness, plan.value().report_rendered_frames);
|
||||
PP_EXPECT(harness, plan.value().reported_frame_count == 7);
|
||||
PP_EXPECT(harness, plan.value().rendered_frames_after_report == 0);
|
||||
PP_EXPECT(harness, plan.value().reload_accumulator == 0.0F);
|
||||
PP_EXPECT(harness, plan.value().check_live_asset_reload);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_loop_timers_reject_invalid_values(pp::tests::Harness& harness)
|
||||
{
|
||||
PP_EXPECT(harness, !pp::app::plan_app_ui_loop_timers(-0.1F, 0.0F, 0.0F, 0.0F, 0, false));
|
||||
PP_EXPECT(harness, !pp::app::plan_app_ui_loop_timers(0.1F, std::nanf(""), 0.0F, 0.0F, 0, false));
|
||||
PP_EXPECT(harness, !pp::app::plan_app_ui_loop_timers(0.1F, 0.0F, 0.0F, 0.0F, -1, false));
|
||||
}
|
||||
|
||||
void ui_loop_redraw_increments_rendered_frames(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto idle = pp::app::plan_app_ui_loop_redraw(false, 2);
|
||||
const auto redraw = pp::app::plan_app_ui_loop_redraw(true, 2);
|
||||
|
||||
PP_EXPECT(harness, idle.tick_app);
|
||||
PP_EXPECT(harness, !idle.enqueue_render_frame);
|
||||
PP_EXPECT(harness, idle.rendered_frames == 2);
|
||||
PP_EXPECT(harness, redraw.update_before_render);
|
||||
PP_EXPECT(harness, redraw.enqueue_render_frame);
|
||||
PP_EXPECT(harness, redraw.reset_frame_accumulator);
|
||||
PP_EXPECT(harness, redraw.rendered_frames == 3);
|
||||
}
|
||||
|
||||
void thread_start_stop_preserve_legacy_intents(pp::tests::Harness& harness)
|
||||
{
|
||||
const auto start = pp::app::plan_app_thread_start();
|
||||
const auto stop_joinable = pp::app::plan_app_thread_stop(true);
|
||||
const auto stop_detached = pp::app::plan_app_thread_stop(false);
|
||||
|
||||
PP_EXPECT(harness, start.start_thread);
|
||||
PP_EXPECT(harness, start.mark_running);
|
||||
PP_EXPECT(harness, stop_joinable.mark_not_running);
|
||||
PP_EXPECT(harness, stop_joinable.notify_worker);
|
||||
PP_EXPECT(harness, stop_joinable.join_thread);
|
||||
PP_EXPECT(harness, !stop_detached.join_thread);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
pp::tests::Harness harness;
|
||||
harness.run("task dispatch executes immediately on target thread", task_dispatch_executes_immediately_on_target_thread);
|
||||
harness.run("task dispatch queues unique work and waits for running worker", task_dispatch_queues_unique_work_and_waits_for_running_worker);
|
||||
harness.run("task dispatch does not wait for stopped worker", task_dispatch_does_not_wait_for_stopped_worker);
|
||||
harness.run("render queue drain wraps non empty work in context", render_queue_drain_wraps_non_empty_work_in_context);
|
||||
harness.run("ui thread tick runs tasks and schedules redraw", ui_thread_tick_runs_tasks_and_schedules_redraw);
|
||||
harness.run("ui loop timers report fps and reload on threshold", ui_loop_timers_report_fps_and_reload_on_threshold);
|
||||
harness.run("ui loop timers reject invalid values", ui_loop_timers_reject_invalid_values);
|
||||
harness.run("ui loop redraw increments rendered frames", ui_loop_redraw_increments_rendered_frames);
|
||||
harness.run("thread start stop preserve legacy intents", thread_start_stop_preserve_legacy_intents);
|
||||
return harness.finish();
|
||||
}
|
||||
Reference in New Issue
Block a user