mirror of
https://github.com/corda/corda.git
synced 2025-02-01 16:58:27 +00:00
Improve robustness of the integration tests that commonly have false positives (Clinton)
This commit is contained in:
parent
88b5e32ab2
commit
37dc6ead82
@ -37,6 +37,7 @@ configurations {
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
|
@ -3,7 +3,6 @@ package net.corda.irs
|
||||
import com.google.common.net.HostAndPort
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.core.crypto.toBase58String
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.DUMMY_BANK_A
|
||||
@ -19,7 +18,9 @@ import net.corda.node.services.config.FullNodeConfiguration
|
||||
import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.IntegrationTestCategory
|
||||
import net.corda.testing.http.HttpApi
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import rx.observables.BlockingObservable
|
||||
import java.net.URL
|
||||
@ -46,9 +47,15 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
).getOrThrow()
|
||||
|
||||
val nextFixingDates = getFixingDateObservable(nodeA.configuration)
|
||||
val numADeals = getTradeCount(nodeAAddr)
|
||||
val numBDeals = getTradeCount(nodeBAddr)
|
||||
|
||||
runUploadRates(controllerAddr)
|
||||
runTrade(nodeAAddr)
|
||||
|
||||
assertThat(getTradeCount(nodeAAddr)).isEqualTo(numADeals + 1)
|
||||
assertThat(getTradeCount(nodeBAddr)).isEqualTo(numBDeals + 1)
|
||||
|
||||
// Wait until the initial trade and all scheduled fixings up to the current date have finished
|
||||
nextFixingDates.first { it == null || it > currentDate }
|
||||
|
||||
@ -88,4 +95,10 @@ class IRSDemoTest : IntegrationTestCategory {
|
||||
val url = URL("http://$host/upload/interest-rates")
|
||||
assert(uploadFile(url, fileContents))
|
||||
}
|
||||
|
||||
private fun getTradeCount(nodeAddr: HostAndPort): Int {
|
||||
val api = HttpApi.fromHostAndPort(nodeAddr, "api/irs")
|
||||
val deals = api.getJson<Array<*>>("deals")
|
||||
return deals.size
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ configurations {
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
|
@ -15,6 +15,7 @@ import net.corda.vega.api.PortfolioApi
|
||||
import net.corda.vega.api.PortfolioApiUtils
|
||||
import net.corda.vega.api.SwapDataModel
|
||||
import net.corda.vega.api.SwapDataView
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import java.math.BigDecimal
|
||||
import java.time.LocalDate
|
||||
@ -22,13 +23,14 @@ import java.time.LocalDate
|
||||
class SimmValuationTest : IntegrationTestCategory {
|
||||
private companion object {
|
||||
// SIMM demo can only currently handle one valuation date due to a lack of market data or a market data source.
|
||||
val valuationDate = LocalDate.parse("2016-06-06")
|
||||
val valuationDate: LocalDate = LocalDate.parse("2016-06-06")
|
||||
val nodeALegalName = DUMMY_BANK_A.name
|
||||
val nodeBLegalName = DUMMY_BANK_B.name
|
||||
val testTradeId = "trade1"
|
||||
}
|
||||
|
||||
@Test fun `runs SIMM valuation demo`() {
|
||||
@Test
|
||||
fun `runs SIMM valuation demo`() {
|
||||
driver(isDebug = true) {
|
||||
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type))).getOrThrow()
|
||||
val (nodeA, nodeB) = Futures.allAsList(startNode(nodeALegalName), startNode(nodeBLegalName)).getOrThrow()
|
||||
@ -38,10 +40,12 @@ class SimmValuationTest : IntegrationTestCategory {
|
||||
val nodeBParty = getPartyWithName(nodeAApi, nodeBLegalName)
|
||||
val nodeAParty = getPartyWithName(nodeBApi, nodeALegalName)
|
||||
|
||||
assert(createTradeBetween(nodeAApi, nodeBParty, testTradeId))
|
||||
assert(tradeExists(nodeBApi, nodeAParty, testTradeId))
|
||||
assert(runValuationsBetween(nodeAApi, nodeBParty))
|
||||
assert(valuationExists(nodeBApi, nodeAParty))
|
||||
assertThat(createTradeBetween(nodeAApi, nodeBParty, testTradeId)).isTrue()
|
||||
assertTradeExists(nodeBApi, nodeAParty, testTradeId)
|
||||
assertTradeExists(nodeAApi, nodeBParty, testTradeId)
|
||||
assertThat(runValuationsBetween(nodeAApi, nodeBParty)).isTrue()
|
||||
assertValuationExists(nodeBApi, nodeAParty)
|
||||
assertValuationExists(nodeAApi, nodeBParty)
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,17 +62,17 @@ class SimmValuationTest : IntegrationTestCategory {
|
||||
return partyApi.putJson("${counterparty.id}/trades", trade)
|
||||
}
|
||||
|
||||
private fun tradeExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String): Boolean {
|
||||
private fun assertTradeExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String) {
|
||||
val trades = partyApi.getJson<Array<SwapDataView>>("${counterparty.id}/trades")
|
||||
return (trades.find { it.id == tradeId } != null)
|
||||
assertThat(trades).filteredOn { it.id == tradeId }.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun runValuationsBetween(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty): Boolean {
|
||||
return partyApi.postJson("${counterparty.id}/portfolio/valuations/calculate", PortfolioApi.ValuationCreationParams(valuationDate))
|
||||
}
|
||||
|
||||
private fun valuationExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty): Boolean {
|
||||
private fun assertValuationExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty) {
|
||||
val valuations = partyApi.getJson<PortfolioApiUtils.ValuationsView>("${counterparty.id}/portfolio/valuations")
|
||||
return (valuations.initialMargin.call["total"] != 0.0)
|
||||
assertThat(valuations.initialMargin.call["total"]).isNotEqualTo(0.0)
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ configurations {
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
|
||||
testCompile "junit:junit:$junit_version"
|
||||
testCompile "org.assertj:assertj-core:${assertj_version}"
|
||||
|
||||
// Corda integration dependencies
|
||||
runtime project(path: ":node:capsule", configuration: 'runtimeArtifacts')
|
||||
|
@ -2,6 +2,7 @@ package net.corda.traderdemo
|
||||
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.core.contracts.DOLLARS
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.utilities.DUMMY_BANK_A
|
||||
@ -13,6 +14,8 @@ import net.corda.node.services.transactions.SimpleNotaryService
|
||||
import net.corda.nodeapi.User
|
||||
import net.corda.testing.BOC
|
||||
import net.corda.testing.node.NodeBasedTest
|
||||
import net.corda.traderdemo.flow.SellerFlow
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
class TraderDemoTest : NodeBasedTest() {
|
||||
@ -20,7 +23,7 @@ class TraderDemoTest : NodeBasedTest() {
|
||||
fun `runs trader demo`() {
|
||||
val permissions = setOf(
|
||||
startFlowPermission<IssuerFlow.IssuanceRequester>(),
|
||||
startFlowPermission<net.corda.traderdemo.flow.SellerFlow>())
|
||||
startFlowPermission<SellerFlow>())
|
||||
val demoUser = listOf(User("demo", "demo", permissions))
|
||||
val user = User("user1", "test", permissions = setOf(startFlowPermission<IssuerFlow.IssuanceRequester>()))
|
||||
val (nodeA, nodeB) = Futures.allAsList(
|
||||
@ -35,7 +38,21 @@ class TraderDemoTest : NodeBasedTest() {
|
||||
client.start(demoUser[0].username, demoUser[0].password).proxy()
|
||||
}
|
||||
|
||||
TraderDemoClientApi(nodeARpc).runBuyer()
|
||||
TraderDemoClientApi(nodeBRpc).runSeller(counterparty = nodeA.info.legalIdentity.name)
|
||||
val clientA = TraderDemoClientApi(nodeARpc)
|
||||
val clientB = TraderDemoClientApi(nodeBRpc)
|
||||
|
||||
val originalACash = clientA.cashCount // A has random number of issued amount
|
||||
val expectedBCash = clientB.cashCount + 1
|
||||
val expectedPaper = listOf(clientA.commercialPaperCount + 1, clientB.commercialPaperCount)
|
||||
|
||||
clientA.runBuyer(amount = 100.DOLLARS)
|
||||
clientB.runSeller(counterparty = nodeA.info.legalIdentity.name, amount = 5.DOLLARS)
|
||||
|
||||
val actualPaper = listOf(clientA.commercialPaperCount, clientB.commercialPaperCount)
|
||||
assertThat(clientA.cashCount).isGreaterThan(originalACash)
|
||||
assertThat(clientB.cashCount).isEqualTo(expectedBCash)
|
||||
assertThat(actualPaper).isEqualTo(expectedPaper)
|
||||
assertThat(clientA.dollarCashBalance).isEqualTo(95.DOLLARS)
|
||||
assertThat(clientB.dollarCashBalance).isEqualTo(5.DOLLARS)
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
package net.corda.traderdemo
|
||||
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import net.corda.contracts.CommercialPaper
|
||||
import net.corda.contracts.asset.Cash
|
||||
import net.corda.contracts.testing.calculateRandomlySizedAmounts
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.DOLLARS
|
||||
import net.corda.core.contracts.USD
|
||||
import net.corda.core.contracts.filterStatesOfType
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.startFlow
|
||||
@ -24,6 +28,12 @@ class TraderDemoClientApi(val rpc: CordaRPCOps) {
|
||||
val logger = loggerFor<TraderDemoClientApi>()
|
||||
}
|
||||
|
||||
val cashCount: Int get() = rpc.vaultAndUpdates().first.filterStatesOfType<Cash.State>().size
|
||||
|
||||
val dollarCashBalance: Amount<Currency> get() = rpc.getCashBalances()[USD]!!
|
||||
|
||||
val commercialPaperCount: Int get() = rpc.vaultAndUpdates().first.filterStatesOfType<CommercialPaper.State>().size
|
||||
|
||||
fun runBuyer(amount: Amount<Currency> = 30000.DOLLARS) {
|
||||
val bankOfCordaParty = rpc.partyFromName(BOC.name)
|
||||
?: throw Exception("Unable to locate ${BOC.name} in Network Map Service")
|
||||
|
@ -18,6 +18,7 @@ import net.corda.nodeapi.User
|
||||
import net.corda.nodeapi.config.parseAs
|
||||
import net.corda.testing.MOCK_NODE_VERSION_INFO
|
||||
import net.corda.testing.getFreeLocalPorts
|
||||
import org.apache.logging.log4j.Level
|
||||
import org.junit.After
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
@ -39,6 +40,10 @@ abstract class NodeBasedTest {
|
||||
|
||||
val networkMapNode: Node get() = _networkMapNode ?: startNetworkMapNode()
|
||||
|
||||
init {
|
||||
System.setProperty("consoleLogLevel", Level.DEBUG.name().toLowerCase())
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the network map node and all the nodes started by [startNode]. This is called automatically after each test
|
||||
* but can also be called manually within a test.
|
||||
|
Loading…
x
Reference in New Issue
Block a user