adaptivedemux: tests: added test for fragment download error
authorFlorin Apostol <florin.apostol@oregan.net>
Tue, 20 Oct 2015 16:21:00 +0000 (17:21 +0100)
committerVincent Penquerc'h <vincent.penquerch@collabora.co.uk>
Fri, 30 Oct 2015 13:28:09 +0000 (13:28 +0000)
https://bugzilla.gnome.org/show_bug.cgi?id=757361

tests/check/elements/dash_demux.c
tests/check/elements/fake_http_src.c
tests/check/elements/fake_http_src.h

index 60e0fa1..b83e2f2 100644 (file)
@@ -1284,6 +1284,112 @@ GST_START_TEST (testDownloadError)
 
 GST_END_TEST;
 
+/* generate error message on adaptive demux pipeline */
+static gboolean
+testFragmentDownloadErrorCheckDataReceived (GstDashDemuxTestData * testData,
+    GstDashDemuxTestOutputStreamData * testOutputStreamData, GstBuffer * buffer)
+{
+  checkDataReceived (testData, testOutputStreamData, buffer);
+
+  if (testOutputStreamData->scratchData->segmentReceivedSize > 2000) {
+    GstPad *fakeHttpSrcPad;
+    GstObject *fakeHttpSrcElement;
+
+    /* tell fake soup http src to post an error on the adaptive demux bus */
+    fakeHttpSrcPad =
+        gst_pad_get_peer (testOutputStreamData->scratchData->internalPad);
+    fakeHttpSrcElement = gst_pad_get_parent (fakeHttpSrcPad);
+
+    gst_fake_soup_http_src_simulate_download_error ((GstFakeSoupHTTPSrc *)
+        fakeHttpSrcElement, 404);
+
+    gst_object_unref (fakeHttpSrcPad);
+    gst_object_unref (fakeHttpSrcElement);
+
+    testData->expectError = TRUE;
+  }
+
+  return TRUE;
+}
+
+/* function to check total size of data received by AppSink
+ * will be called when AppSink receives eos.
+ */
+static gboolean
+testFragmentDownloadErrorCheckSizeOfDataReceived (GstDashDemuxTestData *
+    testData, GstDashDemuxTestOutputStreamData * testOutputStreamData)
+{
+  /* expect to receive more than 0 */
+  fail_unless (testOutputStreamData->scratchData->totalReceivedSize > 0,
+      "size validation failed for %s, expected > 0, received %d",
+      testOutputStreamData->name,
+      testOutputStreamData->scratchData->totalReceivedSize);
+
+  /* expect to receive less than file size */
+  fail_unless (testOutputStreamData->scratchData->totalReceivedSize <
+      testOutputStreamData->expectedSize,
+      "size validation failed for %s, expected < %d received %d",
+      testOutputStreamData->name, testOutputStreamData->expectedSize,
+      testOutputStreamData->scratchData->totalReceivedSize);
+
+  return TRUE;
+}
+
+/*
+ * Test fragment download error
+ * Let the adaptive demux download a few bytes, then instruct the fake soup http
+ * src element to generate an error.
+ */
+GST_START_TEST (testFragmentDownloadError)
+{
+  const gchar *mpd =
+      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+      "<MPD xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
+      "     xmlns=\"urn:mpeg:DASH:schema:MPD:2011\""
+      "     xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\""
+      "     xmlns:yt=\"http://youtube.com/yt/2012/10/10\""
+      "     profiles=\"urn:mpeg:dash:profile:isoff-on-demand:2011\""
+      "     type=\"static\""
+      "     minBufferTime=\"PT1.500S\""
+      "     mediaPresentationDuration=\"PT0.5S\">"
+      "  <Period>"
+      "    <AdaptationSet mimeType=\"audio/webm\""
+      "                   subsegmentAlignment=\"true\">"
+      "      <Representation id=\"171\""
+      "                      codecs=\"vorbis\""
+      "                      audioSamplingRate=\"44100\""
+      "                      startWithSAP=\"1\""
+      "                      bandwidth=\"129553\">"
+      "        <AudioChannelConfiguration"
+      "           schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\""
+      "           value=\"2\" />"
+      "        <BaseURL>audio.webm</BaseURL>"
+      "        <SegmentBase indexRange=\"4452-4686\""
+      "                     indexRangeExact=\"true\">"
+      "          <Initialization range=\"0-4451\" />"
+      "        </SegmentBase>"
+      "      </Representation></AdaptationSet></Period></MPD>";
+
+  const GstFakeHttpSrcInputData inputTestData[] = {
+    {"http://unit.test/test.mpd", mpd, 0},
+    {"http://unit.test/audio.webm", NULL, 5000},
+    {NULL, NULL, 0},
+  };
+
+  GstDashDemuxTestOutputStreamData outputTestData[] = {
+    {"audio_00", 5000, NULL},
+  };
+
+  Callbacks cb = { 0 };
+  cb.appSinkGotDataCallback = testFragmentDownloadErrorCheckDataReceived;
+  cb.appSinkGotEosCallback = testFragmentDownloadErrorCheckSizeOfDataReceived;
+
+  runTest (inputTestData, outputTestData,
+      sizeof (outputTestData) / sizeof (outputTestData[0]), &cb);
+}
+
+GST_END_TEST;
+
 /* generate queries to adaptive demux */
 static gboolean
 testQueryCheckDataReceived (GstDashDemuxTestData * testData,
@@ -1408,6 +1514,7 @@ dash_demux_suite (void)
   tcase_add_test (tc_basicTest, testParameters);
   tcase_add_test (tc_basicTest, testSeek);
   tcase_add_test (tc_basicTest, testDownloadError);
+  tcase_add_test (tc_basicTest, testFragmentDownloadError);
   tcase_add_test (tc_basicTest, testQuery);
 
   tcase_add_unchecked_fixture (tc_basicTest, test_setup, test_teardown);
index b45ef48..b9c2a54 100644 (file)
@@ -55,6 +55,9 @@ typedef struct _GstFakeSoupHTTPSrc
   guint64 position;
   /* index immediately after the last byte from the segment to be retrieved */
   guint64 segment_end;
+
+  /* download error code to simulate during create function */
+  guint downloadErrorCode;
 } GstFakeSoupHTTPSrc;
 
 typedef struct _GstFakeSoupHTTPSrcClass
