* That gives 21 (7 * 3) properties that will be installed.
*/
typedef GTypeInterface TestInterfaceInterface;
+static GType test_interface_get_type (void);
//typedef struct _TestInterface TestInterface;
G_DEFINE_INTERFACE (TestInterface, test_interface, G_TYPE_OBJECT)
static void
if (perms[j] == NULL)
{
+ if (!g_test_undefined ())
+ continue;
+
/* we think that this is impossible. make sure. */
- if (g_test_trap_fork (G_TIME_SPAN_SECOND, G_TEST_TRAP_SILENCE_STDERR))
- {
- GParamSpec *pspec;
+ pspec = g_param_spec_object ("xyz", "xyz", "xyz", types[i], j);
- pspec = g_param_spec_object ("xyz", "xyz", "xyz", types[i], j);
- g_object_interface_install_property (iface, pspec);
- exit (0);
- }
- //g_test_trap_assert_failed (); XXX g_object_interface_install_property has no checks
+ g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+ "*assertion*pspec->flags*failed*");
+ g_object_interface_install_property (iface, pspec);
+ g_test_assert_expected_messages ();
+
+ g_param_spec_unref (pspec);
continue;
}
/* We also try to change the flags. We must ensure that all
* implementations provide all functionality promised by the interface.
* We must therefore never remove readability or writability (but we can
- * add them). Construct/construct-only are restrictions that apply to
- * writability, so we can never add them unless writability was never
- * present in the first place, in which case we should be able to add
- * them.
+ * add them). Construct-only is a restrictions that applies to
+ * writability, so we can never add it unless writability was never
+ * present in the first place, in which case "writable at construct
+ * only" is still better than "not writable".
+ *
+ * The 'construct' flag is of interest only to the implementation. It
+ * may be changed at any time.
*
* Properties Valid Access Reason
*
* *-r r, rw, rwc, rwC Must keep readable, but can restrict newly-added writable
- * *-w w, rw Must keep writable unrestricted
- * *-rw rw Must not add any restrictions
- * *-rwc rw, rwc Can remove 'construct' restriction
- * *-rwC rw, rwC Can remove 'construct-only' restriction
- * *-wc rwc, rw, w, wc Can add readability or remove 'construct' restriction
+ * *-w w, rw, rwc Must keep writable unrestricted
+ * *-rw rw, rwc Must not add any restrictions
+ * *-rwc rw, rwc Must not add any restrictions
+ * *-rwC rw, rwc, rwC Can remove 'construct-only' restriction
+ * *-wc rwc, rw, w, wc Can add readability
* *-wC rwC, rw, w, wC Can add readability or remove 'construct only' restriction
+ * rwc, wc
*
* We can represent this with a 16-by-16 table. The rows represent the
* flags of the property on the interface. The columns is the flags to
* - 'v': valid
* - 'i': invalid because the implementation flags are invalid
* - 'f': invalid because of the removal of functionality
- * - 'r': invalid because of the addition of restrictions
+ * - 'r': invalid because of the addition of restrictions (ie: construct-only)
*
* We also ensure that removal of functionality is reported before
* addition of restrictions, since this is a more basic problem.
/* '' r w rw c rc wc rwc C rC wC rwC cC rcC wcC rwcC */
/* '*-' */ { },
/* '*-r' */ { 'i', 'v', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'i', 'i' },
- /* '*-w' */ { 'i', 'f', 'v', 'v', 'i', 'i', 'r', 'r', 'i', 'i', 'r', 'r', 'i', 'i', 'i', 'i' },
- /* '*-rw' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'r', 'i', 'i', 'f', 'r', 'i', 'i', 'i', 'i' },
+ /* '*-w' */ { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'r', 'r', 'i', 'i', 'i', 'i' },
+ /* '*-rw' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'r', 'i', 'i', 'i', 'i' },
/* '*-c */ { },
/* '*-rc' */ { },
/* '*-wc' */ { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'r', 'r', 'i', 'i', 'i', 'i' },
/* '*-rwc' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'r', 'i', 'i', 'i', 'i' },
/* '*-C */ { },
/* '*-rC' */ { },
- /* '*-wC' */ { 'i', 'f', 'v', 'v', 'i', 'i', 'r', 'r', 'i', 'i', 'v', 'v', 'i', 'i', 'i', 'i' },
- /* '*-rwC' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'r', 'i', 'i', 'f', 'v', 'i', 'i', 'i', 'i' },
+ /* '*-wC' */ { 'i', 'f', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'v', 'v', 'i', 'i', 'i', 'i' },
+ /* '*-rwC' */ { 'i', 'f', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'f', 'v', 'i', 'i', 'i', 'i' },
};
static guint change_this_flag;
if (perms[change_this_flag] == NULL)
g_error ("Interface property does not exist");
- if (!(use_this_flag & (G_PARAM_READABLE | G_PARAM_WRITABLE)))
- g_error ("g_object_class_install_property should probably fail here...");
-
g_snprintf (prop_name, sizeof prop_name, "%s-%s", names[change_this_type], perms[change_this_flag]);
pspec = g_param_spec_object (prop_name, prop_name, prop_name, types[use_this_type], use_this_flag);
g_object_class_install_property (class, 1, pspec);
}
+typedef struct {
+ gint change_this_flag;
+ gint change_this_type;
+ gint use_this_flag;
+ gint use_this_type;
+} TestParamImplementData;
+
static void
-test_param_implement (void)
+test_param_implement_child (gconstpointer user_data)
{
+ TestParamImplementData *data = (gpointer) user_data;
+
/* GObject oddity: GObjectClass must be initialised before we can
* initialise a GTypeInterface.
*/
/* Bring up the interface first. */
g_type_default_interface_ref (test_interface_get_type ());
+ /* Copy the flags into the global vars so
+ * test_implementation_class_init() will see them.
+ */
+ change_this_flag = data->change_this_flag;
+ change_this_type = data->change_this_type;
+ use_this_flag = data->use_this_flag;
+ use_this_type = data->use_this_type;
+
+ g_type_class_ref (test_implementation_get_type ());
+}
+
+static void
+test_param_implement (void)
+{
+ gchar *test_path;
+
for (change_this_flag = 0; change_this_flag < 16; change_this_flag++)
for (change_this_type = 0; change_this_type < 3; change_this_type++)
for (use_this_flag = 0; use_this_flag < 16; use_this_flag++)
for (use_this_type = 0; use_this_type < 4; use_this_type++)
{
- if (g_test_trap_fork (G_TIME_SPAN_SECOND, G_TEST_TRAP_SILENCE_STDERR))
+ if (!g_test_undefined ())
{
- g_type_class_ref (test_implementation_get_type ());
- exit (0);
+ /* only test the valid (defined) cases, e.g. under valgrind */
+ if (valid_impl_flags[change_this_flag][use_this_flag] != 'v')
+ continue;
+
+ if (valid_impl_types[change_this_type * 16 + change_this_flag][use_this_type] != 'v')
+ continue;
}
+ test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
+ change_this_flag, change_this_type,
+ use_this_flag, use_this_type);
+ g_test_trap_subprocess (test_path, G_TIME_SPAN_SECOND, 0);
+ g_free (test_path);
+
/* We want to ensure that any flags mismatch problems are reported first. */
switch (valid_impl_flags[change_this_flag][use_this_flag])
{
}
}
+static void
+test_param_default (void)
+{
+ GParamSpec *param;
+ const GValue *def;
+
+ param = g_param_spec_int ("my-int", "My Int", "Blurb", 0, 20, 10, G_PARAM_READWRITE);
+ def = g_param_spec_get_default_value (param);
+
+ g_assert (G_VALUE_HOLDS (def, G_TYPE_INT));
+ g_assert_cmpint (g_value_get_int (def), ==, 10);
+
+ g_param_spec_unref (param);
+}
+
int
main (int argc, char *argv[])
{
- g_type_init ();
+ TestParamImplementData data, *test_data;
+ gchar *test_path;
+
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/param/value", test_param_value);
g_test_add_func ("/param/qdata", test_param_qdata);
g_test_add_func ("/param/validate", test_param_validate);
g_test_add_func ("/param/convert", test_param_convert);
+
g_test_add_func ("/param/implement", test_param_implement);
+ for (data.change_this_flag = 0; data.change_this_flag < 16; data.change_this_flag++)
+ for (data.change_this_type = 0; data.change_this_type < 3; data.change_this_type++)
+ for (data.use_this_flag = 0; data.use_this_flag < 16; data.use_this_flag++)
+ for (data.use_this_type = 0; data.use_this_type < 4; data.use_this_type++)
+ {
+ test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d",
+ data.change_this_flag, data.change_this_type,
+ data.use_this_flag, data.use_this_type);
+ test_data = g_memdup (&data, sizeof (TestParamImplementData));
+ g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free);
+ g_free (test_path);
+ }
+
g_test_add_func ("/value/transform", test_value_transform);
+ g_test_add_func ("/param/default", test_param_default);
return g_test_run ();
}