Merge remote-tracking branch 'upstream/master' into tizen
[platform/upstream/gstreamer.git] / tests / check / libs / gstharness.c
1 /*
2  * Tests and examples of GstHarness
3  *
4  * Copyright (C) 2015 Havard Graff <havard@pexip.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/check/gstcheck.h>
26 #include <gst/check/gstharness.h>
27
28 GST_START_TEST (test_harness_empty)
29 {
30   GstHarness *h = gst_harness_new_empty ();
31   gst_harness_teardown (h);
32 }
33
34 GST_END_TEST;
35
36 static void
37 create_destroy_element_harness (gpointer data, gpointer user_data)
38 {
39   GstElement *element = user_data;
40   GstHarness *h = gst_harness_new_with_element (element, NULL, NULL);
41   gst_harness_teardown (h);
42 }
43
44 GST_START_TEST (test_harness_element_ref)
45 {
46   GstHarness *h = gst_harness_new ("identity");
47   GstHarnessThread *threads[100];
48   gint i;
49
50   for (i = 0; i < G_N_ELEMENTS (threads); i++)
51     threads[i] = gst_harness_stress_custom_start (h, NULL,
52         create_destroy_element_harness, h->element, 0);
53   for (i = 0; i < G_N_ELEMENTS (threads); i++)
54     gst_harness_stress_thread_stop (threads[i]);
55
56   fail_unless_equals_int (G_OBJECT (h->element)->ref_count, 1);
57
58   gst_harness_teardown (h);
59 }
60
61 GST_END_TEST;
62
63
64 GST_START_TEST (test_src_harness)
65 {
66   GstHarness *h = gst_harness_new ("identity");
67
68   /* add a fakesrc that syncs to the clock and a
69      capsfilter that adds some caps to it */
70   gst_harness_add_src_parse (h,
71       "fakesrc sync=1 ! capsfilter caps=\"mycaps\"", TRUE);
72
73   /* this cranks the clock and transfers the resulting buffer
74      from the src-harness into the identity element */
75   gst_harness_push_from_src (h);
76
77   /* verify that identity outputs a buffer by pulling and unreffing */
78   gst_buffer_unref (gst_harness_pull (h));
79
80   gst_harness_teardown (h);
81 }
82
83 GST_END_TEST;
84
85 GST_START_TEST (test_src_harness_no_forwarding)
86 {
87   GstHarness *h = gst_harness_new ("identity");
88
89   /* turn of forwarding of necessary events */
90   gst_harness_set_forwarding (h, FALSE);
91
92   /* add a fakesrc that syncs to the clock and a
93      capsfilter that adds some caps to it */
94   gst_harness_add_src_parse (h,
95       "fakesrc sync=1 ! capsfilter caps=\"mycaps\"", TRUE);
96
97   /* start the fakesrc to produce the first events */
98   gst_harness_play (h->src_harness);
99
100   /* transfer STREAM_START event */
101   gst_harness_src_push_event (h);
102
103   /* crank the clock to produce the CAPS and SEGMENT events */
104   gst_harness_crank_single_clock_wait (h->src_harness);
105
106   /* transfer CAPS event */
107   gst_harness_src_push_event (h);
108
109   /* transfer SEGMENT event */
110   gst_harness_src_push_event (h);
111
112   /* now transfer the buffer produced by exploiting
113      the ability to say 0 cranks but 1 push */
114   gst_harness_src_crank_and_push_many (h, 0, 1);
115
116   /* and verify that the identity element outputs it */
117   gst_buffer_unref (gst_harness_pull (h));
118
119   gst_harness_teardown (h);
120 }
121
122 GST_END_TEST;
123
124 GST_START_TEST (test_add_sink_harness_without_sinkpad)
125 {
126   GstHarness *h = gst_harness_new ("fakesink");
127
128   gst_harness_add_sink (h, "fakesink");
129
130   gst_harness_teardown (h);
131 }
132
133 GST_END_TEST;
134
135 static GstEvent *
136 create_new_stream_start_event (GstHarness * h, gpointer data)
137 {
138   guint *counter = data;
139   gchar *stream_id = g_strdup_printf ("streamid/%d", *counter);
140   GstEvent *event = gst_event_new_stream_start (stream_id);
141   g_free (stream_id);
142   (*counter)++;
143   return event;
144 }
145
146 static void
147 push_query (gpointer data, gpointer user_data)
148 {
149   GstHarness *h = user_data;
150   GstCaps *caps = gst_caps_new_empty_simple ("mycaps");
151   GstQuery *query = gst_query_new_allocation (caps, FALSE);
152   gst_caps_unref (caps);
153   gst_pad_peer_query (h->srcpad, query);
154   gst_query_unref (query);
155 }
156
157 GST_START_TEST (test_forward_event_and_query_to_sink_harness_while_teardown)
158 {
159   GstHarness *h = gst_harness_new ("identity");
160   guint counter = 0;
161   GstHarnessThread *e_thread = gst_harness_stress_push_event_with_cb_start (h,
162       create_new_stream_start_event, &counter, NULL);
163   GstHarnessThread *q_thread = gst_harness_stress_custom_start (h, NULL,
164       push_query, h, 0);
165   gdouble duration = 1.0;
166   GTimer *timer = g_timer_new ();
167
168   while (g_timer_elapsed (timer, NULL) < duration) {
169     gst_harness_add_sink (h, "fakesink");
170     g_thread_yield ();
171   }
172
173   g_timer_destroy (timer);
174   gst_harness_stress_thread_stop (q_thread);
175   gst_harness_stress_thread_stop (e_thread);
176   gst_harness_teardown (h);
177 }
178
179 GST_END_TEST;
180
181 static void
182 push_sticky_events (gpointer data, G_GNUC_UNUSED gpointer user_data)
183 {
184   GstHarness *h;
185   GstCaps *caps;
186   GstSegment segment;
187
188   h = (GstHarness *) user_data;
189
190   gst_harness_push_event (h, gst_event_new_stream_start ("999"));
191
192   caps = gst_caps_new_empty_simple ("mycaps");
193   gst_harness_push_event (h, gst_event_new_caps (caps));
194   gst_caps_unref (caps);
195
196   gst_segment_init (&segment, GST_FORMAT_TIME);
197   gst_harness_push_event (h, gst_event_new_segment (&segment));
198 }
199
200 GST_START_TEST (test_forward_sticky_events_to_sink_harness_while_teardown)
201 {
202   GstHarness *h = gst_harness_new ("identity");
203   GstHarnessThread *e_thread = gst_harness_stress_custom_start (h, NULL,
204       push_sticky_events, h, 0);
205   gdouble duration = 1.0;
206   GTimer *timer = g_timer_new ();
207
208   while (g_timer_elapsed (timer, NULL) < duration) {
209     gst_harness_add_sink (h, "fakesink");
210     g_thread_yield ();
211   }
212
213   g_timer_destroy (timer);
214   gst_harness_stress_thread_stop (e_thread);
215   gst_harness_teardown (h);
216 }
217
218 GST_END_TEST;
219
220 static GstHarness *
221 harness_new_and_fill_with_data (void)
222 {
223   GstHarness *h = gst_harness_new_parse ("fakesrc num-buffers=5 "
224       "filltype=pattern-span sizetype=fixed sizemin=10 sizemax=10");
225   gboolean have_eos = FALSE;
226
227   gst_harness_play (h);
228
229   do {
230     GstEvent *e = gst_harness_pull_event (h);
231     have_eos = GST_EVENT_TYPE (e) == GST_EVENT_EOS;
232     gst_event_unref (e);
233   } while (!have_eos);
234
235   return h;
236 }
237
238 GST_START_TEST (test_get_all_data)
239 {
240   guint8 expected[50];
241   const guint8 *cdata;
242   GstHarness *h;
243   GstBuffer *buf;
244   GBytes *bytes;
245   guint8 *data;
246   gsize size;
247   guint i;
248
249   for (i = 0; i < G_N_ELEMENTS (expected); ++i)
250     expected[i] = i;
251
252   h = harness_new_and_fill_with_data ();
253   buf = gst_harness_take_all_data_as_buffer (h);
254   fail_unless (buf != NULL);
255   fail_unless_equals_int (gst_buffer_get_size (buf), 5 * 10);
256   fail_unless (gst_buffer_memcmp (buf, 0, expected, 5 * 10) == 0);
257   gst_buffer_unref (buf);
258   /* There should be nothing left now. We should still get a non-NULL buffer */
259   buf = gst_harness_take_all_data_as_buffer (h);
260   fail_unless (buf != NULL);
261   fail_unless_equals_int (gst_buffer_get_size (buf), 0);
262   gst_buffer_unref (buf);
263   gst_harness_teardown (h);
264
265   h = harness_new_and_fill_with_data ();
266   bytes = gst_harness_take_all_data_as_bytes (h);
267   fail_unless (bytes != NULL);
268   cdata = g_bytes_get_data (bytes, &size);
269   fail_unless_equals_int (size, 5 * 10);
270   fail_unless (memcmp (cdata, expected, 50) == 0);
271   g_bytes_unref (bytes);
272   /* There should be nothing left now. We should still get a non-NULL bytes */
273   bytes = gst_harness_take_all_data_as_bytes (h);
274   fail_unless (bytes != NULL);
275   cdata = g_bytes_get_data (bytes, &size);
276   fail_unless (cdata == NULL);
277   fail_unless_equals_int (size, 0);
278   g_bytes_unref (bytes);
279   gst_harness_teardown (h);
280
281   h = harness_new_and_fill_with_data ();
282   data = gst_harness_take_all_data (h, &size);
283   fail_unless (data != NULL);
284   fail_unless_equals_int (size, 5 * 10);
285   fail_unless (memcmp (data, expected, 50) == 0);
286   g_free (data);
287   /* There should be nothing left now. */
288   data = gst_harness_take_all_data (h, &size);
289   fail_unless (data == NULL);
290   fail_unless_equals_int (size, 0);
291   gst_harness_teardown (h);
292 }
293
294 GST_END_TEST;
295
296 static Suite *
297 gst_harness_suite (void)
298 {
299   Suite *s = suite_create ("GstHarness");
300   TCase *tc_chain = tcase_create ("harness");
301
302   suite_add_tcase (s, tc_chain);
303
304   tcase_add_test (tc_chain, test_harness_empty);
305   tcase_add_test (tc_chain, test_harness_element_ref);
306   tcase_add_test (tc_chain, test_src_harness);
307   tcase_add_test (tc_chain, test_src_harness_no_forwarding);
308   tcase_add_test (tc_chain, test_add_sink_harness_without_sinkpad);
309
310   tcase_add_test (tc_chain,
311       test_forward_event_and_query_to_sink_harness_while_teardown);
312   tcase_add_test (tc_chain,
313       test_forward_sticky_events_to_sink_harness_while_teardown);
314
315   tcase_add_test (tc_chain, test_get_all_data);
316
317   return s;
318 }
319
320 GST_CHECK_MAIN (gst_harness);