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}")
}
}
}
}