tests: Add test for destroyed frame clock free timeline actor

This would without 'clutter/timeline: Clear stage view listener when
actor destroyed' result in backtraces such as

Program terminated with signal SIGSEGV, Segmentation fault.
  #0  on_stage_stage_views_changed ()
  #1  g_closure_invoke ()
  #2  signal_emit_unlocked_R ()
  #3  g_signal_emit_valist ()
  #4  g_signal_emit ()
  #5  update_stage_views ()
  #6  clutter_actor_update_stage_views ()
  #7  clutter_stage_update_actor_stage_views ()
  #8  handle_frame_clock_frame ()
  #9  clutter_frame_clock_dispatch ()
  #10 frame_clock_source_dispatch ()
  #11 g_main_dispatch ()

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1719>
This commit is contained in:
Jonas Ådahl 2021-02-08 18:40:18 +01:00 committed by Robert Mader
parent b838ba8166
commit c60cba4eeb

View File

@ -1077,6 +1077,81 @@ meta_test_actor_stage_views_and_frame_clocks_freed (void)
clutter_actor_destroy (actor_2); clutter_actor_destroy (actor_2);
} }
static void
ensure_view_count (int n_views)
{
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaMonitorManagerTest *monitor_manager_test =
META_MONITOR_MANAGER_TEST (monitor_manager);
MonitorTestCaseSetup test_case_setup;
MetaMonitorTestSetup *test_setup;
test_case_setup = initial_test_case_setup;
test_case_setup.n_outputs = n_views;
test_case_setup.n_crtcs = n_views;
test_setup = create_monitor_test_setup (&test_case_setup,
MONITOR_TEST_FLAG_NO_STORED);
meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup);
}
static void
meta_test_timeline_actor_destroyed (void)
{
MetaBackend *backend = meta_get_backend ();
ClutterActor *stage;
GList *stage_views;
ClutterActor *persistent_actor;
ClutterActor *actor;
ClutterTimeline *timeline;
gboolean did_stage_views_changed = FALSE;
ensure_view_count (0);
stage = meta_backend_get_stage (backend);
clutter_actor_show (stage);
persistent_actor = clutter_actor_new ();
clutter_actor_add_child (stage, persistent_actor);
stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage));
g_assert_null (stage_views);
stage_views = clutter_actor_peek_stage_views (stage);
g_assert_null (stage_views);
g_assert_null (clutter_actor_pick_frame_clock (stage, NULL));
actor = clutter_actor_new ();
clutter_actor_add_child (stage, actor);
g_assert_null (clutter_actor_pick_frame_clock (actor, NULL));
timeline = clutter_timeline_new_for_actor (actor, 100);
clutter_timeline_start (timeline);
g_signal_connect (stage, "stage-views-changed",
G_CALLBACK (on_stage_views_changed),
&did_stage_views_changed);
clutter_actor_destroy (actor);
g_object_unref (timeline);
ensure_view_count (1);
stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage));
g_assert_cmpint (g_list_length (stage_views), ==, 1);
g_assert_false (did_stage_views_changed);
clutter_actor_queue_redraw (persistent_actor);
clutter_stage_schedule_update (CLUTTER_STAGE (stage));
wait_for_paint (stage);
g_assert_true (did_stage_views_changed);
g_signal_handlers_disconnect_by_func (stage, on_stage_views_changed,
&did_stage_views_changed);
clutter_actor_destroy (persistent_actor);
}
static void static void
init_tests (int argc, char **argv) init_tests (int argc, char **argv)
{ {
@ -1104,6 +1179,8 @@ init_tests (int argc, char **argv)
meta_test_actor_stage_views_parent_views_changed); meta_test_actor_stage_views_parent_views_changed);
g_test_add_func ("/stage-views/actor-stage-views-and-frame-clocks-freed", g_test_add_func ("/stage-views/actor-stage-views-and-frame-clocks-freed",
meta_test_actor_stage_views_and_frame_clocks_freed); meta_test_actor_stage_views_and_frame_clocks_freed);
g_test_add_func ("/stage-views/timeline/actor-destroyed",
meta_test_timeline_actor_destroyed);
} }
int int