+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 (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ 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 (GST_VALUE_HOLDS_LIST (&dest) == TRUE);
+ 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;
+