1
0
Fork 0
gobject-generator/Tests/SwiftGtkGenCoreTests/ParserTests.swift
Brendan Szymanski 1330f2bd25 Initial commit: SwiftGtkGen GIR-to-Swift binding generator
Extracted from gtk-swift monorepo. Previous history
contains 38 commits across the full Phase 1 development
including GIR XML parsing, IR model, analysis engine,
code generation, CLI, plugins, and documentation.
2026-07-01 03:27:41 -04:00

205 lines
7.6 KiB
Swift

import Testing
import Foundation
@testable import SwiftGtkGenCore
@Test("Parser reads namespace from minimal GIR XML")
func testParsesNamespace() throws {
let xml = """
<?xml version="1.0"?>
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<namespace name="GLib" version="2.0" shared-library="libglib-2.0.so.0"
c:identifier-prefixes="g" c:symbol-prefixes="g"/>
</repository>
"""
let parser = GIRParser()
let repo = try parser.parse(xmlString: xml)
#expect(repo.namespaces.count == 1)
#expect(repo.namespaces[0].name == "GLib")
#expect(repo.namespaces[0].version == "2.0")
}
@Test("Parser reads a class with method and property")
func testParsesClass() throws {
let xml = """
<?xml version="1.0"?>
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<namespace name="Gtk" version="4.0">
<class name="Widget" c:type="GtkWidget" parent="GObject.Object"
glib:type-name="GtkWidget" glib:get-type="gtk_widget_get_type">
<method name="show" c:identifier="gtk_widget_show">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<instance-parameter name="widget" transfer-ownership="none">
<type name="Widget" c:type="GtkWidget*"/>
</instance-parameter>
</parameters>
</method>
<property name="name" writable="1" transfer-ownership="none">
<type name="utf8" c:type="gchar*"/>
</property>
</class>
</namespace>
</repository>
"""
let parser = GIRParser()
let repo = try parser.parse(xmlString: xml)
let cls = repo.namespaces[0].classes[0]
#expect(cls.name == "Widget")
#expect(cls.parent == "GObject.Object")
#expect(cls.methods.count == 1)
#expect(cls.methods[0].name == "show")
#expect(cls.properties.count == 1)
#expect(cls.properties[0].name == "name")
}
@Test("Parser reads an enumeration with members")
func testParsesEnumeration() throws {
let xml = """
<?xml version="1.0"?>
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<namespace name="Gtk" version="4.0">
<enumeration name="Align" glib:type-name="GtkAlign"
glib:get-type="gtk_align_get_type" c:type="GtkAlign">
<member name="fill" value="0" c:identifier="GTK_ALIGN_FILL"/>
<member name="start" value="1" c:identifier="GTK_ALIGN_START"/>
<member name="end" value="2" c:identifier="GTK_ALIGN_END"/>
<member name="center" value="3" c:identifier="GTK_ALIGN_CENTER"/>
</enumeration>
</namespace>
</repository>
"""
let parser = GIRParser()
let repo = try parser.parse(xmlString: xml)
let enums = repo.namespaces[0].enumerations
#expect(enums.count == 1)
#expect(enums[0].name == "Align")
#expect(enums[0].members.count == 4)
#expect(enums[0].members[0].name == "fill")
#expect(enums[0].members[3].cIdentifier == "GTK_ALIGN_CENTER")
}
@Test("Parser reads bitfield with members")
func testParsesBitfield() throws {
let xml = """
<?xml version="1.0"?>
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<namespace name="Gtk" version="4.0">
<bitfield name="SizeGroupMode" c:type="GtkSizeGroupMode"
glib:type-name="GtkSizeGroupMode" glib:get-type="gtk_size_group_mode_get_type">
<member name="none" value="0" c:identifier="GTK_SIZE_GROUP_MODE_NONE"/>
<member name="horizontal" value="1" c:identifier="GTK_SIZE_GROUP_MODE_HORIZONTAL"/>
<member name="vertical" value="2" c:identifier="GTK_SIZE_GROUP_MODE_VERTICAL"/>
<member name="both" value="3" c:identifier="GTK_SIZE_GROUP_MODE_BOTH"/>
</bitfield>
</namespace>
</repository>
"""
let parser = GIRParser()
let repo = try parser.parse(xmlString: xml)
let bf = repo.namespaces[0].bitfields[0]
#expect(bf.name == "SizeGroupMode")
#expect(bf.members.count == 4)
#expect(bf.members[0].name == "none")
#expect(bf.members[3].cIdentifier == "GTK_SIZE_GROUP_MODE_BOTH")
}
@Test("Parser reads interface with method")
func testParsesInterface() throws {
let xml = """
<?xml version="1.0"?>
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<namespace name="Gtk" version="4.0">
<interface name="Buildable" c:type="GtkBuildable">
<method name="buildable_get_id" c:identifier="gtk_buildable_get_id">
<return-value transfer-ownership="none">
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<instance-parameter name="buildable" transfer-ownership="none">
<type name="Buildable" c:type="GtkBuildable*"/>
</instance-parameter>
</parameters>
</method>
</interface>
</namespace>
</repository>
"""
let parser = GIRParser()
let repo = try parser.parse(xmlString: xml)
let iface = repo.namespaces[0].interfaces[0]
#expect(iface.name == "Buildable")
#expect(iface.methods.count == 1)
}
@Test("Parser reads global function")
func testParsesGlobalFunction() throws {
let xml = """
<?xml version="1.0"?>
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0"
xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
<namespace name="GLib" version="2.0">
<function name="getenv" c:identifier="g_getenv"
glib:type-name="GLib" glib:get-type="glib_get_type">
<return-value transfer-ownership="none">
<type name="utf8" c:type="gchar*"/>
</return-value>
<parameters>
<parameter name="variable" transfer-ownership="none">
<type name="utf8" c:type="gchar*"/>
</parameter>
</parameters>
</function>
</namespace>
</repository>
"""
let parser = GIRParser()
let repo = try parser.parse(xmlString: xml)
let fn = repo.namespaces[0].functions[0]
#expect(fn.name == "getenv")
#expect(fn.parameters.count == 1)
}
@Test("Parser throws error on missing required attributes")
func testParsingMissingAttributes() {
let xml = """
<?xml version="1.0"?>
<repository version="1.2"
xmlns="http://www.gtk.org/introspection/core/1.0"
xmlns:c="http://www.gtk.org/introspection/c/1.0">
<namespace name="Gtk" version="4.0">
<class c:type="GtkWidget" parent="GObject.Object"/>
</namespace>
</repository>
"""
let parser = GIRParser()
#expect(throws: GIRParserError.self) {
try parser.parse(xmlString: xml)
}
}
@Test("Parser rejects invalid XML")
func testParsingError() {
let parser = GIRParser()
#expect(throws: GIRParserError.self) {
try parser.parse(xmlString: "not xml")
}
}