# HG changeset patch
# Node ID bde7f507b0e372136c57434a5ddc2a8e7161dfe9
# Parent  42316cdbcf2e2773e5f4b531931f38c31d7ff9c2
diff --git a/birb/birbassert.h b/birb/birbassert.h
new file mode 100644
--- /dev/null
+++ b/birb/birbassert.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023-2025 Birb Developers
+ *
+ * Birb is the legal property of its developers, whose names are too
+ * numerous to list here. Please refer to the AUTHORS file distributed
+ * with this source distribution
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined(BIRB_GLOBAL_HEADER_INSIDE) && !defined(BIRB_COMPILATION)
+# error "only <birb.h> may be included directly"
+#endif
+
+#ifndef BIRB_ASSERT_H
+#define BIRB_ASSERT_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "birbversion.h"
+
+G_BEGIN_DECLS
+
+/**
+ * birb_assert_type:
+ * @instance: the instance whose type to check
+ * @type: the required type
+ *
+ * Asserts that @instance is of type @type.
+ *
+ * Since: 0.3
+ */
+#define birb_assert_type(instance, type) G_STMT_START { \
+    gpointer _instance = (instance); \
+    if(_instance == NULL) { \
+        char *msg = g_strdup_printf("%s is NULL and not an instance of %s", \
+                                    #instance, \
+                                    g_type_name((type))); \
+        g_assertion_message(G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); \
+        g_free(msg); \
+    } else if(!G_IS_OBJECT(_instance)) { \
+        char *msg = g_strdup_printf("%s is not a GObject", #instance); \
+        g_assertion_message(G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); \
+        g_free(msg); \
+    } else if(G_OBJECT_TYPE(_instance) != (type)) { \
+        char *msg = g_strdup_printf("%s is of type %s not %s", \
+                                    #instance, \
+                                    G_OBJECT_TYPE_NAME(_instance), \
+                                    g_type_name((type))); \
+        g_assertion_message(G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); \
+        g_free(msg); \
+    } \
+    } G_STMT_END \
+    BIRB_AVAILABLE_MACRO_IN_0_3
+
+G_END_DECLS
+
+#endif /* BIRB_ASSERT_H */
diff --git a/birb/meson.build b/birb/meson.build
--- a/birb/meson.build
+++ b/birb/meson.build
@@ -12,6 +12,7 @@
 
 BIRB_HEADERS = [
   'birbactionmenu.h',
+  'birbassert.h',
   'birbcustomfilter.h',
   'birbdatetime.h',
   'birbfilter.h',
diff --git a/birb/tests/test_action_menu.c b/birb/tests/test_action_menu.c
--- a/birb/tests/test_action_menu.c
+++ b/birb/tests/test_action_menu.c
@@ -36,7 +36,7 @@
 	guint *counter = data;
 
 	g_assert_nonnull(prefix);
-	g_assert_true(G_IS_ACTION_GROUP(group));
+	birb_assert_type(group, G_TYPE_SIMPLE_ACTION_GROUP);
 
 	*counter = *counter + 1;
 }
@@ -51,10 +51,10 @@
 	guint counter = 0;
 
 	action_menu = birb_action_menu_new();
-	g_assert_true(BIRB_IS_ACTION_MENU(action_menu));
+	birb_assert_type(action_menu, BIRB_TYPE_ACTION_MENU);
 
 	menu = birb_action_menu_get_menu(action_menu);
-	g_assert_true(G_IS_MENU(menu));
+	birb_assert_type(menu, G_TYPE_MENU);
 
 	birb_action_menu_foreach_action_group(action_menu,
 	                                      test_action_menu_foreach_action_group_counter,
@@ -73,7 +73,7 @@
 	guint counter = 0;
 
 	menu = birb_action_menu_new();
-	g_assert_true(BIRB_IS_ACTION_MENU(menu));
+	birb_assert_type(menu, BIRB_TYPE_ACTION_MENU);
 
 	group1 = g_simple_action_group_new();
 	birb_action_menu_add_action_group(menu, "foo", G_ACTION_GROUP(group1));
diff --git a/birb/tests/test_custom_filter.c b/birb/tests/test_custom_filter.c
--- a/birb/tests/test_custom_filter.c
+++ b/birb/tests/test_custom_filter.c
@@ -31,7 +31,7 @@
 test_birb_custom_filter_match_all_func(GObject *item,
                                        G_GNUC_UNUSED gpointer data)
 {
-	g_assert_true(G_IS_OBJECT(item));
+	birb_assert_type(item, G_TYPE_OBJECT);
 
 	return TRUE;
 }
@@ -39,7 +39,7 @@
 static gboolean
 test_birb_custom_filter_match_all_data_func(GObject *item, gpointer data) {
 	g_assert_nonnull(data);
-	g_assert_true(G_IS_OBJECT(item));
+	birb_assert_type(item, G_TYPE_OBJECT);
 
 	return TRUE;
 }
@@ -53,7 +53,7 @@
 
 	filter = birb_custom_filter_new(NULL, NULL, NULL);
 
-	g_assert_true(BIRB_IS_CUSTOM_FILTER(filter));
+	birb_assert_type(filter, BIRB_TYPE_CUSTOM_FILTER);
 
 	g_assert_finalize_object(filter);
 }
