74 lines
3.6 KiB
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 `regression/tier<N>/*.swift`
|
|
// (plus `regression/tier1/SmokeTests.swift`) into the SmokeTests target before
|
|
// running `swift test`. Only installed for tier >= 5 (Gtk's module).
|
|
|
|
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)
|
|
}
|
|
}
|