CORDA-2399: Samples using public TestCordapp API rather than internal one (#4521)

Also moved the contents of TestCordappUtils.kt to InternalTestUtils.kt to make it more obvious they're internal.
This commit is contained in:
Shams Asari 2019-01-08 11:55:23 +00:00 committed by GitHub
parent 8e0b2558ad
commit 8e61d11a49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 102 additions and 96 deletions

View File

@ -15,7 +15,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import static net.corda.testing.core.TestUtils.singleIdentity;
import static net.corda.testing.node.internal.TestCordappsUtilsKt.cordappsForPackages;
import static net.corda.testing.node.internal.InternalTestUtilsKt.cordappsForPackages;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.Assert.fail;

View File

@ -32,7 +32,7 @@ import static net.corda.testing.core.ExpectKt.expectEvents;
import static net.corda.testing.core.TestConstants.ALICE_NAME;
import static net.corda.testing.core.TestConstants.BOB_NAME;
import static net.corda.testing.driver.Driver.driver;
import static net.corda.testing.node.internal.TestCordappsUtilsKt.FINANCE_CORDAPPS;
import static net.corda.testing.node.internal.InternalTestUtilsKt.FINANCE_CORDAPPS;
import static org.junit.Assert.assertEquals;
public class JavaIntegrationTestingTutorial {

View File

@ -7,12 +7,12 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.getOrThrow
import net.corda.finance.DOLLARS
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.asset.AbstractCashSelection
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.contracts.getCashBalance
import net.corda.finance.issuedBy
import net.corda.testing.core.singleIdentity
import net.corda.testing.node.internal.cordappsForPackages
import net.corda.testing.node.internal.FINANCE_CORDAPPS
import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.internal.startFlow
import org.assertj.core.api.Assertions.assertThat
@ -20,7 +20,7 @@ import org.junit.After
import org.junit.Test
class CashSelectionTest {
private val mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.finance"), threadPerNode = true)
private val mockNet = InternalMockNetwork(cordappsForAllNodes = FINANCE_CORDAPPS, threadPerNode = true)
@After
fun cleanUp() {

View File

@ -1,13 +1,12 @@
package net.corda.finance.internal
import net.corda.core.internal.packageName
import net.corda.core.utilities.getOrThrow
import net.corda.finance.EUR
import net.corda.finance.USD
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetworkParameters
import net.corda.testing.node.MockNodeParameters
import net.corda.testing.node.internal.cordappWithPackages
import net.corda.testing.node.internal.FINANCE_WORKFLOWS_CORDAPP
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Test
@ -20,9 +19,9 @@ class CashConfigDataFlowTest {
@Test
fun `issuable currencies read in from cordapp config`() {
val node = mockNet.createNode(MockNodeParameters(additionalCordapps = listOf(
cordappWithPackages(javaClass.packageName).copy(config = mapOf("issuableCurrencies" to listOf("EUR", "USD")))
)))
val node = mockNet.createNode(MockNodeParameters(
additionalCordapps = listOf(FINANCE_WORKFLOWS_CORDAPP.withConfig(mapOf("issuableCurrencies" to listOf("EUR", "USD"))))
))
val config = node.startFlow(CashConfigDataFlow()).getOrThrow()
assertThat(config.issuableCurrencies).containsExactly(EUR, USD)
}

View File

@ -1,7 +1,6 @@
package net.corda.traderdemo
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.internal.packageName
import net.corda.core.messaging.startFlow
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.millis
@ -18,9 +17,9 @@ import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.InProcess
import net.corda.testing.driver.OutOfProcess
import net.corda.testing.driver.driver
import net.corda.testing.node.TestCordapp
import net.corda.testing.node.User
import net.corda.testing.node.internal.FINANCE_CORDAPPS
import net.corda.testing.node.internal.cordappWithPackages
import net.corda.testing.node.internal.poll
import net.corda.traderdemo.flow.CommercialPaperIssueFlow
import net.corda.traderdemo.flow.SellerFlow
@ -37,7 +36,11 @@ class TraderDemoTest {
startFlow<CashPaymentFlow>(),
startFlow<CommercialPaperIssueFlow>(),
all()))
driver(DriverParameters(startNodesInProcess = true, inMemoryDB = false, cordappsForAllNodes = FINANCE_CORDAPPS + cordappWithPackages(javaClass.packageName))) {
driver(DriverParameters(
startNodesInProcess = true,
inMemoryDB = false,
cordappsForAllNodes = FINANCE_CORDAPPS + TestCordapp.findCordapp("net.corda.traderdemo")
)) {
val (nodeA, nodeB, bankNode) = listOf(
startNode(providedName = DUMMY_BANK_A_NAME, rpcUsers = listOf(demoUser)),
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser)),
@ -80,7 +83,11 @@ class TraderDemoTest {
@Test
fun `Test restart node during flow works properly`() {
driver(DriverParameters(startNodesInProcess = false, inMemoryDB = false, cordappsForAllNodes = FINANCE_CORDAPPS + cordappWithPackages(javaClass.packageName))) {
driver(DriverParameters(
startNodesInProcess = false,
inMemoryDB = false,
cordappsForAllNodes = FINANCE_CORDAPPS + TestCordapp.findCordapp("net.corda.traderdemo")
)) {
val demoUser = User("demo", "demo", setOf(startFlow<SellerFlow>(), all()))
val bankUser = User("user1", "test", permissions = setOf(all()))
val (nodeA, nodeB, bankNode) = listOf(

View File

@ -7,6 +7,7 @@ import net.corda.core.concurrent.CordaFuture
import net.corda.core.context.InvocationContext
import net.corda.core.flows.FlowLogic
import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.VisibleForTesting
import net.corda.core.internal.concurrent.openFuture
import net.corda.core.internal.times
import net.corda.core.messaging.CordaRPCOps
@ -24,6 +25,7 @@ import net.corda.testing.internal.chooseIdentity
import net.corda.testing.internal.createTestSerializationEnv
import net.corda.testing.internal.inVMExecutors
import net.corda.testing.node.InMemoryMessagingNetwork
import net.corda.testing.node.TestCordapp
import net.corda.testing.node.User
import net.corda.testing.node.testContext
import org.slf4j.LoggerFactory
@ -37,9 +39,82 @@ import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit
import java.util.jar.JarOutputStream
import java.util.zip.ZipEntry
import kotlin.reflect.KClass
private val log = LoggerFactory.getLogger("net.corda.testing.internal.InternalTestUtils")
/**
* Reference to the finance-contracts CorDapp in this repo. The metadata is taken directly from finance/contracts/build.gradle, including the
* fact that the jar is signed. If you need an unsigned jar then use `cordappWithPackages("net.corda.finance.contracts")`.
*
* You will probably need to use [FINANCE_CORDAPPS] instead to get access to the flows as well.
*/
// TODO We can't use net.corda.finance.contracts as finance-workflows contains the package net.corda.finance.contracts.asset.cash.selection. This should be renamed.
@JvmField
val FINANCE_CONTRACTS_CORDAPP: TestCordappImpl = findCordapp("net.corda.finance.schemas")
/**
* Reference to the finance-workflows CorDapp in this repo. The metadata is taken directly from finance/workflows/build.gradle, including the
* fact that the jar is signed. If you need an unsigned jar then use `cordappWithPackages("net.corda.finance.flows")`.
*
* You will probably need to use [FINANCE_CORDAPPS] instead to get access to the contract classes as well.
*/
@JvmField
val FINANCE_WORKFLOWS_CORDAPP: TestCordappImpl = findCordapp("net.corda.finance.flows")
@JvmField
val FINANCE_CORDAPPS: Set<TestCordappInternal> = setOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP)
fun cordappsForPackages(vararg packageNames: String): Set<CustomCordapp> = cordappsForPackages(packageNames.asList())
fun cordappsForPackages(packageNames: Iterable<String>): Set<CustomCordapp> {
return simplifyScanPackages(packageNames).mapTo(HashSet()) { cordappWithPackages(it) }
}
/**
* Create a *custom* CorDapp which contains all the classes and resoures located in the given packages. The CorDapp's metadata will be the
* default values as defined in the [CustomCordapp] c'tor. Use the `copy` to change them. This means the metadata will *not* be the one defined
* in the original CorDapp(s) that the given packages may represent. If this is not what you want then use [findCordapp] instead.
*/
fun cordappWithPackages(vararg packageNames: String): CustomCordapp = CustomCordapp(packages = simplifyScanPackages(packageNames.asList()))
/** Create a *custom* CorDapp which contains just the given classes. */
// TODO Rename to cordappWithClasses
fun cordappForClasses(vararg classes: Class<*>): CustomCordapp = CustomCordapp(packages = emptySet(), classes = classes.toSet())
/**
* Find the single CorDapp jar on the current classpath which contains the given package. This is a convenience method for
* [TestCordapp.findCordapp] but returns the internal [TestCordappImpl].
*/
fun findCordapp(scanPackage: String): TestCordappImpl = TestCordapp.findCordapp(scanPackage) as TestCordappImpl
private fun getCallerClass(directCallerClass: KClass<*>): Class<*>? {
val stackTrace = Throwable().stackTrace
val index = stackTrace.indexOfLast { it.className == directCallerClass.java.name }
if (index == -1) return null
return try {
Class.forName(stackTrace[index + 1].className)
} catch (e: ClassNotFoundException) {
null
}
}
fun getCallerPackage(directCallerClass: KClass<*>): String? = getCallerClass(directCallerClass)?.`package`?.name
/**
* Squashes child packages if the parent is present. Example: ["com.foo", "com.foo.bar"] into just ["com.foo"].
*/
@VisibleForTesting
internal fun simplifyScanPackages(scanPackages: Iterable<String>): Set<String> {
return scanPackages.sorted().fold(emptySet()) { soFar, packageName ->
when {
soFar.isEmpty() -> setOf(packageName)
packageName.startsWith("${soFar.last()}.") -> soFar
else -> soFar + packageName
}
}
}
/**
* @throws ListenProcessDeathException if [listenProcess] dies before the check succeeds, i.e. the check can't succeed as intended.
*/

View File

@ -1,75 +0,0 @@
package net.corda.testing.node.internal
import net.corda.testing.node.TestCordapp
import kotlin.reflect.KClass
/**
* Reference to the finance-contracts CorDapp in this repo. The metadata is taken directly from finance/contracts/build.gradle, including the
* fact that the jar is signed. If you need an unsigned jar then use `cordappWithPackages("net.corda.finance.contracts")`.
*
* You will probably need to use [FINANCE_CORDAPPS] instead to get access to the flows as well.
*/
// TODO We can't use net.corda.finance.contracts as finance-workflows contains the package net.corda.finance.contracts.asset.cash.selection. This should be renamed.
@JvmField
val FINANCE_CONTRACTS_CORDAPP: TestCordappImpl = findCordapp("net.corda.finance.schemas")
/**
* Reference to the finance-workflows CorDapp in this repo. The metadata is taken directly from finance/workflows/build.gradle, including the
* fact that the jar is signed. If you need an unsigned jar then use `cordappWithPackages("net.corda.finance.flows")`.
*
* You will probably need to use [FINANCE_CORDAPPS] instead to get access to the contract classes as well.
*/
@JvmField
val FINANCE_WORKFLOWS_CORDAPP: TestCordappImpl = findCordapp("net.corda.finance.flows")
@JvmField
val FINANCE_CORDAPPS: Set<TestCordappInternal> = setOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP)
fun cordappsForPackages(vararg packageNames: String): Set<CustomCordapp> = cordappsForPackages(packageNames.asList())
fun cordappsForPackages(packageNames: Iterable<String>): Set<CustomCordapp> {
return simplifyScanPackages(packageNames).mapTo(HashSet()) { cordappWithPackages(it) }
}
/**
* Create a *custom* CorDapp which contains all the classes and resoures located in the given packages. The CorDapp's metadata will be the
* default values as defined in the [CustomCordapp] c'tor. Use the `copy` to change them. This means the metadata will *not* be the one defined
* in the original CorDapp(s) that the given packages may represent. If this is not what you want then use [findCordapp] instead.
*/
fun cordappWithPackages(vararg packageNames: String): CustomCordapp = CustomCordapp(packages = simplifyScanPackages(packageNames.asList()))
/** Create a *custom* CorDapp which contains just the given classes. */
// TODO Rename to cordappWithClasses
fun cordappForClasses(vararg classes: Class<*>): CustomCordapp = CustomCordapp(packages = emptySet(), classes = classes.toSet())
/**
* Find the single CorDapp jar on the current classpath which contains the given package. This is a convenience method for
* [TestCordapp.findCordapp] but returns the internal [TestCordappImpl].
*/
fun findCordapp(scanPackage: String): TestCordappImpl = TestCordapp.findCordapp(scanPackage) as TestCordappImpl
fun getCallerClass(directCallerClass: KClass<*>): Class<*>? {
val stackTrace = Throwable().stackTrace
val index = stackTrace.indexOfLast { it.className == directCallerClass.java.name }
if (index == -1) return null
return try {
Class.forName(stackTrace[index + 1].className)
} catch (e: ClassNotFoundException) {
null
}
}
fun getCallerPackage(directCallerClass: KClass<*>): String? = getCallerClass(directCallerClass)?.`package`?.name
/**
* Squashes child packages if the parent is present. Example: ["com.foo", "com.foo.bar"] into just ["com.foo"].
*/
fun simplifyScanPackages(scanPackages: Iterable<String>): Set<String> {
return scanPackages.sorted().fold(emptySet()) { soFar, packageName ->
when {
soFar.isEmpty() -> setOf(packageName)
packageName.startsWith("${soFar.last()}.") -> soFar
else -> soFar + packageName
}
}
}

View File

@ -13,7 +13,7 @@ import org.junit.rules.ExpectedException;
import java.util.concurrent.Future;
import static net.corda.testing.node.internal.TestCordappsUtilsKt.cordappsForPackages;
import static net.corda.testing.node.internal.InternalTestUtilsKt.cordappsForPackages;
import static org.hamcrest.Matchers.instanceOf;
/**

View File

@ -17,12 +17,12 @@ class CustomCordappTest {
@Test
fun `packageAsJar writes out the CorDapp info into the manifest`() {
val cordapp = cordappWithPackages("net.corda.testing.node.internal").copy(targetPlatformVersion = 123, name = "TestCordappsUtilsTest")
val cordapp = cordappWithPackages("net.corda.testing.node.internal").copy(targetPlatformVersion = 123, name = "CustomCordappTest")
val jarFile = packageAsJar(cordapp)
JarInputStream(jarFile.inputStream()).use {
assertThat(it.manifest[CordappImpl.TARGET_PLATFORM_VERSION]).isEqualTo("123")
assertThat(it.manifest[CordappImpl.CORDAPP_CONTRACT_NAME]).isEqualTo("TestCordappsUtilsTest")
assertThat(it.manifest[CordappImpl.CORDAPP_WORKFLOW_NAME]).isEqualTo("TestCordappsUtilsTest")
assertThat(it.manifest[CordappImpl.CORDAPP_CONTRACT_NAME]).isEqualTo("CustomCordappTest")
assertThat(it.manifest[CordappImpl.CORDAPP_WORKFLOW_NAME]).isEqualTo("CustomCordappTest")
}
}
@ -31,7 +31,7 @@ class CustomCordappTest {
val entries = packageAsJarThenReadBack(cordappWithPackages("net.corda.testing.node.internal"))
assertThat(entries).contains(
"net/corda/testing/node/internal/TestCordappsUtilsTest.class",
"net/corda/testing/node/internal/CustomCordappTest.class",
"net/corda/testing/node/internal/resource.txt" // Make sure non-class resource files are also picked up
).doesNotContain(
"net/corda/testing/node/MockNetworkTest.class"
@ -46,7 +46,7 @@ class CustomCordappTest {
val entries = packageAsJarThenReadBack(cordappWithPackages("net.corda.testing.node"))
assertThat(entries).contains(
"net/corda/testing/node/internal/TestCordappsUtilsTest.class",
"net/corda/testing/node/internal/CustomCordappTest.class",
"net/corda/testing/node/internal/resource.txt",
"net/corda/testing/node/MockNetworkTest.class"
)

View File

@ -3,7 +3,7 @@ package net.corda.testing.node.internal
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
class TestCordappsUtilsTest {
class InternalTestUtilsTest {
@Test
fun `test simplifyScanPackages`() {
assertThat(simplifyScanPackages(emptyList())).isEmpty()