[gjs: 1/18] jsapi-util: Rewrite GjsAutoPointer to only use template data




commit 83347839050c716c8443b3ec192c431d31724a8c
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Tue Sep 29 19:59:49 2020 +0200

    jsapi-util: Rewrite GjsAutoPointer to only use template data
    
    We introduced GjsAutoPointer as part of commit dab3c7d06, to avoid duplication
    of the same code everywhere, and that served us well to create multiple
    smart pointer types, however since we were relying on std::unique_ptr,
    all the times we created a pointer with a custom destructor, we were
    allocating 8bits more, and this can be sensitive when used around in
    wrappers.
    
    However, since we are already constructing the auto-pointers passing all
    these information as template (generating some custom code, for sure),
    we can just rely on the template parameters also for the destructor, and
    so ensuring that the struct size always matches the wrapped pointer,
    removing all the overhead.
    
    This will allow to use GjsAutoPointer's everywhere without increasing
    the size of the wrapped objects.
    
    As per this being all new (even though the API is mainly inspired to
    unique_ptr), adding various unit tests to ensure we behave correctly.

 gi/object.cpp                 |   2 +-
 gjs/jsapi-util.h              |  93 +++++++--
 test/gjs-test-jsapi-utils.cpp | 463 ++++++++++++++++++++++++++++++++++++++++++
 test/gjs-test-utils.h         |   2 +
 test/gjs-tests.cpp            |   1 +
 test/meson.build              |   1 +
 6 files changed, 543 insertions(+), 19 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index f13decdf..08e82081 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -588,7 +588,7 @@ bool ObjectPrototype::is_vfunc_unchanged(GIVFuncInfo* info) {
 
 /* Taken from GLib */
 static void canonicalize_key(const GjsAutoChar& key) {
-    for (char* p = key.get(); *p != 0; p++) {
+    for (char* p = key; *p != 0; p++) {
         char c = *p;
 
         if (c != '-' && (c < '0' || c > '9') && (c < 'A' || c > 'Z') &&
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index d84611be..43d855ac 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -1,18 +1,20 @@
 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2008 litl, LLC
+// SPDX-FileCopyrightText: 2018-2020  Canonical, Ltd
 
 #ifndef GJS_JSAPI_UTIL_H_
 #define GJS_JSAPI_UTIL_H_
 
 #include <config.h>
 
-#include <stddef.h>  // for size_t
 #include <stdint.h>
+#include <stdlib.h>     // for free
 #include <sys/types.h>  // for ssize_t
 
-#include <memory>  // for unique_ptr
 #include <string>  // for string, u16string
+#include <type_traits>  // for enable_if_t, add_pointer_t, add_const_t
+#include <utility>      // IWYU pragma: keep
 #include <vector>
 
 #include <girepository.h>
@@ -34,38 +36,93 @@ class CallArgs;
 
 struct GjsAutoTakeOwnership {};
 
-template <typename T, typename F,
-          void (*free_func)(F*) = nullptr, F* (*ref_func)(F*) = nullptr>
-struct GjsAutoPointer : std::unique_ptr<T, decltype(free_func)> {
-    GjsAutoPointer(T* ptr = nullptr)  // NOLINT(runtime/explicit)
-        : GjsAutoPointer::unique_ptr(ptr, *free_func) {}
-    GjsAutoPointer(T* ptr, const GjsAutoTakeOwnership&)
-        : GjsAutoPointer(nullptr) {
+template <typename T, typename F = void, void (*free_func)(F*) = free,
+          F* (*ref_func)(F*) = nullptr>
+struct GjsAutoPointer {
+    using Ptr = std::add_pointer_t<T>;
+    using ConstPtr = std::add_pointer_t<std::add_const_t<T>>;
+
+    constexpr GjsAutoPointer(Ptr ptr = nullptr)  // NOLINT(runtime/explicit)
+        : m_ptr(ptr) {}
+    constexpr GjsAutoPointer(Ptr ptr, const GjsAutoTakeOwnership&)
+        : GjsAutoPointer(ptr) {
         // FIXME: should use if constexpr (...), but that doesn't work with
         // ubsan, which generates a null pointer check making it not a constexpr
         // anymore: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71962 - Also a
         // bogus warning, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94554
-        auto ref = ref_func;
-        this->reset(ptr && ref ? reinterpret_cast<T*>(ref(ptr)) : ptr);
+        m_ptr = copy();
+    }
+    constexpr GjsAutoPointer(ConstPtr ptr, const GjsAutoTakeOwnership& o)
+        : GjsAutoPointer(const_cast<Ptr>(ptr), o) {}
+    constexpr GjsAutoPointer(GjsAutoPointer&& other) : GjsAutoPointer() {
+        this->swap(other);
+    }
+
+    constexpr GjsAutoPointer& operator=(Ptr ptr) {
+        reset(ptr);
+        return *this;
+    }
+
+    GjsAutoPointer& operator=(GjsAutoPointer&& other) {
+        this->swap(other);
+        return *this;
+    }
+
+    constexpr T operator*() const { return *m_ptr; }
+    constexpr Ptr operator->() { return m_ptr; }
+    constexpr ConstPtr operator->() const { return m_ptr; }
+    constexpr operator Ptr() { return m_ptr; }
+    constexpr operator Ptr() const { return m_ptr; }
+    constexpr operator ConstPtr() const { return m_ptr; }
+    constexpr operator bool() const { return m_ptr != nullptr; }
+
+    constexpr Ptr get() { return m_ptr; }
+    constexpr ConstPtr get() const { return m_ptr; }
+
+    constexpr Ptr release() {
+        auto* ptr = m_ptr;
+        m_ptr = nullptr;
+        return ptr;
     }
 
-    constexpr operator T*() const { return this->get(); }
-    constexpr T& operator[](size_t i) const {
-        return static_cast<T*>(*this)[i];
+    constexpr void reset(Ptr ptr = nullptr) {
+        // FIXME: Should use if constexpr (...) as above
+        auto ffunc = free_func;
+        Ptr old_ptr = m_ptr;
+        m_ptr = ptr;
+        if (old_ptr && ffunc)
+            ffunc(old_ptr);
     }
 
-    [[nodiscard]] constexpr T* copy() const {
-        return reinterpret_cast<T*>(ref_func(this->get()));
+    constexpr void swap(GjsAutoPointer& other) {
+        std::swap(this->m_ptr, other.m_ptr);
+    }
+
+    /* constexpr */ ~GjsAutoPointer() {  // one day, with -std=c++2a
+        reset();
+    }
+
+    [[nodiscard]] constexpr Ptr copy() const {
+        // FIXME: Should use std::enable_if_t<ref_func != nullptr, Ptr>
+        if (!m_ptr)
+            return nullptr;
+
+        auto rf = ref_func;
+        g_assert(rf);
+        return reinterpret_cast<Ptr>(ref_func(m_ptr));
     }
 
     template <typename C>
     [[nodiscard]] constexpr C* as() const {
-        return const_cast<C*>(reinterpret_cast<const C*>(this->get()));
+        return const_cast<C*>(reinterpret_cast<const C*>(m_ptr));
     }
+
+ private:
+    Ptr m_ptr;
 };
 
 template <typename T>
-using GjsAutoFree = GjsAutoPointer<T, void, g_free>;
+using GjsAutoFree = GjsAutoPointer<T>;
 
 struct GjsAutoCharFuncs {
     static char* dup(char* str) { return g_strdup(str); }
diff --git a/test/gjs-test-jsapi-utils.cpp b/test/gjs-test-jsapi-utils.cpp
new file mode 100644
index 00000000..8d8f51f1
--- /dev/null
+++ b/test/gjs-test-jsapi-utils.cpp
@@ -0,0 +1,463 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+ *
+ * Copyright (c) 2020 Marco Trevisan <marco trevisan canonical com>
+ */
+
+#include <glib-object.h>
+#include <glib.h>
+#include <stddef.h>  // for NULL
+#include <utility>   // for move, swap
+
+#include "gjs/jsapi-util.h"
+
+struct _GjsTestObject {
+    GObject parent_instance;
+
+    int stuff;
+};
+
+G_DECLARE_FINAL_TYPE(GjsTestObject, gjs_test_object, GJS_TEST, OBJECT, GObject)
+G_DEFINE_TYPE(GjsTestObject, gjs_test_object, G_TYPE_OBJECT)
+
+static void gjs_test_object_init(GjsTestObject*) {}
+void gjs_test_object_class_init(GjsTestObjectClass*) {}
+static GjsTestObject* gjs_test_object_new() {
+    return GJS_TEST_OBJECT(g_object_new(gjs_test_object_get_type(), NULL));
+}
+
+static unsigned test_gjs_autopointer_refcount(GjsTestObject* test_object) {
+    return G_OBJECT(test_object)->ref_count;
+}
+
+using GjsAutoTestObject =
+    GjsAutoPointer<GjsTestObject, void, g_object_unref, g_object_ref>;
+
+static void test_gjs_autopointer_size() {
+    g_assert_cmpuint(sizeof(GjsAutoTestObject), ==, sizeof(GjsTestObject*));
+}
+
+static void test_gjs_autopointer_ctor_empty() {
+    GjsAutoTestObject autoptr;
+    g_assert_null(autoptr.get());
+    g_assert_null(autoptr);
+}
+
+static void test_gjs_autopointer_ctor_basic() {
+    auto* ptr = gjs_test_object_new();
+    g_assert_nonnull(ptr);
+
+    GjsAutoTestObject autoptr(ptr);
+    g_assert(autoptr == ptr);
+    g_assert(autoptr.get() == ptr);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+}
+
+static void test_gjs_autopointer_ctor_take_ownership() {
+    auto* ptr = gjs_test_object_new();
+    g_assert_nonnull(ptr);
+
+    GjsAutoTestObject autoptr(ptr, GjsAutoTakeOwnership());
+    g_assert(autoptr == ptr);
+    g_assert(autoptr.get() == ptr);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 2);
+    g_object_unref(ptr);
+}
+
+static void test_gjs_autopointer_ctor_assign() {
+    auto* ptr = gjs_test_object_new();
+    g_assert_nonnull(ptr);
+
+    GjsAutoTestObject autoptr = ptr;
+    g_assert(autoptr == ptr);
+    g_assert(autoptr.get() == ptr);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+}
+
+static void test_gjs_autopointer_dtor() {
+    auto* ptr = gjs_test_object_new();
+    g_assert_nonnull(ptr);
+
+    {
+        g_object_ref(ptr);
+        g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 2);
+
+        GjsAutoTestObject autoptr(ptr);
+        g_assert(autoptr == ptr);
+        g_assert(autoptr.get() == ptr);
+    }
+
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+    g_object_unref(ptr);
+}
+
+static void test_gjs_autopointer_dtor_take_ownership() {
+    auto* ptr = gjs_test_object_new();
+    g_assert_nonnull(ptr);
+
+    {
+        GjsAutoTestObject autoptr(ptr, GjsAutoTakeOwnership());
+        g_assert(autoptr == ptr);
+        g_assert(autoptr.get() == ptr);
+        g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 2);
+    }
+
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+    g_object_unref(ptr);
+}
+
+static void test_gjs_autopointer_assign_operator() {
+    GjsAutoTestObject autoptr;
+    auto* ptr = gjs_test_object_new();
+
+    autoptr = ptr;
+
+    g_assert(autoptr == ptr);
+    g_assert(autoptr.get() == ptr);
+}
+
+static void test_gjs_autopointer_assign_operator_other_ptr() {
+    auto* ptr1 = gjs_test_object_new();
+    auto* ptr2 = gjs_test_object_new();
+
+    GjsAutoTestObject autoptr(ptr1);
+
+    g_object_ref(ptr1);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr1), ==, 2);
+
+    autoptr = ptr2;
+
+    g_assert(autoptr == ptr2);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr1), ==, 1);
+    g_object_unref(ptr1);
+}
+
+static void test_gjs_autopointer_assign_operator_self_ptr() {
+    auto* ptr = gjs_test_object_new();
+
+    GjsAutoTestObject autoptr(ptr);
+
+    g_object_ref(ptr);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 2);
+
+    autoptr = ptr;
+
+    g_assert(autoptr == ptr);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+}
+
+static void test_gjs_autopointer_operator_move() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr);
+
+    auto test_move_fun = [ptr](GjsAutoTestObject&& data) {
+        g_assert(ptr == data);
+        g_assert_cmpuint(test_gjs_autopointer_refcount(data.get()), ==, 1);
+    };
+
+    test_move_fun(std::move(autoptr));
+    g_assert_nonnull(autoptr);
+
+    GjsAutoTestObject autoptr2 = std::move(autoptr);
+    g_assert(autoptr2 == ptr);
+    g_assert_null(autoptr);
+}
+
+static void test_gjs_autopointer_operator_swap() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr1(ptr);
+    GjsAutoTestObject autoptr2;
+
+    std::swap(autoptr1, autoptr2);
+    g_assert_null(autoptr1);
+    g_assert(autoptr2 == ptr);
+}
+
+static void test_gjs_autopointer_assign_operator_arrow() {
+    GjsAutoTestObject autoptr(gjs_test_object_new());
+
+    int value = g_random_int();
+    autoptr->stuff = value;
+    g_assert_cmpint(autoptr->stuff, ==, value);
+}
+
+static void test_gjs_autopointer_assign_operator_deference() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr);
+
+    ptr->stuff = g_random_int();
+
+    GjsTestObject tobj = *autoptr;
+    g_assert_cmpint(ptr->stuff, ==, tobj.stuff);
+    g_assert_cmpuint(ptr->parent_instance.ref_count, ==,
+                     tobj.parent_instance.ref_count);
+    g_assert_cmpuint(ptr->parent_instance.g_type_instance.g_class->g_type, ==,
+                     tobj.parent_instance.g_type_instance.g_class->g_type);
+}
+
+static void test_gjs_autopointer_assign_operator_bool() {
+    auto bool_to_gboolean = [](bool v) -> gboolean { return !!v; };
+
+    g_assert_false(bool_to_gboolean(GjsAutoTestObject()));
+    g_assert_true(bool_to_gboolean(GjsAutoTestObject(gjs_test_object_new())));
+
+    GjsAutoTestObject autoptr(gjs_test_object_new());
+    autoptr.reset();
+    g_assert_false(bool_to_gboolean(autoptr));
+}
+
+static void test_gjs_autopointer_assign_operator_array() {
+    auto* ptrs = g_new0(GjsTestObject, 5);
+    GjsAutoPointer<GjsTestObject> autopointers(ptrs);
+
+    for (int i = 0; i < 5; i++) {
+        autopointers[i].stuff = i;
+        g_assert_cmpint(ptrs[i].stuff, ==, i);
+        g_assert_cmpint(autopointers[i].stuff, ==, i);
+    }
+}
+
+static void test_gjs_autopointer_get() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr);
+
+    g_assert(ptr == autoptr.get());
+}
+
+static void test_gjs_autopointer_release() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr);
+
+    g_assert_nonnull(autoptr);
+
+    auto* released = autoptr.release();
+    g_assert(released == ptr);
+    g_assert_null(autoptr);
+
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+    g_object_unref(ptr);
+}
+
+static void test_gjs_autopointer_reset_nullptr() {
+    GjsAutoTestObject empty;
+    empty.reset();
+    g_assert_null(empty);
+
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr);
+
+    g_assert_nonnull(autoptr);
+
+    g_object_ref(ptr);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 2);
+
+    autoptr.reset();
+    g_assert_null(autoptr);
+
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+    g_object_unref(ptr);
+}
+
+static void test_gjs_autopointer_reset_self_ptr() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr);
+
+    g_assert(autoptr == ptr);
+
+    g_object_ref(ptr);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 2);
+
+    autoptr.reset(ptr);
+    g_assert(autoptr == ptr);
+
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+}
+
+static void test_gjs_autopointer_reset_other_ptr() {
+    auto* ptr1 = gjs_test_object_new();
+    auto* ptr2 = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr1);
+
+    g_assert(autoptr == ptr1);
+
+    g_object_ref(ptr1);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr1), ==, 2);
+
+    autoptr.reset(ptr2);
+    g_assert(autoptr == ptr2);
+
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr1), ==, 1);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr2), ==, 1);
+
+    g_object_unref(ptr1);
+}
+
+static void test_gjs_autopointer_swap_other_ptr() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr1(ptr);
+    GjsAutoTestObject autoptr2;
+
+    autoptr1.swap(autoptr2);
+    g_assert_null(autoptr1);
+    g_assert(autoptr2 == ptr);
+
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+}
+
+static void test_gjs_autopointer_swap_self_ptr() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr);
+
+    autoptr.swap(autoptr);
+    g_assert(autoptr == ptr);
+
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+}
+
+static void test_gjs_autopointer_swap_empty() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr1(ptr);
+    GjsAutoTestObject autoptr2;
+
+    autoptr1.swap(autoptr2);
+    g_assert_null(autoptr1);
+
+    g_assert(autoptr2 == ptr);
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 1);
+}
+
+static void test_gjs_autopointer_copy() {
+    auto* ptr = gjs_test_object_new();
+    GjsAutoTestObject autoptr(ptr);
+
+    g_assert(ptr == autoptr.copy());
+    g_assert_cmpuint(test_gjs_autopointer_refcount(ptr), ==, 2);
+
+    g_object_unref(ptr);
+}
+
+static void test_gjs_autopointer_as() {
+    GjsAutoTestObject autoptr(gjs_test_object_new());
+
+    g_assert_cmpuint(autoptr.as<GObject>()->ref_count, ==, 1);
+}
+
+static void test_gjs_autochar_init() {
+    char* str = g_strdup("FoooBar");
+    GjsAutoChar autoptr = str;
+
+    g_assert_cmpstr(autoptr, ==, "FoooBar");
+    g_assert_cmpuint(autoptr[4], ==, 'B');
+    g_assert(autoptr == str);
+}
+
+static void test_gjs_autochar_init_take_ownership() {
+    const char* str = "FoooBarConst";
+    GjsAutoChar autoptr(str, GjsAutoTakeOwnership());
+
+    g_assert_cmpstr(autoptr, ==, str);
+    g_assert_cmpuint(autoptr[4], ==, 'B');
+    g_assert(autoptr != str);
+}
+
+static void test_gjs_autochar_copy() {
+    GjsAutoChar autoptr = g_strdup("FoooBar");
+
+    char* copy = autoptr.copy();
+    g_assert_cmpstr(autoptr, ==, copy);
+    g_assert(autoptr != copy);
+
+    g_free(copy);
+}
+
+static void test_gjs_autostrv_init() {
+    const char* strv[] = {"FOO", "Bar", "BAZ", nullptr};
+    GjsAutoStrv autoptr = g_strdupv(const_cast<char**>(strv));
+
+    g_assert_true(g_strv_equal(strv, autoptr));
+
+    for (int i = g_strv_length(const_cast<char**>(strv)); i >= 0; i--)
+        g_assert_cmpstr(autoptr[i], ==, strv[i]);
+}
+
+static void test_gjs_autotypeclass_init() {
+    GjsAutoTypeClass<GObjectClass> autoclass(gjs_test_object_get_type());
+
+    g_assert_nonnull(autoclass);
+    g_assert_cmpint(autoclass->g_type_class.g_type, ==,
+        gjs_test_object_get_type());
+}
+
+void gjs_test_add_tests_for_jsapi_utils(void) {
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/size",
+                    test_gjs_autopointer_size);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/constructor/empty",
+                    test_gjs_autopointer_ctor_empty);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/constructor/basic",
+                    test_gjs_autopointer_ctor_basic);
+    g_test_add_func(
+        "/gjs/jsapi-utils/gjs-autopointer/constructor/take_ownership",
+        test_gjs_autopointer_ctor_take_ownership);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/constructor/assignment",
+                    test_gjs_autopointer_ctor_assign);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/destructor",
+                    test_gjs_autopointer_dtor);
+    g_test_add_func(
+        "/gjs/jsapi-utils/gjs-autopointer/destructor/take_ownership",
+        test_gjs_autopointer_dtor_take_ownership);
+
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/assign",
+                    test_gjs_autopointer_assign_operator);
+    g_test_add_func(
+        "/gjs/jsapi-utils/gjs-autopointer/operator/assign/other_ptr",
+        test_gjs_autopointer_assign_operator_other_ptr);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/assign/self_ptr",
+                    test_gjs_autopointer_assign_operator_self_ptr);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/move",
+                    test_gjs_autopointer_operator_move);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/swap",
+                    test_gjs_autopointer_operator_swap);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/arrow",
+                    test_gjs_autopointer_assign_operator_arrow);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/deference",
+                    test_gjs_autopointer_assign_operator_deference);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/bool",
+                    test_gjs_autopointer_assign_operator_bool);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/operator/array",
+                    test_gjs_autopointer_assign_operator_array);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/get",
+                    test_gjs_autopointer_get);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/release",
+                    test_gjs_autopointer_release);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/reset/nullptr",
+                    test_gjs_autopointer_reset_nullptr);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/reset/other_ptr",
+                    test_gjs_autopointer_reset_other_ptr);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/reset/self_ptr",
+                    test_gjs_autopointer_reset_self_ptr);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/swap/other_ptr",
+                    test_gjs_autopointer_swap_other_ptr);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/swap/self_ptr",
+                    test_gjs_autopointer_swap_self_ptr);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/swap/empty",
+                    test_gjs_autopointer_swap_empty);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/copy",
+                    test_gjs_autopointer_copy);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autopointer/method/as",
+                    test_gjs_autopointer_as);
+
+    //  Other implementations
+    g_test_add_func("/gjs/jsapi-utils/gjs-autochar/init",
+                    test_gjs_autochar_init);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autochar/init/take_ownership",
+                    test_gjs_autochar_init_take_ownership);
+    g_test_add_func("/gjs/jsapi-utils/gjs-autochar/copy",
+                    test_gjs_autochar_copy);
+
+    g_test_add_func("/gjs/jsapi-utils/gjs-autostrv/init",
+                    test_gjs_autostrv_init);
+
+    g_test_add_func("/gjs/jsapi-utils/gjs-autotypeclass/init",
+                    test_gjs_autotypeclass_init);
+}
diff --git a/test/gjs-test-utils.h b/test/gjs-test-utils.h
index 0348034f..f44298a6 100644
--- a/test/gjs-test-utils.h
+++ b/test/gjs-test-utils.h
@@ -30,4 +30,6 @@ void gjs_test_add_tests_for_parse_call_args(void);
 
 void gjs_test_add_tests_for_rooting(void);
 
+void gjs_test_add_tests_for_jsapi_utils();
+
 #endif  // TEST_GJS_TEST_UTILS_H_
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index 6b89bc35..95eec163 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -672,6 +672,7 @@ main(int    argc,
     gjs_test_add_tests_for_coverage ();
     gjs_test_add_tests_for_parse_call_args();
     gjs_test_add_tests_for_rooting();
+    gjs_test_add_tests_for_jsapi_utils();
 
     g_test_run();
 
diff --git a/test/meson.build b/test/meson.build
index 0e1c5593..b322bc7c 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -13,6 +13,7 @@ gjs_tests_sources = [
     'gjs-test-call-args.cpp',
     'gjs-test-coverage.cpp',
     'gjs-test-rooting.cpp',
+    'gjs-test-jsapi-utils.cpp',
     'gjs-test-no-introspection-object.cpp', 'gjs-test-no-introspection-object.h',
 ]
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]