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