tests: Add GESProject tests
authorThibault Saunier <thibault.saunier@collabora.com>
Sun, 23 Sep 2012 00:13:38 +0000 (02:13 +0200)
committerThibault Saunier <thibault.saunier@collabora.com>
Sat, 29 Dec 2012 22:36:50 +0000 (19:36 -0300)
tests/check/Makefile.am
tests/check/ges/project.c [new file with mode: 0644]
tests/check/ges/test-project.xges [new file with mode: 0644]
tests/check/ges/test.xptv [deleted file]

index d737150..0ecf7e0 100644 (file)
@@ -39,7 +39,8 @@ check_PROGRAMS = \
        ges/titles\
        ges/transition  \
        ges/overlays\
-       ges/text_properties
+       ges/text_properties\
+       ges/project
 
 noinst_LTLIBRARIES=$(testutils_noisnt_libraries)
 noinst_HEADERS=$(testutils_noinst_headers)
@@ -49,4 +50,7 @@ TESTS = $(check_PROGRAMS)
 AM_CFLAGS =  $(common_cflags) -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS
 LDADD = $(common_ldadd) libtestutils.la
 
-EXTRA_DIST = #gst-plugins-bad.supp
+EXTRA_DIST = \
+       ges/test-project.xges \
+       ges/audio_only.ogg \
+       ges/audio_video.ogg
diff --git a/tests/check/ges/project.c b/tests/check/ges/project.c
new file mode 100644 (file)
index 0000000..55a5c04
--- /dev/null
@@ -0,0 +1,437 @@
+/* GStreamer Editing Services
+ *
+ * Copyright (C) <2012> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "test-utils.h"
+#include <ges/ges.h>
+#include <gst/check/gstcheck.h>
+
+GST_START_TEST (test_project_simple)
+{
+  gchar *id;
+  GESProject *project;
+  GESTimeline *timeline;
+
+  ges_init ();
+
+  project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
+  fail_unless (GES_IS_PROJECT (project));
+  assert_equals_string (ges_asset_get_id (GES_ASSET (project)), "project-0");
+
+  timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
+  fail_unless (GES_IS_TIMELINE (timeline));
+  id = ges_extractable_get_id (GES_EXTRACTABLE (timeline));
+  assert_equals_string (id, "project-0");
+
+  g_free (id);
+}
+
+GST_END_TEST;
+
+static void
+asset_removed_add_cb (GESProject * project, GESAsset * asset, gboolean * called)
+{
+  *called = TRUE;
+}
+
+GST_START_TEST (test_project_add_assets)
+{
+  GESProject *project;
+  GESAsset *asset;
+  gboolean added_cb_called = FALSE;
+  gboolean removed_cb_called = FALSE;
+
+  ges_init ();
+
+  project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
+  fail_unless (GES_IS_PROJECT (project));
+  fail_unless (GES_IS_PROJECT (project));
+
+  g_signal_connect (project, "asset-added",
+      (GCallback) asset_removed_add_cb, &added_cb_called);
+  g_signal_connect (project, "asset-removed",
+      (GCallback) asset_removed_add_cb, &removed_cb_called);
+
+  asset = ges_asset_request (GES_TYPE_TIMELINE_TEST_SOURCE, NULL, NULL);
+  fail_unless (GES_IS_ASSET (asset));
+
+  fail_unless (ges_project_add_asset (project, asset));
+  fail_unless (added_cb_called);
+  ASSERT_OBJECT_REFCOUNT (project, "The project", 2);
+  ASSERT_OBJECT_REFCOUNT (asset, "The asset (1 for project and one for "
+      "us + 1 cache)", 3);
+
+  fail_unless (ges_project_remove_asset (project, asset));
+  fail_unless (removed_cb_called);
+  gst_object_unref (asset);
+  gst_object_unref (project);
+
+  ASSERT_OBJECT_REFCOUNT (asset, "The asset (1 ref in cache)", 1);
+  ASSERT_OBJECT_REFCOUNT (project, "The project (1 ref in cache)", 1);
+
+}
+
+GST_END_TEST;
+
+static void
+error_loading_asset_cb (GESProject * project, GError * error, gchar * id,
+    GType extractable_type, GMainLoop * mainloop)
+{
+  fail_unless (g_error_matches (error, GST_PARSE_ERROR,
+          GST_PARSE_ERROR_NO_SUCH_ELEMENT));
+  g_main_loop_quit (mainloop);
+}
+
+GST_START_TEST (test_project_unexistant_effect)
+{
+  GESProject *project;
+  GMainLoop *mainloop;
+  gboolean added_cb_called = FALSE;
+  gboolean removed_cb_called = FALSE;
+
+  ges_init ();
+
+  project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
+  fail_unless (GES_IS_PROJECT (project));
+  fail_unless (GES_IS_PROJECT (project));
+
+  mainloop = g_main_loop_new (NULL, FALSE);
+  g_signal_connect (project, "asset-added",
+      (GCallback) asset_removed_add_cb, &added_cb_called);
+  g_signal_connect (project, "asset-removed",
+      (GCallback) asset_removed_add_cb, &removed_cb_called);
+  g_signal_connect (project, "error-loading-asset",
+      (GCallback) error_loading_asset_cb, mainloop);
+
+  fail_unless (ges_project_create_asset (project, "nowaythiselementexists",
+          GES_TYPE_TRACK_PARSE_LAUNCH_EFFECT));
+  g_main_loop_run (mainloop);
+
+  /* And.... try again! */
+  fail_unless (ges_project_create_asset (project, "nowaythiselementexists",
+          GES_TYPE_TRACK_PARSE_LAUNCH_EFFECT));
+  g_main_loop_run (mainloop);
+
+  fail_if (added_cb_called);
+  fail_if (removed_cb_called);
+
+  ASSERT_OBJECT_REFCOUNT (project, "The project", 2);
+  gst_object_unref (project);
+  g_main_loop_unref (mainloop);
+
+  ASSERT_OBJECT_REFCOUNT (project, "The project (1 ref in cache)", 1);
+
+}
+
+GST_END_TEST;
+
+static GMainLoop *mainloop;
+
+static void
+asset_added_cb (GESProject * project, GESAsset * asset)
+{
+  gchar *uri = ges_test_file_uri ("audio_video.ogg");
+  GstDiscovererInfo *info;
+
+  if (ges_asset_get_extractable_type (asset) ==
+      GES_TYPE_TRACK_PARSE_LAUNCH_EFFECT) {
+    assert_equals_string (ges_asset_get_id (asset), "agingtv");
+  } else {
+    info = ges_asset_filesource_get_info (GES_ASSET_FILESOURCE (asset));
+    fail_unless (GST_IS_DISCOVERER_INFO (info));
+    assert_equals_string (ges_asset_get_id (asset), uri);
+  }
+
+  g_free (uri);
+}
+
+static void
+project_loaded_cb (GESProject * project, GESTimeline * timeline)
+{
+  g_main_loop_quit (mainloop);
+}
+
+static gchar *
+_set_new_uri (GESProject * project, GError * error, GESAsset * wrong_asset)
+{
+  fail_unless (!g_strcmp0 (ges_asset_get_id (wrong_asset),
+          "file:///test/not/exisiting"));
+
+  return ges_test_file_uri ("audio_video.ogg");
+}
+
+static void
+_test_project (GESProject * project, GESTimeline * timeline)
+{
+  guint a_meta;
+  gchar *media_uri;
+  GESTrack *track;
+  const GList *profiles;
+  GstEncodingContainerProfile *profile;
+  GList *tracks, *tmp, *tmptckobj, *tlobjs;
+
+  fail_unless (GES_IS_TIMELINE (timeline));
+  assert_equals_int (g_list_length (timeline->layers), 2);
+
+  assert_equals_string (ges_meta_container_get_string (GES_META_CONTAINER
+          (project), "name"), "Example project");
+  tlobjs =
+      ges_timeline_layer_get_objects (GES_TIMELINE_LAYER (timeline->layers->
+          data));
+  fail_unless (ges_meta_container_get_uint (GES_META_CONTAINER (timeline->
+              layers->data), "a", &a_meta));
+  assert_equals_int (a_meta, 3);
+  assert_equals_int (g_list_length (tlobjs), 1);
+  media_uri = ges_test_file_uri ("audio_video.ogg");
+  assert_equals_string (ges_asset_get_id (ges_extractable_get_asset
+          (GES_EXTRACTABLE (tlobjs->data))), media_uri);
+  g_free (media_uri);
+
+  /* Check tracks and the objects  they contain */
+  tracks = ges_timeline_get_tracks (timeline);
+  assert_equals_int (g_list_length (tracks), 2);
+  for (tmp = tracks; tmp; tmp = tmp->next) {
+    GList *trackobjs;
+    track = GES_TRACK (tmp->data);
+
+    trackobjs = ges_track_get_objects (track);
+    switch (track->type) {
+      case GES_TRACK_TYPE_VIDEO:
+        GST_DEBUG_OBJECT (track, "Testing track");
+        assert_equals_int (g_list_length (trackobjs), 2);
+        for (tmptckobj = trackobjs; tmptckobj; tmptckobj = tmptckobj->next) {
+          GESTrackObject *tckobj = GES_TRACK_OBJECT (tmptckobj->data);
+
+          if (GES_IS_TRACK_EFFECT (tckobj)) {
+            guint nb_scratch_lines;
+
+            ges_track_object_get_child_properties (tckobj, "scratch-lines",
+                &nb_scratch_lines, NULL);
+            assert_equals_int (nb_scratch_lines, 12);
+
+            gnl_object_check (ges_track_object_get_gnlobject (tckobj),
+                0, 1000000000, 0, 1000000000, 0, TRUE);
+          } else {
+            gnl_object_check (ges_track_object_get_gnlobject (tckobj),
+                0, 1000000000, 0, 1000000000, 1, TRUE);
+          }
+        }
+        break;
+      case GES_TRACK_TYPE_AUDIO:
+        assert_equals_int (g_list_length (trackobjs), 2);
+        break;
+      default:
+        g_assert (1);
+    }
+
+    g_list_free_full (trackobjs, gst_object_unref);
+
+  }
+  g_list_free_full (tracks, gst_object_unref);
+
+  /* Now test the encoding profile */
+  profiles = ges_project_list_encoding_profiles (project);
+  assert_equals_int (g_list_length ((GList *) profiles), 1);
+  profile = profiles->data;
+  fail_unless (GST_IS_ENCODING_CONTAINER_PROFILE (profile));
+  profiles = gst_encoding_container_profile_get_profiles (profile);
+  assert_equals_int (g_list_length ((GList *) profiles), 2);
+}
+
+GST_START_TEST (test_project_load_xges)
+{
+  gboolean saved;
+  GESProject *project;
+  GESTimeline *timeline;
+  GESAsset *formatter_asset;
+  gchar *tmpuri, *uri = ges_test_file_uri ("test-project.xges");
+
+  project = ges_project_new (uri);
+  fail_unless (GES_IS_PROJECT (project));
+
+  /* Connect the signals */
+  g_signal_connect (project, "asset-added", (GCallback) asset_added_cb, NULL);
+  g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, NULL);
+
+  /* Make sure we update the project's dummy URL to some actual URL */
+  g_signal_connect (project, "missing-uri", (GCallback) _set_new_uri, NULL);
+
+  /* Now extract a timeline from it */
+  GST_LOG ("Loading project");
+  timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
+  fail_unless (GES_IS_TIMELINE (timeline));
+
+  mainloop = g_main_loop_new (NULL, FALSE);
+  g_main_loop_run (mainloop);
+  GST_LOG ("Test first loading");
+  _test_project (project, timeline);
+  g_free (uri);
+
+  tmpuri = g_build_filename (g_get_tmp_dir (), "test-project_TMP.xges", NULL);
+  uri = gst_filename_to_uri (tmpuri, NULL);
+  g_free (tmpuri);
+
+  formatter_asset = ges_asset_request (GES_TYPE_FORMATTER, "ges", NULL);
+  saved =
+      ges_project_save (project, timeline, uri, formatter_asset, TRUE, NULL);
+  fail_unless (saved);
+  gst_object_unref (timeline);
+  gst_object_unref (project);
+
+  project = ges_project_new (uri);
+  ASSERT_OBJECT_REFCOUNT (project, "Our + cache", 2);
+  g_signal_connect (project, "asset-added", (GCallback) asset_added_cb, NULL);
+  g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, NULL);
+
+  GST_LOG ("Loading saved project");
+  timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
+  fail_unless (GES_IS_TIMELINE (timeline));
+  g_main_loop_run (mainloop);
+  _test_project (project, timeline);
+  gst_object_unref (timeline);
+  gst_object_unref (project);
+  g_free (uri);
+
+  ASSERT_OBJECT_REFCOUNT (project, "Still 1 ref for asset cache", 1);
+
+  g_main_loop_unref (mainloop);
+}
+
+GST_END_TEST;
+
+/*  FIXME This test does not pass for some bad reason */
+#if 0
+static void
+project_loaded_now_play_cb (GESProject * project, GESTimeline * timeline)
+{
+  GstBus *bus;
+  GstMessage *message;
+  gboolean carry_on = TRUE;
+
+  GESTimelinePipeline *pipeline = ges_timeline_pipeline_new ();
+
+  fail_unless (ges_timeline_pipeline_add_timeline (pipeline, timeline));
+
+  bus = gst_element_get_bus (GST_ELEMENT (pipeline));
+  fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
+          GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE);
+
+  GST_DEBUG ("Let's poll the bus");
+
+  while (carry_on) {
+    message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 10);
+    if (message) {
+      GST_ERROR ("GOT MESSAGE: %" GST_PTR_FORMAT, message);
+      switch (GST_MESSAGE_TYPE (message)) {
+        case GST_MESSAGE_EOS:
+          /* we should check if we really finished here */
+          GST_WARNING ("Got an EOS, we did not even start!");
+          carry_on = FALSE;
+          fail_if (TRUE);
+          break;
+        case GST_MESSAGE_SEGMENT_START:
+        case GST_MESSAGE_SEGMENT_DONE:
+          /* We shouldn't see any segement messages, since we didn't do a segment seek */
+          GST_WARNING ("Saw a Segment start/stop");
+          fail_if (TRUE);
+          break;
+        case GST_MESSAGE_ERROR:
+          fail_error_message (message);
+          break;
+        case GST_MESSAGE_ASYNC_DONE:
+          GST_DEBUG ("prerolling done");
+          carry_on = FALSE;
+          break;
+        default:
+          break;
+      }
+      gst_mini_object_unref (GST_MINI_OBJECT (message));
+    }
+  }
+
+  fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
+          GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
+  gst_object_unref (pipeline);
+  g_main_loop_quit (mainloop);
+}
+
+
+GST_START_TEST (test_load_xges_and_play)
+{
+  GESProject *project;
+  GESTimeline *timeline;
+  gchar *uri = ges_test_file_uri ("test-project_TMP.xges");
+
+  project = ges_project_new (uri);
+  fail_unless (GES_IS_PROJECT (project));
+
+  mainloop = g_main_loop_new (NULL, FALSE);
+  /* Connect the signals */
+  g_signal_connect (project, "loaded", (GCallback) project_loaded_now_play_cb,
+      NULL);
+
+  /* Now extract a timeline from it */
+  timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
+  fail_unless (GES_IS_TIMELINE (timeline));
+
+  g_main_loop_run (mainloop);
+
+  g_free (uri);
+  gst_object_unref (project);
+  gst_object_unref (timeline);
+  g_main_loop_unref (mainloop);
+}
+
+GST_END_TEST;
+#endif
+
+static Suite *
+ges_suite (void)
+{
+  Suite *s = suite_create ("ges-project");
+  TCase *tc_chain = tcase_create ("project");
+
+  suite_add_tcase (s, tc_chain);
+
+  tcase_add_test (tc_chain, test_project_simple);
+  tcase_add_test (tc_chain, test_project_add_assets);
+  tcase_add_test (tc_chain, test_project_load_xges);
+  /*tcase_add_test (tc_chain, test_load_xges_and_play); */
+  tcase_add_test (tc_chain, test_project_unexistant_effect);
+
+  return s;
+}
+
+int
+main (int argc, char **argv)
+{
+  int nf;
+
+  Suite *s = ges_suite ();
+  SRunner *sr = srunner_create (s);
+
+  gst_check_init (&argc, &argv);
+  ges_init ();
+
+  srunner_run_all (sr, CK_NORMAL);
+  nf = srunner_ntests_failed (sr);
+  srunner_free (sr);
+
+  return nf;
+}
diff --git a/tests/check/ges/test-project.xges b/tests/check/ges/test-project.xges
new file mode 100644 (file)
index 0000000..c613e87
--- /dev/null
@@ -0,0 +1,28 @@
+<ges version="0.1">
+  <project metadatas='metadatas, name=(string)&quot;Example\ project&quot;;'>
+    <encoding-profiles>
+      <encoding-profile name='first_profile' description='(null)' type='container' format='application/ogg'>
+        <stream-profile parent='first_profile' id='0' type='video' presence='0' format='video/x-h264' pass='0' variableframerate='0' />
+        <stream-profile parent='first_profile' id='1' type='audio' presence='0' format='audio/x-aac' />
+      </encoding-profile>
+    </encoding-profiles>
+    <resources>
+      <asset id="file:///test/not/exisiting"
+         extractable-type-name="GESTimelineFileSource"/>
+    </resources>
+    <timeline>
+      <track track-type="2" caps="audio/x-raw" track-id="0"/>
+      <track track-type="4" caps="video/x-raw" track-id="1"/>
+      <layer priority="0" properties='properties, auto-transition=(boolean)true;' metadatas='metadatas, a=(guint)3'>
+        <timeline-object id="0" layer-priority='0' asset-id="file:///test/not/exisiting" type-name="GESTimelineFileSource" track-types="6" start="0" duration="1000000000">
+        <effect asset-id='agingtv' timeline-object-id='0' type-name='GESTrackParseLaunchEffect' track-type='4' track-id='1' metadatas='metadatas;' children-properties='properties, scratch-lines=(uint)12;'/>
+        </timeline-object>
+      </layer>
+      <layer priority="1" properties='properties, auto-transition=(boolean)true;'>
+        <timeline-object id="1" asset-id="file:///test/not/exisiting" layer-priority="1"
+        type-name="GESTimelineFileSource" track-types="2" start="1000000000" duration="1000000000">
+        </timeline-object>
+      </layer>
+    </timeline>
+  </project>
+</ges>
diff --git a/tests/check/ges/test.xptv b/tests/check/ges/test.xptv
deleted file mode 100644 (file)
index 0dc3f54..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-<pitivi formatter="GES" version="0.2">
- <factories>
-  <sources>
-   <source filename="file://./audio_video.ogg" id="1"/>
-  </sources>
- </factories>
- <timeline>
-  <tracks>
-   <track>
-    <stream caps="video/x-raw-yuv; video/x-raw-rgb" type="pitivi.stream.VideoStream"/>
-    <track-objects>
-     <track-object active="(bool)True" locked="(bool)True" priority="(int)0" duration="(gint64)14400000000" start="(gint64)14400000000" in_point="(gint64)0" id="0" type="pitivi.timeline.track.SourceTrackObject">
-      <factory-ref id="1"/>
-     </track-object>
-     <track-object active="(bool)True" locked="(bool)True" priority="(int)0" duration="(gint64)14400000000" start="(gint64)0" in_point="(gint64)0" id="1" type="pitivi.timeline.track.SourceTrackObject">
-      <factory-ref id="1"/>
-     </track-object>
-    </track-objects>
-   </track>
-   <track>
-    <stream caps="audio/x-raw-int; audio/x-raw-float" type="pitivi.stream.AudioStream"/>
-    <track-objects>
-     <track-object active="(bool)True" locked="(bool)True" priority="(int)0" duration="(gint64)14400000000" start="(gint64)14400000000" in_point="(gint64)0" id="2" type="pitivi.timeline.track.SourceTrackObject">
-      <factory-ref id="1"/>
-     </track-object>
-     <track-object active="(bool)True" locked="(bool)True" priority="(int)0" duration="(gint64)14400000000" start="(gint64)0" in_point="(gint64)0" id="3" type="pitivi.timeline.track.SourceTrackObject">
-      <factory-ref id="1"/>
-     </track-object>
-    </track-objects>
-   </track>
-  </tracks>
-  <timeline-objects>
-   <timeline-object>
-    <factory-ref id="1"/>
-    <track-object-refs>
-     <track-object-ref id="2"/>
-     <track-object-ref id="0"/>
-    </track-object-refs>
-   </timeline-object>
-   <timeline-object>
-    <factory-ref id="1"/>
-    <track-object-refs>
-     <track-object-ref id="3"/>
-     <track-object-ref id="1"/>
-    </track-object-refs>
-   </timeline-object>
-  </timeline-objects>
- </timeline>
-</pitivi>
-