@@ -67,7 +67,7 @@
 
 	filter = birb_custom_filter_new(NULL, g_object_ref(item), g_object_unref);
 
-	g_assert_true(BIRB_IS_CUSTOM_FILTER(filter));
+	birb_assert_type(filter, BIRB_TYPE_CUSTOM_FILTER);
 
 	g_assert_finalize_object(filter);
 	g_assert_finalize_object(item);
@@ -80,7 +80,7 @@
 	filter = birb_custom_filter_new(test_birb_custom_filter_match_all_func,
 	                                NULL, NULL);
 
-	g_assert_true(BIRB_IS_CUSTOM_FILTER(filter));
+	birb_assert_type(filter, BIRB_TYPE_CUSTOM_FILTER);
 
 	g_assert_finalize_object(filter);
 }
@@ -93,7 +93,7 @@
 	filter = birb_custom_filter_new(test_birb_custom_filter_match_all_data_func,
 	                                &data, NULL);
 
-	g_assert_true(BIRB_IS_CUSTOM_FILTER(filter));
+	birb_assert_type(filter, BIRB_TYPE_CUSTOM_FILTER);
 
 	g_assert_finalize_object(filter);
 }
@@ -108,7 +108,7 @@
 	filter = birb_custom_filter_new(test_birb_custom_filter_match_all_data_func,
 	                                g_object_ref(item), g_object_unref);
 
-	g_assert_true(BIRB_IS_CUSTOM_FILTER(filter));
+	birb_assert_type(filter, BIRB_TYPE_CUSTOM_FILTER);
 
 	g_assert_finalize_object(filter);
 	g_assert_finalize_object(item);
@@ -121,7 +121,7 @@
 test_birb_custom_filter_matches_func(GObject *item, gpointer data) {
 	gboolean result = GPOINTER_TO_INT(data);
 
-	g_assert_true(G_IS_OBJECT(item));
+	birb_assert_type(item, G_TYPE_OBJECT);
 
 	return result;
 }
diff --git a/birb/tests/test_filter.c b/birb/tests/test_filter.c
--- a/birb/tests/test_filter.c
+++ b/birb/tests/test_filter.c
@@ -31,7 +31,7 @@
 test_filter_changed_cb(BirbFilter *filter, gpointer data) {
 	guint *counter = data;
 
-	g_assert_true(BIRB_IS_FILTER(filter));
+	birb_assert_type(filter, BIRB_TYPE_FILTER);
 
 	*counter = *counter + 1;
 }
@@ -42,7 +42,7 @@
 	guint counter = 0;
 
 	filter = g_object_new(BIRB_TYPE_FILTER, NULL);
-	g_assert_true(BIRB_IS_FILTER(filter));
+	birb_assert_type(filter, BIRB_TYPE_FILTER);
 
 	g_signal_connect(filter, "changed", G_CALLBACK(test_filter_changed_cb),
 	                 &counter);
