Skip to content

Commit

Permalink
Added Tests For RPC
Browse files Browse the repository at this point in the history
  • Loading branch information
alvinosh committed Sep 16, 2024
1 parent a7bbd64 commit 35a4439
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 1 deletion.
3 changes: 2 additions & 1 deletion rpc_example/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/jniLibs
/bindings
/bindings
/kotlin
140 changes: 140 additions & 0 deletions rpc_example/scripts/build_kotlin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import os
import platform
import subprocess
import shutil
import sys
import time


# Constants
KOTLINC = "kotlinc.bat"
CLASSPATH = os.getenv('CLASSPATH', './rpc_example/kotlin/vendor/jna.jar;./rpc_example/kotlin/vendor/kotlinx-coroutines.jar') # Fetch CLASSPATH from the environment
LIB_NAME = "rpc_example"
TARGET_DIR = "./target/release"
KOTLIN_OUT_DIR = "./rpc_example/kotlin"

def run_command(command, print_only=False):
"""Run a command in the shell."""
print(f"[COMMAND] {' '.join(command)}")
if print_only:
return

return subprocess.run(command, shell=True)

def get_lib_extension():
"""Determine the correct library extension based on the operating system."""
current_os = platform.system().lower()
if current_os == "darwin":
return "dylib"
elif current_os == "linux":
return "so"
elif current_os == "windows":
return "dll"
else:
sys.exit("Unknown OS. Supported OS: mac, linux, windows.")

def build_library():
"""Build the Rust library using cargo."""
print("[INFO] Building library...")

result = run_command(["cargo", "build", "-p", "rpc_example", "--release"])
if result.returncode != 0:
sys.exit("Failed to build library")

def generate_binding(lib_extension):
"""Generate Kotlin bindings using UniFFI."""
print("[INFO] Generating Kotlin binding...")
kotlin_lib_path = os.path.join(KOTLIN_OUT_DIR, LIB_NAME)
if os.path.exists(kotlin_lib_path):
shutil.rmtree(kotlin_lib_path)

run_command(["cargo", "run", "-p", "rpc_example", "--features=uniffi/cli", "--bin", "uniffi-bindgen", "generate",
"--library", f"{TARGET_DIR}/{LIB_NAME}.{lib_extension}",
"--language", "kotlin", "--out-dir", KOTLIN_OUT_DIR])


def copy_cdylib(lib_extension):
"""Copy the built cdylib to the Kotlin output directory."""
print("[INFO] Copying cdylib to output directory...")
src = f"{TARGET_DIR}/{LIB_NAME}.{lib_extension}"
dest = f"{KOTLIN_OUT_DIR}/{LIB_NAME}.{lib_extension}"

print(f"[COMMAND] cp {src} {dest}")
shutil.copy(src, dest)

def build_jar():
"""Compile Kotlin files into a JAR."""
print("[INFO] Building Kotlin JAR...")
jar_file = f"{KOTLIN_OUT_DIR}/rpc_example.jar"
if os.path.exists(jar_file):
os.remove(jar_file)

run_command(
[KOTLINC, "-Werror", "-d", jar_file, f"{KOTLIN_OUT_DIR}/uniffi/rpc_example/rpc_example.kt","-classpath",f'"{CLASSPATH}"'], True)

def run_tests():
"""Run Kotlin script tests."""
print("[INFO] Executing tests...")
test_names = ["blocking"]
for test_name in test_names:
print(f"[INFO] Running {test_name}_test.kts ...")
run_command(
[KOTLINC, "-Werror", "-J-ea", "-classpath",
f'"{CLASSPATH};{KOTLIN_OUT_DIR}/rpc_example.jar;{KOTLIN_OUT_DIR}"',
"-script", f"./rpc_example/tests/{test_name}_test.kts"],
True
)

def dependencies():
vendor_folder = f"{KOTLIN_OUT_DIR}/vendor"

if not os.path.exists(vendor_folder):
os.makedirs(vendor_folder)

# download jna.jar if it doesn't exist


jna_url = "https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.14.0/jna-5.14.0.jar"
jna_file = f"{vendor_folder}/jna.jar"
if os.path.exists(jna_file):
print(f"[INFO] JNA already exists at {jna_file}")
else:
run_command(["curl", "-L", jna_url, "-o", jna_file])

# download kotlinx-coroutines.jar
kotlinx_coroutines_url = "https://repo1.maven.org/maven2/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.6.4/kotlinx-coroutines-core-jvm-1.6.4.jar"
kotlinx_coroutines_file = f"{vendor_folder}/kotlinx-coroutines.jar"
if os.path.exists(kotlinx_coroutines_file):
print(f"[INFO] kotlinx-coroutines already exists at {kotlinx_coroutines_file}")
else:
run_command(["curl", "-L", kotlinx_coroutines_url, "-o", kotlinx_coroutines_file])


def main():
lib_extension = get_lib_extension()

# Build library
build_library()

# Generate Kotlin bindings
generate_binding(lib_extension)

# Copy cdylib
copy_cdylib(lib_extension)

# Get 3rd party dependencies
dependencies();

# Build the Kotlin jar
build_jar()

# # Execute Kotlin tests
run_tests()

if __name__ == "__main__":
try:
main()
except subprocess.CalledProcessError as e:
sys.exit(f"[ERROR] Command failed: {e}")
except Exception as e:
sys.exit(f"[ERROR] An error occurred: {e}")
15 changes: 15 additions & 0 deletions rpc_example/tests/blocking_test.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import uniffi.*

kotlinx.coroutines.runBlocking {
// function factorial does not exist
var factorial = uniffi.rpc_example.call("factorial", listOf("10"))
assert(factorial == "{\"result\": null, \"error\": \"NOT_FOUND: Unknown function\", \"is_success\": false}")

// testing single argument function
var add = uniffi.rpc_example.call("add", listOf("10", "20"))
assert(add == "{\"result\":30,\"error\":null,\"is_success\":true}")

// testing multiple argument function
var add_array = uniffi.rpc_example.call("add_array", listOf("10", "[1,2,3,4,5,6]"))
assert(add_array == "{\"result\":31,\"error\":null,\"is_success\":true}")
}

0 comments on commit 35a4439

Please sign in to comment.