mirror of
https://github.com/status-im/status-app.git
synced 2026-08-31 17:11:10 +00:00
The app ships --mm:orc while the test harness compiled --mm:refc, so gcOrc-gated regressions (the submodel use-after-free guards) skipped and lifetime behaviour under test didn't match production. Flip nim-test-run to --mm:orc and drop the now-redundant nim-test-run-orc split. Seven tests defined local QtObject helpers with the delete body ahead of new(result, delete); under ORC that synthesizes the implicit =destroy first and the finalizer can no longer bind. Reordered to the production idiom: forward-declare delete, constructor, body after.
76 lines
2.7 KiB
Nim
76 lines
2.7 KiB
Nim
## Unit tests for the seaqt-backed SingleInstance (app/global/single_instance).
|
|
## Exercises first/second-instance detection and the eventReceived forwarding path.
|
|
## Needs a QCoreApplication + processEvents pumping to deliver QLocalServer.newConnection.
|
|
|
|
import unittest, os
|
|
import nimqml
|
|
import app/global/single_instance
|
|
# Selective import: pulling all of gen_qcoreapplication would re-export the seaqt
|
|
# gen_qobject_types.QObject and make the nimqml QtObject macro below ambiguous.
|
|
from seaqt/qcoreapplication import QCoreApplication, create,
|
|
processEvents
|
|
|
|
# Minimal receiver to capture the forwarded event via a method-form connect.
|
|
QtObject:
|
|
type Catcher = ref object of QObject
|
|
received: string
|
|
count: int
|
|
|
|
proc delete(self: Catcher)
|
|
|
|
proc newCatcher(): Catcher =
|
|
new(result, delete)
|
|
result.QObject.setup
|
|
|
|
proc delete(self: Catcher) =
|
|
self.QObject.delete
|
|
|
|
proc onEvent*(self: Catcher, eventStr: string) {.slot.} =
|
|
self.received = eventStr
|
|
inc self.count
|
|
|
|
discard QCoreApplication.create() # one app for the whole suite
|
|
|
|
suite "SingleInstance":
|
|
|
|
test "first instance is the owner (not a second instance)":
|
|
let name = "si_test_first_" & $getCurrentProcessId()
|
|
let first = newSingleInstance(name, "")
|
|
check first.secondInstance() == false
|
|
|
|
test "a second instance with the same name is detected":
|
|
let name = "si_test_second_" & $getCurrentProcessId()
|
|
let first = newSingleInstance(name, "")
|
|
check first.secondInstance() == false
|
|
let second = newSingleInstance(name, "")
|
|
check second.secondInstance() == true
|
|
|
|
test "second instance forwards eventStr to the first via eventReceived":
|
|
let name = "si_test_event_" & $getCurrentProcessId()
|
|
let first = newSingleInstance(name, "")
|
|
let catcher = newCatcher()
|
|
discard QObject.connect(first, eventReceived, catcher, onEvent)
|
|
|
|
discard newSingleInstance(name, "status://open?x=1")
|
|
|
|
var spins = 0
|
|
while catcher.count == 0 and spins < 100:
|
|
QCoreApplication.processEvents()
|
|
sleep(5)
|
|
inc spins
|
|
|
|
check catcher.count == 1
|
|
check catcher.received == "status://open?x=1\n"
|
|
|
|
test "delete() tears down the server so a fresh instance can claim the socket again":
|
|
# Proves delete() releases the QLocalServer deterministically (reset -> ~QLocalServer
|
|
# closes/unlinks the socket). If it didn't, `revived` would either detect a second
|
|
# instance (old server still listening) or fail to listen on the in-use socket.
|
|
let name = "si_test_teardown_" & $getCurrentProcessId()
|
|
let first = newSingleInstance(name, "")
|
|
check first.secondInstance() == false
|
|
first.delete()
|
|
let revived = newSingleInstance(name, "")
|
|
check revived.secondInstance() == false
|
|
revived.delete()
|