Skip to content

Commit

Permalink
chore(node-uniffi): Add minimal test case in Kotlin and Swift (#535)
Browse files Browse the repository at this point in the history
Co-authored-by: zvolin <[email protected]>
  • Loading branch information
oblique and zvolin authored Feb 25, 2025
1 parent 9c39050 commit b98e80a
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 1 deletion.
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,30 @@ jobs:
run: cargo test --all-features -p ${{ matrix.crate }}


test-bindings:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
bindings:
- name: uniffi-kotlin
run: ./node-uniffi/tests/kotlin/run.sh
- name: uniffi-swift
run: ./node-uniffi/tests/swift/run.sh

steps:
- uses: actions/checkout@v4

- name: Setup toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache-key: ${{ matrix.crate.name }}

- name: Run ${{ matrix.bindings.name }} tests
run: ${{ matrix.bindings.run }}


test-wasm:
runs-on: ubuntu-latest

Expand Down Expand Up @@ -215,6 +239,7 @@ jobs:
- clippy
- test
- test-wasm
- test-bindings
- build-wasm
- fmt
- docs
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
target

/.env
/.ccls-cache
8 changes: 8 additions & 0 deletions node-uniffi/tests/kotlin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Ignore Gradle project-specific cache directory
.gradle

# Ignore Gradle build output directory
build

/lib/src/main/kotlin/uniffi
/lib/src/main/resources/*.so
9 changes: 9 additions & 0 deletions node-uniffi/tests/kotlin/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[libraries]
jna = { module = "net.java.dev.jna:jna", version = "5.16.0" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version = "2.1.10" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.10.1" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version = "1.10.1" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.8.0" }

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version = "2.0.0" }
32 changes: 32 additions & 0 deletions node-uniffi/tests/kotlin/lib/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
plugins {
alias(libs.plugins.kotlin.jvm)
}

repositories {
mavenCentral()
}

dependencies {
implementation(libs.jna)
implementation(libs.kotlinx.coroutines)
testImplementation(libs.kotlin.test)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.kotlinx.serialization.json)
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

tasks.named<Test>("test") {
useJUnitPlatform()
}

tasks.withType<Test> {
testLogging {
showStandardStreams = true
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package uniffi.lumina_node_uniffi

import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.*
import kotlin.test.Test
import kotlin.test.assertEquals
import uniffi.lumina_node_uniffi.*
import uniffi.lumina_node.*

class LibraryTest {
@Test
fun testRequestHeader() = runTest {
var config = NodeConfig(null, Network.Mainnet, null, null, null, null, null)
var node = LuminaNode(config)

node.start()
node.waitConnectedTrusted()

var headStr = node.requestHeadHeader()
var head: JsonObject = Json.decodeFromString<JsonObject>(headStr)
var headHeader = head.get("header")!!.jsonObject
var headHeight = headHeader.get("height")!!.jsonPrimitive.content.toULong()

var prevStr = node.requestHeaderByHeight(headHeight - 1.toULong())
var prev: JsonObject = Json.decodeFromString<JsonObject>(prevStr)
var prevHash = prev.get("commit")!!.jsonObject.get("block_id")!!.jsonObject.get("hash")!!

var expectedPrevHash = headHeader.get("last_block_id")!!.jsonObject.get("hash")!!
assertEquals(prevHash, expectedPrevHash)
}
}
37 changes: 37 additions & 0 deletions node-uniffi/tests/kotlin/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -xeuo pipefail

cd -- "$(dirname -- "${BASH_SOURCE[0]}")"

cd ../../
cargo build

rm -rf ../target/kotlin-uniffi-bindings
mkdir -p ../target/kotlin-uniffi-bindings

cargo run --bin uniffi-bindgen generate --library ../target/debug/liblumina_node_uniffi.so --language kotlin --out-dir ../target/kotlin-uniffi-bindings

cd tests/kotlin

rm -rf lib/src/main/kotlin/uniffi
rm -rf lib/src/main/resources/*.so

mkdir -p lib/src/main/kotlin
mkdir -p lib/src/main/resources

cp ../../../target/debug/liblumina_node_uniffi.so lib/src/main/resources
cp -r ../../../target/kotlin-uniffi-bindings/uniffi lib/src/main/kotlin

# if user doesn't belong to docker group, run docker with sudo
SUDO=""
if ! id -nG | grep -q docker; then
SUDO=sudo
fi

$SUDO docker run \
--rm \
--user "$(id -u):$(id -g)" \
--volume "$PWD":/app \
--workdir /app \
gradle:8.12-jdk8 \
gradle test
14 changes: 14 additions & 0 deletions node-uniffi/tests/kotlin/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.10.2/userguide/multi_project_builds.html in the Gradle documentation.
*/

plugins {
// Apply the foojay-resolver plugin to allow automatic download of JDKs
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}

rootProject.name = "co.eiger.luminaNode"
include("lib")
11 changes: 11 additions & 0 deletions node-uniffi/tests/swift/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
/Sources/LuminaNode
/Sources/LuminaNodeHeaders
/lib
30 changes: 30 additions & 0 deletions node-uniffi/tests/swift/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// swift-tools-version: 5.10
import PackageDescription

let package = Package(
name: "LuminaNode",
platforms: [
.macOS(.v14)
],
products: [
.library(
name: "LuminaNode",
targets: ["LuminaNode"]),
],
targets: [
.target(
name: "LuminaNodeHeaders",
publicHeadersPath: "."),
.target(
name: "LuminaNode",
dependencies: ["LuminaNodeHeaders"],
linkerSettings: [
.linkedFramework("SystemConfiguration"),
.linkedLibrary("lumina_node_uniffi"),
.unsafeFlags(["-L", "./lib"])
]),
.testTarget(
name: "LuminaNodeTests",
dependencies: ["LuminaNode"]),
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import XCTest
@testable import LuminaNode

final class LuminaNodeTests: XCTestCase {
func testRequestHeader() async throws {
let config = NodeConfig(basePath: nil, network: .mainnet, bootnodes: nil,
syncingWindowSecs: nil, pruningDelaySecs: nil,
batchSize: nil, ed25519SecretKeyBytes: nil)
let node = try LuminaNode(config: config)

let _ = try await node.start()
try await node.waitConnectedTrusted()

let headStr = try await node.requestHeadHeader()
let headData = headStr.data(using: .utf8)!;
let head = try JSONSerialization.jsonObject(with: headData) as! [String: Any]
let headHeader = head["header"] as! [String: Any]
let headHeight = UInt64(headHeader["height"] as! String)!

let prevStr = try await node.requestHeaderByHeight(height: headHeight - 1)
let prevData = prevStr.data(using: .utf8)!;
let prev = try JSONSerialization.jsonObject(with: prevData) as! [String: Any]
let prevHash = ((prev["commit"] as! [String: Any])["block_id"] as! [String: Any])["hash"] as! String

let expectedPrevHash = (headHeader["last_block_id"] as! [String: Any])["hash"] as! String
XCTAssertEqual(prevHash, expectedPrevHash)
}
}
48 changes: 48 additions & 0 deletions node-uniffi/tests/swift/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
set -xeuo pipefail

cd -- "$(dirname -- "${BASH_SOURCE[0]}")"

cd ../../
cargo build

rm -rf ../target/swift-uniffi-bindings
mkdir -p ../target/swift-uniffi-bindings

cargo run --bin uniffi-bindgen generate --library ../target/debug/liblumina_node_uniffi.a --language swift --out-dir ../target/swift-uniffi-bindings

cd tests/swift

rm -rf lib
rm -rf Sources/LuminaNodeHeaders
rm -rf Sources/LuminaNode

mkdir lib
mkdir -p Sources/LuminaNodeHeaders
mkdir -p Sources/LuminaNode

cp ../../../target/debug/liblumina_node_uniffi.a lib
cp ../../../target/swift-uniffi-bindings/*.swift Sources/LuminaNode
cp ../../../target/swift-uniffi-bindings/*.h Sources/LuminaNodeHeaders
cat ../../../target/swift-uniffi-bindings/*.modulemap > Sources/LuminaNodeHeaders/module.modulemap

if [ -n "${CI:-}" ]; then
# On CI there is an issue with permissions as runner has non-standard user & group ids
user=0:0
else
user="$(id -u):$(id -g)"
fi

# if user doesn't belong to docker group, run docker with sudo
SUDO=""
if ! id -nG | grep -q docker; then
SUDO=sudo
fi

$SUDO docker run \
--rm \
--user "$user" \
--volume "$PWD":/app \
--workdir /app \
swift:6.0.3 \
swift test

0 comments on commit b98e80a

Please sign in to comment.