I developed a simple state "item" that represents items a seller will sell to a group of anonymous buyers. I wrote flow tests and everything seems to be going OK. I wanted to also implement integration tests to confirm my logic is working properly. My flow failed due to the fact that the seller node started cannot resolve the buyer from its public key. I was able to reproduce the code without any of my own code. I feel like I missed a registration step or something but then again the seller node can resolve the buyer node using the X500 name. I'm a bit perplexed by why I'm having problems resolving the buyer node through its public key.
To replicate, clone cordapps-kotlin-template and replace the contents of DriverBasedTest.kt with the following code, run gradlew integrationTest
.
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.getOrThrow
import net.corda.testing.core.TestIdentity
import net.corda.testing.driver.DriverDSL
import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver
import net.corda.testing.node.User
import org.junit.Test
import kotlin.test.assertEquals
class AnonymousTest {
private val seller = TestIdentity(CordaX500Name("Seller", "", "GB"))
private val buyer = TestIdentity(CordaX500Name("Buyer", "", "US"))
@Test
fun `anonymous resolution test`() = withDriver {
val sellerUser = User("sellerUser", "testPassword1", permissions = setOf("ALL"))
val buyerUser = User("buyerUser", "testPassword1", permissions = setOf("ALL"))
val sellerHandle = startNode(providedName = seller.name, rpcUsers = listOf(sellerUser)).getOrThrow()
startNode(providedName = buyer.name, rpcUsers = listOf(buyerUser)).getOrThrow()
val resolvedNameBuyerA = sellerHandle.resolveName(buyer.name)
assertEquals(buyer.name, resolvedNameBuyerA)
val resolveFromAnonymous = sellerHandle.resolveFromAnonymous(buyer.party.anonymise())
assertEquals(buyer.name, resolveFromAnonymous)
}
// Runs a test inside the Driver DSL, which provides useful functions for starting nodes, etc.
private fun withDriver(test: DriverDSL.() -> Unit) = driver(
DriverParameters(isDebug = true, startNodesInProcess = true)
) { test() }
// Makes an RPC call to retrieve another node's name from the network map.
private fun NodeHandle.resolveName(name: CordaX500Name) = rpc.wellKnownPartyFromX500Name(name)!!.name
private fun NodeHandle.resolveFromAnonymous(name: AbstractParty) = rpc.wellKnownPartyFromAnonymous(name)!!.name
}
The test result is as follows:
kotlin.KotlinNullPointerException
at com.template.AnonymousTest.resolveFromAnonymous(DriverBasedTest.kt:40)
at com.template.AnonymousTest.access$resolveFromAnonymous(DriverBasedTest.kt:15)
at com.template.AnonymousTest$anonymous resolution test$1.invoke(DriverBasedTest.kt:28)
at com.template.AnonymousTest$anonymous resolution test$1.invoke(DriverBasedTest.kt:15)
at com.template.AnonymousTest$withDriver$1.invoke(DriverBasedTest.kt:35)
at com.template.AnonymousTest$withDriver$1.invoke(DriverBasedTest.kt:15)
at net.corda.testing.node.internal.DriverDSLImplKt.genericDriver(DriverDSLImpl.kt:1289)
at net.corda.testing.driver.Driver.driver(Driver.kt:197)
at com.template.AnonymousTest.withDriver(DriverBasedTest.kt:33)
at com.template.AnonymousTest.anonymous resolution test(DriverBasedTest.kt:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.lang.Thread.run(Thread.java:748)
Be aware that Corda TestIdentity
can be misleading in that way as they're new and semantically separate identities even if you provide the same names.
Glad to hear you're all set Mustafa. good luck
Yeah the template code is super misleading because the helper function
startnodes
takes theTestIdentity
as an input and make me think that the input overrode the node identity. I had to spend a few hours to understand that that isn't the case.