Merge pull request #764 from corda/colljos-merge-230418

OS -> ENT merge
This commit is contained in:
josecoll 2018-04-23 13:26:15 +01:00 committed by GitHub
commit 5ae35b70dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 42 additions and 112 deletions

View File

@ -3228,7 +3228,7 @@ public static final class net.corda.core.transactions.FilteredTransaction$Compan
@org.jetbrains.annotations.NotNull public final List inputsOfType(Class)
public String toString()
public final void verify()
public static final net.corda.core.transactions.LedgerTransaction$Companion Companion
@java.lang.Deprecated public static final net.corda.core.transactions.LedgerTransaction$Companion Companion
##
public static final class net.corda.core.transactions.LedgerTransaction$InOutGroup extends java.lang.Object
public <init>(List, List, Object)
@ -3334,7 +3334,7 @@ public static final class net.corda.core.transactions.NotaryChangeWireTransactio
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignature(java.security.KeyPair, net.corda.core.crypto.SignatureMetadata)
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignature(net.corda.core.crypto.TransactionSignature)
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignatures(Iterable)
public static final net.corda.core.transactions.SignedTransaction$Companion Companion
@java.lang.Deprecated public static final net.corda.core.transactions.SignedTransaction$Companion Companion
##
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.transactions.SignedTransaction$SignaturesMissingException extends java.security.SignatureException implements net.corda.core.CordaThrowable, net.corda.core.contracts.NamedByHash
public <init>(Set, List, net.corda.core.crypto.SecureHash)

View File

@ -183,8 +183,8 @@ allprojects {
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
languageVersion = "1.1"
apiVersion = "1.1"
languageVersion = "1.2"
apiVersion = "1.2"
jvmTarget = "1.8"
javaParameters = true // Useful for reflection.
}

View File

@ -474,3 +474,8 @@ fun NotarisationRequest.generateSignature(serviceHub: ServiceHub): NotarisationR
}
val PublicKey.hash: SecureHash get() = encoded.sha256()
/**
* Extension method for providing a sumBy method that processes and returns a Long
*/
fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long = this.map { selector(it) }.sum()

View File

@ -140,7 +140,3 @@ fun <V> Future<V>.getOrThrow(timeout: Duration? = null): V = try {
throw e.cause!!
}
/**
* Extension method for providing a sumBy method that processes and returns a Long
*/
fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long = this.map { selector(it) }.sum()

View File

