8930b8b167db0da0b9d9c4bf3fc746f15056f207
[platform/upstream/gstreamer.git] / tests / check / gst / gstutils.c
1 /* GStreamer
2  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
3  * Copyright (C) <2006> Tim-Philipp Müller <tim centricular net>
4  *
5  * gstutils.c: Unit test for functions in gstutils
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gst/check/gstcheck.h>
28
29 #define SPECIAL_POINTER(x) ((void*)(19283847+(x)))
30
31 static int n_data_probes = 0;
32 static int n_buffer_probes = 0;
33 static int n_event_probes = 0;
34
35 static GstPadProbeReturn
36 probe_do_nothing (GstPad * pad, GstPadProbeInfo * info, gpointer data)
37 {
38   GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info);
39   GST_DEBUG_OBJECT (pad, "is buffer:%d", GST_IS_BUFFER (obj));
40   return GST_PAD_PROBE_OK;
41 }
42
43 static GstPadProbeReturn
44 data_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
45 {
46   GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info);
47   n_data_probes++;
48   GST_DEBUG_OBJECT (pad, "data probe %d", n_data_probes);
49   g_assert (GST_IS_BUFFER (obj) || GST_IS_EVENT (obj));
50   g_assert (data == SPECIAL_POINTER (0));
51   return GST_PAD_PROBE_OK;
52 }
53
54 static GstPadProbeReturn
55 buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
56 {
57   GstBuffer *obj = GST_PAD_PROBE_INFO_BUFFER (info);
58   n_buffer_probes++;
59   GST_DEBUG_OBJECT (pad, "buffer probe %d", n_buffer_probes);
60   g_assert (GST_IS_BUFFER (obj));
61   g_assert (data == SPECIAL_POINTER (1));
62   return GST_PAD_PROBE_OK;
63 }
64
65 static GstPadProbeReturn
66 event_probe (GstPad * pad, GstPadProbeInfo * info, gpointer data)
67 {
68   GstEvent *obj = GST_PAD_PROBE_INFO_EVENT (info);
69   n_event_probes++;
70   GST_DEBUG_OBJECT (pad, "event probe %d [%s]",
71       n_event_probes, GST_EVENT_TYPE_NAME (obj));
72   g_assert (GST_IS_EVENT (obj));
73   g_assert (data == SPECIAL_POINTER (2));
74   return GST_PAD_PROBE_OK;
75 }
76
77 GST_START_TEST (test_buffer_probe_n_times)
78 {
79   GstElement *pipeline, *fakesrc, *fakesink;
80   GstBus *bus;
81   GstMessage *message;
82   GstPad *pad;
83
84   pipeline = gst_element_factory_make ("pipeline", NULL);
85   fakesrc = gst_element_factory_make ("fakesrc", NULL);
86   fakesink = gst_element_factory_make ("fakesink", NULL);
87
88   g_object_set (fakesrc, "num-buffers", (int) 10, NULL);
89
90   gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
91   gst_element_link (fakesrc, fakesink);
92
93   pad = gst_element_get_static_pad (fakesink, "sink");
94
95   /* add the probes we need for the test */
96   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH, data_probe,
97       SPECIAL_POINTER (0), NULL);
98   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, buffer_probe,
99       SPECIAL_POINTER (1), NULL);
100   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, event_probe,
101       SPECIAL_POINTER (2), NULL);
102
103   /* add some string probes just to test that the data is free'd
104    * properly as it should be */
105   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH, probe_do_nothing,
106       g_strdup ("data probe string"), (GDestroyNotify) g_free);
107   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER, probe_do_nothing,
108       g_strdup ("buffer probe string"), (GDestroyNotify) g_free);
109   gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, probe_do_nothing,
110       g_strdup ("event probe string"), (GDestroyNotify) g_free);
111
112   gst_object_unref (pad);
113
114   gst_element_set_state (pipeline, GST_STATE_PLAYING);
115
116   bus = gst_element_get_bus (pipeline);
117   message = gst_bus_poll (bus, GST_MESSAGE_EOS, -1);
118   gst_message_unref (message);
119   gst_object_unref (bus);
120
121   g_assert (n_buffer_probes == 10);     /* one for every buffer */
122   g_assert (n_event_probes == 3);       /* new segment, latency and eos */
123   g_assert (n_data_probes == 13);       /* duh */
124
125   gst_element_set_state (pipeline, GST_STATE_NULL);
126   gst_object_unref (pipeline);
127
128   /* make sure nothing was sent in addition to the above when shutting down */
129   g_assert (n_buffer_probes == 10);     /* one for every buffer */
130   g_assert (n_event_probes == 3);       /* new segment, latency and eos */
131   g_assert (n_data_probes == 13);       /* duh */
132 } GST_END_TEST;
133
134 static int n_data_probes_once = 0;
135 static int n_buffer_probes_once = 0;
136 static int n_event_probes_once = 0;
137
138 static GstPadProbeReturn
139 data_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data)
140 {
141   GstMiniObject *obj = GST_PAD_PROBE_INFO_DATA (info);
142
143   n_data_probes_once++;
144   g_assert (GST_IS_BUFFER (obj) || GST_IS_EVENT (obj));
145
146   gst_pad_remove_probe (pad, *data);
147
148   return GST_PAD_PROBE_OK;
149 }
150
151 static GstPadProbeReturn
152 buffer_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data)
153 {
154   GstBuffer *obj = GST_PAD_PROBE_INFO_BUFFER (info);
155
156   n_buffer_probes_once++;
157   g_assert (GST_IS_BUFFER (obj));
158
159   gst_pad_remove_probe (pad, *data);
160
161   return GST_PAD_PROBE_OK;
162 }
163
164 static GstPadProbeReturn
165 event_probe_once (GstPad * pad, GstPadProbeInfo * info, guint * data)
166 {
167   GstEvent *obj = GST_PAD_PROBE_INFO_EVENT (info);
168
169   n_event_probes_once++;
170   g_assert (GST_IS_EVENT (obj));
171
172   gst_pad_remove_probe (pad, *data);
173
174   return GST_PAD_PROBE_OK;
175 }
176
177 GST_START_TEST (test_buffer_probe_once)
178 {
179   GstElement *pipeline, *fakesrc, *fakesink;
180   GstBus *bus;
181   GstMessage *message;
182   GstPad *pad;
183   guint id1, id2, id3;
184
185   pipeline = gst_element_factory_make ("pipeline", NULL);
186   fakesrc = gst_element_factory_make ("fakesrc", NULL);
187   fakesink = gst_element_factory_make ("fakesink", NULL);
188
189   g_object_set (fakesrc, "num-buffers", (int) 10, NULL);
190
191   gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
192   gst_element_link (fakesrc, fakesink);
193
194   pad = gst_element_get_static_pad (fakesink, "sink");
195   id1 =
196       gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_DATA_BOTH,
197       (GstPadProbeCallback) data_probe_once, &id1, NULL);
198   id2 =
199       gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
200       (GstPadProbeCallback) buffer_probe_once, &id2, NULL);
201   id3 =
202       gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_BOTH,
203       (GstPadProbeCallback) event_probe_once, &id3, NULL);
204   gst_object_unref (pad);
205
206   gst_element_set_state (pipeline, GST_STATE_PLAYING);
207
208   bus = gst_element_get_bus (pipeline);
209   message = gst_bus_poll (bus, GST_MESSAGE_EOS, -1);
210   gst_message_unref (message);
211   gst_object_unref (bus);
212
213   gst_element_set_state (pipeline, GST_STATE_NULL);
214   gst_object_unref (pipeline);
215
216   g_assert (n_buffer_probes_once == 1); /* can we hit it and quit? */
217   g_assert (n_event_probes_once == 1);  /* i said, can we hit it and quit? */
218   g_assert (n_data_probes_once == 1);   /* let's hit it and quit!!! */
219 } GST_END_TEST;
220
221 GST_START_TEST (test_math_scale)
222 {
223   fail_if (gst_util_uint64_scale_int (1, 1, 1) != 1);
224
225   fail_if (gst_util_uint64_scale_int (10, 10, 1) != 100);
226   fail_if (gst_util_uint64_scale_int (10, 10, 2) != 50);
227
228   fail_if (gst_util_uint64_scale_int (0, 10, 2) != 0);
229   fail_if (gst_util_uint64_scale_int (0, 0, 2) != 0);
230
231   fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 5, 1) != G_MAXUINT32 * 5LL);
232   fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 10, 2) != G_MAXUINT32 * 5LL);
233
234   fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 1, 5) != G_MAXUINT32 / 5LL);
235   fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 2, 10) != G_MAXUINT32 / 5LL);
236
237   /* not quite overflow */
238   fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, 10,
239           10) != G_MAXUINT64 - 1);
240   fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, G_MAXINT32,
241           G_MAXINT32) != G_MAXUINT64 - 1);
242   fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 100, G_MAXINT32,
243           G_MAXINT32) != G_MAXUINT64 - 100);
244
245   /* overflow */
246   fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, 10, 1) != G_MAXUINT64);
247   fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, G_MAXINT32,
248           1) != G_MAXUINT64);
249
250 } GST_END_TEST;
251
252 GST_START_TEST (test_math_scale_round)
253 {
254   fail_if (gst_util_uint64_scale_int_round (2, 1, 2) != 1);
255   fail_if (gst_util_uint64_scale_int_round (3, 1, 2) != 2);
256   fail_if (gst_util_uint64_scale_int_round (4, 1, 2) != 2);
257
258   fail_if (gst_util_uint64_scale_int_round (200, 100, 20000) != 1);
259   fail_if (gst_util_uint64_scale_int_round (299, 100, 20000) != 1);
260   fail_if (gst_util_uint64_scale_int_round (300, 100, 20000) != 2);
261   fail_if (gst_util_uint64_scale_int_round (301, 100, 20000) != 2);
262   fail_if (gst_util_uint64_scale_int_round (400, 100, 20000) != 2);
263 } GST_END_TEST;
264
265 GST_START_TEST (test_math_scale_ceil)
266 {
267   fail_if (gst_util_uint64_scale_int_ceil (2, 1, 2) != 1);
268   fail_if (gst_util_uint64_scale_int_ceil (3, 1, 2) != 2);
269   fail_if (gst_util_uint64_scale_int_ceil (4, 1, 2) != 2);
270
271   fail_if (gst_util_uint64_scale_int_ceil (200, 100, 20000) != 1);
272   fail_if (gst_util_uint64_scale_int_ceil (299, 100, 20000) != 2);
273   fail_if (gst_util_uint64_scale_int_ceil (300, 100, 20000) != 2);
274   fail_if (gst_util_uint64_scale_int_ceil (301, 100, 20000) != 2);
275   fail_if (gst_util_uint64_scale_int_ceil (400, 100, 20000) != 2);
276 } GST_END_TEST;
277
278 GST_START_TEST (test_math_scale_uint64)
279 {
280   fail_if (gst_util_uint64_scale (1, 1, 1) != 1);
281
282   fail_if (gst_util_uint64_scale (10, 10, 1) != 100);
283   fail_if (gst_util_uint64_scale (10, 10, 2) != 50);
284
285   fail_if (gst_util_uint64_scale (0, 10, 2) != 0);
286   fail_if (gst_util_uint64_scale (0, 0, 2) != 0);
287
288   fail_if (gst_util_uint64_scale (G_MAXUINT32, 5, 1) != G_MAXUINT32 * 5LL);
289   fail_if (gst_util_uint64_scale (G_MAXUINT32, 10, 2) != G_MAXUINT32 * 5LL);
290
291   fail_if (gst_util_uint64_scale (G_MAXUINT32, 1, 5) != G_MAXUINT32 / 5LL);
292   fail_if (gst_util_uint64_scale (G_MAXUINT32, 2, 10) != G_MAXUINT32 / 5LL);
293
294   /* not quite overflow */
295   fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, 10, 10) != G_MAXUINT64 - 1);
296   fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, G_MAXUINT32,
297           G_MAXUINT32) != G_MAXUINT64 - 1);
298   fail_if (gst_util_uint64_scale (G_MAXUINT64 - 100, G_MAXUINT32,
299           G_MAXUINT32) != G_MAXUINT64 - 100);
300
301   fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, 10, 10) != G_MAXUINT64 - 1);
302   fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, G_MAXUINT64,
303           G_MAXUINT64) != G_MAXUINT64 - 1);
304   fail_if (gst_util_uint64_scale (G_MAXUINT64 - 100, G_MAXUINT64,
305           G_MAXUINT64) != G_MAXUINT64 - 100);
306
307   /* overflow */
308   fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, 10, 1) != G_MAXUINT64);
309   fail_if (gst_util_uint64_scale (G_MAXUINT64 - 1, G_MAXUINT64,
310           1) != G_MAXUINT64);
311
312 } GST_END_TEST;
313
314 GST_START_TEST (test_math_scale_random)
315 {
316   guint64 val, num, denom, res;
317   GRand *rand;
318   gint i;
319
320   rand = g_rand_new ();
321
322   i = 100000;
323   while (i--) {
324     guint64 check, diff;
325
326     val = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
327     num = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
328     denom = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
329
330     res = gst_util_uint64_scale (val, num, denom);
331     check = gst_gdouble_to_guint64 (gst_guint64_to_gdouble (val) *
332         gst_guint64_to_gdouble (num) / gst_guint64_to_gdouble (denom));
333
334     if (res < G_MAXUINT64 && check < G_MAXUINT64) {
335       if (res > check)
336         diff = res - check;
337       else
338         diff = check - res;
339
340       /* some arbitrary value, really.. someone do the proper math to get
341        * the upper bound */
342       if (diff > 20000)
343         fail_if (diff > 20000);
344     }
345   }
346   g_rand_free (rand);
347
348 }
349
350 GST_END_TEST;
351
352 GST_START_TEST (test_guint64_to_gdouble)
353 {
354   guint64 from[] = { 0, 1, 100, 10000, (guint64) (1) << 63,
355     ((guint64) (1) << 63) + 1,
356     ((guint64) (1) << 63) + (G_GINT64_CONSTANT (1) << 62)
357   };
358   gdouble to[] = { 0., 1., 100., 10000., 9223372036854775808.,
359     9223372036854775809., 13835058055282163712.
360   };
361   gdouble tolerance[] = { 0., 0., 0., 0., 0., 1., 1. };
362   gint i;
363   gdouble result;
364   gdouble delta;
365
366   for (i = 0; i < G_N_ELEMENTS (from); ++i) {
367     result = gst_util_guint64_to_gdouble (from[i]);
368     delta = ABS (to[i] - result);
369     fail_unless (delta <= tolerance[i],
370         "Could not convert %d: %" G_GUINT64_FORMAT
371         " -> %f, got %f instead, delta of %e with tolerance of %e",
372         i, from[i], to[i], result, delta, tolerance[i]);
373   }
374 }
375
376 GST_END_TEST;
377
378 GST_START_TEST (test_gdouble_to_guint64)
379 {
380   gdouble from[] = { 0., 1., 100., 10000., 9223372036854775808.,
381     9223372036854775809., 13835058055282163712.
382   };
383   guint64 to[] = { 0, 1, 100, 10000, (guint64) (1) << 63,
384     ((guint64) (1) << 63) + 1,
385     ((guint64) (1) << 63) + (G_GINT64_CONSTANT (1) << 62)
386   };
387   guint64 tolerance[] = { 0, 0, 0, 0, 0, 1, 1 };
388   gint i;
389   gdouble result;
390   guint64 delta;
391
392   for (i = 0; i < G_N_ELEMENTS (from); ++i) {
393     result = gst_util_gdouble_to_guint64 (from[i]);
394     delta = ABS (to[i] - result);
395     fail_unless (delta <= tolerance[i],
396         "Could not convert %f: %" G_GUINT64_FORMAT
397         " -> %d, got %d instead, delta of %e with tolerance of %e",
398         i, from[i], to[i], result, delta, tolerance[i]);
399   }
400 }
401
402 GST_END_TEST;
403
404 #ifndef GST_DISABLE_PARSE
405 GST_START_TEST (test_parse_bin_from_description)
406 {
407   struct
408   {
409     const gchar *bin_desc;
410     const gchar *pad_names;
411   } bin_tests[] = {
412     {
413     "identity", "identity0/sink,identity0/src"}, {
414     "identity ! identity ! identity", "identity1/sink,identity3/src"}, {
415     "identity ! fakesink", "identity4/sink"}, {
416     "fakesrc ! identity", "identity5/src"}, {
417     "fakesrc ! fakesink", ""}
418   };
419   gint i;
420
421   for (i = 0; i < G_N_ELEMENTS (bin_tests); ++i) {
422     GstElement *bin, *parent;
423     GString *s;
424     GstPad *ghost_pad, *target_pad;
425     GError *err = NULL;
426
427     bin = gst_parse_bin_from_description (bin_tests[i].bin_desc, TRUE, &err);
428     if (err) {
429       g_error ("ERROR in gst_parse_bin_from_description (%s): %s",
430           bin_tests[i].bin_desc, err->message);
431     }
432     g_assert (bin != NULL);
433
434     s = g_string_new ("");
435     if ((ghost_pad = gst_element_get_static_pad (bin, "sink"))) {
436       g_assert (GST_IS_GHOST_PAD (ghost_pad));
437
438       target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost_pad));
439       g_assert (target_pad != NULL);
440       g_assert (GST_IS_PAD (target_pad));
441
442       parent = gst_pad_get_parent_element (target_pad);
443       g_assert (parent != NULL);
444
445       g_string_append_printf (s, "%s/sink", GST_ELEMENT_NAME (parent));
446
447       gst_object_unref (parent);
448       gst_object_unref (target_pad);
449       gst_object_unref (ghost_pad);
450     }
451
452     if ((ghost_pad = gst_element_get_static_pad (bin, "src"))) {
453       g_assert (GST_IS_GHOST_PAD (ghost_pad));
454
455       target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ghost_pad));
456       g_assert (target_pad != NULL);
457       g_assert (GST_IS_PAD (target_pad));
458
459       parent = gst_pad_get_parent_element (target_pad);
460       g_assert (parent != NULL);
461
462       if (s->len > 0) {
463         g_string_append (s, ",");
464       }
465
466       g_string_append_printf (s, "%s/src", GST_ELEMENT_NAME (parent));
467
468       gst_object_unref (parent);
469       gst_object_unref (target_pad);
470       gst_object_unref (ghost_pad);
471     }
472
473     if (strcmp (s->str, bin_tests[i].pad_names) != 0) {
474       g_error ("FAILED: expected '%s', got '%s' for bin '%s'",
475           bin_tests[i].pad_names, s->str, bin_tests[i].bin_desc);
476     }
477     g_string_free (s, TRUE);
478
479     gst_object_unref (bin);
480   }
481 }
482
483 GST_END_TEST;
484 #endif
485
486 GST_START_TEST (test_element_found_tags)
487 {
488   GstElement *pipeline, *fakesrc, *fakesink;
489   GstTagList *list;
490   GstBus *bus;
491   GstMessage *message;
492   GstPad *srcpad;
493
494   pipeline = gst_element_factory_make ("pipeline", NULL);
495   fakesrc = gst_element_factory_make ("fakesrc", NULL);
496   fakesink = gst_element_factory_make ("fakesink", NULL);
497   list = gst_tag_list_new_empty ();
498
499   g_object_set (fakesrc, "num-buffers", (int) 10, NULL);
500
501   gst_bin_add_many (GST_BIN (pipeline), fakesrc, fakesink, NULL);
502   gst_element_link (fakesrc, fakesink);
503
504   gst_element_set_state (pipeline, GST_STATE_PLAYING);
505
506   srcpad = gst_element_get_static_pad (fakesrc, "src");
507   gst_pad_push_event (srcpad, gst_event_new_tag (list));
508   gst_object_unref (srcpad);
509
510   bus = gst_element_get_bus (pipeline);
511   message = gst_bus_poll (bus, GST_MESSAGE_EOS, -1);
512   gst_message_unref (message);
513   gst_object_unref (bus);
514
515   /* FIXME: maybe also check if the fakesink receives the message */
516
517   gst_element_set_state (pipeline, GST_STATE_NULL);
518   gst_object_unref (pipeline);
519 }
520
521 GST_END_TEST;
522
523 GST_START_TEST (test_element_unlink)
524 {
525   GstElement *src, *sink;
526
527   src = gst_element_factory_make ("fakesrc", NULL);
528   sink = gst_element_factory_make ("fakesink", NULL);
529   fail_unless (gst_element_link (src, sink) != FALSE);
530   gst_element_unlink (src, sink);
531   gst_object_unref (src);
532   gst_object_unref (sink);
533 }
534
535 GST_END_TEST;
536
537 GST_START_TEST (test_set_value_from_string)
538 {
539   GValue val = { 0, };
540
541   /* g_return_if_fail */
542   ASSERT_CRITICAL (gst_util_set_value_from_string (NULL, "xyz"));
543
544   g_value_init (&val, G_TYPE_STRING);
545   ASSERT_CRITICAL (gst_util_set_value_from_string (&val, NULL));
546   g_value_unset (&val);
547
548   /* string => string */
549   g_value_init (&val, G_TYPE_STRING);
550   gst_util_set_value_from_string (&val, "Y00");
551   fail_unless (g_value_get_string (&val) != NULL);
552   fail_unless_equals_string (g_value_get_string (&val), "Y00");
553   g_value_unset (&val);
554
555   /* string => int */
556   g_value_init (&val, G_TYPE_INT);
557   gst_util_set_value_from_string (&val, "987654321");
558   fail_unless (g_value_get_int (&val) == 987654321);
559   g_value_unset (&val);
560
561   g_value_init (&val, G_TYPE_INT);
562   ASSERT_CRITICAL (gst_util_set_value_from_string (&val, "xyz"));
563   g_value_unset (&val);
564
565   /* string => uint */
566   g_value_init (&val, G_TYPE_UINT);
567   gst_util_set_value_from_string (&val, "987654321");
568   fail_unless (g_value_get_uint (&val) == 987654321);
569   g_value_unset (&val);
570
571   /* CHECKME: is this really desired behaviour? (tpm) */
572   g_value_init (&val, G_TYPE_UINT);
573   gst_util_set_value_from_string (&val, "-999");
574   fail_unless (g_value_get_uint (&val) == ((guint) 0 - (guint) 999));
575   g_value_unset (&val);
576
577   g_value_init (&val, G_TYPE_UINT);
578   ASSERT_CRITICAL (gst_util_set_value_from_string (&val, "xyz"));
579   g_value_unset (&val);
580
581   /* string => long */
582   g_value_init (&val, G_TYPE_LONG);
583   gst_util_set_value_from_string (&val, "987654321");
584   fail_unless (g_value_get_long (&val) == 987654321);
585   g_value_unset (&val);
586
587   g_value_init (&val, G_TYPE_LONG);
588   ASSERT_CRITICAL (gst_util_set_value_from_string (&val, "xyz"));
589   g_value_unset (&val);
590
591   /* string => ulong */
592   g_value_init (&val, G_TYPE_ULONG);
593   gst_util_set_value_from_string (&val, "987654321");
594   fail_unless (g_value_get_ulong (&val) == 987654321);
595   g_value_unset (&val);
596
597   /* CHECKME: is this really desired behaviour? (tpm) */
598   g_value_init (&val, G_TYPE_ULONG);
599   gst_util_set_value_from_string (&val, "-999");
600   fail_unless (g_value_get_ulong (&val) == ((gulong) 0 - (gulong) 999));
601   g_value_unset (&val);
602
603   g_value_init (&val, G_TYPE_ULONG);
604   ASSERT_CRITICAL (gst_util_set_value_from_string (&val, "xyz"));
605   g_value_unset (&val);
606
607   /* string => boolean */
608   g_value_init (&val, G_TYPE_BOOLEAN);
609   gst_util_set_value_from_string (&val, "true");
610   fail_unless_equals_int (g_value_get_boolean (&val), TRUE);
611   g_value_unset (&val);
612
613   g_value_init (&val, G_TYPE_BOOLEAN);
614   gst_util_set_value_from_string (&val, "TRUE");
615   fail_unless_equals_int (g_value_get_boolean (&val), TRUE);
616   g_value_unset (&val);
617
618   g_value_init (&val, G_TYPE_BOOLEAN);
619   gst_util_set_value_from_string (&val, "false");
620   fail_unless_equals_int (g_value_get_boolean (&val), FALSE);
621   g_value_unset (&val);
622
623   g_value_init (&val, G_TYPE_BOOLEAN);
624   gst_util_set_value_from_string (&val, "FALSE");
625   fail_unless_equals_int (g_value_get_boolean (&val), FALSE);
626   g_value_unset (&val);
627
628   g_value_init (&val, G_TYPE_BOOLEAN);
629   gst_util_set_value_from_string (&val, "bleh");
630   fail_unless_equals_int (g_value_get_boolean (&val), FALSE);
631   g_value_unset (&val);
632
633 #if 0
634   /* string => float (yay, localisation issues involved) */
635   g_value_init (&val, G_TYPE_FLOAT);
636   gst_util_set_value_from_string (&val, "987.654");
637   fail_unless (g_value_get_float (&val) >= 987.653 &&
638       g_value_get_float (&val) <= 987.655);
639   g_value_unset (&val);
640
641   g_value_init (&val, G_TYPE_FLOAT);
642   gst_util_set_value_from_string (&val, "987,654");
643   fail_unless (g_value_get_float (&val) >= 987.653 &&
644       g_value_get_float (&val) <= 987.655);
645   g_value_unset (&val);
646
647   /* string => double (yay, localisation issues involved) */
648   g_value_init (&val, G_TYPE_DOUBLE);
649   gst_util_set_value_from_string (&val, "987.654");
650   fail_unless (g_value_get_double (&val) >= 987.653 &&
651       g_value_get_double (&val) <= 987.655);
652   g_value_unset (&val);
653
654   g_value_init (&val, G_TYPE_DOUBLE);
655   gst_util_set_value_from_string (&val, "987,654");
656   fail_unless (g_value_get_double (&val) >= 987.653 &&
657       g_value_get_double (&val) <= 987.655);
658   g_value_unset (&val);
659 #endif
660 }
661
662 GST_END_TEST;
663
664 static gint
665 _binary_search_compare (guint32 * a, guint32 * b)
666 {
667   return *a - *b;
668 }
669
670 GST_START_TEST (test_binary_search)
671 {
672   guint32 data[257];
673   guint32 *match;
674   guint32 search_element = 121 * 2;
675   guint i;
676
677   for (i = 0; i < 257; i++)
678     data[i] = (i + 1) * 2;
679
680   match =
681       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
682       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_EXACT,
683       &search_element, NULL);
684   fail_unless (match != NULL);
685   fail_unless_equals_int (match - data, 120);
686
687   match =
688       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
689       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_BEFORE,
690       &search_element, NULL);
691   fail_unless (match != NULL);
692   fail_unless_equals_int (match - data, 120);
693
694   match =
695       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
696       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_AFTER,
697       &search_element, NULL);
698   fail_unless (match != NULL);
699   fail_unless_equals_int (match - data, 120);
700
701   search_element = 0;
702   match =
703       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
704       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_EXACT,
705       &search_element, NULL);
706   fail_unless (match == NULL);
707
708   match =
709       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
710       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_AFTER,
711       &search_element, NULL);
712   fail_unless (match != NULL);
713   fail_unless_equals_int (match - data, 0);
714
715   match =
716       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
717       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_BEFORE,
718       &search_element, NULL);
719   fail_unless (match == NULL);
720
721   search_element = 1000;
722   match =
723       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
724       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_EXACT,
725       &search_element, NULL);
726   fail_unless (match == NULL);
727
728   match =
729       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
730       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_AFTER,
731       &search_element, NULL);
732   fail_unless (match == NULL);
733
734   match =
735       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
736       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_BEFORE,
737       &search_element, NULL);
738   fail_unless (match != NULL);
739   fail_unless_equals_int (match - data, 256);
740
741   search_element = 121 * 2 - 1;
742   match =
743       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
744       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_EXACT,
745       &search_element, NULL);
746   fail_unless (match == NULL);
747
748   match =
749       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
750       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_AFTER,
751       &search_element, NULL);
752   fail_unless (match != NULL);
753   fail_unless_equals_int (match - data, 120);
754
755   match =
756       (guint32 *) gst_util_array_binary_search (data, 257, sizeof (guint32),
757       (GCompareDataFunc) _binary_search_compare, GST_SEARCH_MODE_BEFORE,
758       &search_element, NULL);
759   fail_unless (match != NULL);
760   fail_unless_equals_int (match - data, 119);
761
762 }
763
764 GST_END_TEST;
765
766 #ifdef HAVE_GSL
767 #ifdef HAVE_GMP
768
769 #include <gsl/gsl_rng.h>
770 #include <gmp.h>
771
772 static guint64
773 randguint64 (gsl_rng * rng, guint64 n)
774 {
775   union
776   {
777     guint64 x;
778     struct
779     {
780       guint16 a, b, c, d;
781     } parts;
782   } x;
783   x.parts.a = gsl_rng_uniform_int (rng, 1 << 16);
784   x.parts.b = gsl_rng_uniform_int (rng, 1 << 16);
785   x.parts.c = gsl_rng_uniform_int (rng, 1 << 16);
786   x.parts.d = gsl_rng_uniform_int (rng, 1 << 16);
787   return x.x % n;
788 }
789
790
791 enum round_t
792 {
793   ROUND_TONEAREST = 0,
794   ROUND_UP,
795   ROUND_DOWN
796 };
797
798 static void
799 gmp_set_uint64 (mpz_t mp, guint64 x)
800 {
801   mpz_t two_32, tmp;
802
803   mpz_init (two_32);
804   mpz_init (tmp);
805
806   mpz_ui_pow_ui (two_32, 2, 32);
807   mpz_set_ui (mp, (unsigned long) ((x >> 32) & G_MAXUINT32));
808   mpz_mul (tmp, mp, two_32);
809   mpz_add_ui (mp, tmp, (unsigned long) (x & G_MAXUINT32));
810   mpz_clear (two_32);
811   mpz_clear (tmp);
812 }
813
814 static guint64
815 gmp_get_uint64 (mpz_t mp)
816 {
817   mpz_t two_64, two_32, tmp;
818   guint64 ret;
819
820   mpz_init (two_64);
821   mpz_init (two_32);
822   mpz_init (tmp);
823
824   mpz_ui_pow_ui (two_64, 2, 64);
825   mpz_ui_pow_ui (two_32, 2, 32);
826   if (mpz_cmp (tmp, two_64) >= 0)
827     return G_MAXUINT64;
828   mpz_clear (two_64);
829
830   mpz_tdiv_q (tmp, mp, two_32);
831   ret = mpz_get_ui (tmp);
832   ret <<= 32;
833   ret |= mpz_get_ui (mp);
834   mpz_clear (two_32);
835   mpz_clear (tmp);
836
837   return ret;
838 }
839
840 static guint64
841 gmp_scale (guint64 x, guint64 a, guint64 b, enum round_t mode)
842 {
843   mpz_t mp1, mp2, mp3;
844   if (!b)
845     /* overflow */
846     return G_MAXUINT64;
847   mpz_init (mp1);
848   mpz_init (mp2);
849   mpz_init (mp3);
850
851   gmp_set_uint64 (mp1, x);
852   gmp_set_uint64 (mp3, a);
853   mpz_mul (mp2, mp1, mp3);
854   switch (mode) {
855     case ROUND_TONEAREST:
856       gmp_set_uint64 (mp1, b);
857       mpz_tdiv_q_ui (mp3, mp1, 2);
858       mpz_add (mp1, mp2, mp3);
859       mpz_set (mp2, mp1);
860       break;
861     case ROUND_UP:
862       gmp_set_uint64 (mp1, b);
863       mpz_sub_ui (mp3, mp1, 1);
864       mpz_add (mp1, mp2, mp3);
865       mpz_set (mp2, mp1);
866       break;
867     case ROUND_DOWN:
868       break;
869   }
870   gmp_set_uint64 (mp3, b);
871   mpz_tdiv_q (mp1, mp2, mp3);
872   x = gmp_get_uint64 (mp1);
873   mpz_clear (mp1);
874   mpz_clear (mp2);
875   mpz_clear (mp3);
876   return x;
877 }
878
879 static void
880 _gmp_test_scale (gsl_rng * rng)
881 {
882   guint64 bygst, bygmp;
883   guint64 a = randguint64 (rng, gsl_rng_uniform_int (rng,
884           2) ? G_MAXUINT64 : G_MAXUINT32);
885   guint64 b = randguint64 (rng, gsl_rng_uniform_int (rng, 2) ? G_MAXUINT64 - 1 : G_MAXUINT32 - 1) + 1;  /* 0 not allowed */
886   guint64 val = randguint64 (rng, gmp_scale (G_MAXUINT64, b, a, ROUND_DOWN));
887   enum round_t mode = gsl_rng_uniform_int (rng, 3);
888   const char *func;
889
890   bygmp = gmp_scale (val, a, b, mode);
891   switch (mode) {
892     case ROUND_TONEAREST:
893       bygst = gst_util_uint64_scale_round (val, a, b);
894       func = "gst_util_uint64_scale_round";
895       break;
896     case ROUND_UP:
897       bygst = gst_util_uint64_scale_ceil (val, a, b);
898       func = "gst_util_uint64_scale_ceil";
899       break;
900     case ROUND_DOWN:
901       bygst = gst_util_uint64_scale (val, a, b);
902       func = "gst_util_uint64_scale";
903       break;
904     default:
905       g_assert_not_reached ();
906       break;
907   }
908   fail_unless (bygst == bygmp,
909       "error: %s(): %" G_GUINT64_FORMAT " * %" G_GUINT64_FORMAT " / %"
910       G_GUINT64_FORMAT " = %" G_GUINT64_FORMAT ", correct = %" G_GUINT64_FORMAT
911       "\n", func, val, a, b, bygst, bygmp);
912 }
913
914 static void
915 _gmp_test_scale_int (gsl_rng * rng)
916 {
917   guint64 bygst, bygmp;
918   gint32 a = randguint64 (rng, G_MAXINT32);
919   gint32 b = randguint64 (rng, G_MAXINT32 - 1) + 1;     /* 0 not allowed */
920   guint64 val = randguint64 (rng, gmp_scale (G_MAXUINT64, b, a, ROUND_DOWN));
921   enum round_t mode = gsl_rng_uniform_int (rng, 3);
922   const char *func;
923
924   bygmp = gmp_scale (val, a, b, mode);
925   switch (mode) {
926     case ROUND_TONEAREST:
927       bygst = gst_util_uint64_scale_int_round (val, a, b);
928       func = "gst_util_uint64_scale_int_round";
929       break;
930     case ROUND_UP:
931       bygst = gst_util_uint64_scale_int_ceil (val, a, b);
932       func = "gst_util_uint64_scale_int_ceil";
933       break;
934     case ROUND_DOWN:
935       bygst = gst_util_uint64_scale_int (val, a, b);
936       func = "gst_util_uint64_scale_int";
937       break;
938     default:
939       g_assert_not_reached ();
940       break;
941   }
942   fail_unless (bygst == bygmp,
943       "error: %s(): %" G_GUINT64_FORMAT " * %d / %d = %" G_GUINT64_FORMAT
944       ", correct = %" G_GUINT64_FORMAT "\n", func, val, a, b, bygst, bygmp);
945 }
946
947 #define GMP_TEST_RUNS 100000
948
949 GST_START_TEST (test_math_scale_gmp)
950 {
951   gsl_rng *rng = gsl_rng_alloc (gsl_rng_mt19937);
952   gint n;
953
954   for (n = 0; n < GMP_TEST_RUNS; n++)
955     _gmp_test_scale (rng);
956
957   gsl_rng_free (rng);
958 }
959
960 GST_END_TEST;
961
962 GST_START_TEST (test_math_scale_gmp_int)
963 {
964   gsl_rng *rng = gsl_rng_alloc (gsl_rng_mt19937);
965   gint n;
966
967   for (n = 0; n < GMP_TEST_RUNS; n++)
968     _gmp_test_scale_int (rng);
969
970   gsl_rng_free (rng);
971 }
972
973 GST_END_TEST;
974
975 #endif
976 #endif
977
978 GST_START_TEST (test_pad_proxy_getcaps_aggregation)
979 {
980   GstElement *tee, *sink1, *sink2;
981   GstCaps *caps;
982   GstPad *tee_src1, *tee_src2, *tee_sink, *sink1_sink, *sink2_sink;
983
984   tee = gst_element_factory_make ("tee", "tee");
985
986   sink1 = gst_element_factory_make ("fakesink", "sink1");
987   tee_src1 = gst_element_get_request_pad (tee, "src_%u");
988   sink1_sink = gst_element_get_static_pad (sink1, "sink");
989   fail_unless_equals_int (gst_pad_link (tee_src1, sink1_sink), GST_PAD_LINK_OK);
990
991   sink2 = gst_element_factory_make ("fakesink", "sink2");
992   tee_src2 = gst_element_get_request_pad (tee, "src_%u");
993   sink2_sink = gst_element_get_static_pad (sink2, "sink");
994   fail_unless_equals_int (gst_pad_link (tee_src2, sink2_sink), GST_PAD_LINK_OK);
995
996   tee_sink = gst_element_get_static_pad (tee, "sink");
997
998   gst_element_set_state (sink1, GST_STATE_PAUSED);
999   gst_element_set_state (sink2, GST_STATE_PAUSED);
1000   gst_element_set_state (tee, GST_STATE_PAUSED);
1001
1002   /* by default, ANY caps should intersect to ANY */
1003   caps = gst_pad_get_caps (tee_sink, NULL);
1004   GST_INFO ("got caps: %" GST_PTR_FORMAT, caps);
1005   fail_unless (caps != NULL);
1006   fail_unless (gst_caps_is_any (caps));
1007   gst_caps_unref (caps);
1008
1009   /* these don't intersect we should get empty caps */
1010   caps = gst_caps_new_empty_simple ("foo/bar");
1011   fail_unless (gst_pad_set_caps (sink1_sink, caps));
1012   gst_pad_use_fixed_caps (sink1_sink);
1013   gst_caps_unref (caps);
1014
1015   caps = gst_caps_new_empty_simple ("bar/ter");
1016   fail_unless (gst_pad_set_caps (sink2_sink, caps));
1017   gst_pad_use_fixed_caps (sink2_sink);
1018   gst_caps_unref (caps);
1019
1020   caps = gst_pad_get_caps (tee_sink, NULL);
1021   GST_INFO ("got caps: %" GST_PTR_FORMAT, caps);
1022   fail_unless (caps != NULL);
1023   fail_unless (gst_caps_is_empty (caps));
1024   gst_caps_unref (caps);
1025
1026   /* test intersection */
1027   caps = gst_caps_new_simple ("foo/bar", "barversion", G_TYPE_INT, 1, NULL);
1028   fail_unless (gst_pad_set_caps (sink2_sink, caps));
1029   gst_pad_use_fixed_caps (sink2_sink);
1030   gst_caps_unref (caps);
1031
1032   caps = gst_pad_get_caps (tee_sink, NULL);
1033   GST_INFO ("got caps: %" GST_PTR_FORMAT, caps);
1034   fail_unless (caps != NULL);
1035   fail_if (gst_caps_is_empty (caps));
1036   {
1037     GstStructure *s = gst_caps_get_structure (caps, 0);
1038
1039     fail_unless_equals_string (gst_structure_get_name (s), "foo/bar");
1040     fail_unless (gst_structure_has_field_typed (s, "barversion", G_TYPE_INT));
1041   }
1042   gst_caps_unref (caps);
1043
1044   gst_element_set_state (sink1, GST_STATE_NULL);
1045   gst_element_set_state (sink2, GST_STATE_NULL);
1046   gst_element_set_state (tee, GST_STATE_NULL);
1047
1048   /* clean up */
1049   gst_element_release_request_pad (tee, tee_src1);
1050   gst_object_unref (tee_src1);
1051   gst_element_release_request_pad (tee, tee_src2);
1052   gst_object_unref (tee_src2);
1053   gst_object_unref (tee_sink);
1054   gst_object_unref (tee);
1055   gst_object_unref (sink1_sink);
1056   gst_object_unref (sink1);
1057   gst_object_unref (sink2_sink);
1058   gst_object_unref (sink2);
1059 }
1060
1061 GST_END_TEST;
1062
1063 GST_START_TEST (test_greatest_common_divisor)
1064 {
1065   fail_if (gst_util_greatest_common_divisor (1, 1) != 1);
1066   fail_if (gst_util_greatest_common_divisor (2, 3) != 1);
1067   fail_if (gst_util_greatest_common_divisor (3, 5) != 1);
1068   fail_if (gst_util_greatest_common_divisor (-1, 1) != 1);
1069   fail_if (gst_util_greatest_common_divisor (-2, 3) != 1);
1070   fail_if (gst_util_greatest_common_divisor (-3, 5) != 1);
1071   fail_if (gst_util_greatest_common_divisor (-1, -1) != 1);
1072   fail_if (gst_util_greatest_common_divisor (-2, -3) != 1);
1073   fail_if (gst_util_greatest_common_divisor (-3, -5) != 1);
1074   fail_if (gst_util_greatest_common_divisor (1, -1) != 1);
1075   fail_if (gst_util_greatest_common_divisor (2, -3) != 1);
1076   fail_if (gst_util_greatest_common_divisor (3, -5) != 1);
1077   fail_if (gst_util_greatest_common_divisor (2, 2) != 2);
1078   fail_if (gst_util_greatest_common_divisor (2, 4) != 2);
1079   fail_if (gst_util_greatest_common_divisor (1001, 11) != 11);
1080
1081 }
1082
1083 GST_END_TEST;
1084
1085 static Suite *
1086 gst_utils_suite (void)
1087 {
1088   Suite *s = suite_create ("GstUtils");
1089   TCase *tc_chain = tcase_create ("general");
1090
1091   suite_add_tcase (s, tc_chain);
1092   tcase_add_test (tc_chain, test_buffer_probe_n_times);
1093   tcase_add_test (tc_chain, test_buffer_probe_once);
1094   tcase_add_test (tc_chain, test_math_scale);
1095   tcase_add_test (tc_chain, test_math_scale_round);
1096   tcase_add_test (tc_chain, test_math_scale_ceil);
1097   tcase_add_test (tc_chain, test_math_scale_uint64);
1098   tcase_add_test (tc_chain, test_math_scale_random);
1099 #ifdef HAVE_GSL
1100 #ifdef HAVE_GMP
1101   tcase_add_test (tc_chain, test_math_scale_gmp);
1102   tcase_add_test (tc_chain, test_math_scale_gmp_int);
1103 #endif
1104 #endif
1105
1106   tcase_add_test (tc_chain, test_guint64_to_gdouble);
1107   tcase_add_test (tc_chain, test_gdouble_to_guint64);
1108 #ifndef GST_DISABLE_PARSE
1109   tcase_add_test (tc_chain, test_parse_bin_from_description);
1110 #endif
1111   tcase_add_test (tc_chain, test_element_found_tags);
1112   tcase_add_test (tc_chain, test_element_unlink);
1113   tcase_add_test (tc_chain, test_set_value_from_string);
1114   tcase_add_test (tc_chain, test_binary_search);
1115
1116   tcase_add_test (tc_chain, test_pad_proxy_getcaps_aggregation);
1117   tcase_add_test (tc_chain, test_greatest_common_divisor);
1118   return s;
1119 }
1120
1121 GST_CHECK_MAIN (gst_utils);