actr-cli 0.3.1

Command line tool for Actor-RTC framework projects
Documentation
package {{PACKAGE_NAME}}

import android.content.Context
import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import echo.Echo.EchoRequest
import echo.Echo.EchoResponse
import io.actor_rtc.actr.PayloadType
import io.actor_rtc.actr.dsl.*
import java.io.File
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith

/**
 * {{PROJECT_NAME_PASCAL}} Echo Integration Test
 *
 * This test verifies the RPC call to the remote EchoService.
 * The EchoService server should be running remotely before executing this test.
 *
 * This test demonstrates using generated UnifiedWorkload from actr gen.
 */
@RunWith(AndroidJUnit4::class)
class EchoIntegrationTest {

    companion object {
        private const val TAG = "EchoIntegrationTest"
    }

    private fun getContext(): Context {
        return InstrumentationRegistry.getInstrumentation().targetContext
    }

    private fun copyAssetToInternalStorage(assetName: String): String {
        val context = getContext()
        val inputStream = context.assets.open(assetName)
        val outputFile = File(context.filesDir, assetName)
        outputFile.parentFile?.mkdirs()
        inputStream.use { input ->
            outputFile.outputStream().use { output -> input.copyTo(output) }
        }
        return outputFile.absolutePath
    }

    /**
     * Test RPC call to remote EchoService using generated client workload
     *
     * This test:
     * 1. Creates a UnifiedWorkload (generated by actr gen)
     * 2. UnifiedWorkload discovers the remote EchoService in onStart
     * 3. Sends an echo request via ActrRef.call()
     * 4. Verifies the response matches expected format
     *
     * Prerequisites:
     * - EchoService server must be running remotely
     * - Signaling server must be accessible
     */
    @Test
    fun testRpcCallToEchoServer(): Unit = runBlocking {
        Log.i(TAG, "=== Starting RPC Call Test (Client Only - Server is remote) ===")
        val configPath = copyAssetToInternalStorage("manifest.toml")
        // Also copy lock file - required by ActrNode
        copyAssetToInternalStorage("manifest.lock.toml")
        var clientRef: ActrRef? = null

        try {
            // Create ActrNode for client
            val clientSystem = createActrNode(configPath)

            val testMessage = "Hello from {{PROJECT_NAME_PASCAL}}!"
            val expectedResponse = "Echo: $testMessage"

            // === Start Client ===
            Log.i(TAG, "🚀 Starting EchoClient...")
            val clientWorkload = UnifiedWorkload()
            val clientNode = clientSystem.attach(clientWorkload)
            clientRef = clientNode.start()
            Log.i(TAG, "✅ Client started: ${clientRef.actorId().serialNumber}")

            // Wait for client to discover the remote server
            delay(3000)

            // Create EchoRequest using generated protobuf class
            val request = EchoRequest.newBuilder()
                .setMessage(testMessage)
                .build()

            // Send RPC via ActrRef.call() - this triggers the dispatch() method
            Log.i(TAG, "📞 Sending RPC via ActrRef.call()...")
            val responsePayload = clientRef.call(
                "echo.EchoService.Echo",
                PayloadType.RPC_RELIABLE,
                request.toByteArray(),
                30000L
            )

            // Parse response using generated protobuf class
            val response = EchoResponse.parseFrom(responsePayload)
            Log.i(TAG, "📬 Response: ${response.reply}")

            assertEquals("Echo mismatch", expectedResponse, response.reply)
            Log.i(TAG, "=== RPC Call Test PASSED ===")
        } finally {
            // Cleanup: stop client
            try {
                clientRef?.shutdown()
                clientRef?.awaitShutdown()
            } catch (e: Exception) {
                Log.w(TAG, "Error during client cleanup: ${e.message}")
            }
        }
    }
}