import Testing import GObjectGeneratorCore @Test("Namespace can hold types") func testNamespaceHoldsTypes() { let ns = Namespace(name: "Gtk", version: "4.0") #expect(ns.name == "Gtk") #expect(ns.version == "4.0") #expect(ns.classes.isEmpty) #expect(ns.interfaces.isEmpty) #expect(ns.enumerations.isEmpty) #expect(ns.records.isEmpty) } @Test("Class has properties and methods") func testClassHasProperties() { let cls = Class(name: "Widget", cType: "GtkWidget", parent: nil, isAbstract: false) #expect(cls.name == "Widget") #expect(cls.properties.isEmpty) #expect(cls.methods.isEmpty) #expect(cls.signals.isEmpty) } @Test("Method stores parameters and return type") func testMethodStoresParameters() { let param = Parameter(name: "label", type: .string, isNullable: false, transferOwnership: .none) let method = Method(name: "set_label", cIdentifier: "gtk_label_set_text", parameters: [param]) #expect(method.name == "set_label") #expect(method.parameters.count == 1) #expect(method.returnValue.type == .void) } @Test("Method carries return ownership and nullability") func testMethodCarriesReturnSemantics() { let method = Method( name: "get_name", cIdentifier: "gtk_widget_get_name", returnValue: ReturnValue(type: .string, isNullable: true, transferOwnership: .full) ) #expect(method.returnValue.type == .string) #expect(method.returnValue.isNullable) #expect(method.returnValue.transferOwnership == .full) #expect(!method.throwsGError) } @Test("Parameter defaults to in-direction with no callback scope") func testParameterDirectionDefaults() { let param = Parameter(name: "value", type: .int32) #expect(param.direction == .in) #expect(param.scope == nil) #expect(param.closureIndex == nil) #expect(!param.callerAllocates) } @Test("Parameter records out-direction and callback metadata") func testParameterRecordsOutAndCallbackMetadata() { let out = Parameter(name: "natural", type: .int32, direction: .out, callerAllocates: true) #expect(out.direction == .out) #expect(out.callerAllocates) let callback = Parameter( name: "callback", type: .typeRef("Callback"), scope: .notified, closureIndex: 1, destroyIndex: 2 ) #expect(callback.scope == .notified) #expect(callback.closureIndex == 1) #expect(callback.destroyIndex == 2) } @Test("Enumeration stores members") func testEnumerationStoresMembers() { let member = EnumMember(name: "GTK_ALIGN_FILL", value: "1", cIdentifier: "GTK_ALIGN_FILL") let enumeration = Enumeration(name: "GtkAlign", cType: "GtkAlign", members: [member]) #expect(enumeration.name == "GtkAlign") #expect(enumeration.members.count == 1) #expect(enumeration.members[0].value == "1") } @Test("Signal stores parameters and return type") func testSignalStoresParameters() { let signal = Signal(name: "clicked", parameters: [], isDetailed: false) #expect(signal.name == "clicked") #expect(signal.returnValue.type == .void) #expect(signal.isDetailed == false) } @Test("Property stores type and flags") func testPropertyStoresTypeAndFlags() { let prop = Property(name: "label", type: .string, isReadable: true, isWritable: true, isConstructOnly: false) #expect(prop.name == "label") #expect(prop.type == .string) #expect(prop.isReadable == true) #expect(prop.isWritable == true) } @Test("Repository holds multiple namespaces") func testRepositoryHoldsMultipleNamespaces() { let gtk = Namespace(name: "Gtk", version: "4.0") let gdk = Namespace(name: "Gdk", version: "4.0") let repo = Repository(namespaces: [gtk, gdk]) #expect(repo.namespaces.count == 2) #expect(repo.namespaces[0].name == "Gtk") #expect(repo.namespaces[1].name == "Gdk") } @Test("GIRType equality works") func testGIRTypeEquality() { #expect(GIRType.void == GIRType.void) #expect(GIRType.string == GIRType.string) #expect(GIRType.typeRef("GtkWidget") == GIRType.typeRef("GtkWidget")) #expect(GIRType.typeRef("GtkWidget") != GIRType.typeRef("GtkLabel")) #expect(GIRType.cArray(.string) == GIRType.cArray(.string)) #expect(GIRType.cArray(.string) != GIRType.cArray(.int32)) #expect(GIRType.optional(.string) == GIRType.optional(.string)) #expect(GIRType.optional(.string) != GIRType.string) #expect(GIRType.container(.list, elements: [.string]) == GIRType.container(.list, elements: [.string])) #expect(GIRType.container(.list, elements: [.string]) != GIRType.container(.slist, elements: [.string])) } @Test("Array length metadata distinguishes bridgeable arrays") func testArrayInfoKnownLength() { #expect(!ArrayInfo().hasKnownLength) #expect(ArrayInfo(lengthParameterIndex: 1).hasKnownLength) #expect(ArrayInfo(fixedSize: 4).hasKnownLength) #expect(ArrayInfo(isZeroTerminated: true).hasKnownLength) // Length metadata participates in type identity: two arrays of the same // element type but different lengths are not interchangeable. #expect(GIRType.cArray(.string, ArrayInfo(lengthParameterIndex: 1)) != GIRType.cArray(.string, ArrayInfo(isZeroTerminated: true))) } @Test("SymbolInfo gates binding on introspectability and shadowing") func testSymbolInfoBindability() { #expect(SymbolInfo().isBindable) #expect(!SymbolInfo(isIntrospectable: false).isBindable) #expect(!SymbolInfo(shadowedBy: "g_object_set_valist").isBindable) #expect(!SymbolInfo(movedTo: "Gtk.Widget.newer").isBindable) // Deprecation alone does not make a symbol unbindable. #expect(SymbolInfo(isDeprecated: true).isBindable) } @Test("Record boxedness follows GType registration") func testRecordBoxedness() { let boxed = Record(name: "RGBA", cType: "GdkRGBA", getTypeFunction: "gdk_rgba_get_type") #expect(boxed.isBoxed) let plain = Record(name: "Bogus", cType: "GBogus") #expect(!plain.isBoxed) let typeStruct = Record(name: "WidgetClass", cType: "GtkWidgetClass", isGTypeStructFor: "Widget") #expect(typeStruct.isGTypeStructFor == "Widget") } @Test("Interface stores methods, properties, signals, and prereqs") func testInterfaceStoresMembers() { let iface = Interface(name: "GtkBuildable", cType: "GtkBuildable", prereqs: ["GtkWidget"]) #expect(iface.name == "GtkBuildable") #expect(iface.prereqs.count == 1) }