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.
205 lines
7.6 KiB
Swift
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")
|
|
}
|
|
}
|