@ -11,6 +11,7 @@
package net.corda.core.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Primitives;
import net.corda.core.identity.Party;
import net.corda.testing.core.TestConstants;
@ -23,13 +24,12 @@ import org.junit.Test;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import static java.util.Collections.emptyList;
import static net.corda.testing.core.TestUtils.singleIdentity;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.Assert.fail;
public class FlowsInJavaTest {
private final MockNetwork mockNet = new MockNetwork(emptyList());
private final MockNetwork mockNet = new MockNetwork(ImmutableList.of("net.corda.core.flows"));
private StartedMockNode aliceNode;
private StartedMockNode bobNode;
private Party bob;
@ -48,7 +48,6 @@ public class FlowsInJavaTest {
@Test
public void suspendableActionInsideUnwrap() throws Exception {
bobNode.registerInitiatedFlow(SendHelloAndThenReceive.class);
Future<String> result = aliceNode.startFlow(new SendInUnwrapFlow(bob));
mockNet.runNetwork();
assertThat(result.get()).isEqualTo("Hello");

View File

@ -51,7 +51,7 @@ class CollectSignaturesFlowTests {
@Before
fun setup() {
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.core.flows"))
aliceNode = mockNet.createPartyNode(ALICE_NAME)
bobNode = mockNet.createPartyNode(BOB_NAME)
charlieNode = mockNet.createPartyNode(CHARLIE_NAME)
@ -66,12 +66,6 @@ class CollectSignaturesFlowTests {
mockNet.stopNodes()
}
private fun registerFlowOnAllNodes(flowClass: KClass<out FlowLogic<*>>) {
listOf(aliceNode, bobNode, charlieNode).forEach {
it.registerInitiatedFlow(flowClass.java)
}
}
// With this flow, the initiator starts the "CollectTransactionFlow". It is then the responders responsibility to
// override "checkTransaction" and add whatever logic their require to verify the SignedTransaction they are
// receiving off the wire.
@ -120,7 +114,6 @@ class CollectSignaturesFlowTests {
// Normally this is handled by TransactionKeyFlow, but here we have to manually let A know about the identity
aliceNode.services.identityService.verifyAndRegisterIdentity(bConfidentialIdentity)
}
registerFlowOnAllNodes(TestFlow.Responder::class)
val magicNumber = 1337
val parties = listOf(alice, bConfidentialIdentity.party, charlie)
val state = DummyContract.MultiOwnerState(magicNumber, parties)

View File

@ -48,12 +48,10 @@ class ResolveTransactionsFlowTest {
@Before
fun setup() {
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.core.internal"))
notaryNode = mockNet.defaultNotaryNode
megaCorpNode = mockNet.createPartyNode(CordaX500Name("MegaCorp", "London", "GB"))
miniCorpNode = mockNet.createPartyNode(CordaX500Name("MiniCorp", "London", "GB"))
megaCorpNode.registerInitiatedFlow(TestResponseFlow::class.java)
miniCorpNode.registerInitiatedFlow(TestResponseFlow::class.java)
notary = mockNet.defaultNotaryIdentity
megaCorp = megaCorpNode.info.singleIdentity()
miniCorp = miniCorpNode.info.singleIdentity()

View File

@ -165,24 +165,6 @@ Nodes are created on the ``MockNetwork`` using:
}
}
Registering a node's initiated flows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Regular Corda nodes automatically register any response flows defined in their installed CorDapps. When using a
``MockNetwork``, each ``StartedMockNode`` must manually register any responder flows it wishes to use.
Responder flows are registered as follows:
.. container:: codeset
.. sourcecode:: kotlin
nodeA.registerInitiatedFlow(ExampleFlow.Acceptor::class.java)
.. sourcecode:: java
nodeA.registerInitiatedFlow(ExampleFlow.Acceptor.class);
Running the network
^^^^^^^^^^^^^^^^^^^

View File

@ -11,6 +11,7 @@
package net.corda.docs.tutorial.mocknetwork
import co.paralleluniverse.fibers.Suspendable
import com.google.common.collect.ImmutableList
import net.corda.core.contracts.requireThat
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession
@ -72,10 +73,9 @@ class TutorialMockNetwork {
@Before
fun setUp() {
mockNet = MockNetwork(emptyList())
mockNet = MockNetwork(ImmutableList.of("net.corda.docs.tutorial.mocknetwork"))
nodeA = mockNet.createPartyNode()
nodeB = mockNet.createPartyNode()
nodeB.registerInitiatedFlow(FlowB::class.java)
}
@After

View File

@ -61,10 +61,6 @@ transactions are valid) inside a ``database.transaction``. All node flows run w
nodes themselves, but any time we need to use the database directly from a unit test, you need to provide a database
transaction as shown here.
With regards to initiated flows (see :doc:`flow-state-machines` for information on initiated and initiating flows), the
full node automatically registers them by scanning the CorDapp jars. In a unit test environment this is not possible so
``MockNode`` has the ``registerInitiatedFlow`` method to manually register an initiated flow.
.. MockNetwork message manipulation
.. --------------------------------
.. The MockNetwork has the ability to manipulate message streams. You can use this to test your flows behaviour on corrupted,

View File

@ -15,6 +15,7 @@ import net.corda.behave.file.currentDirectory
import net.corda.behave.logging.getLogger
import net.corda.behave.process.output.OutputListener
import rx.Observable
import rx.Subscriber
import java.io.Closeable
import java.io.File
import java.io.IOException
@ -153,8 +154,9 @@ open class Command(
return exitCode
}
fun use(action: (Command, Observable<String>) -> Unit = { _, _ -> }): Int {
fun use(subscriber: Subscriber<String>, action: (Command, Observable<String>) -> Unit = { _, _ -> }): Int {
try {
output.subscribe(subscriber)
start()
action(this, output)
} finally {

View File

@ -1,18 +0,0 @@
package net.corda.behave.scenarios
import cucumber.api.java.After
import cucumber.api.java.Before
@Suppress("KDocMissingDocumentation")
class ScenarioHooks(private val state: ScenarioState) {
@Before
fun beforeScenario() {
}
@After
fun afterScenario() {
state.stopNetwork()
}
}

View File

@ -4,7 +4,7 @@ import net.corda.behave.scenarios.ScenarioState
import net.corda.behave.scenarios.api.StepsBlock
import net.corda.behave.scenarios.helpers.Vault
import net.corda.core.contracts.ContractState
import net.corda.core.utilities.sumByLong
import net.corda.core.internal.sumByLong
import net.corda.finance.contracts.asset.Cash
class VaultSteps : StepsBlock {

View File

@ -31,8 +31,7 @@ class CommandTests {
@Test
fun `output stream for command can be observed`() {
val subscriber = TestSubscriber<String>()
val exitCode = Command(listOf("ls", "/")).use { _, output ->
output.subscribe(subscriber)
val exitCode = Command(listOf("ls", "/")).use(subscriber) { _, output ->
subscriber.awaitTerminalEvent()
subscriber.assertCompleted()
subscriber.assertNoErrors()

View File

@ -1,29 +0,0 @@
/*
* R3 Proprietary and Confidential
*
* Copyright (c) 2018 R3 Limited. All rights reserved.
*
* The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law.
*
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
*/
package net.corda.behave.service
import net.corda.behave.service.database.PostgreSQLService
import org.assertj.core.api.Assertions.assertThat
import org.junit.Ignore
import org.junit.Test
class PostreSQLServiceTests {
@Ignore
@Test
fun `postgres can be started and stopped`() {
val service = PostgreSQLService("test-postgres", 12345, "postgres")
val didStart = service.start()
service.stop()
assertThat(didStart).isTrue()
}
}

View File

@ -13,40 +13,53 @@ package net.corda.nodeapi.internal
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
import net.corda.core.contracts.Contract
import net.corda.core.contracts.ContractClassName
import net.corda.core.contracts.UpgradedContract
import net.corda.core.contracts.UpgradedContractWithLegacyConstraint
import net.corda.core.internal.copyTo
import net.corda.core.internal.deleteIfExists
import net.corda.core.internal.logElapsedTime
import net.corda.core.internal.read
import org.slf4j.LoggerFactory
import java.io.InputStream
import java.lang.reflect.Modifier
import java.net.URLClassLoader
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
import java.util.Collections.singleton
// When scanning of the CorDapp Jar is performed without "corda-core.jar" being the in the classpath, there is no way to appreciate
// relationships between those interfaces, therefore they have to be listed explicitly.
val coreContractClasses = setOf(Contract::class, UpgradedContractWithLegacyConstraint::class, UpgradedContract::class)
/**
* Scans the jar for contracts.
* @returns: found contract class names or null if none found
*/
fun scanJarForContracts(cordappJar: Path): List<ContractClassName> {
val currentClassLoader = Contract::class.java.classLoader
val scanResult = FastClasspathScanner()
.addClassLoader(currentClassLoader)
.overrideClasspath(cordappJar, Paths.get(Contract::class.java.protectionDomain.codeSource.location.toURI()))
// A set of a single element may look odd, but if this is removed "Path" which itself is an `Iterable`
// is getting broken into pieces to scan individually, which doesn't yield desired effect.
.overrideClasspath(singleton(cordappJar))
.scan()
val contracts = (scanResult.getNamesOfClassesImplementing(Contract::class.qualifiedName) ).distinct()
val contracts = coreContractClasses.flatMap { contractClass -> scanResult.getNamesOfClassesImplementing(contractClass.qualifiedName) }.distinct()
// Only keep instantiable contracts
return URLClassLoader(arrayOf(cordappJar.toUri().toURL()), currentClassLoader).use {
return URLClassLoader(arrayOf(cordappJar.toUri().toURL()), Contract::class.java.classLoader).use {
contracts.map(it::loadClass).filter { !it.isInterface && !Modifier.isAbstract(it.modifiers) }
}.map { it.name }
}
private val logger = LoggerFactory.getLogger("ClassloaderUtils")
fun <T> withContractsInJar(jarInputStream: InputStream, withContracts: (List<ContractClassName>, InputStream) -> T): T {
val tempFile = Files.createTempFile("attachment", ".jar")
try {
jarInputStream.copyTo(tempFile, StandardCopyOption.REPLACE_EXISTING)
val contracts = scanJarForContracts(tempFile.toAbsolutePath())
val cordappJar = tempFile.toAbsolutePath()
val contracts = logElapsedTime("Contracts loading for '$cordappJar'", logger) {
scanJarForContracts(cordappJar)
}
return tempFile.read { withContracts(contracts, it) }
} finally {
tempFile.deleteIfExists()

View File

@ -27,6 +27,7 @@ import net.corda.core.serialization.SerializeAsToken
import net.corda.core.utilities.contextLogger
import net.corda.node.internal.classloading.requireAnnotation
import net.corda.node.services.config.NodeConfiguration
import net.corda.nodeapi.internal.coreContractClasses
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
import org.apache.commons.collections4.map.LRUMap
import java.io.File
@ -251,13 +252,7 @@ class CordappLoader private constructor(private val cordappJarPaths: List<Restri
}
private fun findContractClassNames(scanResult: RestrictedScanResult): List<String> {
return (scanResult.getNamesOfClassesImplementing(Contract::class) +
scanResult.getNamesOfClassesImplementing(UpgradedContract::class) +
// Even though UpgradedContractWithLegacyConstraint implements UpgradedContract
// we need to specify it separately. Otherwise, classes implementing UpgradedContractWithLegacyConstraint
// don't get picked up.
scanResult.getNamesOfClassesImplementing(UpgradedContractWithLegacyConstraint::class))
.distinct()
return coreContractClasses.flatMap { scanResult.getNamesOfClassesImplementing(it) }.distinct()
}
private fun findPlugins(cordappJarPath: RestrictedURL): List<SerializationWhitelist> {

View File

@ -59,7 +59,6 @@ class TraderDemoTest : IntegrationTest() {
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser)),
startNode(providedName = BOC_NAME, rpcUsers = listOf(bankUser))
).map { (it.getOrThrow() as InProcess) }
nodeA.registerInitiatedFlow(BuyerFlow::class.java)
val (nodeARpc, nodeBRpc) = listOf(nodeA, nodeB).map {
val client = CordaRPCClient(it.rpcAddress)
client.start(demoUser.username, demoUser.password).proxy