diff --git a/src/tests/clutter/conform/timeline-interpolate.c b/src/tests/clutter/conform/timeline-interpolate.c index 6167f1e9f..4c9d058c5 100644 --- a/src/tests/clutter/conform/timeline-interpolate.c +++ b/src/tests/clutter/conform/timeline-interpolate.c @@ -5,21 +5,13 @@ #include "tests/clutter-test-utils.h" -/* We ask for 1 frame per millisecond. - * Whenever this rate can't be achieved then the timeline - * will interpolate the number frames that should have - * passed between timeouts. */ -#define TEST_TIMELINE_FPS 1000 -#define TEST_TIMELINE_DURATION 5000 +#define TEST_TIMELINE_DURATION 3000 -/* We are at the mercy of the system scheduler so this - * may not be a very reliable tolerance. - * - * It's set as very tolerable (1 ms shorter than the frame interval) as - * otherwise CI, which are very prone to not get CPU time scheduled, tend to - * often fail. +/* + * Make the test tolarate being half a second off track in each direction, + * the thing we're testing for will still be tested for. */ -#define TEST_ERROR_TOLERANCE ((TEST_TIMELINE_FPS / 4) - 1) +#define TEST_ERROR_TOLERANCE 500 typedef struct _TestState { @@ -28,7 +20,7 @@ typedef struct _TestState int new_frame_counter; int expected_frame; int completion_count; - gboolean passed; + int cycle_frame_counter; } TestState; @@ -41,7 +33,6 @@ new_frame_cb (ClutterTimeline *timeline, int current_frame; long msec_diff; int loop_overflow = 0; - static int step = 1; current_time = g_get_real_time (); @@ -61,57 +52,100 @@ new_frame_cb (ClutterTimeline *timeline, state->expected_frame = TEST_TIMELINE_DURATION; } - if (current_frame >= (state->expected_frame-TEST_ERROR_TOLERANCE) - && current_frame <= (state->expected_frame+TEST_ERROR_TOLERANCE)) + switch (state->cycle_frame_counter) { - g_test_message ("elapsed milliseconds=%-5li " - "expected frame=%-4i actual frame=%-4i (OK)", - msec_diff, - state->expected_frame, - current_frame); - } - else - { - g_test_message ("elapsed milliseconds=%-5li " - "expected frame=%-4i actual frame=%-4i (FAILED)", - msec_diff, - state->expected_frame, - current_frame); - state->passed = FALSE; + case 0: + case 1: + if (current_frame >= (state->expected_frame - TEST_ERROR_TOLERANCE) && + current_frame <= (state->expected_frame + TEST_ERROR_TOLERANCE)) + { + g_test_message ("elapsed milliseconds=%-5li " + "expected frame=%-4i actual frame=%-4i (OK)", + msec_diff, + state->expected_frame, + current_frame); + } + else + { + g_test_message ("elapsed milliseconds=%-5li " + "expected frame=%-4i actual frame=%-4i (FAILED)", + msec_diff, + state->expected_frame, + current_frame); + g_test_fail (); + } + break; + case 2: + g_assert_cmpint (current_frame, ==, TEST_TIMELINE_DURATION); + break; + default: + g_assert_not_reached (); } - if (step>0) + /* We already tested that we interpolated when looping, lets stop now. */ + if (state->completion_count == 1 && + state->cycle_frame_counter == 0) { - state->expected_frame = current_frame + (TEST_TIMELINE_FPS / 4); - g_test_message ("Sleeping for 250ms " - "so next frame should be (%i + %i) = %i", - current_frame, - (TEST_TIMELINE_FPS / 4), - state->expected_frame); - g_usleep (250000); - } - else - { - state->expected_frame = current_frame + TEST_TIMELINE_FPS; - g_test_message ("Sleeping for 1sec " - "so next frame should be (%i + %i) = %i", - current_frame, - TEST_TIMELINE_FPS, - state->expected_frame); - g_usleep (1000000); + clutter_timeline_stop (timeline); + return; } - if (current_frame >= TEST_TIMELINE_DURATION) + switch (state->cycle_frame_counter) { - state->expected_frame += loop_overflow; - state->expected_frame -= TEST_TIMELINE_DURATION; - g_test_message ("End of timeline reached: " - "Wrapping expected frame too %i", - state->expected_frame); + case 0: + { + /* + * First frame, sleep so we're about in the middle of the cycle, + * before the end of the timeline cycle. + */ + int delay_ms = ms (1500); + + state->expected_frame = current_frame + delay_ms; + g_test_message ("Sleeping for 1.5 seconds " + "so next frame should be (%d + %d) = %d", + current_frame, + delay_ms, + state->expected_frame); + g_usleep (ms2us (delay_ms)); + break; + } + case 1: + { + /* + * Second frame, we're about in the middle of the cycle; sleep one cycle, + * and check that we end up in the middle again. + */ + int delay_ms = TEST_TIMELINE_DURATION; + + state->expected_frame = current_frame + delay_ms; + g_test_message ("Sleeping for %d seconds " + "so next frame should be (%d + %d) = %d, " + "which is %d into the next cycle", + TEST_TIMELINE_DURATION / 1000, + current_frame, + delay_ms, + state->expected_frame, + state->expected_frame - TEST_TIMELINE_DURATION); + g_usleep (ms2us (delay_ms)); + + g_assert_cmpint (state->expected_frame, >, TEST_TIMELINE_DURATION); + + state->expected_frame += loop_overflow; + state->expected_frame -= TEST_TIMELINE_DURATION; + g_test_message ("End of timeline reached: " + "Wrapping expected frame too %d", + state->expected_frame); + break; + } + case 2: + case 3: + { + break; + } } state->new_frame_counter++; - step = -step; + state->cycle_frame_counter++; } static void @@ -119,14 +153,20 @@ completed_cb (ClutterTimeline *timeline, TestState *state) { state->completion_count++; + state->cycle_frame_counter = 0; - if (state->completion_count == 2) - { - if (state->passed) - clutter_test_quit (); - else - g_assert_not_reached (); - } + if (state->completion_count >= 2) + g_assert_not_reached (); +} + +static void +stopped_cb (ClutterTimeline *timeline, + gboolean is_finished, + TestState *state) +{ + g_assert_cmpint (state->completion_count, ==, 1); + + clutter_test_quit (); } static void @@ -148,10 +188,14 @@ timeline_interpolation (void) "completed", G_CALLBACK (completed_cb), &state); + g_signal_connect (state.timeline, + "stopped", + G_CALLBACK (stopped_cb), + &state); state.completion_count = 0; state.new_frame_counter = 0; - state.passed = TRUE; + state.cycle_frame_counter = 0; state.expected_frame = 0; clutter_actor_show (stage);