gstreamer/tests/check/gst/gstvalue.c
Thibault Saunier 109bdd0c25 value: Refactor parsing lists to allow trailing comas
Before that commit `{test, }` wouldn't be accepted as an array
because of the trailing coma, the commit fixes that.

At the same time, the code has been refactored to avoid special casing
the first element of the list, making `{,}` or `<,>` valid lists.
2020-03-12 14:50:20 +00:00

3531 lines
116 KiB
C

/* GStreamer
* Copyright (C) <2004> David Schleef <david at schleef dot org>
* Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
*
* gstvalue.c: Unit tests for GstValue
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define GLIB_DISABLE_DEPRECATION_WARNINGS
#include <gst/check/gstcheck.h>
GST_START_TEST (test_deserialize_buffer)
{
GValue value = { 0 };
GstBuffer *buf;
guint8 data[8];
guint64 val;
g_value_init (&value, GST_TYPE_BUFFER);
fail_unless (gst_value_deserialize (&value, "1234567890abcdef"));
/* does not increase the refcount */
buf = GST_BUFFER (g_value_get_boxed (&value));
ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
/* does not increase the refcount */
buf = gst_value_get_buffer (&value);
ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
gst_buffer_extract (buf, 0, data, 8);
val = GST_READ_UINT64_BE (data);
fail_unless_equals_uint64 (val, G_GUINT64_CONSTANT (0x1234567890abcdef));
/* cleanup */
g_value_unset (&value);
}
GST_END_TEST;
/* create and serialize a buffer */
GST_START_TEST (test_serialize_buffer)
{
GValue value = { 0 };
GstBuffer *buf;
gchar *serialized;
const guint8 buf_data[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef };
gint len;
len = sizeof (buf_data);
buf = gst_buffer_new_and_alloc (len);
gst_buffer_fill (buf, 0, (gchar *) buf_data, len);
ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
/* and assign buffer to mini object */
g_value_init (&value, GST_TYPE_BUFFER);
gst_value_take_buffer (&value, buf);
ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
/* now serialize it */
serialized = gst_value_serialize (&value);
GST_DEBUG ("serialized buffer to %s", serialized);
fail_unless (serialized != NULL);
fail_unless_equals_string (serialized, "1234567890abcdef");
/* refcount should not change */
ASSERT_MINI_OBJECT_REFCOUNT (buf, "buffer", 1);
/* cleanup */
g_free (serialized);
g_value_unset (&value);
/* take NULL buffer */
g_value_init (&value, GST_TYPE_BUFFER);
GST_DEBUG ("setting NULL buffer");
gst_value_take_buffer (&value, NULL);
/* now serialize it */
GST_DEBUG ("serializing NULL buffer");
serialized = gst_value_serialize (&value);
/* should return NULL */
fail_unless (serialized == NULL);
g_free (serialized);
g_value_unset (&value);
}
GST_END_TEST;
GST_START_TEST (test_deserialize_gint64)
{
GValue value = { 0 };
const char *strings[] = {
"12345678901",
"-12345678901",
"1152921504606846976",
"-1152921504606846976",
};
gint64 results[] = {
12345678901LL,
-12345678901LL,
1152921504606846976LL,
-1152921504606846976LL,
};
int i;
g_value_init (&value, G_TYPE_INT64);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (g_value_get_int64 (&value) == results[i],
"resulting value is %" G_GINT64_FORMAT ", not %" G_GINT64_FORMAT
", for string %s (%d)", g_value_get_int64 (&value),
results[i], strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_guint64)
{
GValue value = { 0 };
const char *strings[] = {
"0xffffffffffffffff",
"9223372036854775810",
"-9223372036854775810",
"-1",
"1",
"-0",
};
guint64 results[] = {
0xffffffffffffffffULL,
9223372036854775810ULL,
9223372036854775806ULL,
(guint64) - 1,
1,
0,
};
int i;
g_value_init (&value, G_TYPE_UINT64);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (g_value_get_uint64 (&value) == results[i],
"resulting value is %" G_GUINT64_FORMAT ", not %" G_GUINT64_FORMAT
", for string %s (%d)", g_value_get_uint64 (&value),
results[i], strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_guchar)
{
GValue value = { 0 };
const char *strings[] = {
"0xff",
"255",
"-1",
"1",
"-0",
};
guchar results[] = {
0xff,
255,
(guchar) - 1,
1,
0,
};
int i;
g_value_init (&value, G_TYPE_UCHAR);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (g_value_get_uchar (&value) == results[i],
"resulting value is %u not %u, for string %s (%d)",
g_value_get_uchar (&value), results[i], strings[i], i);
}
/* test serialisation as well while we're at it */
{
gchar *str;
GValue value = { 0 };
g_value_init (&value, G_TYPE_UCHAR);
g_value_set_uchar (&value, 255);
str = gst_value_serialize (&value);
fail_unless_equals_string (str, "255");
g_free (str);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_gstfraction)
{
GValue value = { 0 };
const char *strings[] = {
"4/5",
"-8/9"
};
gint64 result_numers[] = {
4,
-8
};
gint64 result_denoms[] = {
5,
9
};
int i;
g_value_init (&value, GST_TYPE_FRACTION);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (gst_value_get_fraction_numerator (&value) == result_numers[i],
"resulting numerator value is %d, not %d"
", for string %s (%d)", gst_value_get_fraction_numerator (&value),
result_numers[i], strings[i], i);
fail_unless (gst_value_get_fraction_denominator (&value) ==
result_denoms[i], "resulting denominator value is %d, not %d"
", for string %s (%d)", gst_value_get_fraction_denominator (&value),
result_denoms[i], strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_gint)
{
GValue value = { 0 };
const char *strings[] = {
"123456",
"-123456",
"0xFFFF",
"0x0000FFFF",
/* a positive long long, serializing to highest possible positive sint */
"0x7FFFFFFF",
/* a positive long long, serializing to lowest possible negative sint */
"0x80000000",
/* a negative long long, serializing to lowest possible negative sint */
"0xFFFFFFFF80000000",
"0xFF000000",
/* a positive long long serializing to -1 */
"0xFFFFFFFF",
"0xFFFFFFFF",
/* a negative long long serializing to -1 */
"0xFFFFFFFFFFFFFFFF",
"0xFFFFFFFFFFFFFFFF",
"0xEFFFFFFF",
};
/* some casts need to be explicit because of unsigned -> signed */
gint results[] = {
123456,
-123456,
0xFFFF,
0xFFFF,
0x7FFFFFFF,
(gint) 0x80000000,
(gint) 0x80000000,
(gint) 0xFF000000,
-1,
(gint) 0xFFFFFFFF,
-1,
(gint) 0xFFFFFFFFFFFFFFFFLL,
(gint) 0xEFFFFFFF,
};
int i;
g_value_init (&value, G_TYPE_INT);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (g_value_get_int (&value) == results[i],
"resulting value is %d, not %d, for string %s (%d)",
g_value_get_int (&value), results[i], strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_gint_failures)
{
GValue value = { 0 };
const char *strings[] = {
"-", /* not a complete number */
"- TEST", /* not a complete number */
"0x0000000100000000", /* lowest long long that cannot fit in 32 bits */
"0xF000000000000000",
"0xFFFFFFF000000000",
"0xFFFFFFFF00000000",
"0x10000000000000000", /* first number too long to fit into a long long */
/* invent a new processor first before trying to make this one pass */
"0x10000000000000000000000000000000000000000000",
};
int i;
g_value_init (&value, G_TYPE_INT);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_if (gst_value_deserialize (&value, strings[i]),
"deserialized %s (%d), while it should have failed", strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_guint)
{
GValue value = { 0 };
const char *strings[] = {
"123456",
"-123456",
"0xFFFF",
"0x0000FFFF",
/* a positive long long, serializing to highest possible positive sint */
"0x7FFFFFFF",
/* a positive long long, serializing to lowest possible negative sint */
"0x80000000",
"2147483648",
/* a negative long long, serializing to lowest possible negative sint */
"0xFFFFFFFF80000000",
/* a value typically used for rgb masks */
"0xFF000000",
/* a positive long long serializing to highest possible positive uint */
"0xFFFFFFFF",
"0xFFFFFFFF",
/* a negative long long serializing to highest possible positive uint */
"0xFFFFFFFFFFFFFFFF",
"0xEFFFFFFF",
};
guint results[] = {
123456,
(guint) - 123456,
0xFFFF,
0xFFFF,
0x7FFFFFFF,
0x80000000,
(guint) 2147483648LL,
0x80000000,
0xFF000000,
0xFFFFFFFF,
G_MAXUINT,
(guint) 0xFFFFFFFFFFFFFFFFLL,
0xEFFFFFFF,
};
int i;
g_value_init (&value, G_TYPE_UINT);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (g_value_get_uint (&value) == results[i],
"resulting value is %d, not %d, for string %s (%d)",
g_value_get_uint (&value), results[i], strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_guint_failures)
{
GValue value = { 0 };
const char *strings[] = {
"-", /* not a complete number */
"- TEST", /* not a complete number */
#if 0
/* FIXME: these values should not be deserializable, since they overflow
* the target format */
"0x0000000100000000", /* lowest long long that cannot fit in 32 bits */
"0xF000000000000000",
"0xFFFFFFF000000000",
"0xFFFFFFFF00000000",
"0x10000000000000000", /* first number too long to fit into a long long */
/* invent a new processor first before trying to make this one pass */
"0x10000000000000000000000000000000000000000000",
#endif
};
int i;
g_value_init (&value, G_TYPE_UINT);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_if (gst_value_deserialize (&value, strings[i]),
"deserialized %s (%d), while it should have failed", strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_serialize_flags)
{
GValue value = { 0 };
gchar *string;
GstSeekFlags flags[] = {
0,
GST_SEEK_FLAG_NONE,
GST_SEEK_FLAG_FLUSH,
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
};
const char *results[] = {
"GST_SEEK_FLAG_NONE",
"GST_SEEK_FLAG_NONE",
"GST_SEEK_FLAG_FLUSH",
"GST_SEEK_FLAG_FLUSH+GST_SEEK_FLAG_ACCURATE",
};
int i;
g_value_init (&value, GST_TYPE_SEEK_FLAGS);
for (i = 0; i < G_N_ELEMENTS (flags); ++i) {
g_value_set_flags (&value, flags[i]);
string = gst_value_serialize (&value);
fail_if (string == NULL, "could not serialize flags %d", i);
fail_unless (strcmp (string, results[i]) == 0,
"resulting value is %s, not %s, for flags #%d", string, results[i], i);
g_free (string);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_flags)
{
GValue value = { 0 };
const char *strings[] = {
"",
"0",
"GST_SEEK_FLAG_NONE",
"GST_SEEK_FLAG_FLUSH",
"0xf",
"15",
"GST_SEEK_FLAG_FLUSH+GST_SEEK_FLAG_ACCURATE",
};
GstSeekFlags results[] = {
GST_SEEK_FLAG_NONE,
GST_SEEK_FLAG_NONE,
GST_SEEK_FLAG_NONE,
GST_SEEK_FLAG_FLUSH,
0xf,
15,
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
};
int i;
g_value_init (&value, GST_TYPE_SEEK_FLAGS);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (g_value_get_flags (&value) == results[i],
"resulting value is %d, not %d, for string %s (%d)",
g_value_get_flags (&value), results[i], strings[i], i);
}
fail_if (gst_value_deserialize (&value, "foo"),
"flag deserializing for bogus value should have failed!");
fail_if (gst_value_deserialize (&value, "GST_SEEK_FLAG_FLUSH+foo"),
"flag deserializing for bogus value should have failed!");
fail_if (gst_value_deserialize (&value,
"GST_SEEK_FLAG_FLUSH+foo+GST_SEEK_FLAG_ACCURATE"),
"flag deserializing for bogus value should have failed!");
}
GST_END_TEST;
GST_START_TEST (test_deserialize_gtype)
{
GValue value = { 0 };
const char *strings[] = {
"gchararray",
"gint",
};
GType results[] = {
G_TYPE_STRING,
G_TYPE_INT,
};
int i;
g_value_init (&value, G_TYPE_GTYPE);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (g_value_get_gtype (&value) == results[i],
"resulting value is %" G_GSIZE_FORMAT ", not %" G_GSIZE_FORMAT
", for string %s (%d)",
g_value_get_gtype (&value), results[i], strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_gtype_failures)
{
GValue value = { 0 };
const char *strings[] = {
"-", /* not a gtype */
};
int i;
g_value_init (&value, G_TYPE_GTYPE);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_if (gst_value_deserialize (&value, strings[i]),
"deserialized %s (%d), while it should have failed", strings[i], i);
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_bitmask)
{
GValue value = { 0 };
const char *strings[] = {
"0xffffffffffffffff",
"0x1234567890ABCDEF",
};
guint64 results[] = {
0xffffffffffffffffULL,
0x1234567890ABCDEFULL,
};
int i;
g_value_init (&value, GST_TYPE_BITMASK);
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
fail_unless (gst_value_deserialize (&value, strings[i]),
"could not deserialize %s (%d)", strings[i], i);
fail_unless (gst_value_get_bitmask (&value) == results[i],
"resulting value is 0x%016" G_GINT64_MODIFIER "x, not 0x%016"
G_GINT64_MODIFIER "x, for string %s (%d)",
gst_value_get_bitmask (&value), results[i], strings[i], i);
}
}
GST_END_TEST;
static void
check_flagset_mask_serialisation (GValue * value, guint test_flags,
guint test_mask)
{
gchar *string;
gst_value_set_flagset (value, test_flags, test_mask);
/* Normalise our test flags against the mask now for easier testing,
* as that's what we expect to get back from the flagset after it
* normalises internally */
test_flags &= test_mask;
/* Check the values got stored correctly */
fail_unless (gst_value_get_flagset_flags (value) == test_flags,
"resulting flags value is 0x%u, not 0x%x",
gst_value_get_flagset_flags (value), test_flags);
fail_unless (gst_value_get_flagset_mask (value) == test_mask,
"resulting mask is 0x%u, not 0x%x",
gst_value_get_flagset_mask (value), test_mask);
string = gst_value_serialize (value);
fail_if (string == NULL, "could not serialize flagset");
GST_DEBUG ("Serialized flagset to: %s", string);
fail_unless (gst_value_deserialize (value, string),
"could not deserialize %s", string);
fail_unless (gst_value_get_flagset_flags (value) == test_flags,
"resulting flags value is 0x%u, not 0x%x, for string %s",
gst_value_get_flagset_flags (value), test_flags, string);
fail_unless (gst_value_get_flagset_mask (value) == test_mask,
"resulting mask is 0x%u, not 0x%x, for string %s",
gst_value_get_flagset_mask (value), test_mask, string);
g_free (string);
}
GST_START_TEST (test_flagset)
{
GValue value = G_VALUE_INIT;
GValue value2 = G_VALUE_INIT;
GValue dest = G_VALUE_INIT;
gchar *string;
GType test_flagset_type;
guint test_flags, test_mask;
/* Test serialisation of abstract type */
g_value_init (&value, GST_TYPE_FLAG_SET);
test_flags = 0xf1f1;
test_mask = 0xffff;
gst_value_set_flagset (&value, test_flags, test_mask);
string = gst_value_serialize (&value);
fail_if (string == NULL, "could not serialize flagset");
fail_unless (gst_value_deserialize (&value, string),
"could not deserialize %s", string);
fail_unless (gst_value_get_flagset_flags (&value) == test_flags,
"resulting value is 0x%u, not 0x%x, for string %s",
gst_value_get_flagset_flags (&value), test_flags, string);
fail_unless (gst_value_get_flagset_mask (&value) == test_mask,
"resulting value is 0x%u, not 0x%x, for string %s",
gst_value_get_flagset_mask (&value), test_mask, string);
g_free (string);
g_value_unset (&value);
/* Check we can't wrap a random non-flags type */
ASSERT_CRITICAL (gst_flagset_register (GST_TYPE_OBJECT));
test_flagset_type = gst_flagset_register (GST_TYPE_SEEK_FLAGS);
fail_unless (g_type_is_a (test_flagset_type, GST_TYPE_FLAG_SET));
g_value_init (&value, test_flagset_type);
test_flags =
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE |
GST_SEEK_FLAG_TRICKMODE_KEY_UNITS;
test_mask =
GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE |
GST_SEEK_FLAG_TRICKMODE_NO_AUDIO;
check_flagset_mask_serialisation (&value, test_flags, test_mask);
/* Check serialisation works with the generic 'exact' flag */
check_flagset_mask_serialisation (&value, test_flags,
GST_FLAG_SET_MASK_EXACT);
/* Check deserialisation of flagset in 'flags' form, without
* the hex strings at the start */
test_flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE;
test_mask = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_TRICKMODE |
GST_SEEK_FLAG_TRICKMODE_NO_AUDIO;
string = g_strdup ("+flush+trickmode/trickmode-no-audio");
fail_unless (gst_value_deserialize (&value, string),
"could not deserialize %s", string);
GST_DEBUG ("Deserialized %s to 0x%x:0x%x", string,
gst_value_get_flagset_flags (&value),
gst_value_get_flagset_mask (&value));
fail_unless (gst_value_get_flagset_flags (&value) == test_flags,
"resulting flags value is 0x%u, not 0x%x, for string %s",
gst_value_get_flagset_flags (&value), (test_flags & test_mask), string);
fail_unless (gst_value_get_flagset_mask (&value) == test_mask,
"resulting mask is 0x%u, not 0x%x, for string %s",
gst_value_get_flagset_mask (&value), test_mask, string);
g_free (string);
g_value_unset (&value);
/* Test that fixating don't-care fields works, using our
* sub-type flagset for good measure */
g_value_init (&value, test_flagset_type);
gst_value_set_flagset (&value, test_flags, test_mask);
fail_unless (gst_value_fixate (&dest, &value));
fail_unless (gst_value_get_flagset_flags (&dest) == test_flags);
fail_unless (gst_value_get_flagset_mask (&dest) == GST_FLAG_SET_MASK_EXACT);
g_value_unset (&value);
/* Intersection tests */
g_value_init (&value, GST_TYPE_FLAG_SET);
g_value_init (&value2, test_flagset_type);
/* We want Accurate, but not Snap-Before */
gst_value_set_flagset (&value, GST_SEEK_FLAG_ACCURATE,
GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SNAP_BEFORE);
/* This only cares that things are flushing */
gst_value_set_flagset (&value2, GST_SEEK_FLAG_FLUSH, GST_SEEK_FLAG_FLUSH);
test_flags = GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH;
test_mask =
GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SNAP_BEFORE;
/* GstFlagSet should always intersect with itself */
g_value_unset (&dest);
fail_unless (gst_value_can_intersect (&value, &value));
fail_unless (gst_value_intersect (&dest, &value, &value));
/* GstFlagSet subtype should intersect with itself */
g_value_unset (&dest);
fail_unless (gst_value_can_intersect (&value2, &value2));
fail_unless (gst_value_intersect (&dest, &value2, &value2));
/* Check we can intersect custom flagset subtype with flagset */
g_value_unset (&dest);
fail_unless (gst_value_can_intersect (&value2, &value));
fail_unless (gst_value_intersect (&dest, &value2, &value));
/* and in the other order */
g_value_unset (&dest);
fail_unless (gst_value_can_intersect (&value, &value2));
fail_unless (gst_value_intersect (&dest, &value, &value2));
fail_unless (gst_value_get_flagset_flags (&dest) == test_flags,
"resulting flags value is 0x%u, not 0x%x",
gst_value_get_flagset_flags (&dest), test_flags);
fail_unless (gst_value_get_flagset_mask (&dest) == test_mask,
"resulting mask is 0x%u, not 0x%x",
gst_value_get_flagset_mask (&dest), test_mask);
gst_value_set_flagset (&value,
GST_SEEK_FLAG_ACCURATE, GST_SEEK_FLAG_ACCURATE);
gst_value_set_flagset (&value2, GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH,
GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_SNAP_BEFORE | GST_SEEK_FLAG_FLUSH);
/* Check that accurate alone is a subset of accurate+!snap_before+flush,
* but not vice-versa */
fail_unless (gst_value_is_subset (&value, &value2));
fail_if (gst_value_is_subset (&value2, &value));
g_value_unset (&dest);
g_value_unset (&value);
g_value_unset (&value2);
}
GST_END_TEST;
GST_START_TEST (test_string)
{
const gchar *try[] = {
"Dude",
"Hi, I'm a string",
"tüüüt!",
"\"\"" /* Empty string */
};
gchar *tmp;
GValue v = { 0, };
guint i;
g_value_init (&v, G_TYPE_STRING);
for (i = 0; i < G_N_ELEMENTS (try); i++) {
g_value_set_string (&v, try[i]);
tmp = gst_value_serialize (&v);
fail_if (tmp == NULL, "couldn't serialize: %s\n", try[i]);
fail_unless (gst_value_deserialize (&v, tmp),
"couldn't deserialize: %s\n", tmp);
g_free (tmp);
fail_unless (g_str_equal (g_value_get_string (&v), try[i]),
"\nserialized : %s\ndeserialized: %s", try[i],
g_value_get_string (&v));
}
/* NULL strings should not be serializable */
g_value_set_string (&v, NULL);
fail_unless (gst_value_serialize (&v) == NULL);
g_value_unset (&v);
}
GST_END_TEST;
GST_START_TEST (test_deserialize_string)
{
struct
{
const gchar *from;
const gchar *to;
} tests[] = {
{
"\"foo\"", "foo"}, {
"\"foo\\%\"", "foo%"}, {
"\"0123456789_-+/:.\"", "0123456789_-+/:."}, {
"\"Hello\\ World\"", "Hello World"}, {
"\"Hello\\ World", "\"Hello\\ World"}, {
"\"\\", "\"\\"}, {
"\"\\0", "\"\\0"}, {
"", ""}, /* empty strings */
{
"\"\"", ""}, /* quoted empty string -> empty string */
/* Expected FAILURES: */
{
"\"\\0\"", NULL}, /* unfinished escaped character */
{
"\"", NULL}, /* solitary quote */
{
"\" \"", NULL}, /* spaces must be escaped */
#if 0
/* FIXME 0.9: this test should fail, but it doesn't */
{
"tüüt", NULL} /* string with special chars must be escaped */
#endif
};
guint i;
GValue v = { 0, };
g_value_init (&v, G_TYPE_STRING);
for (i = 0; i < G_N_ELEMENTS (tests); i++) {
if (gst_value_deserialize (&v, tests[i].from)) {
fail_if (tests[i].to == NULL,
"I got %s instead of a failure", g_value_get_string (&v));
fail_unless (g_str_equal (g_value_get_string (&v), tests[i].to),
"\nwanted: %s\ngot : %s", tests[i].to, g_value_get_string (&v));
} else {
fail_if (tests[i].to != NULL, "failed, but wanted: %s", tests[i].to);
}
}
g_value_unset (&v);
}
GST_END_TEST;
GST_START_TEST (test_value_compare)
{
GValue value1 = { 0 };
GValue value2 = { 0 };
GValue tmp = { 0 };
GstAllocationParams alloc_params = { 0 };
g_value_init (&value1, G_TYPE_INT);
g_value_set_int (&value1, 10);
g_value_init (&value2, G_TYPE_INT);
g_value_set_int (&value2, 20);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN);
fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
g_value_init (&value1, G_TYPE_DOUBLE);
g_value_set_double (&value1, 10);
g_value_init (&value2, G_TYPE_DOUBLE);
g_value_set_double (&value2, 20);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN);
fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
g_value_init (&value1, G_TYPE_STRING);
g_value_set_string (&value1, "a");
g_value_init (&value2, G_TYPE_STRING);
g_value_set_string (&value2, "b");
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN);
fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
/* Test some NULL string comparisons */
g_value_set_string (&value2, NULL);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED);
fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_UNORDERED);
fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
/* comparing 2/3 with 3/4 */
g_value_init (&value1, GST_TYPE_FRACTION);
gst_value_set_fraction (&value1, 2, 3);
g_value_init (&value2, GST_TYPE_FRACTION);
gst_value_set_fraction (&value2, 3, 4);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN);
fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
/* comparing -4/5 with 2/-3 */
g_value_init (&value1, GST_TYPE_FRACTION);
gst_value_set_fraction (&value1, -4, 5);
g_value_init (&value2, GST_TYPE_FRACTION);
gst_value_set_fraction (&value2, 2, -3);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN);
fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
/* comparing 10/100 with 200/2000 */
g_value_init (&value1, GST_TYPE_FRACTION);
gst_value_set_fraction (&value1, 10, 100);
g_value_init (&value2, GST_TYPE_FRACTION);
gst_value_set_fraction (&value2, 200, 2000);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
/* comparing -4/5 with 2/-3 */
g_value_init (&value1, GST_TYPE_FRACTION);
gst_value_set_fraction (&value1, -4, 5);
g_value_init (&value2, GST_TYPE_FRACTION);
gst_value_set_fraction (&value2, 2, -3);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_LESS_THAN);
fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_GREATER_THAN);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
/* Check that lists are equal regardless of order */
g_value_init (&value1, GST_TYPE_LIST);
g_value_init (&tmp, G_TYPE_INT);
g_value_set_int (&tmp, 1);
gst_value_list_append_value (&value1, &tmp);
g_value_set_int (&tmp, 2);
gst_value_list_append_value (&value1, &tmp);
g_value_set_int (&tmp, 3);
gst_value_list_append_value (&value1, &tmp);
g_value_set_int (&tmp, 4);
gst_value_list_append_value (&value1, &tmp);
g_value_init (&value2, GST_TYPE_LIST);
g_value_set_int (&tmp, 4);
gst_value_list_append_value (&value2, &tmp);
g_value_set_int (&tmp, 3);
gst_value_list_append_value (&value2, &tmp);
g_value_set_int (&tmp, 2);
gst_value_list_append_value (&value2, &tmp);
g_value_set_int (&tmp, 1);
gst_value_list_append_value (&value2, &tmp);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
"value lists with different order were not equal when they should be");
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL,
"value lists with same order were not equal when they should be");
fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL,
"value lists with same order were not equal when they should be");
/* Carry over the lists to this next check: */
/* Lists with different sizes are unequal */
g_value_set_int (&tmp, 1);
gst_value_list_append_value (&value2, &tmp);
fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
"Value lists with different size were equal when they shouldn't be");
/* Carry over the lists to this next check: */
/* Lists with same size but list1 contains one more element not in list2 */
g_value_set_int (&tmp, 5);
gst_value_list_append_value (&value1, &tmp);
fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
"Value lists with different elements were equal when they shouldn't be");
fail_if (gst_value_compare (&value2, &value1) == GST_VALUE_EQUAL,
"Value lists with different elements were equal when they shouldn't be");
g_value_unset (&value1);
g_value_unset (&value2);
g_value_unset (&tmp);
/* Arrays are only equal when in the same order */
g_value_init (&value1, GST_TYPE_ARRAY);
g_value_init (&tmp, G_TYPE_INT);
g_value_set_int (&tmp, 1);
gst_value_array_append_value (&value1, &tmp);
g_value_set_int (&tmp, 2);
gst_value_array_append_value (&value1, &tmp);
g_value_set_int (&tmp, 3);
gst_value_array_append_value (&value1, &tmp);
g_value_set_int (&tmp, 4);
gst_value_array_append_value (&value1, &tmp);
g_value_init (&value2, GST_TYPE_ARRAY);
g_value_set_int (&tmp, 4);
gst_value_array_append_value (&value2, &tmp);
g_value_set_int (&tmp, 3);
gst_value_array_append_value (&value2, &tmp);
g_value_set_int (&tmp, 2);
gst_value_array_append_value (&value2, &tmp);
g_value_set_int (&tmp, 1);
gst_value_array_append_value (&value2, &tmp);
fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
"Value arrays with different order were equal when they shouldn't be");
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL,
"Identical value arrays were not equal when they should be");
fail_unless (gst_value_compare (&value2, &value2) == GST_VALUE_EQUAL,
"Identical value arrays were not equal when they should be");
/* Carry over the arrays to this next check: */
/* Arrays with different sizes are unequal */
g_value_unset (&value2);
g_value_init (&value2, GST_TYPE_ARRAY);
g_value_copy (&value1, &value2);
g_value_set_int (&tmp, 1);
gst_value_array_append_value (&value2, &tmp);
fail_if (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL,
"Value arrays with different size were equal when they shouldn't be");
/* order should not matter */
fail_if (gst_value_compare (&value2, &value1) == GST_VALUE_EQUAL,
"Value arrays with different size were equal when they shouldn't be");
g_value_unset (&value1);
g_value_unset (&value2);
g_value_unset (&tmp);
g_value_init (&value1, GST_TYPE_BITMASK);
gst_value_set_bitmask (&value1, 0x123);
g_value_init (&value2, GST_TYPE_BITMASK);
gst_value_set_bitmask (&value2, 0x321);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED);
fail_unless (gst_value_compare (&value2, &value1) == GST_VALUE_UNORDERED);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
/* Check that we can compare objects */
g_value_init (&value1, GST_TYPE_BIN);
g_value_take_object (&value1, gst_bin_new (NULL));
g_value_init (&value2, GST_TYPE_BIN);
g_value_take_object (&value2, gst_bin_new (NULL));
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
/* Check that we can compare allocation params */
g_value_init (&value1, GST_TYPE_ALLOCATION_PARAMS);
g_value_set_boxed (&value1, &alloc_params);
g_value_init (&value2, GST_TYPE_ALLOCATION_PARAMS);
alloc_params.align = 1;
g_value_set_boxed (&value2, &alloc_params);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED);
fail_unless (gst_value_compare (&value1, &value1) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
/* Check that we can compare structure */
{
GstStructure *s = gst_structure_new_empty ("test");
g_value_init (&value1, GST_TYPE_STRUCTURE);
g_value_init (&value2, GST_TYPE_STRUCTURE);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL);
gst_value_set_structure (&value1, s);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_UNORDERED);
gst_value_set_structure (&value2, s);
fail_unless (gst_value_compare (&value1, &value2) == GST_VALUE_EQUAL);
g_value_unset (&value1);
g_value_unset (&value2);
gst_structure_free (s);
}
}
GST_END_TEST;
GST_START_TEST (test_value_intersect)
{
GValue dest = { 0 };
GValue src1 = { 0 };
GValue src2 = { 0 };
GValue item = { 0 };
gboolean ret;
g_value_init (&src1, G_TYPE_INT);
g_value_set_int (&src1, 10);
g_value_init (&src2, G_TYPE_INT);
g_value_set_int (&src2, 20);
ret = gst_value_intersect (&dest, &src1, &src2);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
g_value_init (&src1, G_TYPE_STRING);
g_value_set_static_string (&src1, "YUY2");
g_value_init (&src2, GST_TYPE_LIST);
g_value_init (&item, G_TYPE_STRING);
g_value_set_static_string (&item, "YUY2");
gst_value_list_append_value (&src2, &item);
g_value_set_static_string (&item, "I420");
gst_value_list_append_value (&src2, &item);
g_value_set_static_string (&item, "ABCD");
gst_value_list_append_value (&src2, &item);
fail_unless (gst_value_intersect (&dest, &src1, &src2));
fail_unless (G_VALUE_HOLDS_STRING (&dest));
fail_unless (g_str_equal (g_value_get_string (&dest), "YUY2"));
g_value_unset (&src1);
g_value_unset (&src2);
g_value_unset (&dest);
}
GST_END_TEST;
GST_START_TEST (test_value_subtract_int)
{
GValue dest = { 0 };
GValue src1 = { 0 };
GValue src2 = { 0 };
const GValue *tmp;
gboolean ret;
/* int <-> int
*/
g_value_init (&src1, G_TYPE_INT);
g_value_set_int (&src1, 10);
g_value_init (&src2, G_TYPE_INT);
g_value_set_int (&src2, 20);
/* subtract as in sets, result is 10 */
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* same values, yields empty set */
ret = gst_value_subtract (&dest, &src1, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* int <-> int_range
*/
/* would yield an empty set */
g_value_init (&src1, G_TYPE_INT);
g_value_set_int (&src1, 10);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 0, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should create a list of two ranges. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int_range_min (tmp) == 0);
fail_unless (gst_value_get_int_range_max (tmp) == 9);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int_range_min (tmp) == 11);
fail_unless (gst_value_get_int_range_max (tmp) == 20);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* border case 1, empty set */
g_value_init (&src1, G_TYPE_INT);
g_value_set_int (&src1, 10);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 10, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should create a new range. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_get_int_range_min (&dest) == 11);
fail_unless (gst_value_get_int_range_max (&dest) == 20);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* border case 2, empty set */
g_value_init (&src1, G_TYPE_INT);
g_value_set_int (&src1, 20);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 10, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should create a new range. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_get_int_range_min (&dest) == 10);
fail_unless (gst_value_get_int_range_max (&dest) == 19);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* case 3, valid set */
g_value_init (&src1, G_TYPE_INT);
g_value_set_int (&src1, 0);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 10, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_HOLDS_INT (&dest) == TRUE);
fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* and the other way around, should keep the range. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_get_int_range_min (&dest) == 10);
fail_unless (gst_value_get_int_range_max (&dest) == 20);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* int_range <-> int_range
*/
/* same range, empty set */
g_value_init (&src1, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src1, 10, 20);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 10, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* non overlapping ranges */
g_value_init (&src1, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src1, 10, 20);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 30, 40);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_get_int_range_min (&dest) == 10);
fail_unless (gst_value_get_int_range_max (&dest) == 20);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_get_int_range_min (&dest) == 30);
fail_unless (gst_value_get_int_range_max (&dest) == 40);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* completely overlapping ranges */
g_value_init (&src1, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src1, 10, 20);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 10, 30);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_get_int_range_min (&dest) == 21);
fail_unless (gst_value_get_int_range_max (&dest) == 30);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* partially overlapping ranges */
g_value_init (&src1, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src1, 10, 20);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 15, 30);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_get_int_range_min (&dest) == 10);
fail_unless (gst_value_get_int_range_max (&dest) == 14);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_get_int_range_min (&dest) == 21);
fail_unless (gst_value_get_int_range_max (&dest) == 30);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole { int_range, int_range } */
g_value_init (&src1, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src1, 10, 30);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 15, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int_range_min (tmp) == 10);
fail_unless (gst_value_get_int_range_max (tmp) == 14);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int_range_min (tmp) == 21);
fail_unless (gst_value_get_int_range_max (tmp) == 30);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole, { int, int } */
g_value_init (&src1, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src1, 10, 30);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 11, 29);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
fail_unless (g_value_get_int (tmp) == 10);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
fail_unless (g_value_get_int (tmp) == 30);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole, { int, int_range } */
g_value_init (&src1, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src1, 10, 30);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 11, 28);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
fail_unless (g_value_get_int (tmp) == 10);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int_range_min (tmp) == 29);
fail_unless (gst_value_get_int_range_max (tmp) == 30);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole, { int_range, int } */
g_value_init (&src1, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src1, 10, 30);
g_value_init (&src2, GST_TYPE_INT_RANGE);
gst_value_set_int_range (&src2, 12, 29);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (GST_VALUE_HOLDS_INT_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int_range_min (tmp) == 10);
fail_unless (gst_value_get_int_range_max (tmp) == 11);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (G_VALUE_HOLDS_INT (tmp) == TRUE);
fail_unless (g_value_get_int (tmp) == 30);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
}
GST_END_TEST;
GST_START_TEST (test_value_subtract_int64)
{
GValue dest = { 0 };
GValue src1 = { 0 };
GValue src2 = { 0 };
const GValue *tmp;
gboolean ret;
/* int64 <-> int64
*/
g_value_init (&src1, G_TYPE_INT64);
g_value_set_int64 (&src1, 10);
g_value_init (&src2, G_TYPE_INT64);
g_value_set_int64 (&src2, 20);
/* subtract as in sets, result is 10 */
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* same values, yields empty set */
ret = gst_value_subtract (&dest, &src1, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* int64 <-> int64_range
*/
/* would yield an empty set */
g_value_init (&src1, G_TYPE_INT64);
g_value_set_int64 (&src1, 10);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 0, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should create a list of two ranges. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int64_range_min (tmp) == 0);
fail_unless (gst_value_get_int64_range_max (tmp) == 9);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int64_range_min (tmp) == 11);
fail_unless (gst_value_get_int64_range_max (tmp) == 20);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* border case 1, empty set */
g_value_init (&src1, G_TYPE_INT64);
g_value_set_int64 (&src1, 10);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 10, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should create a new range. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_get_int64_range_min (&dest) == 11);
fail_unless (gst_value_get_int64_range_max (&dest) == 20);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* border case 2, empty set */
g_value_init (&src1, G_TYPE_INT64);
g_value_set_int64 (&src1, 20);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 10, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should create a new range. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_get_int64_range_min (&dest) == 10);
fail_unless (gst_value_get_int64_range_max (&dest) == 19);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* case 3, valid set */
g_value_init (&src1, G_TYPE_INT64);
g_value_set_int64 (&src1, 0);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 10, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_HOLDS_INT64 (&dest) == TRUE);
fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* and the other way around, should keep the range. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_get_int64_range_min (&dest) == 10);
fail_unless (gst_value_get_int64_range_max (&dest) == 20);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* int64_range <-> int64_range
*/
/* same range, empty set */
g_value_init (&src1, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src1, 10, 20);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 10, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* non overlapping ranges */
g_value_init (&src1, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src1, 10, 20);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 30, 40);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_get_int64_range_min (&dest) == 10);
fail_unless (gst_value_get_int64_range_max (&dest) == 20);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_get_int64_range_min (&dest) == 30);
fail_unless (gst_value_get_int64_range_max (&dest) == 40);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* completely overlapping ranges */
g_value_init (&src1, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src1, 10, 20);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 10, 30);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_get_int64_range_min (&dest) == 21);
fail_unless (gst_value_get_int64_range_max (&dest) == 30);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* partially overlapping ranges */
g_value_init (&src1, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src1, 10, 20);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 15, 30);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_get_int64_range_min (&dest) == 10);
fail_unless (gst_value_get_int64_range_max (&dest) == 14);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_get_int64_range_min (&dest) == 21);
fail_unless (gst_value_get_int64_range_max (&dest) == 30);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole { int64_range, int64_range } */
g_value_init (&src1, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src1, 10, 30);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 15, 20);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int64_range_min (tmp) == 10);
fail_unless (gst_value_get_int64_range_max (tmp) == 14);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int64_range_min (tmp) == 21);
fail_unless (gst_value_get_int64_range_max (tmp) == 30);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole, { int64, int64 } */
g_value_init (&src1, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src1, 10, 30);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 11, 29);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE);
fail_unless (g_value_get_int64 (tmp) == 10);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE);
fail_unless (g_value_get_int64 (tmp) == 30);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole, { int64, int64_range } */
g_value_init (&src1, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src1, 10, 30);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 11, 28);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE);
fail_unless (g_value_get_int64 (tmp) == 10);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int64_range_min (tmp) == 29);
fail_unless (gst_value_get_int64_range_max (tmp) == 30);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole, { int64_range, int64 } */
g_value_init (&src1, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src1, 10, 30);
g_value_init (&src2, GST_TYPE_INT64_RANGE);
gst_value_set_int64_range (&src2, 12, 29);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_int64_range_min (tmp) == 10);
fail_unless (gst_value_get_int64_range_max (tmp) == 11);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE);
fail_unless (g_value_get_int64 (tmp) == 30);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
}
GST_END_TEST;
GST_START_TEST (test_value_subtract_double)
{
GValue dest = { 0 };
GValue src1 = { 0 };
GValue src2 = { 0 };
const GValue *tmp;
gboolean ret;
/* double <-> double
*/
g_value_init (&src1, G_TYPE_DOUBLE);
g_value_set_double (&src1, 10.0);
g_value_init (&src2, G_TYPE_DOUBLE);
g_value_set_double (&src2, 20.0);
/* subtract as in sets, result is 10 */
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* same values, yields empty set */
ret = gst_value_subtract (&dest, &src1, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* double <-> double_range
*/
/* would yield an empty set */
g_value_init (&src1, G_TYPE_DOUBLE);
g_value_set_double (&src1, 10.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 0.0, 20.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, we cannot create open ranges
* so the result is the range again */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 0.0);
fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* border case 1, empty set */
g_value_init (&src1, G_TYPE_DOUBLE);
g_value_set_double (&src1, 10.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 10.0, 20.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should keep same range as
* we don't have open ranges. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* border case 2, empty set */
g_value_init (&src1, G_TYPE_DOUBLE);
g_value_set_double (&src1, 20.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 10.0, 20.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should keep same range as
* we don't have open ranges. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* case 3, valid set */
g_value_init (&src1, G_TYPE_DOUBLE);
g_value_set_double (&src1, 0.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 10.0, 20.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_HOLDS_DOUBLE (&dest) == TRUE);
fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* and the other way around, should keep the range. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* double_range <-> double_range
*/
/* Check equality */
g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src1, 10.0, 20.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 10.0, 15.0);
/* They are not equal (higher bound is different */
fail_if (gst_value_compare (&src1, &src2) == GST_VALUE_EQUAL);
g_value_unset (&src1);
/* They are not equal (lower bound is different */
g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src1, 5.0, 15.0);
fail_if (gst_value_compare (&src1, &src2) == GST_VALUE_EQUAL);
g_value_unset (&src1);
/* And finally check equality */
g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src1, 10.0, 15.0);
fail_unless (gst_value_compare (&src1, &src2) == GST_VALUE_EQUAL);
g_value_unset (&src1);
g_value_unset (&src2);
/* same range, empty set */
g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src1, 10.0, 20.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 10.0, 20.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* non overlapping ranges */
g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src1, 10.0, 20.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 30.0, 40.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
fail_unless (gst_value_get_double_range_max (&dest) == 20.0);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 30.0);
fail_unless (gst_value_get_double_range_max (&dest) == 40.0);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* completely overlapping ranges */
g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src1, 10.0, 20.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 10.0, 30.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 20.0);
fail_unless (gst_value_get_double_range_max (&dest) == 30.0);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* partially overlapping ranges */
g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src1, 10.0, 20.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 15.0, 30.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 10.0);
fail_unless (gst_value_get_double_range_max (&dest) == 15.0);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_DOUBLE_RANGE);
fail_unless (gst_value_get_double_range_min (&dest) == 20.0);
fail_unless (gst_value_get_double_range_max (&dest) == 30.0);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole { double_range, double_range } */
g_value_init (&src1, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src1, 10.0, 30.0);
g_value_init (&src2, GST_TYPE_DOUBLE_RANGE);
gst_value_set_double_range (&src2, 15.0, 20.0);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_double_range_min (tmp) == 10.0);
fail_unless (gst_value_get_double_range_max (tmp) == 15.0);
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (GST_VALUE_HOLDS_DOUBLE_RANGE (tmp) == TRUE);
fail_unless (gst_value_get_double_range_min (tmp) == 20.0);
fail_unless (gst_value_get_double_range_max (tmp) == 30.0);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
}
GST_END_TEST;
/* Test arithmetic subtraction of fractions */
GST_START_TEST (test_value_subtract_fraction)
{
GValue result = { 0 };
GValue src1 = { 0 };
GValue src2 = { 0 };
/* Subtract 1/4 from 1/2 */
g_value_init (&src1, GST_TYPE_FRACTION);
g_value_init (&src2, GST_TYPE_FRACTION);
g_value_init (&result, GST_TYPE_FRACTION);
gst_value_set_fraction (&src1, 1, 2);
gst_value_set_fraction (&src2, 1, 4);
fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE);
fail_unless (gst_value_get_fraction_numerator (&result) == 1);
fail_unless (gst_value_get_fraction_denominator (&result) == 4);
g_value_unset (&src1);
g_value_unset (&src2);
g_value_unset (&result);
/* Subtract 1/12 from 7/8 */
g_value_init (&src1, GST_TYPE_FRACTION);
g_value_init (&src2, GST_TYPE_FRACTION);
g_value_init (&result, GST_TYPE_FRACTION);
gst_value_set_fraction (&src1, 7, 8);
gst_value_set_fraction (&src2, 1, 12);
fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE);
fail_unless (gst_value_get_fraction_numerator (&result) == 19);
fail_unless (gst_value_get_fraction_denominator (&result) == 24);
g_value_unset (&src1);
g_value_unset (&src2);
g_value_unset (&result);
/* Subtract 12/13 from 4/3 */
g_value_init (&src1, GST_TYPE_FRACTION);
g_value_init (&src2, GST_TYPE_FRACTION);
g_value_init (&result, GST_TYPE_FRACTION);
gst_value_set_fraction (&src1, 4, 3);
gst_value_set_fraction (&src2, 12, 13);
fail_unless (gst_value_fraction_subtract (&result, &src1, &src2) == TRUE);
fail_unless (gst_value_get_fraction_numerator (&result) == 16);
fail_unless (gst_value_get_fraction_denominator (&result) == 39);
g_value_unset (&src1);
g_value_unset (&src2);
g_value_unset (&result);
/* Subtract 1/12 from 7/8 */
}
GST_END_TEST;
/* Test set subtraction operations on fraction ranges */
GST_START_TEST (test_value_subtract_fraction_range)
{
GValue dest = { 0 };
GValue src1 = { 0 };
GValue src2 = { 0 };
GValue cmp = { 0 };
const GValue *tmp;
gboolean ret;
/* Value for tests */
g_value_init (&cmp, GST_TYPE_FRACTION);
/* fraction <-> fraction
*/
g_value_init (&src1, GST_TYPE_FRACTION);
gst_value_set_fraction (&src1, 10, 1);
g_value_init (&src2, GST_TYPE_FRACTION);
gst_value_set_fraction (&src2, 20, 1);
gst_value_set_fraction (&src1, 10, 1);
/* subtract as in sets, result is 10 */
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* same values, yields empty set */
ret = gst_value_subtract (&dest, &src1, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* fraction <-> fraction_range
*/
/* would yield an empty set */
g_value_init (&src1, GST_TYPE_FRACTION);
gst_value_set_fraction (&src1, 10, 1);
g_value_init (&src2, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src2, 0, 1, 20, 1);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, we cannot create open ranges
* so the result is the range again */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction (&cmp, 0, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 20, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest),
&cmp) == GST_VALUE_EQUAL);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* border case 1, empty set */
g_value_init (&src1, GST_TYPE_FRACTION);
gst_value_set_fraction (&src1, 10, 1);
g_value_init (&src2, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src2, 10, 1, 20, 1);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* and the other way around, should keep same range as
* we don't have open ranges. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction (&cmp, 10, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 20, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest),
&cmp) == GST_VALUE_EQUAL);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* case 2, valid set */
g_value_init (&src1, GST_TYPE_FRACTION);
gst_value_set_fraction (&src1, 0, 1);
g_value_init (&src2, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src2, 10, 1, 20, 1);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION);
fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* and the other way around, should keep the range. */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
fail_unless (gst_value_compare (&dest, &src2) == GST_VALUE_EQUAL);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* fraction_range <-> fraction_range
*/
/* same range, empty set */
g_value_init (&src1, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src1, 10, 2, 20, 2);
g_value_init (&src2, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src2, 10, 2, 20, 2);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
/* non overlapping ranges */
g_value_init (&src1, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src1, 10, 2, 10, 1);
g_value_init (&src2, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src2, 30, 2, 40, 2);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction (&cmp, 5, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 10, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest),
&cmp) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction (&cmp, 15, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 20, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest),
&cmp) == GST_VALUE_EQUAL);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* completely overlapping ranges */
g_value_init (&src1, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src1, 10, 1, 20, 1);
g_value_init (&src2, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src2, 10, 1, 30, 1);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == FALSE);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction (&cmp, 20, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 30, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest),
&cmp) == GST_VALUE_EQUAL);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* partially overlapping ranges */
g_value_init (&src1, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src1, 10, 1, 20, 1);
g_value_init (&src2, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src2, 15, 1, 30, 1);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction (&cmp, 10, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 15, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest),
&cmp) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction (&cmp, 20, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (&dest),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 30, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (&dest),
&cmp) == GST_VALUE_EQUAL);
g_value_unset (&dest);
g_value_unset (&src1);
g_value_unset (&src2);
/* create a hole { double_range, double_range } */
g_value_init (&src1, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src1, 10, 1, 30, 1);
g_value_init (&src2, GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range_full (&src2, 15, 1, 20, 1);
ret = gst_value_subtract (&dest, &src1, &src2);
fail_unless (ret == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_LIST);
/* 1st list entry */
tmp = gst_value_list_get_value (&dest, 0);
fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (tmp) == TRUE);
gst_value_set_fraction (&cmp, 10, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (tmp),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 15, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (tmp),
&cmp) == GST_VALUE_EQUAL);
/* 2nd list entry */
tmp = gst_value_list_get_value (&dest, 1);
fail_unless (GST_VALUE_HOLDS_FRACTION_RANGE (tmp) == TRUE);
gst_value_set_fraction (&cmp, 20, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_min (tmp),
&cmp) == GST_VALUE_EQUAL);
gst_value_set_fraction (&cmp, 30, 1);
fail_unless (gst_value_compare (gst_value_get_fraction_range_max (tmp),
&cmp) == GST_VALUE_EQUAL);
g_value_unset (&dest);
/* the other way */
ret = gst_value_subtract (&dest, &src2, &src1);
fail_unless (ret == FALSE);
g_value_unset (&src1);
g_value_unset (&src2);
g_value_unset (&cmp);
}
GST_END_TEST;
/* Test set subtraction operations on fraction lists */
GST_START_TEST (test_value_subtract_fraction_list)
{
GValue list1 = { 0 };
GValue list2 = { 0 };
GValue val1 = { 0 };
GValue val2 = { 0 };
GValue tmp = { 0 };
gboolean ret;
g_value_init (&list1, GST_TYPE_LIST);
g_value_init (&val1, GST_TYPE_FRACTION);
gst_value_set_fraction (&val1, 15, 2);
gst_value_list_append_value (&list1, &val1);
g_value_init (&tmp, GST_TYPE_FRACTION);
gst_value_set_fraction (&tmp, 5, 1);
gst_value_list_append_value (&list1, &tmp);
g_value_unset (&tmp);
g_value_init (&list2, GST_TYPE_LIST);
g_value_init (&val2, GST_TYPE_FRACTION);
gst_value_set_fraction (&val2, 15, 1);
gst_value_list_append_value (&list2, &val2);
g_value_init (&tmp, GST_TYPE_FRACTION);
gst_value_set_fraction (&tmp, 5, 1);
gst_value_list_append_value (&list2, &tmp);
g_value_unset (&tmp);
/* should subtract all common elements */
ret = gst_value_subtract (&tmp, &list1, &list2);
fail_unless (ret == TRUE);
fail_unless (gst_value_compare (&tmp, &val1) == GST_VALUE_EQUAL);
g_value_unset (&val1);
g_value_unset (&tmp);
ret = gst_value_subtract (&tmp, &list2, &list1);
fail_unless (ret == TRUE);
fail_unless (gst_value_compare (&tmp, &val2) == GST_VALUE_EQUAL);
g_value_unset (&val2);
g_value_unset (&tmp);
g_value_unset (&list1);
g_value_unset (&list2);
}
GST_END_TEST;
GST_START_TEST (test_date)
{
GstStructure *s;
GDate *date, *date2;
gchar *str;
date = g_date_new_dmy (22, 9, 2005);
s = gst_structure_new ("media/x-type", "SOME_DATE_TAG", G_TYPE_DATE,
date, NULL);
fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TAG", G_TYPE_DATE));
fail_unless (gst_structure_get_date (s, "SOME_DATE_TAG", &date2));
fail_unless (date2 != NULL);
fail_unless (g_date_valid (date2));
fail_unless (g_date_compare (date, date2) == 0);
g_date_free (date);
g_date_free (date2);
date = NULL;
date2 = NULL;
str = gst_structure_to_string (s);
gst_structure_free (s);
s = NULL;
fail_unless (g_str_equal (str,
"media/x-type, SOME_DATE_TAG=(date)2005-09-22;"));
s = gst_structure_from_string (str, NULL);
g_free (str);
str = NULL;
fail_unless (s != NULL);
fail_unless (gst_structure_has_name (s, "media/x-type"));
fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TAG", G_TYPE_DATE));
fail_unless (gst_structure_get_date (s, "SOME_DATE_TAG", &date));
fail_unless (date != NULL);
fail_unless (g_date_valid (date));
fail_unless (g_date_get_day (date) == 22);
fail_unless (g_date_get_month (date) == 9);
fail_unless (g_date_get_year (date) == 2005);
g_date_free (date);
date = NULL;
str = gst_structure_to_string (s);
gst_structure_free (s);
s = NULL;
fail_unless (g_str_equal (str,
"media/x-type, SOME_DATE_TAG=(date)2005-09-22;"));
g_free (str);
str = NULL;
}
GST_END_TEST;
static gboolean
date_time_equal (GstDateTime * a, GstDateTime * b)
{
if (gst_date_time_get_year (a) != gst_date_time_get_year (b) ||
gst_date_time_get_month (a) != gst_date_time_get_month (b) ||
gst_date_time_get_day (a) != gst_date_time_get_day (b))
return FALSE;
if (gst_date_time_get_hour (a) != gst_date_time_get_hour (b) ||
gst_date_time_get_minute (a) != gst_date_time_get_minute (b) ||
gst_date_time_get_second (a) != gst_date_time_get_second (b) ||
gst_date_time_get_microsecond (a) != gst_date_time_get_microsecond (b))
return FALSE;
if (gst_date_time_get_time_zone_offset (a) !=
gst_date_time_get_time_zone_offset (b))
return FALSE;
return TRUE;
}
GST_START_TEST (test_date_time)
{
GstStructure *s;
GstDateTime *datetime, *datetime2;
GValue val = { 0, };
gchar *str;
/* utc timezone */
datetime = gst_date_time_new (0, 2010, 6, 23, 7, 40, 10);
s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME, datetime, NULL);
fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME));
fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
&datetime2));
fail_unless (datetime2 != NULL);
fail_unless (date_time_equal (datetime, datetime2));
gst_date_time_unref (datetime);
gst_date_time_unref (datetime2);
datetime = NULL;
datetime2 = NULL;
str = gst_structure_to_string (s);
gst_structure_free (s);
s = NULL;
fail_unless_equals_string (str,
"media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10Z;");
s = gst_structure_from_string (str, NULL);
g_free (str);
str = NULL;
fail_unless (s != NULL);
fail_unless (gst_structure_has_name (s, "media/x-type"));
fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME));
fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
&datetime));
fail_unless (datetime != NULL);
fail_unless (gst_date_time_get_year (datetime) == 2010);
fail_unless (gst_date_time_get_month (datetime) == 6);
fail_unless (gst_date_time_get_day (datetime) == 23);
fail_unless (gst_date_time_get_hour (datetime) == 7);
fail_unless (gst_date_time_get_minute (datetime) == 40);
fail_unless (gst_date_time_get_second (datetime) == 10);
fail_unless (gst_date_time_get_microsecond (datetime) == 0);
fail_unless (gst_date_time_get_time_zone_offset (datetime) == 0);
gst_date_time_unref (datetime);
datetime = NULL;
str = gst_structure_to_string (s);
gst_structure_free (s);
s = NULL;
fail_unless_equals_string (str,
"media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10Z;");
g_free (str);
str = NULL;
/* with timezone */
datetime = gst_date_time_new (-3.0, 2010, 6, 23, 7, 40, 10.000001);
s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME, datetime, NULL);
fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME));
fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
&datetime2));
fail_unless (datetime2 != NULL);
fail_unless (date_time_equal (datetime, datetime2));
gst_date_time_unref (datetime);
gst_date_time_unref (datetime2);
datetime = NULL;
datetime2 = NULL;
str = gst_structure_to_string (s);
gst_structure_free (s);
s = NULL;
fail_unless_equals_string (str,
"media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10.000001-0300;");
s = gst_structure_from_string (str, NULL);
g_free (str);
str = NULL;
fail_unless (s != NULL);
fail_unless (gst_structure_has_name (s, "media/x-type"));
fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME));
fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
&datetime));
fail_unless (datetime != NULL);
fail_unless (gst_date_time_get_year (datetime) == 2010);
fail_unless (gst_date_time_get_month (datetime) == 6);
fail_unless (gst_date_time_get_day (datetime) == 23);
fail_unless (gst_date_time_get_hour (datetime) == 7);
fail_unless (gst_date_time_get_minute (datetime) == 40);
fail_unless (gst_date_time_get_second (datetime) == 10);
fail_unless (gst_date_time_get_microsecond (datetime) == 1);
fail_unless (gst_date_time_get_time_zone_offset (datetime) == -3);
gst_date_time_unref (datetime);
datetime = NULL;
str = gst_structure_to_string (s);
gst_structure_free (s);
s = NULL;
fail_unless_equals_string (str,
"media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10.000001-0300;");
g_free (str);
str = NULL;
/* with positive timezone */
datetime = gst_date_time_new (2.0, 2010, 6, 23, 7, 40, 10.000001);
s = gst_structure_new ("media/x-type", "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME, datetime, NULL);
fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME));
fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
&datetime2));
fail_unless (datetime2 != NULL);
fail_unless (date_time_equal (datetime, datetime2));
gst_date_time_unref (datetime);
gst_date_time_unref (datetime2);
datetime = NULL;
datetime2 = NULL;
str = gst_structure_to_string (s);
gst_structure_free (s);
s = NULL;
fail_unless_equals_string (str,
"media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10.000001+0200;");
s = gst_structure_from_string (str, NULL);
g_free (str);
str = NULL;
fail_unless (s != NULL);
fail_unless (gst_structure_has_name (s, "media/x-type"));
fail_unless (gst_structure_has_field_typed (s, "SOME_DATE_TIME_TAG",
GST_TYPE_DATE_TIME));
fail_unless (gst_structure_get_date_time (s, "SOME_DATE_TIME_TAG",
&datetime));
fail_unless (datetime != NULL);
fail_unless (gst_date_time_get_year (datetime) == 2010);
fail_unless (gst_date_time_get_month (datetime) == 6);
fail_unless (gst_date_time_get_day (datetime) == 23);
fail_unless (gst_date_time_get_hour (datetime) == 7);
fail_unless (gst_date_time_get_minute (datetime) == 40);
fail_unless (gst_date_time_get_second (datetime) == 10);
fail_unless (gst_date_time_get_microsecond (datetime) == 1);
fail_unless (gst_date_time_get_time_zone_offset (datetime) == 2);
gst_date_time_unref (datetime);
datetime = NULL;
str = gst_structure_to_string (s);
gst_structure_free (s);
s = NULL;
fail_unless_equals_string (str,
"media/x-type, SOME_DATE_TIME_TAG=(datetime)2010-06-23T07:40:10.000001+0200;");
g_free (str);
str = NULL;
/* test partial dates */
datetime = gst_date_time_new (0.0, 2010, -1, -1, -1, -1, -1.0);
g_value_init (&val, GST_TYPE_DATE_TIME);
g_value_take_boxed (&val, datetime);
str = gst_value_serialize (&val);
g_value_reset (&val);
fail_unless_equals_string (str, "2010");
fail_unless (gst_value_deserialize (&val, str));
datetime = g_value_get_boxed (&val);
fail_if (!gst_date_time_has_year (datetime));
fail_if (gst_date_time_has_month (datetime));
fail_if (gst_date_time_has_day (datetime));
fail_if (gst_date_time_has_time (datetime));
g_value_unset (&val);
g_free (str);
datetime = gst_date_time_new (0.0, 2010, 9, -1, -1, -1, -1.0);
g_value_init (&val, GST_TYPE_DATE_TIME);
g_value_take_boxed (&val, datetime);
str = gst_value_serialize (&val);
g_value_reset (&val);
fail_unless_equals_string (str, "2010-09");
fail_unless (gst_value_deserialize (&val, str));
datetime = g_value_get_boxed (&val);
fail_if (!gst_date_time_has_year (datetime));
fail_if (!gst_date_time_has_month (datetime));
fail_if (gst_date_time_has_day (datetime));
fail_if (gst_date_time_has_time (datetime));
g_value_unset (&val);
g_free (str);
datetime = gst_date_time_new (0.0, 1983, 11, 30, -1, -1, -1.0);
g_value_init (&val, GST_TYPE_DATE_TIME);
g_value_take_boxed (&val, datetime);
str = gst_value_serialize (&val);
g_value_reset (&val);
fail_unless_equals_string (str, "1983-11-30");
fail_unless (gst_value_deserialize (&val, str));
datetime = g_value_get_boxed (&val);
fail_if (!gst_date_time_has_year (datetime));
fail_if (!gst_date_time_has_month (datetime));
fail_if (!gst_date_time_has_day (datetime));
fail_if (gst_date_time_has_time (datetime));
g_value_unset (&val);
g_free (str);
datetime = gst_date_time_new (0.0, 1983, 11, 30, 3, 52, -1.0);
g_value_init (&val, GST_TYPE_DATE_TIME);
g_value_take_boxed (&val, datetime);
str = gst_value_serialize (&val);
g_value_reset (&val);
fail_unless_equals_string (str, "1983-11-30T03:52Z");
fail_unless (gst_value_deserialize (&val, str));
datetime = g_value_get_boxed (&val);
fail_if (!gst_date_time_has_year (datetime));
fail_if (!gst_date_time_has_month (datetime));
fail_if (!gst_date_time_has_day (datetime));
fail_if (!gst_date_time_has_time (datetime));
fail_if (gst_date_time_has_second (datetime));
fail_unless_equals_float (gst_date_time_get_time_zone_offset (datetime), 0.0);
g_value_unset (&val);
g_free (str);
datetime = gst_date_time_new (-4.5, 1983, 11, 30, 3, 52, -1.0);
g_value_init (&val, GST_TYPE_DATE_TIME);
g_value_take_boxed (&val, datetime);
str = gst_value_serialize (&val);
g_value_reset (&val);
fail_unless_equals_string (str, "1983-11-30T03:52-0430");
fail_unless (gst_value_deserialize (&val, str));
datetime = g_value_get_boxed (&val);
fail_if (!gst_date_time_has_year (datetime));
fail_if (!gst_date_time_has_month (datetime));
fail_if (!gst_date_time_has_day (datetime));
fail_if (!gst_date_time_has_time (datetime));
fail_if (gst_date_time_has_second (datetime));
fail_unless_equals_float (gst_date_time_get_time_zone_offset (datetime),
-4.5);
g_value_unset (&val);
g_free (str);
datetime = gst_date_time_new (4.5, 1983, 11, 30, 14, 52, 9);
g_value_init (&val, GST_TYPE_DATE_TIME);
g_value_take_boxed (&val, datetime);
str = gst_value_serialize (&val);
g_value_reset (&val);
fail_unless_equals_string (str, "1983-11-30T14:52:09+0430");
fail_unless (gst_value_deserialize (&val, str));
datetime = g_value_get_boxed (&val);
fail_if (!gst_date_time_has_year (datetime));
fail_if (!gst_date_time_has_month (datetime));
fail_if (!gst_date_time_has_day (datetime));
fail_if (!gst_date_time_has_time (datetime));
fail_if (!gst_date_time_has_second (datetime));
fail_unless_equals_float (gst_date_time_get_time_zone_offset (datetime), 4.5);
g_value_unset (&val);
g_free (str);
datetime = gst_date_time_new (-4.5, 1983, 11, 30, 14, 52, 9.702);
g_value_init (&val, GST_TYPE_DATE_TIME);
g_value_take_boxed (&val, datetime);
str = gst_value_serialize (&val);
g_value_reset (&val);
fail_unless_equals_string (str, "1983-11-30T14:52:09.702-0430");
fail_unless (gst_value_deserialize (&val, str));
datetime = g_value_get_boxed (&val);
fail_if (!gst_date_time_has_year (datetime));
fail_if (!gst_date_time_has_month (datetime));
fail_if (!gst_date_time_has_day (datetime));
fail_if (!gst_date_time_has_time (datetime));
fail_if (!gst_date_time_has_second (datetime));
fail_unless_equals_float (gst_date_time_get_time_zone_offset (datetime),
-4.5);
g_value_unset (&val);
g_free (str);
}
GST_END_TEST;
GST_START_TEST (test_fraction_range)
{
GValue range = { 0, };
GValue start = { 0, };
GValue end = { 0, };
GValue src = { 0, };
GValue dest = { 0, };
GValue range2 = { 0, };
g_value_init (&range, GST_TYPE_FRACTION_RANGE);
g_value_init (&range2, GST_TYPE_FRACTION_RANGE);
g_value_init (&start, GST_TYPE_FRACTION);
g_value_init (&end, GST_TYPE_FRACTION);
g_value_init (&src, GST_TYPE_FRACTION);
gst_value_set_fraction (&src, 1, 2);
/* Check that a intersection of fraction & range = fraction */
gst_value_set_fraction (&start, 1, 4);
gst_value_set_fraction (&end, 2, 3);
gst_value_set_fraction_range (&range, &start, &end);
fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION);
fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL);
/* Check that a intersection selects the overlapping range */
gst_value_set_fraction (&start, 1, 3);
gst_value_set_fraction (&end, 2, 3);
gst_value_set_fraction_range (&range2, &start, &end);
g_value_unset (&dest);
fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_FRACTION_RANGE);
gst_value_set_fraction_range (&range2, &start, &end);
fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL);
/* Check that non intersection ranges don't intersect */
gst_value_set_fraction (&start, 4, 2);
gst_value_set_fraction (&end, 5, 2);
gst_value_set_fraction_range (&range2, &start, &end);
g_value_unset (&dest);
fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE);
g_value_unset (&start);
g_value_unset (&end);
g_value_unset (&range);
g_value_unset (&range2);
g_value_unset (&src);
}
GST_END_TEST;
GST_START_TEST (test_serialize_deserialize_format_enum)
{
GstStructure *s, *s2;
GstFormat foobar_fmt;
gchar *str, *str2, *end = NULL;
/* make sure custom formats are serialised properly as well */
foobar_fmt = gst_format_register ("foobar", "GST_FORMAT_FOOBAR");
fail_unless (foobar_fmt != GST_FORMAT_UNDEFINED);
s = gst_structure_new ("foo/bar", "format1", GST_TYPE_FORMAT,
GST_FORMAT_BYTES, "format2", GST_TYPE_FORMAT, GST_FORMAT_TIME,
"format3", GST_TYPE_FORMAT, GST_FORMAT_DEFAULT, "format4",
GST_TYPE_FORMAT, foobar_fmt, NULL);
str = gst_structure_to_string (s);
GST_LOG ("Got structure string '%s'", GST_STR_NULL (str));
fail_unless (str != NULL);
fail_unless (strstr (str, "time") != NULL);
fail_unless (strstr (str, "byte") != NULL);
fail_unless (strstr (str, "default") != NULL);
fail_unless (strstr (str, "FOOBAR") != NULL);
s2 = gst_structure_from_string (str, &end);
fail_unless (s2 != NULL);
str2 = gst_structure_to_string (s2);
fail_unless (str2 != NULL);
fail_unless (g_str_equal (str, str2));
g_free (str);
g_free (str2);
gst_structure_free (s);
gst_structure_free (s2);
}
GST_END_TEST;
GST_START_TEST (test_serialize_deserialize_value_array)
{
GValue v = G_VALUE_INIT, v2 = G_VALUE_INIT, v3 = G_VALUE_INIT;
gchar *str = NULL;
g_value_init (&v, GST_TYPE_ARRAY);
g_value_init (&v2, GST_TYPE_ARRAY);
g_value_init (&v3, G_TYPE_DOUBLE);
g_value_set_double (&v3, 1);
gst_value_array_append_value (&v2, &v3);
g_value_unset (&v3);
g_value_init (&v3, G_TYPE_DOUBLE);
g_value_set_double (&v3, 0);
gst_value_array_append_value (&v2, &v3);
g_value_unset (&v3);
gst_value_array_append_value (&v, &v2);
g_value_unset (&v2);
str = gst_value_serialize (&v);
g_value_init (&v2, GST_TYPE_ARRAY);
fail_unless (gst_value_deserialize (&v2, str));
fail_unless (gst_value_compare (&v, &v2) == 0);
g_value_unset (&v2);
g_value_unset (&v);
g_free (str);
}
GST_END_TEST;
GST_START_TEST (test_serialize_deserialize_caps)
{
GValue value = { 0 }
, value2 = {
0};
GstCaps *caps, *caps2;
GstCaps *incaps;
gchar *serialized;
incaps = gst_caps_new_simple ("caps/internal",
"in-field", G_TYPE_INT, 20, "in-field2",
G_TYPE_STRING, "some in ternal field", NULL);
caps = gst_caps_new_simple ("test/caps",
"foo", G_TYPE_INT, 10, "bar", G_TYPE_STRING, "test",
"int-caps", GST_TYPE_CAPS, incaps, NULL);
fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
gst_caps_unref (incaps);
/* and assign caps to gvalue */
g_value_init (&value, GST_TYPE_CAPS);
g_value_take_boxed (&value, caps);
fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
/* now serialize it */
serialized = gst_value_serialize (&value);
GST_DEBUG ("serialized caps to %s", serialized);
fail_unless (serialized != NULL);
/* refcount should not change */
fail_if (GST_CAPS_REFCOUNT_VALUE (caps) != 1);
/* now deserialize again */
g_value_init (&value2, GST_TYPE_CAPS);
gst_value_deserialize (&value2, serialized);
caps2 = g_value_get_boxed (&value2);
fail_if (GST_CAPS_REFCOUNT_VALUE (caps2) != 1);
/* they should be equal */
fail_unless (gst_caps_is_equal (caps, caps2));
/* cleanup */
g_value_unset (&value);
g_value_unset (&value2);
g_free (serialized);
}
GST_END_TEST;
GST_START_TEST (test_int_range)
{
GValue range = { 0, };
GValue start = { 0, };
GValue end = { 0, };
GValue src = { 0, };
GValue dest = { 0, };
GValue range2 = { 0, };
g_value_init (&range, GST_TYPE_INT_RANGE);
g_value_init (&range2, GST_TYPE_INT_RANGE);
g_value_init (&start, G_TYPE_INT);
g_value_init (&end, G_TYPE_INT);
g_value_init (&src, G_TYPE_INT);
g_value_set_int (&src, 2);
/* Check that a intersection of int & range = int */
gst_value_set_int_range (&range, 1, 5);
fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == G_TYPE_INT);
fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL);
/* Check that a intersection selects the overlapping range */
gst_value_set_int_range (&range2, 2, 3);
g_value_unset (&dest);
fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE);
fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL);
/* Check that non intersection ranges don't intersect */
gst_value_set_int_range (&range2, 6, 7);
g_value_unset (&dest);
fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE);
gst_value_set_int_range (&range, -7, -6);
fail_unless_equals_int (gst_value_get_int_range_min (&range), -7);
fail_unless_equals_int (gst_value_get_int_range_max (&range), -6);
gst_value_set_int_range (&range, -7, 7);
fail_unless_equals_int (gst_value_get_int_range_min (&range), -7);
fail_unless_equals_int (gst_value_get_int_range_max (&range), 7);
g_value_unset (&start);
g_value_unset (&end);
g_value_unset (&range);
g_value_unset (&range2);
g_value_unset (&src);
}
GST_END_TEST;
GST_START_TEST (test_int64_range)
{
GValue range = { 0, };
GValue start = { 0, };
GValue end = { 0, };
GValue src = { 0, };
GValue dest = { 0, };
GValue range2 = { 0, };
g_value_init (&range, GST_TYPE_INT64_RANGE);
g_value_init (&range2, GST_TYPE_INT64_RANGE);
g_value_init (&start, G_TYPE_INT64);
g_value_init (&end, G_TYPE_INT64);
g_value_init (&src, G_TYPE_INT64);
g_value_set_int64 (&src, 2);
/* Check that a intersection of int64 & range = int64 */
gst_value_set_int64_range (&range, 1, 5);
fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == G_TYPE_INT64);
fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL);
/* Check that a intersection selects the overlapping range */
gst_value_set_int64_range (&range2, 2, 3);
g_value_unset (&dest);
fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE);
fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE);
fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL);
/* Check that non intersection ranges don't intersect */
gst_value_set_int64_range (&range2, 6, 7);
g_value_unset (&dest);
fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE);
g_value_unset (&start);
g_value_unset (&end);
g_value_unset (&range);
g_value_unset (&range2);
g_value_unset (&src);
}
GST_END_TEST;
GST_START_TEST (test_serialize_int64_range)
{
int i = 0;
gint64 int64_ranges[] = {
0, 5,
0, G_MAXINT,
5, G_MAXINT32,
5, G_MAXINT64,
};
gint int64_ranges_size = sizeof (int64_ranges) / sizeof (int64_ranges[0]) / 2;
gchar *int64_range_strings[] = {
g_strdup ("[ 0, 5 ]"),
g_strdup_printf ("[ 0, %" G_GINT64_FORMAT " ]", (gint64) G_MAXINT),
g_strdup_printf ("[ 5, %" G_GINT64_FORMAT " ]", (gint64) G_MAXINT32),
g_strdup_printf ("[ 5, %" G_GINT64_FORMAT " ]", G_MAXINT64),
};
gint int64_range_strings_size =
sizeof (int64_range_strings) / sizeof (int64_range_strings[0]);
fail_unless (int64_ranges_size == int64_range_strings_size);
while (i + 1 < (int64_ranges_size * 2)) {
if ((i + 1) % 2) {
gchar *str;
gchar *str2;
GValue value = { 0 };
const GValue *deserialized_value;
int idx = i / 2;
GstStructure *s;
g_value_init (&value, GST_TYPE_INT64_RANGE);
/* check serialization */
gst_value_set_int64_range (&value, int64_ranges[i], int64_ranges[i + 1]);
str = gst_value_serialize (&value);
fail_unless (strcmp (str, int64_range_strings[idx]) == 0);
g_free (int64_range_strings[idx]);
g_value_unset (&value);
/* now deserialize again to an int64 range */
s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT64_RANGE,
int64_ranges[i], int64_ranges[i + 1], NULL);
deserialized_value = gst_structure_get_value (s, "range");
fail_unless (GST_VALUE_HOLDS_INT64_RANGE (deserialized_value) == TRUE);
str2 = gst_value_serialize (deserialized_value);
fail_unless (gst_value_get_int64_range_min (deserialized_value) ==
int64_ranges[i]);
fail_unless (gst_value_get_int64_range_max (deserialized_value) ==
int64_ranges[i + 1]);
gst_structure_free (s);
g_free (str);
g_free (str2);
}
i++;
}
}
GST_END_TEST;
GST_START_TEST (test_deserialize_int_range)
{
GstStructure *s;
gchar *str, *str2;
gchar *end = NULL;
const GValue *deserialized_value;
/* check a valid int_range deserialization */
str = g_strdup_printf ("foo/bar, range=[ 1, %d ];", G_MAXINT);
s = gst_structure_from_string (str, &end);
fail_unless (*end == '\0');
deserialized_value = gst_structure_get_value (s, "range");
fail_unless (GST_VALUE_HOLDS_INT_RANGE (deserialized_value) == TRUE);
fail_unless (gst_value_get_int_range_min (deserialized_value) == 1);
fail_unless (gst_value_get_int_range_max (deserialized_value) == G_MAXINT);
gst_structure_free (s);
end = NULL;
g_free (str);
/* check invalid int_range deserialization */
str =
g_strdup_printf ("foo/bar, range=[ 1, %" G_GINT64_FORMAT " ];",
(gint64) G_MAXINT + 1);
s = NULL;
ASSERT_CRITICAL (s = gst_structure_from_string (str, &end));
g_free (str);
if (s)
gst_structure_free (s);
str =
g_strdup_printf ("foo/bar, range=[ %" G_GINT64_FORMAT ", %"
G_GINT64_FORMAT " ];", (gint64) G_MAXINT, (gint64) G_MAXINT + 1);
ASSERT_CRITICAL (s = gst_structure_from_string (str, NULL));
end = NULL;
g_free (str);
if (s)
gst_structure_free (s);
/* check a valid int64_range deserialization. Those ranges need to
* be explicit about their storage type. */
str = g_strdup_printf ("foo/bar, range=(gint64)[ 1, %d ];", G_MAXINT);
s = gst_structure_from_string (str, &end);
fail_unless (*end == '\0');
deserialized_value = gst_structure_get_value (s, "range");
fail_unless (GST_VALUE_HOLDS_INT64_RANGE (deserialized_value) == TRUE);
fail_unless (gst_value_get_int64_range_min (deserialized_value) == 1);
fail_unless (gst_value_get_int64_range_max (deserialized_value) == G_MAXINT);
str2 = gst_structure_to_string (s);
fail_unless (strcmp (str, str2) == 0);
gst_structure_free (s);
end = NULL;
g_free (str);
g_free (str2);
/* check invalid int64_range (starting with a gint) deserialization */
str =
g_strdup_printf ("foo/bar, range=(gint64)[ 1, %" G_GUINT64_FORMAT " ];",
(guint64) G_MAXINT64 + 1);
s = NULL;
ASSERT_CRITICAL (s = gst_structure_from_string (str, &end));
if (s) {
fail_unless (*end == '\0');
gst_structure_free (s);
end = NULL;
}
g_free (str);
/* check invalid int64_range deserialization into a int64_range */
str =
g_strdup_printf ("foo/bar, range=(gint64)[ %" G_GINT64_FORMAT ", %"
G_GUINT64_FORMAT " ];", (gint64) G_MAXINT, (guint64) G_MAXINT64 + 1);
ASSERT_CRITICAL (s = gst_structure_from_string (str, NULL));
g_free (str);
if (s)
gst_structure_free (s);
/* check invalid int64_range deserialization into a int_range */
str =
g_strdup_printf ("foo/bar, range=[ %" G_GINT64_FORMAT ", %"
G_GUINT64_FORMAT " ];", (gint64) G_MAXINT, (guint64) G_MAXINT64 + 1);
s = gst_structure_from_string (str, &end);
fail_unless (s == NULL);
fail_unless (end == NULL);
g_free (str);
}
GST_END_TEST;
GST_START_TEST (test_stepped_range_collection)
{
GstStructure *s;
const GValue *v;
s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT_RANGE, 8, 12, NULL);
fail_unless (s != NULL);
v = gst_structure_get_value (s, "range");
fail_unless (v != NULL);
fail_unless (gst_value_get_int_range_min (v) == 8);
fail_unless (gst_value_get_int_range_max (v) == 12);
fail_unless (gst_value_get_int_range_step (v) == 1);
gst_structure_free (s);
s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT64_RANGE, (gint64) 8,
(gint64) 12, NULL);
fail_unless (s != NULL);
v = gst_structure_get_value (s, "range");
fail_unless (v != NULL);
fail_unless (gst_value_get_int64_range_min (v) == 8);
fail_unless (gst_value_get_int64_range_max (v) == 12);
fail_unless (gst_value_get_int64_range_step (v) == 1);
gst_structure_free (s);
}
GST_END_TEST;
GST_START_TEST (test_stepped_int_range_parsing)
{
gchar *str;
guint n;
gchar *end = NULL;
GstStructure *s;
static const gchar *good_ranges[] = {
"[0, 1, 1]",
"[-2, 2, 2]",
"[16, 4096, 16]",
};
static const gchar *bad_ranges[] = {
"[0, 1, -1]",
"[1, 2, 2]",
"[2, 3, 2]",
"[0, 0, 0]",
};
/* check we can parse good ranges */
for (n = 0; n < G_N_ELEMENTS (good_ranges); ++n) {
str = g_strdup_printf ("foo/bar, range=%s", good_ranges[n]);
s = gst_structure_from_string (str, &end);
fail_unless (s != NULL);
fail_unless (*end == '\0');
gst_structure_free (s);
s = NULL;
g_free (str);
}
/* check we cannot parse bad ranges */
for (n = 0; n < G_N_ELEMENTS (bad_ranges); ++n) {
str = g_strdup_printf ("foo/bar, range=%s", bad_ranges[n]);
ASSERT_CRITICAL (s = gst_structure_from_string (str, &end));
if (s)
gst_structure_free (s);
g_free (str);
}
}
GST_END_TEST;
GST_START_TEST (test_stepped_int_range_ops)
{
gchar *str1, *str2, *str3;
guint n;
GstStructure *s1, *s2, *s3;
const GValue *v1, *v2, *v3;
static const struct
{
const gchar *set1;
const gchar *op;
const gchar *set2;
const gchar *result;
} ranges[] = {
{
"[16, 4096, 16]", "inter", "[100, 200, 10]", "160"}, {
"[16, 4096, 16]", "inter", "[100, 200, 100]", NULL}, {
"[16, 4096, 16]", "inter", "[0, 512, 256]", "[256, 512, 256]"}, {
"[16, 32, 16]", "union", "[32, 96, 16]", "[16, 96, 16]"}, {
"[16, 32, 16]", "union", "[48, 96, 16]", "[16, 96, 16]"}, {
"[112, 192, 16]", "union", "[48, 96, 16]", "[48, 192, 16]"}, {
"[16, 32, 16]", "union", "[64, 96, 16]", NULL}, {
"[112, 192, 16]", "union", "[48, 96, 8]", NULL}, {
"[10, 20, 5]", "union", "10", "[10, 20, 5]"}, {
"[10, 20, 5]", "union", "20", "[10, 20, 5]"}, {
"[10, 20, 5]", "union", "15", "[10, 20, 5]"}, {
"[10, 20, 5]", "union", "5", "[5, 20, 5]"}, {
"[10, 20, 5]", "union", "12", NULL}, {
"[10, 20, 5]", "union", "30", NULL}, {
"[10, 20, 5]", "union", "25", "[10, 25, 5]"},};
for (n = 0; n < G_N_ELEMENTS (ranges); ++n) {
gchar *end = NULL;
GValue dest = { 0 };
gboolean ret;
str1 = g_strdup_printf ("foo/bar, range=%s", ranges[n].set1);
s1 = gst_structure_from_string (str1, &end);
fail_unless (s1 != NULL);
fail_unless (*end == '\0');
v1 = gst_structure_get_value (s1, "range");
fail_unless (v1 != NULL);
str2 = g_strdup_printf ("foo/bar, range=%s", ranges[n].set2);
s2 = gst_structure_from_string (str2, &end);
fail_unless (s2 != NULL);
fail_unless (*end == '\0');
v2 = gst_structure_get_value (s2, "range");
fail_unless (v2 != NULL);
if (!strcmp (ranges[n].op, "inter")) {
ret = gst_value_intersect (&dest, v1, v2);
} else if (!strcmp (ranges[n].op, "union")) {
ret = gst_value_union (&dest, v1, v2);
} else {
fail_unless (FALSE);
ret = FALSE;
}
if (ranges[n].result) {
fail_unless (ret);
} else {
fail_unless (!ret);
}
if (ret) {
str3 = g_strdup_printf ("foo/bar, range=%s", ranges[n].result);
s3 = gst_structure_from_string (str3, &end);
fail_unless (s3 != NULL);
fail_unless (*end == '\0');
v3 = gst_structure_get_value (s3, "range");
fail_unless (v3 != NULL);
if (gst_value_compare (&dest, v3) != GST_VALUE_EQUAL) {
GST_ERROR ("%s %s %s yielded %s, expected %s", str1, ranges[n].op, str2,
gst_value_serialize (&dest), gst_value_serialize (v3));
fail_unless (FALSE);
}
gst_structure_free (s3);
g_free (str3);
g_value_unset (&dest);
}
gst_structure_free (s2);
g_free (str2);
gst_structure_free (s1);
g_free (str1);
}
}
GST_END_TEST;
GST_START_TEST (test_structure_basic)
{
GstStructure *s1, *s2;
GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
/* sanity test */
s1 = gst_structure_from_string ("foo,bar=1", NULL);
g_value_init (&v1, GST_TYPE_STRUCTURE);
gst_value_set_structure (&v1, s1);
fail_unless (gst_structure_is_equal (s1, gst_value_get_structure (&v1)));
s2 = gst_structure_copy (s1);
g_value_init (&v2, GST_TYPE_STRUCTURE);
gst_value_set_structure (&v2, s2);
/* can do everything but subtract */
fail_unless (gst_value_can_compare (&v1, &v2));
fail_unless (gst_value_can_intersect (&v1, &v2));
fail_unless (!gst_value_can_subtract (&v1, &v2));
fail_unless (gst_value_can_union (&v1, &v2));
gst_structure_free (s1);
gst_structure_free (s2);
g_value_unset (&v1);
g_value_unset (&v2);
}
GST_END_TEST;
GST_START_TEST (test_structure_single_ops)
{
static const struct
{
const gchar *str1;
gboolean is_fixed;
gboolean can_fixate;
} single_struct[] = {
{
"foo,bar=(int)1", TRUE, TRUE}, {
"foo,bar=(int)[1,2]", FALSE, TRUE},};
gint i;
for (i = 0; i < G_N_ELEMENTS (single_struct); i++) {
GstStructure *s1 = gst_structure_from_string (single_struct[i].str1, NULL);
GValue v1 = G_VALUE_INIT;
GValue v2 = G_VALUE_INIT;
fail_unless (s1 != NULL);
GST_DEBUG ("checking structure %" GST_PTR_FORMAT, s1);
g_value_init (&v1, GST_TYPE_STRUCTURE);
gst_value_set_structure (&v1, s1);
fail_unless (gst_value_is_fixed (&v1) == single_struct[i].is_fixed);
fail_unless (gst_value_fixate (&v2, &v1) == single_struct[i].can_fixate);
if (single_struct[i].can_fixate)
g_value_unset (&v2);
g_value_unset (&v1);
gst_structure_free (s1);
}
}
GST_END_TEST;
GST_START_TEST (test_structure_ops)
{
struct
{
const gchar *str1;
const gchar *str2;
const gchar *op;
gint ret;
GType str_type;
const gchar *str_result;
} comparisons[] = {
/* *INDENT-OFF* */
{"foo,bar=(int)1", "foo,bar=(int)1", "compare", GST_VALUE_EQUAL, 0, NULL},
{"foo,bar=(int)1", "foo,bar=(int)1", "is_subset", TRUE, 0, NULL},
{"foo,bar=(int)1", "foo,bar=(int)1", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"},
{"foo,bar=(int)1", "foo,bar=(int)1", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"},
{"foo,bar=(int)[1,2]", "foo,bar=(int)1", "compare", GST_VALUE_UNORDERED, 0, NULL},
{"foo,bar=(int)[1,2]", "foo,bar=(int)1", "is_subset", FALSE, 0, NULL},
{"foo,bar=(int)[1,2]", "foo,bar=(int)1", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"},
{"foo,bar=(int)[1,2]", "foo,bar=(int)1", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"},
{"foo,bar=(int)1", "foo,bar=(int)[1,2]", "compare", GST_VALUE_UNORDERED, 0, NULL},
{"foo,bar=(int)1", "foo,bar=(int)[1,2]", "is_subset", TRUE, 0, NULL},
{"foo,bar=(int)1", "foo,bar=(int)[1,2]", "intersect", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)1"},
{"foo,bar=(int)1", "foo,bar=(int)[1,2]", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"},
{"foo,bar=(int)1", "foo,bar=(int)2", "compare", GST_VALUE_UNORDERED, 0, NULL},
{"foo,bar=(int)1", "foo,bar=(int)2", "is_subset", FALSE, 0, NULL},
{"foo,bar=(int)1", "foo,bar=(int)2", "intersect", FALSE, 0, NULL},
{"foo,bar=(int)1", "foo,bar=(int)2", "union", TRUE, GST_TYPE_STRUCTURE, "foo,bar=(int)[1,2]"},
{"foo,bar=(int)1", "baz,bar=(int)1", "compare", GST_VALUE_UNORDERED, 0, NULL},
{"foo,bar=(int)1", "baz,bar=(int)1", "is_subset", FALSE, 0, NULL},
{"foo,bar=(int)1", "baz,bar=(int)1", "intersect", FALSE, 0, NULL},
#if 0
/* deserializing lists is not implemented (but this should still work!) */
{"foo,bar=(int)1", "baz,bar=(int)1", "union", TRUE, G_TYPE_LIST, "{foo,bar=(int)1;, baz,bar=(int)1;}"},
#endif
/* *INDENT-ON* */
};
gint i;
for (i = 0; i < G_N_ELEMENTS (comparisons); i++) {
GstStructure *s1 = gst_structure_from_string (comparisons[i].str1, NULL);
GstStructure *s2 = gst_structure_from_string (comparisons[i].str2, NULL);
GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT, v3 = G_VALUE_INIT;
fail_unless (s1 != NULL);
fail_unless (s2 != NULL);
GST_DEBUG ("checking %s with structure1 %" GST_PTR_FORMAT " structure2 %"
GST_PTR_FORMAT " is %d, %s", comparisons[i].op, s1, s2,
comparisons[i].ret, comparisons[i].str_result);
g_value_init (&v1, GST_TYPE_STRUCTURE);
gst_value_set_structure (&v1, s1);
g_value_init (&v2, GST_TYPE_STRUCTURE);
gst_value_set_structure (&v2, s2);
if (g_strcmp0 (comparisons[i].op, "compare") == 0) {
fail_unless (gst_value_compare (&v1, &v2) == comparisons[i].ret);
} else if (g_strcmp0 (comparisons[i].op, "is_subset") == 0) {
fail_unless (gst_value_is_subset (&v1, &v2) == comparisons[i].ret);
} else {
if (g_strcmp0 (comparisons[i].op, "intersect") == 0) {
fail_unless (gst_value_intersect (&v3, &v1, &v2) == comparisons[i].ret);
} else if (g_strcmp0 (comparisons[i].op, "union") == 0) {
fail_unless (gst_value_union (&v3, &v1, &v2) == comparisons[i].ret);
}
if (comparisons[i].ret) {
GValue result = G_VALUE_INIT;
gchar *str;
str = gst_value_serialize (&v3);
GST_LOG ("result %s", str);
g_free (str);
g_value_init (&result, comparisons[i].str_type);
fail_unless (gst_value_deserialize (&result,
comparisons[i].str_result));
fail_unless (gst_value_compare (&result, &v3) == GST_VALUE_EQUAL);
g_value_unset (&v3);
g_value_unset (&result);
}
}
gst_structure_free (s1);
gst_structure_free (s2);
g_value_unset (&v1);
g_value_unset (&v2);
}
}
GST_END_TEST;
static void
setup_test_value_array (GValue * value)
{
GValueArray *array;
GValue v = G_VALUE_INIT;
g_value_init (&v, G_TYPE_INT);
g_value_init (value, G_TYPE_VALUE_ARRAY);
array = g_value_array_new (3);
g_value_set_int (&v, 1);
g_value_array_append (array, &v);
g_value_set_int (&v, 2);
g_value_array_append (array, &v);
g_value_set_int (&v, 3);
g_value_array_append (array, &v);
g_value_take_boxed (value, array);
}
static void
test_revert_array_transform (GValue * v1, GValue * v2)
{
GValueArray *array;
g_value_reset (v1);
fail_unless (g_value_transform (v2, v1));
array = g_value_get_boxed (v1);
fail_unless (array->n_values == 3);
fail_unless (g_value_get_int (g_value_array_get_nth (array, 0)) == 1);
fail_unless (g_value_get_int (g_value_array_get_nth (array, 1)) == 2);
fail_unless (g_value_get_int (g_value_array_get_nth (array, 2)) == 3);
}
GST_START_TEST (test_transform_array)
{
GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
setup_test_value_array (&v1);
g_value_init (&v2, GST_TYPE_ARRAY);
fail_unless (g_value_transform (&v1, &v2));
fail_unless (gst_value_array_get_size (&v2) == 3);
fail_unless (g_value_get_int (gst_value_array_get_value (&v2, 0)) == 1);
fail_unless (g_value_get_int (gst_value_array_get_value (&v2, 1)) == 2);
fail_unless (g_value_get_int (gst_value_array_get_value (&v2, 2)) == 3);
test_revert_array_transform (&v1, &v2);
g_value_unset (&v1);
g_value_unset (&v2);
}
GST_END_TEST;
GST_START_TEST (test_transform_list)
{
GValue v1 = G_VALUE_INIT, v2 = G_VALUE_INIT;
setup_test_value_array (&v1);
g_value_init (&v2, GST_TYPE_LIST);
fail_unless (g_value_transform (&v1, &v2));
fail_unless (gst_value_list_get_size (&v2) == 3);
fail_unless (g_value_get_int (gst_value_list_get_value (&v2, 0)) == 1);
fail_unless (g_value_get_int (gst_value_list_get_value (&v2, 1)) == 2);
fail_unless (g_value_get_int (gst_value_list_get_value (&v2, 2)) == 3);
test_revert_array_transform (&v1, &v2);
g_value_unset (&v1);
g_value_unset (&v2);
}
GST_END_TEST;
GST_START_TEST (test_serialize_null_aray)
{
gchar *serialized;
GValue v = G_VALUE_INIT;
g_value_init (&v, G_TYPE_VALUE_ARRAY);
g_value_set_boxed (&v, NULL);
serialized = gst_value_serialize (&v);
fail_unless_equals_string (serialized, "< >");
g_value_unset (&v);
g_free (serialized);
}
GST_END_TEST;
GST_START_TEST (test_deserialize_array)
{
GValue value = { 0 };
const gchar *strings[] = {
"{ test, }",
"{ , }",
"{ test,, }",
"{ , , }",
};
gint results_size[] = { 1, 0, -1, -1 }; /* -1 means deserialization should fail */
int i;
for (i = 0; i < G_N_ELEMENTS (strings); ++i) {
/* Workaround a bug in our parser that would lead to segfaults
* when deserializing container types using static strings */
gchar *str = g_strdup (strings[i]);
g_value_init (&value, GST_TYPE_LIST);
if (results_size[i] == -1) {
fail_if (gst_value_deserialize (&value, str),
"Should not be able to deserialize %s (%d) as list", str, i);
} else {
fail_unless (gst_value_deserialize (&value, str),
"could not deserialize %s (%d)", str, i);
fail_unless (gst_value_list_get_size (&value) == results_size[i],
"Wrong array size: %d. expected %d",
gst_value_array_get_size (&value), results_size[i]);
}
g_value_unset (&value);
g_free (str);
}
}
GST_END_TEST;
static Suite *
gst_value_suite (void)
{
Suite *s = suite_create ("GstValue");
TCase *tc_chain = tcase_create ("general");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_deserialize_buffer);
tcase_add_test (tc_chain, test_serialize_buffer);
tcase_add_test (tc_chain, test_deserialize_gint);
tcase_add_test (tc_chain, test_deserialize_gint_failures);
tcase_add_test (tc_chain, test_deserialize_guint);
tcase_add_test (tc_chain, test_deserialize_guint_failures);
tcase_add_test (tc_chain, test_deserialize_gint64);
tcase_add_test (tc_chain, test_deserialize_guint64);
tcase_add_test (tc_chain, test_deserialize_guchar);
tcase_add_test (tc_chain, test_deserialize_gstfraction);
tcase_add_test (tc_chain, test_deserialize_gtype);
tcase_add_test (tc_chain, test_deserialize_gtype_failures);
tcase_add_test (tc_chain, test_deserialize_bitmask);
tcase_add_test (tc_chain, test_deserialize_array);
tcase_add_test (tc_chain, test_serialize_flags);
tcase_add_test (tc_chain, test_deserialize_flags);
tcase_add_test (tc_chain, test_serialize_deserialize_format_enum);
tcase_add_test (tc_chain, test_serialize_deserialize_value_array);
tcase_add_test (tc_chain, test_string);
tcase_add_test (tc_chain, test_deserialize_string);
tcase_add_test (tc_chain, test_value_compare);
tcase_add_test (tc_chain, test_value_intersect);
tcase_add_test (tc_chain, test_value_subtract_int);
tcase_add_test (tc_chain, test_value_subtract_int64);
tcase_add_test (tc_chain, test_value_subtract_double);
tcase_add_test (tc_chain, test_value_subtract_fraction);
tcase_add_test (tc_chain, test_value_subtract_fraction_range);
tcase_add_test (tc_chain, test_value_subtract_fraction_list);
tcase_add_test (tc_chain, test_date);
tcase_add_test (tc_chain, test_date_time);
tcase_add_test (tc_chain, test_fraction_range);
tcase_add_test (tc_chain, test_serialize_deserialize_caps);
tcase_add_test (tc_chain, test_int_range);
tcase_add_test (tc_chain, test_int64_range);
tcase_add_test (tc_chain, test_serialize_int64_range);
tcase_add_test (tc_chain, test_deserialize_int_range);
tcase_add_test (tc_chain, test_stepped_range_collection);
tcase_add_test (tc_chain, test_stepped_int_range_parsing);
tcase_add_test (tc_chain, test_stepped_int_range_ops);
tcase_add_test (tc_chain, test_flagset);
tcase_add_test (tc_chain, test_structure_basic);
tcase_add_test (tc_chain, test_structure_single_ops);
tcase_add_test (tc_chain, test_structure_ops);
tcase_add_test (tc_chain, test_transform_array);
tcase_add_test (tc_chain, test_transform_list);
tcase_add_test (tc_chain, test_serialize_null_aray);
return s;
}
GST_CHECK_MAIN (gst_value);