mirror of
https://github.com/corda/corda.git
synced 2025-06-17 14:48:16 +00:00
BFT tests no longer use NodeBasedTest (#917)
* Move Raft config to the interface * Inline method only used in 1 test
This commit is contained in:
@ -1,55 +1,63 @@
|
||||
package net.corda.node.services
|
||||
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.google.common.net.HostAndPort
|
||||
import com.nhaarman.mockito_kotlin.whenever
|
||||
import net.corda.core.*
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.appendToCommonName
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.ALICE
|
||||
import net.corda.core.utilities.DUMMY_NOTARY
|
||||
import net.corda.flows.NotaryError
|
||||
import net.corda.flows.NotaryException
|
||||
import net.corda.flows.NotaryFlow
|
||||
import net.corda.node.internal.AbstractNode
|
||||
import net.corda.node.services.network.NetworkMapService
|
||||
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
||||
import net.corda.node.services.transactions.minClusterSize
|
||||
import net.corda.node.services.transactions.minCorrectReplicas
|
||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import net.corda.node.utilities.transaction
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.junit.Ignore
|
||||
import org.junit.After
|
||||
import org.junit.Test
|
||||
import java.nio.file.Files
|
||||
import kotlin.test.*
|
||||
|
||||
class BFTNotaryServiceTests : NodeBasedTest() {
|
||||
class BFTNotaryServiceTests {
|
||||
companion object {
|
||||
private val clusterName = X500Name("CN=BFT,O=R3,OU=corda,L=Zurich,C=CH")
|
||||
private val serviceType = BFTNonValidatingNotaryService.type
|
||||
}
|
||||
|
||||
private fun bftNotaryCluster(clusterSize: Int): ListenableFuture<Party> {
|
||||
private val mockNet = MockNetwork()
|
||||
private val node = mockNet.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||
@After
|
||||
fun stopNodes() {
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
|
||||
private fun bftNotaryCluster(clusterSize: Int): Party {
|
||||
Files.deleteIfExists("config" / "currentView") // XXX: Make config object warn if this exists?
|
||||
val replicaIds = (0 until clusterSize)
|
||||
val replicaNames = replicaIds.map { DUMMY_NOTARY.name.appendToCommonName(" $it") }
|
||||
val party = ServiceIdentityGenerator.generateToDisk(
|
||||
replicaNames.map { baseDirectory(it) },
|
||||
replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) },
|
||||
serviceType.id,
|
||||
clusterName)
|
||||
val advertisedServices = setOf(ServiceInfo(serviceType, clusterName))
|
||||
val config = mapOf("notaryClusterAddresses" to replicaIds.map { "localhost:${11000 + it * 10}" })
|
||||
return Futures.allAsList(replicaIds.map {
|
||||
startNode(
|
||||
replicaNames[it],
|
||||
advertisedServices = advertisedServices,
|
||||
configOverrides = mapOf("bftReplicaId" to it) + config
|
||||
)
|
||||
}).map { party }
|
||||
val bftNotaryService = ServiceInfo(serviceType, clusterName)
|
||||
val notaryClusterAddresses = replicaIds.map { HostAndPort.fromParts("localhost", 11000 + it * 10) }
|
||||
replicaIds.forEach { replicaId ->
|
||||
mockNet.createNode(
|
||||
node.info.address,
|
||||
advertisedServices = bftNotaryService,
|
||||
configOverrides = {
|
||||
whenever(it.bftReplicaId).thenReturn(replicaId)
|
||||
whenever(it.notaryClusterAddresses).thenReturn(notaryClusterAddresses)
|
||||
})
|
||||
}
|
||||
return party
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -66,9 +74,8 @@ class BFTNotaryServiceTests : NodeBasedTest() {
|
||||
|
||||
private fun detectDoubleSpend(faultyReplicas: Int) {
|
||||
val clusterSize = minClusterSize(faultyReplicas)
|
||||
val aliceFuture = startNode(ALICE.name)
|
||||
val notary = bftNotaryCluster(clusterSize).getOrThrow()
|
||||
aliceFuture.getOrThrow().run {
|
||||
val notary = bftNotaryCluster(clusterSize)
|
||||
node.run {
|
||||
val issueTx = signInitialTransaction(notary) {
|
||||
addOutputState(DummyContract.SingleOwnerState(owner = info.legalIdentity))
|
||||
}
|
||||
@ -83,6 +90,7 @@ class BFTNotaryServiceTests : NodeBasedTest() {
|
||||
assertEquals(spendTxs.size, spendTxs.map { it.id }.distinct().size)
|
||||
val flows = spendTxs.map { NotaryFlow.Client(it) }
|
||||
val stateMachines = flows.map { services.startFlow(it) }
|
||||
mockNet.runNetwork()
|
||||
val results = stateMachines.map { ErrorOr.catch { it.resultFuture.getOrThrow() } }
|
||||
val successfulIndex = results.mapIndexedNotNull { index, result ->
|
||||
if (result.error == null) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.corda.services.messaging
|
||||
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.nhaarman.mockito_kotlin.whenever
|
||||
import net.corda.core.crypto.X509Utilities
|
||||
import net.corda.core.crypto.cert
|
||||
import net.corda.core.getOrThrow
|
||||
@ -16,9 +17,9 @@ import net.corda.node.services.network.NetworkMapService.RegistrationRequest
|
||||
import net.corda.node.services.network.NodeRegistration
|
||||
import net.corda.node.utilities.AddOrRemove
|
||||
import net.corda.testing.MOCK_VERSION_INFO
|
||||
import net.corda.testing.TestNodeConfiguration
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import net.corda.testing.node.SimpleNode
|
||||
import net.corda.testing.testNodeConfiguration
|
||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
@ -57,10 +58,11 @@ class P2PSecurityTest : NodeBasedTest() {
|
||||
|
||||
private fun startSimpleNode(legalName: X500Name,
|
||||
trustRoot: X509Certificate): SimpleNode {
|
||||
val config = TestNodeConfiguration(
|
||||
val config = testNodeConfiguration(
|
||||
baseDirectory = baseDirectory(legalName),
|
||||
myLegalName = legalName,
|
||||
networkMapService = NetworkMapInfo(networkMapNode.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
|
||||
myLegalName = legalName).also {
|
||||
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
|
||||
}
|
||||
config.configureWithDevSSLCertificate() // This creates the node's TLS cert with the CN as the legal name
|
||||
return SimpleNode(config, trustRoot = trustRoot).apply { start() }
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ import net.corda.core.utilities.getTestPartyAndCertificate
|
||||
import net.corda.flows.*
|
||||
import net.corda.node.services.*
|
||||
import net.corda.node.services.api.*
|
||||
import net.corda.node.services.config.FullNodeConfiguration
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.config.configureWithDevSSLCertificate
|
||||
import net.corda.node.services.database.HibernateConfiguration
|
||||
@ -686,7 +685,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
ValidatingNotaryService.type -> ValidatingNotaryService(timeWindowChecker, uniquenessProvider)
|
||||
RaftNonValidatingNotaryService.type -> RaftNonValidatingNotaryService(timeWindowChecker, uniquenessProvider as RaftUniquenessProvider)
|
||||
RaftValidatingNotaryService.type -> RaftValidatingNotaryService(timeWindowChecker, uniquenessProvider as RaftUniquenessProvider)
|
||||
BFTNonValidatingNotaryService.type -> with(configuration as FullNodeConfiguration) {
|
||||
BFTNonValidatingNotaryService.type -> with(configuration) {
|
||||
val replicaId = bftReplicaId ?: throw IllegalArgumentException("bftReplicaId value must be specified in the configuration")
|
||||
BFTSMaRtConfig(notaryClusterAddresses).use { config ->
|
||||
BFTNonValidatingNotaryService(config, services, timeWindowChecker, replicaId, database).also {
|
||||
|
@ -26,6 +26,9 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
||||
val certificateChainCheckPolicies: List<CertChainPolicyConfig>
|
||||
val verifierType: VerifierType
|
||||
val messageRedeliveryDelaySeconds: Int
|
||||
val bftReplicaId: Int?
|
||||
val notaryNodeAddress: HostAndPort?
|
||||
val notaryClusterAddresses: List<HostAndPort>
|
||||
}
|
||||
|
||||
data class FullNodeConfiguration(
|
||||
@ -53,9 +56,9 @@ data class FullNodeConfiguration(
|
||||
// Instead this should be a Boolean indicating whether that broker is an internal one started by the node or an external one
|
||||
val messagingServerAddress: HostAndPort?,
|
||||
val extraAdvertisedServiceIds: List<String>,
|
||||
val bftReplicaId: Int?,
|
||||
val notaryNodeAddress: HostAndPort?,
|
||||
val notaryClusterAddresses: List<HostAndPort>,
|
||||
override val bftReplicaId: Int?,
|
||||
override val notaryNodeAddress: HostAndPort?,
|
||||
override val notaryClusterAddresses: List<HostAndPort>,
|
||||
override val certificateChainCheckPolicies: List<CertChainPolicyConfig>,
|
||||
override val devMode: Boolean = false,
|
||||
val useTestClock: Boolean = false,
|
||||
|
@ -1,21 +1,43 @@
|
||||
package net.corda.node.services.config
|
||||
|
||||
import com.google.common.net.HostAndPort
|
||||
import net.corda.core.crypto.commonName
|
||||
import net.corda.core.utilities.ALICE
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.testConfiguration
|
||||
import net.corda.testing.node.makeTestDataSourceProperties
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.junit.Test
|
||||
import java.net.URL
|
||||
import java.nio.file.Paths
|
||||
|
||||
class FullNodeConfigurationTest {
|
||||
@Test
|
||||
fun `Artemis special characters not permitted in RPC usernames`() {
|
||||
fun configWithRPCUsername(username: String): FullNodeConfiguration {
|
||||
return testConfiguration(Paths.get("."), ALICE.name, 0).copy(
|
||||
rpcUsers = listOf(User(username, "pass", emptySet())))
|
||||
}
|
||||
val testConfiguration = FullNodeConfiguration(
|
||||
basedir = Paths.get("."),
|
||||
myLegalName = ALICE.name,
|
||||
networkMapService = null,
|
||||
emailAddress = "",
|
||||
keyStorePassword = "cordacadevpass",
|
||||
trustStorePassword = "trustpass",
|
||||
dataSourceProperties = makeTestDataSourceProperties(ALICE.name.commonName),
|
||||
certificateSigningService = URL("http://localhost"),
|
||||
rpcUsers = emptyList(),
|
||||
verifierType = VerifierType.InMemory,
|
||||
useHTTPS = false,
|
||||
p2pAddress = HostAndPort.fromParts("localhost", 0),
|
||||
rpcAddress = HostAndPort.fromParts("localhost", 1),
|
||||
messagingServerAddress = null,
|
||||
extraAdvertisedServiceIds = emptyList(),
|
||||
bftReplicaId = null,
|
||||
notaryNodeAddress = null,
|
||||
notaryClusterAddresses = emptyList(),
|
||||
certificateChainCheckPolicies = emptyList(),
|
||||
devMode = true)
|
||||
|
||||
fun configWithRPCUsername(username: String) {
|
||||
testConfiguration.copy(rpcUsers = listOf(User(username, "pass", emptySet())))
|
||||
}
|
||||
assertThatThrownBy { configWithRPCUsername("user.1") }.hasMessageContaining(".")
|
||||
assertThatThrownBy { configWithRPCUsername("user*1") }.hasMessageContaining("*")
|
||||
assertThatThrownBy { configWithRPCUsername("user#1") }.hasMessageContaining("#")
|
||||
|
@ -22,10 +22,10 @@ import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
|
||||
import net.corda.node.utilities.configureDatabase
|
||||
import net.corda.node.utilities.transaction
|
||||
import net.corda.testing.MOCK_VERSION_INFO
|
||||
import net.corda.testing.TestNodeConfiguration
|
||||
import net.corda.testing.freeLocalHostAndPort
|
||||
import net.corda.testing.freePort
|
||||
import net.corda.testing.node.makeTestDataSourceProperties
|
||||
import net.corda.testing.testNodeConfiguration
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
@ -70,10 +70,9 @@ class ArtemisMessagingTests {
|
||||
fun setUp() {
|
||||
val baseDirectory = temporaryFolder.root.toPath()
|
||||
userService = RPCUserServiceImpl(emptyList())
|
||||
config = TestNodeConfiguration(
|
||||
config = testNodeConfiguration(
|
||||
baseDirectory = baseDirectory,
|
||||
myLegalName = ALICE.name,
|
||||
networkMapService = null)
|
||||
myLegalName = ALICE.name)
|
||||
LogHelper.setLevel(PersistentUniquenessProvider::class)
|
||||
val dataSourceAndDatabase = configureDatabase(makeTestDataSourceProperties())
|
||||
dataSource = dataSourceAndDatabase.first
|
||||
|
@ -7,8 +7,8 @@ import net.corda.core.crypto.*
|
||||
import net.corda.core.exists
|
||||
import net.corda.core.toTypedArray
|
||||
import net.corda.core.utilities.ALICE
|
||||
import net.corda.testing.TestNodeConfiguration
|
||||
import net.corda.testing.getTestX509Name
|
||||
import net.corda.testing.testNodeConfiguration
|
||||
import org.bouncycastle.cert.X509CertificateHolder
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@ -38,10 +38,9 @@ class NetworkRegistrationHelperTest {
|
||||
on { retrieveCertificates(eq(id)) }.then { certs }
|
||||
}
|
||||
|
||||
val config = TestNodeConfiguration(
|
||||
val config = testNodeConfiguration(
|
||||
baseDirectory = tempFolder.root.toPath(),
|
||||
myLegalName = ALICE.name,
|
||||
networkMapService = null)
|
||||
myLegalName = ALICE.name)
|
||||
|
||||
assertFalse(config.nodeKeystore.exists())
|
||||
assertFalse(config.sslKeystore.exists())
|
||||
|
Reference in New Issue
Block a user