@@ -138,6 +141,7 @@ gst_fake_soup_http_src_init (GstFakeSoupHTTPSrc * src)
   src->position = 0;
   src->size = 0;
   src->segment_end = 0;
+  src->downloadErrorCode = 0;
   gst_base_src_set_blocksize (GST_BASE_SRC (src),
       GST_FAKE_SOUP_HTTP_SRC_MAX_BUF_SIZE);
 }
@@ -163,7 +167,8 @@ gst_fake_soup_http_src_start (GstBaseSrc * basesrc)
   src = GST_FAKE_SOUP_HTTP_SRC (basesrc);
 
   if (!src->uri) {
-    GST_WARNING ("gst_fake_soup_http_src_start without location");
+    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (("No URL set.")),
+        ("Missing location property"));
     return FALSE;
   }
 
@@ -176,6 +181,7 @@ gst_fake_soup_http_src_start (GstBaseSrc * basesrc)
       else
         src->size = input[i].size;
       src->segment_end = src->size;
+      src->downloadErrorCode = 0;
       gst_base_src_set_dynamic_size (basesrc, FALSE);
       return TRUE;
     }
@@ -295,6 +301,13 @@ gst_fake_soup_http_src_create (GstBaseSrc * basesrc, guint64 offset,
     GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
     return GST_FLOW_ERROR;
   }
+  if (src->downloadErrorCode) {
+    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("%s",
+            "Generated requested error"), ("%s (%d), URL: %s, Redirect to: %s",
+            "Generated requested error", src->downloadErrorCode, src->uri,
+            GST_STR_NULL (NULL)));
+    return GST_FLOW_ERROR;
+  }
 
   bytes_read = MIN ((src->segment_end - src->position),
       GST_FAKE_SOUP_HTTP_SRC_MAX_BUF_SIZE);
@@ -431,3 +444,10 @@ gst_fake_soup_http_src_set_input_data (const GstFakeHttpSrcInputData * input)
 {
   gst_fake_soup_http_src_inputData = input;
 }
+
+void
+gst_fake_soup_http_src_simulate_download_error (GstFakeSoupHTTPSrc *
+    fakeSoupHTTPSrc, guint downloadErrorCode)
+{
+  fakeSoupHTTPSrc->downloadErrorCode = downloadErrorCode;
+}
index 5ddbfa0..abcaa16 100644 (file)
@@ -43,6 +43,8 @@ typedef struct _GstFakeHttpSrcInputData
   guint64 size;
 } GstFakeHttpSrcInputData;
 
+typedef struct _GstFakeSoupHTTPSrc GstFakeSoupHTTPSrc;
+
 /* GstFakeSoupHTTPSrc will send buffers up to this size */
 #define GST_FAKE_SOUP_HTTP_SRC_MAX_BUF_SIZE (1024)
 
@@ -51,3 +53,9 @@ GType gst_fake_soup_http_src_get_type (void);
 gboolean gst_fake_soup_http_src_register_plugin (GstRegistry * registry, const gchar * name);
 
 void gst_fake_soup_http_src_set_input_data (const GstFakeHttpSrcInputData *input);
+
+/* TODO: use SoupKnownStatusCode. But it requires makefile support to include
+ * <libsoup/soup.h>
+ */
+void gst_fake_soup_http_src_simulate_download_error (
+    GstFakeSoupHTTPSrc *fakeSoupHTTPSrc, guint downloadErrorCode);