Add Swift FFI executable smoke

This commit is contained in:
Mikhail Kilin
2026-05-21 00:12:08 +03:00
parent 5ac63b84fb
commit 9b4e277ce0
3 changed files with 102 additions and 0 deletions

View File

@@ -21,6 +21,8 @@ jobs:
run: cargo test --workspace --all-features
- name: Fake iOS FFI tests
run: cargo test -p tele-ios-ffi --no-default-features --features standalone-fake
- name: Swift FFI smoke
run: scripts/smoke-ios-ffi-swift.sh /tmp/tele-ios-ffi-swift-smoke
- name: Generate iOS FFI bindings
run: scripts/generate-ios-ffi-bindings.sh /tmp/tele-ios-ffi
- name: Swift bindings typecheck

View File

@@ -24,6 +24,12 @@ Build the fake-only iOS simulator XCFramework without linking TDLib:
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer scripts/build-ios-fake-ffi-xcframework.sh
```
Run an executable Swift smoke test against matching fake-only UniFFI bindings:
```bash
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer scripts/smoke-ios-ffi-swift.sh
```
Current linking status:
- Xcode is installed at `/Applications/Xcode.app`, and `DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcodebuild -version` reports Xcode 26.5.

94
scripts/smoke-ios-ffi-swift.sh Executable file
View File

@@ -0,0 +1,94 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
out_dir="${1:-/private/tmp/tele-ios-ffi-swift-smoke}"
lib_path="${repo_root}/target/release/libtele_ios_ffi.a"
if [[ -z "${DEVELOPER_DIR:-}" && -d /Applications/Xcode.app/Contents/Developer ]]; then
export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
fi
cd "${repo_root}"
case "${out_dir}" in
"" | "/" | "/tmp" | "/private" | "/private/tmp")
printf 'Refusing unsafe output directory: %s\n' "${out_dir}" >&2
exit 2
;;
esac
cargo build \
-p tele-ios-ffi \
--no-default-features \
--features standalone-fake \
--release
rm -rf "${out_dir}"
mkdir -p "${out_dir}/Swift" "${out_dir}/Headers"
cargo run -p uniffi-bindgen-swift -- "${lib_path}" "${out_dir}/Swift" --swift-sources
cargo run -p uniffi-bindgen-swift -- "${lib_path}" "${out_dir}/Headers" --headers
cargo run -p uniffi-bindgen-swift -- "${lib_path}" "${out_dir}/Headers" \
--modulemap \
--module-name tele_ios_ffiFFI \
--modulemap-filename module.modulemap
cat > "${out_dir}/Smoke.swift" <<'SWIFT'
import Foundation
@main
struct Smoke {
static func main() throws {
func require(_ condition: @autoclosure () -> Bool, _ message: String) {
if !condition() {
fatalError(message)
}
}
let session = try createSession(config: IosSessionConfig(
accountId: "fake",
displayName: "Fake",
databasePath: "/tmp/tele-ios-ffi-swift-smoke-db",
useFakeTdlib: true
))
let chats = try session.loadChats(limit: 20)
require(chats.count == 1, "expected one fake chat")
let chat = chats[0]
let history = try session.loadHistory(chatId: chat.id, limit: 20)
require(history.first?.text == "Hello from fake TDLib", "expected seeded history")
let sent = try session.sendMessage(chatId: chat.id, text: "Hi from Swift FFI", replyToMessageId: nil)
require(sent.text == "Hi from Swift FFI", "expected sent message text")
let copiedText = try session.copyPayload(chatId: chat.id, messageId: sent.id)
require(copiedText == "Hi from Swift FFI", "expected copy payload")
let reactions = try session.react(chatId: chat.id, messageId: sent.id, reaction: "+1")
require(reactions.first?.emoji == "+1", "expected reaction")
let results = try session.searchMessages(chatId: chat.id, query: "Swift FFI")
require(results.count == 1, "expected search result")
session.simulateIncomingMessage(chatId: chat.id, text: "Incoming from Swift smoke", senderName: "Bob")
let events = session.pollEvents()
require(events.contains { if case .messageAdded = $0 { return true }; return false }, "expected messageAdded event")
require(events.contains { if case .incomingNotificationCandidate = $0 { return true }; return false }, "expected notification candidate")
print("tele-ios-ffi Swift smoke passed")
}
}
SWIFT
swiftc \
-parse-as-library \
-module-cache-path "${out_dir}/module-cache" \
-I "${out_dir}/Headers" \
"${out_dir}/Swift/tele_ios_ffi.swift" \
"${out_dir}/Smoke.swift" \
"${lib_path}" \
-o "${out_dir}/smoke"
"${out_dir}/smoke"