summary refs log tree commit diff
path: root/src/libnm-client-impl/tests
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2022-11-18 17:48:09 +0100
committerMichael Biebl <biebl@debian.org>2022-11-18 17:48:09 +0100
commit913bcb40f6c699f8a38351c69e7ea263fe78f71f (patch)
tree79508469b79e31338d898459da15070e2a62b049 /src/libnm-client-impl/tests
parent9f101839d9e64df832e9e43c5181887369c46a7e (diff)
New upstream version 1.40.4 upstream/1.40.4
Diffstat (limited to 'src/libnm-client-impl/tests')
-rw-r--r--src/libnm-client-impl/tests/meson.build12
-rwxr-xr-xsrc/libnm-client-impl/tests/test-gir.py153
2 files changed, 165 insertions, 0 deletions
diff --git a/src/libnm-client-impl/tests/meson.build b/src/libnm-client-impl/tests/meson.build
index 3f2e78a7..0c0e188b 100644
--- a/src/libnm-client-impl/tests/meson.build
+++ b/src/libnm-client-impl/tests/meson.build
@@ -44,3 +44,15 @@ foreach test_unit: test_units
     args: test_args + [exe.full_path()],
   )
 endforeach
+
+if enable_introspection
+  test(
+    'check-local-libnm-gir',
+    python,
+    args: [
+      join_paths(meson.source_root(), 'src', 'libnm-client-impl', 'tests', 'test-gir.py'),
+      '--gir', libnm_gir[0],
+      '--ver', join_paths(meson.source_root(), 'src', 'libnm-client-impl', 'libnm.ver'),
+    ],
+  )
+endif
diff --git a/src/libnm-client-impl/tests/test-gir.py b/src/libnm-client-impl/tests/test-gir.py
new file mode 100755
index 00000000..d91849b8
--- /dev/null
+++ b/src/libnm-client-impl/tests/test-gir.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Copyright (C) 2022 Red Hat, Inc.
+#
+
+from __future__ import print_function
+import xml.etree.ElementTree as ET
+import argparse
+import sys
+
+C_NS = "http://www.gtk.org/introspection/c/1.0"
+CORE_NS = "http://www.gtk.org/introspection/core/1.0"
+GLIB_NS = "http://www.gtk.org/introspection/glib/1.0"
+
+
+def syms_from_gir(girfile):
+    def xml_symbols(xml, types):
+        ret = []
+        for t in types:
+            ret += xml.findall("./{%s}namespace/{%s}%s" % (CORE_NS, CORE_NS, t))
+            ret += xml.findall("./{%s}namespace/*/{%s}%s" % (CORE_NS, CORE_NS, t))
+        return ret
+
+    girxml = ET.parse(girfile)
+    c_syms = {}
+    for sym in xml_symbols(girxml, ("constructor", "function", "method")):
+        c_syms[sym.get("{%s}identifier" % C_NS)] = sym.get("version")
+
+    for sym in xml_symbols(
+        girxml, ("bitfield", "class", "enumeration", "interface", "record")
+    ):
+        get_type = sym.get("{%s}get-type" % GLIB_NS)
+        if get_type is None:
+            continue
+        version = sym.get("version")
+
+        if version is None:
+            # FIXME: The get_type() functions should be exported in the same
+            # version the type itself appeared. However, a large number of
+            # classes lack Since: tags in their doc blocks. Fall back to using
+            # the tag on _new() method for the test to be able to proceed
+            # reasonably. This should be fixed eventually.
+            constructor = sym.find("./{%s}constructor" % CORE_NS)
+            if constructor is not None:
+                version = constructor.get("version")
+
+        c_syms[get_type] = version
+    return c_syms
+
+
+# Older Python doesn't have str.removesuffix()
+def str_removesuffix(string, suffix):
+    try:
+        return string.removesuffix(suffix)
+    except AttributeError:
+        if string.endswith(suffix):
+            return string[: -len(suffix)]
+        else:
+            return string
+
+
+# Older Python doesn't have str.removeprefix()
+def str_removeprefix(string, prefix):
+    try:
+        return string.removeprefix(prefix)
+    except AttributeError:
+        if string.startswith(prefix):
+            return string[len(prefix) :]
+        else:
+            return string
+
+
+def syms_from_ver(verfile):
+    c_syms = {}
+    for line in open(verfile).readlines():
+        line = line.strip()
+
+        if line.endswith("{"):
+            line = str_removesuffix(line, " {")
+            line = str_removeprefix(line, "libnm_")
+            (major, minor, micro) = line.split("_")
+            if int(major) > 1 or int(minor) > 0:
+                if int(micro) > 0:
+                    # Snap to next major version. Perhaps not
+                    # exactly correct, but good for all symbols
+                    # we export but nm_ethtool_optname_is_feature().
+                    minor = str(int(minor) + 2)
+                version = major + "." + minor
+            else:
+                version = None
+        elif (
+            line.endswith(";")
+            and not line.startswith("}")
+            and not line.startswith("#")
+            and not line == "*;"
+        ):
+            c_syms[str_removesuffix(line, ";")] = version
+
+    # This one is... messy.
+    c_syms["nm_ethtool_optname_is_feature"] = "1.20"
+
+    return c_syms
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument(
+    "--gir",
+    metavar="FILE",
+    help="NM-1.0.gir file",
+    required=True,
+)
+parser.add_argument(
+    "--ver",
+    metavar="FILE",
+    help="libnm.ver file",
+    required=True,
+)
+
+args = parser.parse_args()
+
+gir_syms = syms_from_gir(args.gir)
+ver_syms = syms_from_ver(args.ver)
+
+exit_code = 0
+
+for (gir_sym, gir_ver) in gir_syms.items():
+    if gir_sym not in ver_syms:
+        exit_code = 1
+        print(
+            'FAIL: "%s" found in "%s", but is not exported. Needs adding to "%s"?'
+            % (gir_sym, args.gir, args.ver),
+            file=sys.stderr,
+        )
+        continue
+    if gir_ver != ver_syms[gir_sym]:
+        exit_code = 1
+        print(
+            'FAIL: "%s" exported in version "%s" but documented as available since "%s"'
+            % (gir_sym, ver_syms[gir_sym], gir_ver),
+            file=sys.stderr,
+        )
+
+# In python2, dict.keys() returns lists, not sets. Cast them.
+for sym in set(ver_syms.keys()) - set(gir_syms.keys()):
+    exit_code = 1
+    print(
+        'FAIL: "%s" found in "%s", but not in "%s". Maybe the doc comment is wrong or g-ir-scanner messed up?'
+        % (sym, args.ver, args.gir),
+        file=sys.stderr,
+    )
+
+sys.exit(exit_code)