1
0
Fork 0
gobject-generator/regression/tier5/GtkSmoke.swift

74 lines
3.6 KiB
Swift

// GtkSmoke.swift
// Tier-5-only runtime smoke test for Gtk (Phase E4). Proves against the
// REAL libgtk-4, linked at runtime that the generated bindings reach real
// GTK C symbols and that the no-unsafe-pointer public API policy still
// produces a fully usable, pointer-free surface.
//
// Both cases are deliberately display-free (no `gtk_init`, no
// `realize()`/`present()`, no display/backend connection):
// 1. `getMajorVersion()`/`getMinorVersion()` are plain free-function calls
// into `gtk_get_major_version`/`gtk_get_minor_version` guaranteed
// display-free, proves Gtk links and the friendly public API is
// callable.
// 2. `Adjustment(value:lower:upper:stepIncrement:pageIncrement:pageSize:)`
// reaches the real `gtk_adjustment_new` C constructor and adopts the
// returned pointer through `init(takingOwnership:)`. `GtkAdjustment` is
// a plain GObject (not a widget no realize/display dependency) with a
// value round-trip through `getValue()`/`setValue(value:)`. Every call
// in this test uses ONLY plain-public API no `@_spi` import which
// is itself part of the proof that the pointer-free surface is complete
// enough for real, non-toy usage.
//
// Not generated. `scripts/smoke-test.sh <tier>` copies tier 1 and the selected
// tier's fixtures for tiers 2 through 5. Tier 6/all copies every tier's fixtures
// into one full-stack SmokeTests target. Only installed for tier >= 5.
import Testing
import GLib
import GObject
import Gtk
@Suite("Tier 5 Gtk smoke tests")
struct GtkSmokeTests {
@Test("getMajorVersion()/getMinorVersion() reach the real gtk_get_major_version/gtk_get_minor_version and report GTK 4")
func versionFunctionsReachRealGtk() throws {
#expect(getMajorVersion() == 4)
// GTK 4's minor version is a real, non-placeholder value reported by
// the linked library, not a stubbed default.
#expect(getMinorVersion() >= 0)
}
@Test("Adjustment(...) reaches the real gtk_adjustment_new and constructs a live, display-free GObject")
func adjustmentConstructsAndRoundTrips() throws {
let adjustment = Adjustment(value: 5, lower: 0, upper: 10, stepIncrement: 1, pageIncrement: 2, pageSize: 0)
#expect(adjustment.getValue() == 5)
#expect(adjustment.getLower() == 0)
#expect(adjustment.getUpper() == 10)
// Property computed-var path (GValue-free delegates to the real
// getter/setter methods above) round-trips through the real C call.
adjustment.value = 7
#expect(adjustment.value == 7)
#expect(adjustment.getValue() == 7)
}
@Test("A transfer-full object parameter keeps the Swift wrapper's reference balanced")
func transferFullParameterDoesNotOverRelease() throws {
// `gtk_shortcut_set_action` is annotated `(transfer full)`: it consumes
// one reference. The generated binding must add one before the call, or
// the `NamedAction` wrapper's `deinit` releases a reference it no longer
// owns, GTK finalizes the action while the shortcut still points at it,
// and reading it back trips `g_object_unref: assertion 'G_IS_OBJECT
// (object)' failed` plus a use-after-free.
let shortcut = Shortcut(trigger: nil, action: nil)
do {
let action = NamedAction(name: "app.quit")
shortcut.setAction(action: action)
}
// The wrapper is gone; the action must still be alive inside `shortcut`.
let stored = shortcut.getAction()
#expect(stored != nil)
#expect(stored?.toString().contains("app.quit") == true)
}
}