CORDA-939 - Modify Api Scanner to check api for internal exposures (#2534)

* CORDA-939 Modify Api Scanner to check api for internal exposures (#2510)

* Update check api changes to look for internals

* Update several more uses of internal

* Make check-api-changes script filter out internal class usages

* Make CordaClock part of API

* Update api-current.txt

* Remove exclusion of nodeapi.internal

* Remove access to CordaPersistence from public api

* Don't expose DB Connection from StartedMockNode and remove unnecessary transaction from CustomVaultQueryTest

* Make internal tests that use need db access use InternalMockNetwork

* Make test certificates internal

* Address further review comments

* Revert some accidental changes to api-current.txt

* Address Shams' review comments

* Update Api Scanner to filter out CordaInternal attribute

* Update api-current.txt

* Remove superfluous brackets

* Add transaction to StartedMockNode

* More leaky transaction fixes

# Conflicts:
#	.ci/api-current.txt
#	node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderStaticContractTests.kt
#	node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderTests.kt
#	node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt
#	node/src/test/kotlin/net/corda/node/internal/cordapp/CordappProviderImplTests.kt
#	testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt
#	testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappConfigProvider.kt
#	testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt

* Bump gradle plugins version

* One last internal exposure

* Update constants.properties

* Fix api-current

* Address mikes review comments
This commit is contained in:
Anthony Keenan 2018-02-16 15:22:13 +00:00 committed by Katelyn Baker
parent b68957cf83
commit b24ec9f680
47 changed files with 220 additions and 133 deletions

View File

@ -1219,7 +1219,6 @@ public abstract class net.corda.core.flows.FlowLogic extends java.lang.Object
@org.jetbrains.annotations.Nullable public net.corda.core.utilities.ProgressTracker getProgressTracker()
@org.jetbrains.annotations.NotNull public final net.corda.core.flows.StateMachineRunId getRunId()
@org.jetbrains.annotations.NotNull public final net.corda.core.node.ServiceHub getServiceHub()
@net.corda.core.CordaInternal @org.jetbrains.annotations.NotNull public final net.corda.core.internal.FlowStateMachine getStateMachine()
@co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public final net.corda.core.flows.FlowSession initiateFlow(net.corda.core.identity.Party)
@co.paralleluniverse.fibers.Suspendable public final void persistFlowStackSnapshot()
@kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public net.corda.core.utilities.UntrustworthyData receive(Class, net.corda.core.identity.Party)
@ -1228,7 +1227,6 @@ public abstract class net.corda.core.flows.FlowLogic extends java.lang.Object
public final void recordAuditEvent(String, String, Map)
@kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable public void send(net.corda.core.identity.Party, Object)
@kotlin.Deprecated @co.paralleluniverse.fibers.Suspendable @org.jetbrains.annotations.NotNull public net.corda.core.utilities.UntrustworthyData sendAndReceive(Class, net.corda.core.identity.Party, Object)
@net.corda.core.CordaInternal public final void setStateMachine(net.corda.core.internal.FlowStateMachine)
@co.paralleluniverse.fibers.Suspendable @kotlin.jvm.JvmStatic public static final void sleep(java.time.Duration)
@co.paralleluniverse.fibers.Suspendable public Object subFlow(net.corda.core.flows.FlowLogic)
@org.jetbrains.annotations.Nullable public final net.corda.core.messaging.DataFeed track()

View File

@ -31,8 +31,7 @@ if [ $removalCount -gt 0 ]; then
fi
# Adding new abstract methods could also break the API.
# However, first exclude anything with the @DoNotImplement annotation.
# However, first exclude classes marked with the @DoNotImplement annotation
function forUserImpl() {
awk '/DoNotImplement/,/^##/{ next }{ print }' $1
}
@ -45,13 +44,28 @@ $newAbstracts
EOF
`
#Get a list of any methods that expose classes in .internal. namespaces, and any classes which extend/implement
#an internal class
newInternalExposures=$(echo "$userDiffContents" | grep "^+" | grep "\.internal\." )
internalCount=`grep -v "^$" <<EOF | wc -l
$newInternalExposures
EOF
`
echo "Number of new internal class exposures: "$internalCount
if [ $internalCount -gt 0 ]; then
echo "$newInternalExposures"
echo
fi
echo "Number of new abstract APIs: "$abstractCount
if [ $abstractCount -gt 0 ]; then
echo "$newAbstracts"
echo
fi
badChanges=$(($removalCount + $abstractCount))
badChanges=$(($removalCount + $abstractCount + $internalCount))
if [ $badChanges -gt 255 ]; then
echo "OVERFLOW! Number of bad API changes: $badChanges"
badChanges=255

View File

@ -19,6 +19,7 @@ import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.CHARLIE_NAME
import net.corda.testing.core.singleIdentity
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.startFlow
import org.junit.After
import org.junit.Before
@ -28,12 +29,12 @@ import kotlin.test.assertNotNull
import kotlin.test.assertNull
class IdentitySyncFlowTests {
private lateinit var mockNet: MockNetwork
private lateinit var mockNet: InternalMockNetwork
@Before
fun before() {
// We run this in parallel threads to help catch any race conditions that may exist.
mockNet = MockNetwork(
mockNet = InternalMockNetwork(
networkSendManuallyPumped = false,
threadPerNode = true,
cordappPackages = listOf("net.corda.finance.contracts.asset")

View File

@ -4,18 +4,19 @@ import net.corda.core.identity.*
import net.corda.core.utilities.getOrThrow
import net.corda.testing.core.*
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.internal.InternalMockNetwork
import org.junit.Before
import net.corda.testing.node.startFlow
import org.junit.Test
import kotlin.test.*
class SwapIdentitiesFlowTests {
private lateinit var mockNet: MockNetwork
private lateinit var mockNet: InternalMockNetwork
@Before
fun setup() {
// We run this in parallel threads to help catch any race conditions that may exist.
mockNet = MockNetwork(emptyList(), networkSendManuallyPumped = false, threadPerNode = true)
mockNet = InternalMockNetwork(emptyList(), networkSendManuallyPumped = false, threadPerNode = true)
}
@Test

View File

@ -1,4 +1,4 @@
gradlePluginsVersion=3.0.5
gradlePluginsVersion=3.0.8
kotlinVersion=1.1.60
platformVersion=2
guavaVersion=21.0
@ -6,4 +6,4 @@ bouncycastleVersion=1.57
typesafeConfigVersion=1.3.1
jsr305Version=3.0.2
artifactoryPluginVersion=4.4.18
snakeYamlVersion=1.19
snakeYamlVersion=1.19

View File

@ -11,12 +11,13 @@ import net.corda.core.identity.groupAbstractPartyByWellKnownParty
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.StartedNode
import net.corda.testing.contracts.DummyContract
import net.corda.testing.core.*
import net.corda.testing.internal.rigorousMock
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.StartedMockNode
import net.corda.testing.node.MockServices
import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
import net.corda.testing.node.startFlow
import org.junit.After
import org.junit.Before
@ -29,10 +30,10 @@ class CollectSignaturesFlowTests {
private val miniCorp = TestIdentity(CordaX500Name("MiniCorp", "London", "GB"))
}
private lateinit var mockNet: MockNetwork
private lateinit var aliceNode: StartedMockNode
private lateinit var bobNode: StartedMockNode
private lateinit var charlieNode: StartedMockNode
private lateinit var mockNet: InternalMockNetwork
private lateinit var aliceNode: StartedNode<MockNode>
private lateinit var bobNode: StartedNode<MockNode>
private lateinit var charlieNode: StartedNode<MockNode>
private lateinit var alice: Party
private lateinit var bob: Party
private lateinit var charlie: Party
@ -40,7 +41,7 @@ class CollectSignaturesFlowTests {
@Before
fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
aliceNode = mockNet.createPartyNode(ALICE_NAME)
bobNode = mockNet.createPartyNode(BOB_NAME)
charlieNode = mockNet.createPartyNode(CHARLIE_NAME)

View File

@ -7,9 +7,9 @@ import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.nodeapi.internal.crypto.X509KeyStore
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.testing.core.DEV_ROOT_CA
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.core.getTestPartyAndCertificate
import net.corda.testing.internal.DEV_ROOT_CA
import org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import org.junit.Test

View File

@ -8,10 +8,11 @@ import net.corda.core.identity.Party
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.sequence
import net.corda.node.internal.StartedNode
import net.corda.testing.contracts.DummyContract
import net.corda.testing.node.MockNetwork
import net.corda.testing.core.singleIdentity
import net.corda.testing.node.StartedMockNode
import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
import net.corda.testing.node.startFlow
import org.junit.After
import org.junit.Before
@ -27,17 +28,17 @@ import kotlin.test.assertNull
// DOCSTART 3
class ResolveTransactionsFlowTest {
private lateinit var mockNet: MockNetwork
private lateinit var notaryNode: StartedMockNode
private lateinit var megaCorpNode: StartedMockNode
private lateinit var miniCorpNode: StartedMockNode
private lateinit var mockNet: InternalMockNetwork
private lateinit var notaryNode: StartedNode<MockNode>
private lateinit var megaCorpNode: StartedNode<MockNode>
private lateinit var miniCorpNode: StartedNode<MockNode>
private lateinit var megaCorp: Party
private lateinit var miniCorp: Party
private lateinit var notary: Party
@Before
fun setup() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
notaryNode = mockNet.defaultNotaryNode
megaCorpNode = mockNet.createPartyNode(CordaX500Name("MegaCorp", "London", "GB"))
miniCorpNode = mockNet.createPartyNode(CordaX500Name("MiniCorp", "London", "GB"))

View File

@ -10,6 +10,7 @@ import net.corda.core.identity.Party
import net.corda.node.services.api.IdentityServiceInternal
import net.corda.testing.contracts.DummyContract
import net.corda.testing.core.*
import net.corda.testing.internal.MockCordappProvider
import net.corda.testing.internal.rigorousMock
import net.corda.testing.node.MockServices
import org.junit.Before
@ -37,7 +38,7 @@ class LedgerTransactionQueryTests {
@Before
fun setup() {
services.mockCordappProvider.addMockCordapp(DummyContract.PROGRAM_ID, services.attachments)
services.addMockCordapp(DummyContract.PROGRAM_ID)
}
interface Commands {

View File

@ -74,16 +74,14 @@ class CustomVaultQueryTest {
private fun getBalances(): Pair<Map<Currency, Amount<Currency>>, Map<Currency, Amount<Currency>>> {
// Print out the balances
val balancesNodesA =
nodeA.database.transaction {
nodeA.services.getCashBalances()
}
val balancesNodesA = nodeA.transaction {
nodeA.services.getCashBalances()
}
println("BalanceA\n" + balancesNodesA)
val balancesNodesB =
nodeB.database.transaction {
nodeB.services.getCashBalances()
}
val balancesNodesB = nodeB.transaction {
nodeB.services.getCashBalances()
}
println("BalanceB\n" + balancesNodesB)
return Pair(balancesNodesA, balancesNodesB)

View File

@ -68,13 +68,14 @@ class FxTransactionBuildTutorialTest {
doIt.getOrThrow()
// Get the balances when the vault updates
nodeAVaultUpdate.get()
val balancesA = nodeA.database.transaction {
val balancesA = nodeA.transaction {
nodeA.services.getCashBalances()
}
nodeBVaultUpdate.get()
val balancesB = nodeB.database.transaction {
val balancesB = nodeB.transaction {
nodeB.services.getCashBalances()
}
println("BalanceA\n" + balancesA)
println("BalanceB\n" + balancesB)
// Verify the transfers occurred as expected
@ -86,10 +87,10 @@ class FxTransactionBuildTutorialTest {
private fun printBalances() {
// Print out the balances
nodeA.database.transaction {
nodeA.transaction {
println("BalanceA\n" + nodeA.services.getCashBalances())
}
nodeB.database.transaction {
nodeB.transaction {
println("BalanceB\n" + nodeB.services.getCashBalances())
}
}

View File

@ -49,7 +49,7 @@ class CashPaymentFlowTests {
val expectedPayment = 500.DOLLARS
val expectedChange = 1500.DOLLARS
bankOfCordaNode.database.transaction {
bankOfCordaNode.transaction {
// Register for vault updates
val criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)
val (_, vaultUpdatesBoc) = bankOfCordaNode.services.vaultService.trackBy<Cash.State>(criteria)

View File

@ -5,6 +5,7 @@ apply plugin: 'com.jfrog.artifactory'
description "Generates a summary of the artifact's public API"
repositories {
mavenLocal()
mavenCentral()
}
@ -17,3 +18,4 @@ dependencies {
publish {
name project.name
}

View File

@ -202,6 +202,14 @@ public class ScanApi extends DefaultTask {
// These classes belong to internal Corda packages.
return;
}
if (className.contains("$$inlined$")) {
/*
* These classes are internally generated by the Kotlin compiler
* and are not exposed as part of the public API
* TODO: Filter out using EnclosingMethod attribute in classfile
*/
return;
}
ClassInfo classInfo = allInfo.get(className);
if (classInfo.getClassLoaders() == null) {
// Ignore classes that belong to one of our target ClassLoader's parents.
@ -275,6 +283,7 @@ public class ScanApi extends DefaultTask {
for (MethodInfo method : methods) {
if (isVisible(method.getAccessFlags()) // Only public and protected methods
&& isValid(method.getAccessFlags(), METHOD_MASK) // Excludes bridge and synthetic methods
&& !hasCordaInternal(method.getAnnotationNames()) // Excludes methods annotated as @CordaInternal
&& !isKotlinInternalScope(method)) {
writer.append(" ").println(filterAnnotationsFor(method));
}
@ -355,6 +364,10 @@ public class ScanApi extends DefaultTask {
return method.getMethodName().indexOf('$') >= 0;
}
private static boolean hasCordaInternal(Collection<String> annotationNames) {
return annotationNames.contains("net.corda.core.CordaInternal");
}
private static boolean isValid(int modifiers, int mask) {
return (modifiers & mask) == modifiers;
}

View File

@ -13,25 +13,26 @@ import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.internal.deleteIfExists
import net.corda.core.internal.div
import net.corda.core.node.NotaryInfo
import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.Try
import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.StartedNode
import net.corda.node.services.config.BFTSMaRtConfiguration
import net.corda.node.services.config.NotaryConfig
import net.corda.node.services.transactions.minClusterSize
import net.corda.node.services.transactions.minCorrectReplicas
import net.corda.nodeapi.internal.DevIdentityGenerator
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.core.node.NotaryInfo
import net.corda.testing.core.chooseIdentity
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.contracts.DummyContract
import net.corda.testing.core.chooseIdentity
import net.corda.testing.core.dummyCommand
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.StartedMockNode
import net.corda.testing.node.MockNodeParameters
import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.internal.InternalMockNetwork.MockNode
import net.corda.testing.node.startFlow
import org.junit.After
import org.junit.Before
@ -41,13 +42,13 @@ import kotlin.test.assertEquals
import kotlin.test.assertTrue
class BFTNotaryServiceTests {
private lateinit var mockNet: MockNetwork
private lateinit var mockNet: InternalMockNetwork
private lateinit var notary: Party
private lateinit var node: StartedMockNode
private lateinit var node: StartedNode<MockNode>
@Before
fun before() {
mockNet = MockNetwork(emptyList())
mockNet = InternalMockNetwork(emptyList())
}
@After
@ -153,7 +154,7 @@ class BFTNotaryServiceTests {
}
}
private fun StartedMockNode.signInitialTransaction(notary: Party, block: TransactionBuilder.() -> Any?): SignedTransaction {
private fun StartedNode<MockNode>.signInitialTransaction(notary: Party, block: TransactionBuilder.() -> Any?): SignedTransaction {
return services.signInitialTransaction(
TransactionBuilder(notary).apply {
addCommand(dummyCommand(services.myInfo.chooseIdentity().owningKey))

View File

@ -17,6 +17,7 @@ import net.corda.testing.driver.driver
import net.corda.testing.core.dummyCommand
import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.InProcess
import net.corda.testing.driver.internal.InProcessImpl
import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.NotarySpec
import net.corda.testing.node.startFlow
@ -62,7 +63,7 @@ class RaftNotaryServiceTests {
}
private fun issueState(nodeHandle: InProcess, notary: Party): StateAndRef<*> {
return nodeHandle.database.transaction {
return (nodeHandle as InProcessImpl).database.transaction {
val builder = DummyContract.generateInitial(Random().nextInt(), notary, nodeHandle.services.myInfo.chooseIdentity().ref(0))
val stx = nodeHandle.services.signInitialTransaction(builder)

View File

@ -16,10 +16,10 @@ import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.DEV_ROOT_CA
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.core.singleIdentity
import net.corda.testing.driver.PortAllocation
import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.node.NotarySpec
import net.corda.testing.node.internal.CompatibilityZoneParams
import net.corda.testing.node.internal.internalDriver

View File

@ -1,4 +1,4 @@
package net.corda.node.internal
package net.corda.node
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext

View File

@ -30,6 +30,7 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.debug
import net.corda.core.utilities.getOrThrow
import net.corda.node.CordaClock
import net.corda.node.VersionInfo
import net.corda.node.internal.classloading.requireAnnotation
import net.corda.node.internal.cordapp.CordappLoader

View File

@ -15,6 +15,8 @@ import net.corda.core.serialization.internal.SerializationEnvironmentImpl
import net.corda.core.serialization.internal.nodeSerializationEnv
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.contextLogger
import net.corda.node.CordaClock
import net.corda.node.SimpleClock
import net.corda.node.VersionInfo
import net.corda.node.internal.artemis.ArtemisBroker
import net.corda.node.internal.artemis.BrokerAddresses

View File

@ -21,8 +21,8 @@ import net.corda.core.schemas.PersistentStateRef
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.trace
import net.corda.node.internal.CordaClock
import net.corda.node.internal.MutableClock
import net.corda.node.CordaClock
import net.corda.node.MutableClock
import net.corda.node.services.api.FlowStarter
import net.corda.node.services.api.NodePropertiesStore
import net.corda.node.services.api.SchedulerService

View File

@ -1,7 +1,7 @@
package net.corda.node.utilities
import net.corda.core.internal.until
import net.corda.node.internal.MutableClock
import net.corda.node.MutableClock
import java.time.Clock
import java.time.LocalDate
import javax.annotation.concurrent.ThreadSafe

View File

@ -11,6 +11,8 @@ import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.crypto.x509Certificates
import net.corda.testing.core.*
import net.corda.testing.internal.DEV_INTERMEDIATE_CA
import net.corda.testing.internal.DEV_ROOT_CA
import org.junit.Rule
import org.junit.Test
import kotlin.test.assertEquals

View File

@ -15,6 +15,8 @@ import net.corda.nodeapi.internal.crypto.x509Certificates
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.core.*
import net.corda.testing.internal.DEV_INTERMEDIATE_CA
import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.node.makeTestIdentityService
import org.junit.After

View File

@ -6,9 +6,9 @@ import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
import net.corda.node.services.api.NetworkMapCacheInternal
import net.corda.testing.core.getTestPartyAndCertificate
import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNodeParameters
import net.corda.testing.core.singleIdentity
import net.corda.testing.node.internal.InternalMockNetwork
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Test
@ -18,7 +18,7 @@ import kotlin.test.assertNotNull
import kotlin.test.assertNull
class NetworkMapCacheTest {
private val mockNet = MockNetwork(emptyList())
private val mockNet = InternalMockNetwork(emptyList())
@After
fun teardown() {

View File

@ -7,10 +7,10 @@ import net.corda.core.serialization.serialize
import net.corda.core.utilities.seconds
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.DEV_ROOT_CA
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.driver.PortAllocation
import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.internal.TestNodeInfoBuilder
import net.corda.testing.internal.createNodeInfoAndSigned
import net.corda.testing.internal.signWith

View File

@ -28,6 +28,7 @@ import net.corda.nodeapi.internal.network.ParametersUpdate
import net.corda.nodeapi.internal.network.verifiedNetworkMapCert
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.*
import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.internal.TestNodeInfoBuilder
import net.corda.testing.internal.createNodeInfoAndSigned
import org.assertj.core.api.Assertions.assertThat

View File

@ -12,9 +12,9 @@ import net.corda.nodeapi.internal.network.NETWORK_PARAMS_UPDATE_FILE_NAME
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.network.verifiedNetworkMapCert
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.DEV_ROOT_CA
import net.corda.testing.core.SerializationEnvironmentRule
import net.corda.testing.driver.PortAllocation
import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.node.internal.network.NetworkMapServer
import org.junit.After
import org.junit.Before

View File

@ -14,6 +14,7 @@ import net.corda.node.services.schema.NodeSchemaService.NodeNotaryV1
import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.InProcess
import net.corda.testing.driver.driver
import net.corda.testing.driver.internal.InProcessImpl
import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
import net.corda.testing.node.MockNetwork
import org.hibernate.annotations.Cascade
@ -80,7 +81,7 @@ class NodeSchemaServiceTest {
fun `custom schemas are loaded eagerly`() {
val expected = setOf("PARENTS", "CHILDREN")
val tables = driver(DriverParameters(startNodesInProcess = true)) {
(defaultNotaryNode.getOrThrow() as InProcess).database.transaction {
(defaultNotaryNode.getOrThrow() as InProcessImpl).database.transaction {
session.createNativeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES").list()
}
}

View File

@ -8,8 +8,8 @@ import com.google.common.util.concurrent.SettableFuture
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.hours
import net.corda.core.utilities.minutes
import net.corda.node.internal.CordaClock
import net.corda.node.internal.SimpleClock
import net.corda.node.CordaClock
import net.corda.node.SimpleClock
import net.corda.node.services.events.NodeSchedulerService
import net.corda.testing.node.TestClock
import org.junit.After

View File

@ -25,6 +25,7 @@ import java.net.InetSocketAddress
import java.net.ServerSocket
import java.nio.file.Path
import java.nio.file.Paths
import java.sql.Connection
import java.util.concurrent.atomic.AtomicInteger
/**
@ -58,7 +59,6 @@ interface OutOfProcess : NodeHandle {
@DoNotImplement
interface InProcess : NodeHandle {
val database: CordaPersistence
val services: StartedNodeServices
/**
* Register a flow that is initiated by another flow

View File

@ -15,6 +15,7 @@ import net.corda.testing.driver.OutOfProcess
import net.corda.testing.node.User
import rx.Observable
import java.nio.file.Path
import java.sql.Connection
interface NodeHandleInternal : NodeHandle {
val configuration: NodeConfiguration
@ -57,7 +58,7 @@ data class InProcessImpl(
private val onStopCallback: () -> Unit,
private val node: StartedNode<Node>
) : InProcess, NodeHandleInternal {
override val database: CordaPersistence get() = node.database
val database: CordaPersistence = node.database
override val services: StartedNodeServices get() = node.services
override val rpcUsers: List<User> = configuration.rpcUsers.map { User(it.username, it.password, it.permissions) }
override fun stop() {

View File

@ -1,5 +1,6 @@
package net.corda.testing.node
import net.corda.core.CordaInternal
import net.corda.core.DoNotImplement
import net.corda.core.crypto.CompositeKey
import net.corda.core.identity.CordaX500Name
@ -48,7 +49,7 @@ import kotlin.concurrent.thread
* a service is addressed.
*/
@ThreadSafe
class InMemoryMessagingNetwork internal constructor(
class InMemoryMessagingNetwork private constructor(
private val sendManuallyPumped: Boolean,
private val servicePeerAllocationStrategy: ServicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(),
private val messagesInFlight: ReusableLatch = ReusableLatch()
@ -56,6 +57,13 @@ class InMemoryMessagingNetwork internal constructor(
companion object {
private const val MESSAGES_LOG_NAME = "messages"
private val log = LoggerFactory.getLogger(MESSAGES_LOG_NAME)
internal fun create(
sendManuallyPumped: Boolean,
servicePeerAllocationStrategy: ServicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random(),
messagesInFlight: ReusableLatch = ReusableLatch()): InMemoryMessagingNetwork {
return InMemoryMessagingNetwork(sendManuallyPumped, servicePeerAllocationStrategy, messagesInFlight)
}
}
private var counter = 0 // -1 means stopped.
@ -115,7 +123,8 @@ class InMemoryMessagingNetwork internal constructor(
val peerHandle = PeerHandle(id, description)
peersMapping[peerHandle.description] = peerHandle // Assume that the same name - the same entity in MockNetwork.
notaryService?.let { if (it.owningKey !is CompositeKey) peersMapping[it.name] = peerHandle }
val serviceHandles = notaryService?.let { listOf(ServiceHandle(it.party)) } ?: emptyList() //TODO only notary can be distributed?
val serviceHandles = notaryService?.let { listOf(ServiceHandle(it.party)) }
?: emptyList() //TODO only notary can be distributed?
synchronized(this) {
val node = InMemoryMessaging(manuallyPumped, peerHandle, executor, database)
handleEndpointMap[peerHandle] = node
@ -304,7 +313,8 @@ class InMemoryMessagingNetwork internal constructor(
override fun getAddressOfParty(partyInfo: PartyInfo): MessageRecipients {
return when (partyInfo) {
is PartyInfo.SingleNode -> peersMapping[partyInfo.party.name] ?: throw IllegalArgumentException("No StartedMockNode for party ${partyInfo.party.name}")
is PartyInfo.SingleNode -> peersMapping[partyInfo.party.name]
?: throw IllegalArgumentException("No StartedMockNode for party ${partyInfo.party.name}")
is PartyInfo.DistributedNode -> ServiceHandle(partyInfo.party)
}
}

View File

@ -13,6 +13,8 @@ import net.corda.node.services.api.StartedNodeServices
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.messaging.MessagingService
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseTransaction
import net.corda.nodeapi.internal.persistence.TransactionIsolationLevel
import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.testing.node.internal.InternalMockNetwork
import net.corda.testing.node.internal.setMessagingServiceSpy
@ -87,7 +89,6 @@ class StartedMockNode private constructor(private val node: StartedNode<Internal
}
val services get() : StartedNodeServices = node.services
val database get() : CordaPersistence = node.database
val id get() : Int = node.internals.id
val info get() : NodeInfo = node.services.myInfo
val network get() : MessagingService = node.network
@ -110,6 +111,16 @@ class StartedMockNode private constructor(private val node: StartedNode<Internal
/** Returns the currently live flows of type [flowClass], and their corresponding result future. */
fun <F : FlowLogic<*>> findStateMachines(flowClass: Class<F>): List<Pair<F, CordaFuture<*>>> = node.smm.findStateMachines(flowClass)
/**
* Executes given statement in the scope of a transaction.
* @param statement to be executed in the scope of this transaction.
*/
fun <T> transaction(statement: () -> T): T {
return node.database.transaction {
statement()
}
}
}
/**
@ -211,4 +222,4 @@ open class MockNetwork(
/** Get the base directory for the given node id. **/
fun baseDirectory(nodeId: Int): Path = internalMockNetwork.baseDirectory(nodeId)
}
}

View File

@ -1,6 +1,7 @@
package net.corda.testing.node
import com.google.common.collect.MutableClassToInstanceMap
import net.corda.core.contracts.ContractClassName
import net.corda.core.cordapp.CordappProvider
import net.corda.core.crypto.*
import net.corda.core.flows.FlowLogic
@ -31,11 +32,10 @@ import net.corda.node.services.vault.NodeVaultService
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.nodeapi.internal.persistence.HibernateConfiguration
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.DEV_ROOT_CA
import net.corda.testing.core.TestIdentity
import net.corda.testing.internal.DEV_ROOT_CA
import net.corda.testing.services.MockAttachmentStorage
import net.corda.testing.services.MockCordappProvider
import net.corda.testing.internal.MockCordappProvider
import org.bouncycastle.operator.ContentSigner
import rx.Observable
import rx.subjects.PublishSubject
@ -209,7 +209,7 @@ open class MockServices private constructor(
return NodeInfo(emptyList(), listOf(initialIdentity.identity), 1, serial = 1L)
}
override val transactionVerifierService: TransactionVerifierService get() = InMemoryTransactionVerifierService(2)
val mockCordappProvider = MockCordappProvider(cordappLoader, attachments)
private val mockCordappProvider: MockCordappProvider = MockCordappProvider(cordappLoader, attachments)
override val cordappProvider: CordappProvider get() = mockCordappProvider
internal fun makeVaultService(hibernateConfig: HibernateConfiguration, schemaService: SchemaService): VaultServiceInternal {
@ -221,12 +221,17 @@ open class MockServices private constructor(
val cordappServices: MutableClassToInstanceMap<SerializeAsToken> = MutableClassToInstanceMap.create<SerializeAsToken>()
override fun <T : SerializeAsToken> cordaService(type: Class<T>): T {
require(type.isAnnotationPresent(CordaService::class.java)) { "${type.name} is not a Corda service" }
return cordappServices.getInstance(type) ?: throw IllegalArgumentException("Corda service ${type.name} does not exist")
return cordappServices.getInstance(type)
?: throw IllegalArgumentException("Corda service ${type.name} does not exist")
}
override fun jdbcSession(): Connection = throw UnsupportedOperationException()
override fun registerUnloadHandler(runOnStop: () -> Unit) = throw UnsupportedOperationException()
fun addMockCordapp(contractClassName: ContractClassName) {
mockCordappProvider.addMockCordapp(contractClassName, attachments)
}
}
class MockKeyManagementService(val identityService: IdentityService,
@ -252,7 +257,8 @@ class MockKeyManagementService(val identityService: IdentityService,
private fun getSigner(publicKey: PublicKey): ContentSigner = getSigner(getSigningKeyPair(publicKey))
private fun getSigningKeyPair(publicKey: PublicKey): KeyPair {
val pk = publicKey.keys.firstOrNull { keyStore.containsKey(it) } ?: throw IllegalArgumentException("Public key not found: ${publicKey.toStringShort()}")
val pk = publicKey.keys.firstOrNull { keyStore.containsKey(it) }
?: throw IllegalArgumentException("Public key not found: ${publicKey.toStringShort()}")
return KeyPair(pk, keyStore[pk]!!)
}

View File

@ -1,7 +1,7 @@
package net.corda.testing.node
import net.corda.core.internal.until
import net.corda.node.internal.MutableClock
import net.corda.node.MutableClock
import java.time.Clock
import java.time.Duration
import java.time.Instant

View File

@ -43,7 +43,7 @@ import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.DUMMY_BANK_A_NAME
import net.corda.testing.core.setGlobalSerialization
import net.corda.testing.internal.setGlobalSerialization
import net.corda.testing.driver.*
import net.corda.testing.driver.internal.InProcessImpl
import net.corda.testing.driver.internal.NodeHandleInternal

View File

@ -46,12 +46,13 @@ import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.setGlobalSerialization
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.testThreadFactory
import net.corda.testing.node.*
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.internal.setGlobalSerialization
import net.corda.testing.node.TestClock
import org.apache.activemq.artemis.utils.ReusableLatch
import org.apache.sshd.common.util.security.SecurityUtils
import rx.internal.schedulers.CachedThreadScheduler
@ -111,7 +112,7 @@ open class InternalMockNetwork(private val cordappPackages: List<String>,
private set
private val filesystem = Jimfs.newFileSystem(unix())
private val busyLatch = ReusableLatch()
val messagingNetwork = InMemoryMessagingNetwork(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch)
val messagingNetwork = InMemoryMessagingNetwork.create(networkSendManuallyPumped, servicePeerAllocationStrategy, busyLatch)
// A unique identifier for this network to segregate databases with the same nodeID but different networks.
private val networkId = random63BitValue()
private val networkParameters: NetworkParametersCopier

View File

@ -16,6 +16,8 @@ import net.corda.nodeapi.internal.serialization.*
import net.corda.nodeapi.internal.serialization.amqp.AMQPClientSerializationScheme
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
import net.corda.testing.common.internal.asContextEnv
import net.corda.testing.internal.createTestSerializationEnv
import net.corda.testing.internal.inVMExecutors
import net.corda.testing.internal.rigorousMock
import net.corda.testing.internal.testThreadFactory
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnector
@ -26,8 +28,6 @@ import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
private val inVMExecutors = ConcurrentHashMap<SerializationEnvironment, ExecutorService>()
/** @param inheritable whether new threads inherit the environment, use sparingly. */
class SerializationEnvironmentRule(private val inheritable: Boolean = false) : TestRule {
companion object {
@ -78,42 +78,3 @@ interface GlobalSerializationEnvironment : SerializationEnvironment {
fun unset()
}
/**
* Should only be used by Driver and MockNode.
* @param armed true to install, false to do nothing and return a dummy env.
*/
fun setGlobalSerialization(armed: Boolean): GlobalSerializationEnvironment {
return if (armed) {
object : GlobalSerializationEnvironment, SerializationEnvironment by createTestSerializationEnv("<global>") {
override fun unset() {
_globalSerializationEnv.set(null)
inVMExecutors.remove(this)
}
}.also {
_globalSerializationEnv.set(it)
}
} else {
rigorousMock<GlobalSerializationEnvironment>().also {
doNothing().whenever(it).unset()
}
}
}
private fun createTestSerializationEnv(label: String): SerializationEnvironmentImpl {
val factory = SerializationFactoryImpl().apply {
registerScheme(KryoClientSerializationScheme())
registerScheme(KryoServerSerializationScheme())
registerScheme(AMQPClientSerializationScheme(emptyList()))
registerScheme(AMQPServerSerializationScheme(emptyList()))
}
return object : SerializationEnvironmentImpl(
factory,
AMQP_P2P_CONTEXT,
KRYO_RPC_SERVER_CONTEXT,
KRYO_RPC_CLIENT_CONTEXT,
AMQP_STORAGE_CONTEXT,
KRYO_CHECKPOINT_CONTEXT
) {
override fun toString() = "testSerializationEnv($label)"
}
}

View File

@ -30,10 +30,6 @@ val BOB_NAME = CordaX500Name("Bob Plc", "Rome", "IT")
@JvmField
val CHARLIE_NAME = CordaX500Name("Charlie Ltd", "Athens", "GR")
val DEV_INTERMEDIATE_CA: CertificateAndKeyPair by lazy { net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA }
val DEV_ROOT_CA: CertificateAndKeyPair by lazy { net.corda.nodeapi.internal.DEV_ROOT_CA }
fun dummyCommand(vararg signers: PublicKey = arrayOf(generateKeyPair().public)) = Command<TypeOnlyCommandData>(DummyCommandData, signers.toList())
object DummyCommandData : TypeOnlyCommandData()

View File

@ -20,6 +20,8 @@ import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.testing.internal.DEV_INTERMEDIATE_CA
import net.corda.testing.internal.DEV_ROOT_CA
import java.math.BigInteger
import java.security.KeyPair
import java.security.PublicKey

View File

@ -14,7 +14,7 @@ import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction
import net.corda.testing.services.MockAttachmentStorage
import net.corda.testing.services.MockCordappProvider
import net.corda.testing.internal.MockCordappProvider
import net.corda.testing.core.dummyCommand
import java.io.InputStream
import java.security.PublicKey

View File

@ -1,8 +1,19 @@
package net.corda.testing.internal
import net.corda.core.serialization.internal._contextSerializationEnv
import net.corda.core.serialization.internal._inheritableContextSerializationEnv
import com.nhaarman.mockito_kotlin.doNothing
import com.nhaarman.mockito_kotlin.whenever
import net.corda.client.rpc.internal.KryoClientSerializationScheme
import net.corda.core.serialization.internal.*
import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.nodeapi.internal.serialization.*
import net.corda.nodeapi.internal.serialization.amqp.AMQPClientSerializationScheme
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
import net.corda.testing.core.GlobalSerializationEnvironment
import net.corda.testing.core.SerializationEnvironmentRule
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ExecutorService
val inVMExecutors = ConcurrentHashMap<SerializationEnvironment, ExecutorService>()
/**
* For example your test class uses [SerializationEnvironmentRule] but you want to turn it off for one method.
@ -17,3 +28,43 @@ fun <T> withoutTestSerialization(callable: () -> T): T { // TODO: Delete this, s
property.set(env)
}
}
internal fun createTestSerializationEnv(label: String): SerializationEnvironmentImpl {
val factory = SerializationFactoryImpl().apply {
registerScheme(KryoClientSerializationScheme())
registerScheme(KryoServerSerializationScheme())
registerScheme(AMQPClientSerializationScheme(emptyList()))
registerScheme(AMQPServerSerializationScheme(emptyList()))
}
return object : SerializationEnvironmentImpl(
factory,
AMQP_P2P_CONTEXT,
KRYO_RPC_SERVER_CONTEXT,
KRYO_RPC_CLIENT_CONTEXT,
AMQP_STORAGE_CONTEXT,
KRYO_CHECKPOINT_CONTEXT
) {
override fun toString() = "testSerializationEnv($label)"
}
}
/**
* Should only be used by Driver and MockNode.
* @param armed true to install, false to do nothing and return a dummy env.
*/
fun setGlobalSerialization(armed: Boolean): GlobalSerializationEnvironment {
return if (armed) {
object : GlobalSerializationEnvironment, SerializationEnvironment by createTestSerializationEnv("<global>") {
override fun unset() {
_globalSerializationEnv.set(null)
inVMExecutors.remove(this)
}
}.also {
_globalSerializationEnv.set(it)
}
} else {
rigorousMock<GlobalSerializationEnvironment>().also {
doNothing().whenever(it).unset()
}
}
}

View File

@ -0,0 +1,7 @@
package net.corda.testing.internal
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
val DEV_INTERMEDIATE_CA: CertificateAndKeyPair by lazy { net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA }
val DEV_ROOT_CA: CertificateAndKeyPair by lazy { net.corda.nodeapi.internal.DEV_ROOT_CA }

View File

@ -1,4 +1,4 @@
package net.corda.testing.services
package net.corda.testing.internal
import net.corda.core.contracts.ContractClassName
import net.corda.core.cordapp.Cordapp
@ -7,6 +7,7 @@ import net.corda.core.node.services.AttachmentId
import net.corda.core.node.services.AttachmentStorage
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.internal.cordapp.CordappProviderImpl
import net.corda.testing.services.MockAttachmentStorage
import java.nio.file.Paths
import java.util.*
@ -24,7 +25,7 @@ class MockCordappProvider(cordappLoader: CordappLoader, attachmentStorage: Attac
serializationWhitelists = emptyList(),
serializationCustomSerializers = emptyList(),
customSchemas = emptySet(),
jarPath = Paths.get(".").toUri().toURL())
jarPath = Paths.get("").toUri().toURL())
if (cordappRegistry.none { it.first.contractClassNames.contains(contractClassName) }) {
cordappRegistry.add(Pair(cordapp, findOrImportAttachment(contractClassName.toByteArray(), attachments)))
}

View File

@ -12,8 +12,6 @@ import net.corda.nodeapi.internal.createDevNodeCa
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.testing.core.DEV_INTERMEDIATE_CA
import net.corda.testing.core.DEV_ROOT_CA
import java.security.KeyPair
import java.security.PrivateKey
import java.security.cert.X509Certificate

View File

@ -43,11 +43,11 @@ class MockAttachmentStorage : AttachmentStorage, SingletonSerializeAsToken() {
val files = HashMap<SecureHash, ByteArray>()
private class MockAttachment(dataLoader: () -> ByteArray, override val id: SecureHash): AbstractAttachment(dataLoader)
override fun openAttachment(id: SecureHash): Attachment? {
val f = files[id] ?: return null
return object : AbstractAttachment({ f }) {
override val id = id
}
return MockAttachment({f}, id)
}
override fun queryAttachments(criteria: AttachmentQueryCriteria, sorting: AttachmentSort?): List<AttachmentId> {