@@ -60,8 +60,8 @@
 test_filter_matches_impl(BirbFilter *filter, GObject *item) {
 	gpointer ret = NULL;
 
-	g_assert_true(BIRB_IS_FILTER(filter));
-	g_assert_true(G_IS_OBJECT(item));
+	birb_assert_type(filter, BIRB_TYPE_FILTER);
+	birb_assert_type(item, G_TYPE_OBJECT);
 
 	ret = g_object_get_data(G_OBJECT(filter), "matches");
 
@@ -77,7 +77,7 @@
 	gboolean expected = GPOINTER_TO_INT(data);
 
 	filter = g_object_new(BIRB_TYPE_FILTER, NULL);
-	g_assert_true(BIRB_IS_FILTER(filter));
+	birb_assert_type(filter, BIRB_TYPE_FILTER);
 
 	klass = BIRB_FILTER_GET_CLASS(filter);
 	klass->matches = test_filter_matches_impl;
diff --git a/birb/tests/test_queued_output_stream.c b/birb/tests/test_queued_output_stream.c
--- a/birb/tests/test_queued_output_stream.c
+++ b/birb/tests/test_queued_output_stream.c
@@ -46,10 +46,10 @@
 	gboolean ret = FALSE;
 
 	output = g_memory_output_stream_new_resizable();
-	g_assert_true(G_IS_MEMORY_OUTPUT_STREAM(output));
+	birb_assert_type(output, G_TYPE_MEMORY_OUTPUT_STREAM);
 
 	queued = birb_queued_output_stream_new(output);
-	g_assert_true(BIRB_IS_QUEUED_OUTPUT_STREAM(queued));
+	birb_assert_type(queued, BIRB_TYPE_QUEUED_OUTPUT_STREAM);
 
 	ret = g_output_stream_close(G_OUTPUT_STREAM(queued), NULL, &error);
 	g_assert_no_error(error);
@@ -89,10 +89,10 @@
 	int counter = 0;
 
 	output = g_memory_output_stream_new_resizable();
-	g_assert_true(G_IS_MEMORY_OUTPUT_STREAM(output));
+	birb_assert_type(output, G_TYPE_MEMORY_OUTPUT_STREAM);
 
 	queued = birb_queued_output_stream_new(output);
-	g_assert_true(BIRB_IS_QUEUED_OUTPUT_STREAM(queued));
+	birb_assert_type(queued, BIRB_TYPE_QUEUED_OUTPUT_STREAM);
 
 	bytes = g_bytes_new_static(test_bytes_data, test_bytes_data_len);
 	birb_queued_output_stream_push_bytes_async(BIRB_QUEUED_OUTPUT_STREAM(queued),
@@ -151,10 +151,10 @@
 	int counter = 0;
 
 	output = g_memory_output_stream_new_resizable();
-	g_assert_true(G_IS_MEMORY_OUTPUT_STREAM(output));
+	birb_assert_type(output, G_TYPE_MEMORY_OUTPUT_STREAM);
 
 	queued = birb_queued_output_stream_new(output);
-	g_assert_true(BIRB_IS_QUEUED_OUTPUT_STREAM(queued));
+	birb_assert_type(queued, BIRB_TYPE_QUEUED_OUTPUT_STREAM);
 
 	bytes = g_bytes_new_static(test_bytes_data, test_bytes_data_len);
 	birb_queued_output_stream_push_bytes_async(BIRB_QUEUED_OUTPUT_STREAM(queued),
@@ -245,10 +245,10 @@
 	int counter = 0;
 
 	output = g_memory_output_stream_new_resizable();
-	g_assert_true(G_IS_MEMORY_OUTPUT_STREAM(output));
+	birb_assert_type(output, G_TYPE_MEMORY_OUTPUT_STREAM);
 
 	queued = birb_queued_output_stream_new(output);
-	g_assert_true(BIRB_IS_QUEUED_OUTPUT_STREAM(queued));
+	birb_assert_type(queued, BIRB_TYPE_QUEUED_OUTPUT_STREAM);
 
 	cancellable = g_cancellable_new();
 	g_assert_nonnull(cancellable);
diff --git a/birb/tests/test_string_object.c b/birb/tests/test_string_object.c
--- a/birb/tests/test_string_object.c
+++ b/birb/tests/test_string_object.c
@@ -34,7 +34,7 @@
 {
 	guint *counter = data;
 
-	g_assert_true(BIRB_IS_STRING_OBJECT(obj));
+	birb_assert_type(obj, BIRB_TYPE_STRING_OBJECT);
 
 	*counter = *counter + 1;
 }
@@ -47,7 +47,7 @@
 	BirbStringObject *obj = NULL;
 
 	obj = birb_string_object_new("birdy");
-	g_assert_true(BIRB_IS_STRING_OBJECT(obj));
+	birb_assert_type(obj, BIRB_TYPE_STRING_OBJECT);
 
 	g_assert_finalize_object(obj);
 }
