CORDA-3663 MockServices crashes when two of the provided packages to … (#6472)

* CORDA-3663 MockServices crashes when two of the provided packages to scan are deemed empty in 4.4 RC05

this happends when a given package is not found on the classpath. Now it is handled and an exception is thrown

* replace dummy package names in tests with valid ones

* allow empty package list for CustomCordapps and exclude those from the created jars

* detekt fix

* always true logic fix

* fix to check for empty packages instead of empty classes

* fix for classes and fixups

* logic refactor because of detekt stupidity

* PR related minor refactors
This commit is contained in:
Tamas Veingartner 2020-08-03 09:19:48 +01:00 committed by GitHub
parent c288073e7c
commit 85be50779b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 13 deletions

View File

@ -96,5 +96,5 @@ class FinalityFlowTests : WithFinality {
}
/** "Old" CorDapp which will force its node to keep its FinalityHandler enabled */
private fun tokenOldCordapp() = cordappWithPackages("com.template").copy(targetPlatformVersion = 3)
private fun tokenOldCordapp() = cordappWithPackages().copy(targetPlatformVersion = 3)
}

View File

@ -6,6 +6,8 @@ import net.corda.core.context.InvocationOrigin
import net.corda.core.contracts.ContractState
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByService
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.packageName
import net.corda.core.node.AppServiceHub
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.CordaService
@ -16,12 +18,20 @@ import net.corda.core.utilities.OpaqueBytes
import net.corda.core.utilities.ProgressTracker
import net.corda.finance.DOLLARS
import net.corda.finance.flows.CashIssueFlow
import net.corda.finance.schemas.CashSchemaV1
import net.corda.node.internal.cordapp.DummyRPCFlow
import net.corda.testing.core.BOC_NAME
import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.testing.core.TestIdentity
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetworkParameters
import net.corda.testing.node.MockServices
import net.corda.testing.node.StartedMockNode
import net.corda.testing.node.internal.FINANCE_CONTRACTS_CORDAPP
import net.corda.testing.node.internal.enclosedCordapp
import net.corda.testing.node.makeTestIdentityService
import org.assertj.core.api.Assertions
import org.junit.After
import org.junit.Before
import org.junit.Test
@ -100,6 +110,22 @@ class CordaServiceTest {
nodeA.services.cordaService(EntityManagerService::class.java)
}
@Test(timeout=300_000)
fun `MockServices when initialized with package name not on classpath throws ClassNotFoundException`() {
val cordappPackages = listOf(
"com.r3.corda.sdk.tokens.money",
"net.corda.finance.contracts",
CashSchemaV1::class.packageName,
DummyLinearStateSchemaV1::class.packageName)
val bankOfCorda = TestIdentity(BOC_NAME)
val dummyCashIssuer = TestIdentity(CordaX500Name("Snake Oil Issuer", "London", "GB"), 10)
val dummyNotary = TestIdentity(DUMMY_NOTARY_NAME, 20)
val identityService = makeTestIdentityService(dummyNotary.identity)
Assertions.assertThatThrownBy { MockServices(cordappPackages, dummyNotary, identityService, dummyCashIssuer.keyPair, bankOfCorda.keyPair) }
.isInstanceOf(ClassNotFoundException::class.java).hasMessage("Could not create jar file as the given package is not found on the classpath: com.r3.corda.sdk.tokens.money")
}
@StartableByService
class DummyServiceFlow : FlowLogic<InvocationContext>() {
companion object {

View File

@ -37,11 +37,6 @@ data class CustomCordapp(
val signingInfo: SigningInfo? = null,
override val config: Map<String, Any> = emptyMap()
) : TestCordappInternal() {
init {
require(packages.isNotEmpty() || classes.isNotEmpty() || fixups.isNotEmpty()) {
"At least one package or class must be specified"
}
}
override val jarFile: Path get() = getJarFile(this)
@ -55,7 +50,7 @@ data class CustomCordapp(
@VisibleForTesting
internal fun packageAsJar(file: Path) {
val classGraph = ClassGraph()
if (packages.isNotEmpty()) {
if(packages.isNotEmpty()){
classGraph.whitelistPaths(*packages.map { it.replace('.', '/') }.toTypedArray())
}
if (classes.isNotEmpty()) {
@ -78,6 +73,10 @@ data class CustomCordapp(
}
}
if (scanResult.allResources.isEmpty()){
throw ClassNotFoundException("Could not create jar file as the given package is not found on the classpath: ${packages.toList()[0]}")
}
// The same resource may be found in different locations (this will happen when running from gradle) so just
// pick the first one found.
scanResult.allResources.asMap().forEach { path, resourceList ->
@ -178,8 +177,8 @@ data class CustomCordapp(
val jarFile = cordappsDirectory.createDirectories() / filename
if (it.fixups.isNotEmpty()) {
it.createFixupJar(jarFile)
} else {
it.packageAsJar(jarFile)
} else if(it.packages.isNotEmpty() || it.classes.isNotEmpty() || it.fixups.isNotEmpty()) {
it.packageAsJar(jarFile)
}
it.signJar(jarFile)
logger.debug { "$it packaged into $jarFile" }

View File

@ -30,14 +30,17 @@ abstract class TestCordappInternal : TestCordapp() {
// Precedence is given to node-specific CorDapps
val allCordapps = nodeSpecificCordapps + generalCordapps.filter { it.withOnlyJarContents() !in nodeSpecificCordappsWithoutMeta }
// Ignore any duplicate jar files
val jarToCordapp = allCordapps.associateBy { it.jarFile }
val jarToCordapp = allCordapps.filter {
it !is CustomCordapp || it.packages.isNotEmpty() || it.classes.isNotEmpty() || it.fixups.isNotEmpty() }.associateBy { it.jarFile }
val cordappsDir = baseDirectory / "cordapps"
val configDir = (cordappsDir / "config").createDirectories()
jarToCordapp.forEach { jar, cordapp ->
try {
jar.copyToDirectory(cordappsDir)
if (jar.toFile().exists()) {
jar.copyToDirectory(cordappsDir)
}
} catch (e: FileAlreadyExistsException) {
// Ignore if the node already has the same CorDapp jar. This can happen if the node is being restarted.
}

View File

@ -22,7 +22,7 @@ import org.junit.Test
*/
class TestResponseFlowInIsolation {
private val network: MockNetwork = MockNetwork(MockNetworkParameters(cordappsForAllNodes = cordappsForPackages("com.template")))
private val network: MockNetwork = MockNetwork(MockNetworkParameters(cordappsForAllNodes = cordappsForPackages()))
private val a = network.createNode()
private val b = network.createNode()

View File

@ -28,7 +28,7 @@ import static org.hamcrest.Matchers.instanceOf;
*/
public class TestResponseFlowInIsolationInJava {
private final MockNetwork network = new MockNetwork(new MockNetworkParameters().withCordappsForAllNodes(cordappsForPackages("com.template")));
private final MockNetwork network = new MockNetwork(new MockNetworkParameters().withCordappsForAllNodes(cordappsForPackages()));
private final StartedMockNode a = network.createNode();
private final StartedMockNode b = network.createNode();