diff --git a/tests/Makefile.am b/tests/Makefile.am index d529f3e6f..9c602fd00 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,9 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \ test-actors test-behave test-text test-entry test-project \ test-perspective test-rotate test-depth \ + test-threads test-timeline test-timeline-dup-frames \ + test-timeline-interpolate test-timeline-rewind \ + test-timeline-smoothness test-timeline-frame-count \ test-threads test-timeline test-score test-script \ test-model test-grab test-effects test-fullscreen \ test-shader test-unproject test-viewport test-fbo \ @@ -27,6 +30,11 @@ test_rotate_SOURCES = test-rotate.c test_depth_SOURCES = test-depth.c test_threads_SOURCES = test-threads.c test_timeline_SOURCES = test-timeline.c +test_timeline_dup_frames_SOURCES = test-timeline-dup-frames.c +test_timeline_interpolate_SOURCES = test-timeline-interpolate.c +test_timeline_rewind_SOURCES = test-timeline-rewind.c +test_timeline_smoothness_SOURCES = test-timeline-smoothness.c +test_timeline_frame_count_SOURCES = test-timeline-frame-count.c test_shader_SOURCES = test-shader.c test_score_SOURCES = test-score.c test_script_SOURCES = test-script.c diff --git a/tests/test-timeline-dup-frames.c b/tests/test-timeline-dup-frames.c new file mode 100644 index 000000000..eb7c90bb8 --- /dev/null +++ b/tests/test-timeline-dup-frames.c @@ -0,0 +1,97 @@ +#include +#include +#include + +/* We use a nice slow timeline for this test since we + * dont want the timeouts to interpolate the timeline + * forward multiple frames */ +#define TEST_TIMELINE_FPS 10 +#define TEST_TIMELINE_FRAME_COUNT 20 + +typedef struct _TestState { + ClutterTimeline *timeline; + gint prev_frame; + gint completion_count; + gint passed; +}TestState; + + +static void +new_frame_cb (ClutterTimeline *timeline, + gint frame_num, + TestState *state) +{ + gint current_frame = clutter_timeline_get_current_frame (state->timeline); + + if (state->prev_frame != clutter_timeline_get_current_frame (state->timeline)) + { + g_print("timeline previous frame=%-4i actual frame=%-4i (OK)\n", + state->prev_frame, + current_frame); + } + else + { + g_print("timeline previous frame=%-4i actual frame=%-4i (FAILED)\n", + state->prev_frame, + current_frame); + + state->passed = FALSE; + } + + state->prev_frame = current_frame; +} + + +static void +completed_cb (ClutterTimeline *timeline, + TestState *state) +{ + state->completion_count++; + + if (state->completion_count == 2) + { + if (state->passed) + { + g_print("Passed\n"); + exit(EXIT_SUCCESS); + } + else + { + g_print("Failed\n"); + exit(EXIT_FAILURE); + } + } +} + + +int +main(int argc, char **argv) +{ + TestState state; + + clutter_init(&argc, &argv); + + state.timeline = + clutter_timeline_new (TEST_TIMELINE_FRAME_COUNT, + TEST_TIMELINE_FPS); + clutter_timeline_set_loop (state.timeline, TRUE); + g_signal_connect (G_OBJECT(state.timeline), + "new-frame", + G_CALLBACK(new_frame_cb), + &state); + g_signal_connect (G_OBJECT(state.timeline), + "completed", + G_CALLBACK(completed_cb), + &state); + + state.prev_frame = -1; + state.completion_count = 0; + state.passed = TRUE; + + clutter_timeline_start (state.timeline); + + clutter_main(); + + return EXIT_FAILURE; +} + diff --git a/tests/test-timeline-interpolate.c b/tests/test-timeline-interpolate.c new file mode 100644 index 000000000..bfc55d07c --- /dev/null +++ b/tests/test-timeline-interpolate.c @@ -0,0 +1,155 @@ +#include +#include +#include + +/* 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_FRAME_COUNT 5000 + +/* We are at the mercy of the system scheduler so this + * may not be a very reliable tolerance. */ +#define TEST_ERROR_TOLERANCE 20 + +typedef struct _TestState { + ClutterTimeline *timeline; + GTimeVal start_time; + guint new_frame_counter; + gint expected_frame; + gint completion_count; + gboolean passed; +}TestState; + + +static void +new_frame_cb (ClutterTimeline *timeline, + gint frame_num, + TestState *state) +{ + GTimeVal current_time; + gint current_frame; + glong msec_diff; + gint loop_overflow = 0; + static gint step = 1; + + g_get_current_time (¤t_time); + + current_frame = clutter_timeline_get_current_frame (state->timeline); + + msec_diff = (current_time.tv_sec - state->start_time.tv_sec) * 1000; + msec_diff += (current_time.tv_usec - state->start_time.tv_usec)/1000; + + /* If we expect to have interpolated past the end of the timeline + * we keep track of the overflow so we can determine when + * the next timeout will happen. We then clip expected_frames + * to TEST_TIMELINE_FRAME_COUNT since clutter-timeline + * semantics guaranty this frame is always signaled before + * looping */ + if (state->expected_frame > TEST_TIMELINE_FRAME_COUNT) + { + loop_overflow = state->expected_frame - TEST_TIMELINE_FRAME_COUNT; + state->expected_frame = TEST_TIMELINE_FRAME_COUNT; + } + + if (current_frame >= (state->expected_frame-TEST_ERROR_TOLERANCE) + && current_frame <= (state->expected_frame+TEST_ERROR_TOLERANCE)) + { + g_print ("\nelapsed milliseconds=%-5li expected frame=%-4i actual frame=%-4i (OK)\n", + msec_diff, + state->expected_frame, + current_frame); + } + else + { + g_print ("\nelapsed milliseconds=%-5li expected frame=%-4i actual frame=%-4i (FAILED)\n", + msec_diff, + state->expected_frame, + current_frame); + state->passed = FALSE; + } + + if (step>0) + { + state->expected_frame = current_frame + (TEST_TIMELINE_FPS / 4); + g_print ("Sleeping for 250ms so next frame should be (%i + %i) = %i\n", + current_frame, (TEST_TIMELINE_FPS / 4), state->expected_frame); + g_usleep (250000); + } + else + { + state->expected_frame = current_frame + TEST_TIMELINE_FPS; + g_print ("Sleeping for 1sec so next frame should be (%i + %i) = %i\n", + current_frame, TEST_TIMELINE_FPS, state->expected_frame); + g_usleep (1000000); + } + + if (current_frame >= TEST_TIMELINE_FRAME_COUNT) + { + state->expected_frame += loop_overflow; + state->expected_frame -= TEST_TIMELINE_FRAME_COUNT; + g_print ("End of timeline reached: Wrapping expected frame too %i\n", + state->expected_frame); + } + + state->new_frame_counter++; + step = -step; +} + + +static void +completed_cb (ClutterTimeline *timeline, + TestState *state) +{ + state->completion_count++; + + if (state->completion_count == 2) + { + if (state->passed) + { + g_print("Passed\n"); + exit(EXIT_SUCCESS); + } + else + { + g_print("Failed\n"); + exit(EXIT_FAILURE); + } + } +} + + +int +main (int argc, char **argv) +{ + TestState state; + + clutter_init (&argc, &argv); + + state.timeline = + clutter_timeline_new (TEST_TIMELINE_FRAME_COUNT, + TEST_TIMELINE_FPS); + clutter_timeline_set_loop (state.timeline, TRUE); + g_signal_connect (G_OBJECT(state.timeline), + "new-frame", + G_CALLBACK(new_frame_cb), + &state); + g_signal_connect (G_OBJECT(state.timeline), + "completed", + G_CALLBACK(completed_cb), + &state); + + state.completion_count = 0; + state.new_frame_counter = 0; + state.passed = TRUE; + state.expected_frame = 0; + + g_get_current_time (&state.start_time); + clutter_timeline_start (state.timeline); + + clutter_main(); + + return EXIT_FAILURE; +} + diff --git a/tests/test-timeline-rewind.c b/tests/test-timeline-rewind.c new file mode 100644 index 000000000..77edf0d84 --- /dev/null +++ b/tests/test-timeline-rewind.c @@ -0,0 +1,96 @@ +#include +#include +#include + +#define TEST_TIMELINE_FPS 10 +#define TEST_TIMELINE_FRAME_COUNT 5 +#define TEST_WATCHDOG_KICK_IN_SECONDS 10 + +typedef struct _TestState { + ClutterTimeline *timeline; + gint rewind_count; +}TestState; + + +static gboolean +watchdog_timeout (TestState *state) +{ + g_print ("Watchdog timer kicking in\n"); + g_print ("rewind_count=%i\n", state->rewind_count); + if (state->rewind_count <= 3) + { + /* The test has hung */ + g_print ("Failed (This test shouldn't have hung!)\n"); + exit (EXIT_FAILURE); + } + else + { + g_print ("Passed\n"); + exit (EXIT_SUCCESS); + } + + return FALSE; +} + + +static void +new_frame_cb (ClutterTimeline *timeline, + gint frame_num, + TestState *state) +{ + gint current_frame = clutter_timeline_get_current_frame (timeline); + + if (current_frame == TEST_TIMELINE_FRAME_COUNT) + { + g_print ("new-frame signal recieved (end of timeline)\n"); + g_print ("Rewinding timeline\n"); + clutter_timeline_rewind (timeline); + state->rewind_count++; + } + else + { + if (current_frame == 0) + { + g_print ("new-frame signal recieved (start of timeline)\n"); + } + else + { + g_print ("new-frame signal recieved (mid frame)\n"); + } + + if (state->rewind_count >= 2) + { + g_print ("Sleeping for 1 second\n"); + g_usleep (1000000); + } + } +} + + +int +main (int argc, char **argv) +{ + TestState state; + + clutter_init (&argc, &argv); + + state.timeline = + clutter_timeline_new (TEST_TIMELINE_FRAME_COUNT, + TEST_TIMELINE_FPS); + g_signal_connect (G_OBJECT(state.timeline), + "new-frame", + G_CALLBACK(new_frame_cb), + &state); + g_print ("Installing a watchdog timeout to determin if this test hangs\n"); + g_timeout_add (TEST_WATCHDOG_KICK_IN_SECONDS*1000, + (GSourceFunc)watchdog_timeout, + &state); + state.rewind_count = 0; + + clutter_timeline_start (state.timeline); + + clutter_main(); + + return EXIT_FAILURE; +} + diff --git a/tests/test-timeline-smoothness.c b/tests/test-timeline-smoothness.c new file mode 100644 index 000000000..30917643e --- /dev/null +++ b/tests/test-timeline-smoothness.c @@ -0,0 +1,113 @@ +#include +#include +#include + +#define TEST_TIMELINE_FPS 10 +#define TEST_TIMELINE_FRAME_COUNT 20 +#define TEST_ERROR_TOLERANCE 5 + +typedef struct _TestState { + ClutterTimeline *timeline; + GTimeVal start_time; + GTimeVal prev_frame_time; + guint frame; + gint completion_count; + gint passed; +}TestState; + + +static void +new_frame_cb (ClutterTimeline *timeline, + gint frame_num, + TestState *state) +{ + GTimeVal current_time; + glong total_elapsed_ms; + glong frame_elapsed_ms = 0; + gchar *bump = ""; + + g_get_current_time (¤t_time); + + total_elapsed_ms = (current_time.tv_sec - state->start_time.tv_sec) * 1000; + total_elapsed_ms += (current_time.tv_usec - state->start_time.tv_usec)/1000; + + if (state->frame>0) + { + frame_elapsed_ms = + (current_time.tv_sec - state->prev_frame_time.tv_sec) * 1000; + frame_elapsed_ms += + (current_time.tv_usec - state->prev_frame_time.tv_usec)/1000; + + if (ABS(frame_elapsed_ms - (1000/TEST_TIMELINE_FPS)) + > TEST_ERROR_TOLERANCE) + { + state->passed = FALSE; + bump = " (BUMP)"; + } + } + + g_print ("timeline frame=%-2d total elapsed=%-4li(ms) since last frame=%-4li(ms)%s\n", + clutter_timeline_get_current_frame(state->timeline), + total_elapsed_ms, + frame_elapsed_ms, + bump); + + state->prev_frame_time = current_time; + state->frame++; +} + + +static void +completed_cb (ClutterTimeline *timeline, + TestState *state) +{ + state->completion_count++; + + if (state->completion_count == 2) + { + if (state->passed) + { + g_print("Passed\n"); + exit(EXIT_SUCCESS); + } + else + { + g_print("Failed\n"); + exit(EXIT_FAILURE); + } + } +} + + +int +main(int argc, char **argv) +{ + TestState state; + + clutter_init (&argc, &argv); + + state.timeline = + clutter_timeline_new (TEST_TIMELINE_FRAME_COUNT, + TEST_TIMELINE_FPS); + clutter_timeline_set_loop (state.timeline, TRUE); + g_signal_connect (G_OBJECT(state.timeline), + "new-frame", + G_CALLBACK(new_frame_cb), + &state); + g_signal_connect (G_OBJECT(state.timeline), + "completed", + G_CALLBACK(completed_cb), + &state); + + state.frame = 0; + state.completion_count = 0; + state.passed = TRUE; + + g_get_current_time (&state.start_time); + clutter_timeline_start (state.timeline); + + clutter_main(); + + return EXIT_FAILURE; +} +