From 709b3791a3b5be2bf922dedbb38de1f2a68d8033 Mon Sep 17 00:00:00 2001 From: szymonsztuka Date: Fri, 1 Dec 2017 17:17:51 +0000 Subject: [PATCH] SQL Azure and SQL Server database integration tests (#115) * Integration test are parameterised (extends IntegrationTest) to run against a remote database with 4 db scripts run @BeforeClass, @Before, @After and @AfterClass. * SQL script for SQL Azure and SQL Server databases and templates of JDBC configuration. --- client/jfx/build.gradle | 3 + .../corda/client/jfx/NodeMonitorModelTest.kt | 7 + client/rpc/build.gradle | 3 + .../client/rpc/CordaRPCJavaClientTest.java | 8 ++ .../client/rpc/BlacklistKotlinClosureTest.kt | 7 +- .../corda/client/rpc/CordaRPCClientTest.kt | 5 + .../net/corda/client/rpc/RPCStabilityTests.kt | 10 +- docs/source/example-code/build.gradle | 3 + .../corda/docs/IntegrationTestingTutorial.kt | 3 + finance/build.gradle | 3 + .../finance/flows/CashConfigDataFlowTest.kt | 8 +- .../selection/CashSelectionSQLServerImpl.kt | 2 +- node/build.gradle | 1 + .../kotlin/net/corda/node/BootTests.kt | 9 +- .../corda/node/CordappScanningDriverTest.kt | 11 +- .../net/corda/node/NodePerformanceTests.kt | 10 +- .../corda/node/NodeStartupPerformanceTests.kt | 8 +- .../kotlin/net/corda/node/SSHServerTest.kt | 11 +- .../node/services/AttachmentLoadingTests.kt | 7 +- .../node/services/BFTNotaryServiceTests.kt | 9 +- .../node/services/DistributedServiceTests.kt | 7 +- .../node/services/RaftNotaryServiceTests.kt | 12 +- .../network/PersistentNetworkMapCacheTest.kt | 10 +- .../statemachine/FlowVersioningTest.kt | 11 +- .../statemachine/LargeTransactionsTest.kt | 8 +- .../vault/VaultQueryIntegrationTests.kt | 40 ++++++ .../services/messaging/MQSecurityTest.kt | 21 ++- .../services/messaging/P2PMessagingTest.kt | 10 +- .../test/node/NodeStatePersistenceTests.kt | 10 +- .../node/services/vault/VaultQueryTests.kt | 8 +- samples/attachment-demo/build.gradle | 3 + .../attachmentdemo/AttachmentDemoTest.kt | 11 +- samples/bank-of-corda-demo/build.gradle | 3 + .../corda/bank/BankOfCordaRPCClientTest.kt | 7 + samples/irs-demo/build.gradle | 3 + .../kotlin/net/corda/irs/IRSDemoTest.kt | 7 +- samples/simm-valuation-demo/build.gradle | 3 + .../net/corda/vega/SimmValuationTest.kt | 9 +- samples/trader-demo/build.gradle | 3 + .../net/corda/traderdemo/TraderDemoTest.kt | 13 +- testing/node-driver/build.gradle | 1 + .../net/corda/testing/driver/DriverTests.kt | 10 +- .../net/corda/testing/node/MockServices.kt | 53 ++++++-- .../net/corda/testing/IntegrationTest.kt | 29 ++++- .../testing/database/DatabaseConstants.kt | 10 ++ .../corda/testing/database/DbScriptRunner.kt | 123 ++++++++++++++++-- .../database-scripts/sql-azure/db-setup.sql | 49 +++++++ .../sql-azure/master-user-setup.sql | 87 +++++++++++++ .../main/resources/integration-sql-azure.conf | 11 ++ .../resources/integration-sql-server.conf | 11 ++ 50 files changed, 606 insertions(+), 105 deletions(-) create mode 100644 node/src/integration-test/kotlin/net/corda/node/services/vault/VaultQueryIntegrationTests.kt create mode 100644 testing/test-utils/src/main/kotlin/net/corda/testing/database/DatabaseConstants.kt create mode 100644 testing/test-utils/src/main/resources/database-scripts/sql-azure/db-setup.sql create mode 100644 testing/test-utils/src/main/resources/database-scripts/sql-azure/master-user-setup.sql create mode 100644 testing/test-utils/src/main/resources/integration-sql-azure.conf create mode 100644 testing/test-utils/src/main/resources/integration-sql-server.conf diff --git a/client/jfx/build.gradle b/client/jfx/build.gradle index 0e84e78f37..a17d8f79d5 100644 --- a/client/jfx/build.gradle +++ b/client/jfx/build.gradle @@ -18,6 +18,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + resources { + srcDir file('../../testing/test-utils/src/main/resources') + } } } diff --git a/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt b/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt index 2c98a4c174..ff8a529994 100644 --- a/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt +++ b/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt @@ -31,6 +31,7 @@ import net.corda.node.services.Permissions.Companion.startFlow import net.corda.nodeapi.User import net.corda.testing.* import net.corda.testing.driver.driver +import org.junit.ClassRule import org.junit.Test import rx.Observable @@ -50,6 +51,12 @@ class NodeMonitorModelTest : IntegrationTest() { private lateinit var networkMapUpdates: Observable private lateinit var newNode: (CordaX500Name) -> NodeInfo + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(ALICE, BOB, CHARLIE, DUMMY_NOTARY) + .map { it.toDatabaseSchemaNames("","_10000","_10003") }.flatten().toTypedArray()) + } + private fun setup(runTest: () -> Unit) { driver(extraCordappPackagesToScan = listOf("net.corda.finance")) { val cashUser = User("user1", "test", permissions = setOf( diff --git a/client/rpc/build.gradle b/client/rpc/build.gradle index bd234e8ee1..43ebde9e89 100644 --- a/client/rpc/build.gradle +++ b/client/rpc/build.gradle @@ -27,6 +27,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/java') } + resources { + srcDir file('../../testing/test-utils/src/main/resources') + } } smokeTest { kotlin { diff --git a/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java b/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java index 642d172651..60fbe117c9 100644 --- a/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java +++ b/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java @@ -12,9 +12,12 @@ import net.corda.node.internal.Node; import net.corda.node.internal.StartedNode; import net.corda.nodeapi.User; import net.corda.testing.CoreTestUtils; +import net.corda.testing.IntegrationTestKt; +import net.corda.testing.IntegrationTestSchemas; import net.corda.testing.internal.NodeBasedTest; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import java.io.IOException; @@ -29,12 +32,17 @@ import static net.corda.finance.contracts.GetBalances.getCashBalance; import static net.corda.node.services.Permissions.invokeRpc; import static net.corda.node.services.Permissions.startFlow; import static net.corda.testing.TestConstants.getALICE; +import static net.corda.testing.TestConstants.getDUMMY_NOTARY; public class CordaRPCJavaClientTest extends NodeBasedTest { public CordaRPCJavaClientTest() { super(Arrays.asList("net.corda.finance.contracts", CashSchemaV1.class.getPackage().getName())); } + @ClassRule + public static IntegrationTestSchemas databaseSchemas = new IntegrationTestSchemas(IntegrationTestKt.toDatabaseSchemaName(getALICE()), + IntegrationTestKt.toDatabaseSchemaName(getDUMMY_NOTARY())); + private List perms = Arrays.asList( startFlow(CashPaymentFlow.class), startFlow(CashIssueFlow.class), diff --git a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/BlacklistKotlinClosureTest.kt b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/BlacklistKotlinClosureTest.kt index 2dbc293a35..c675f35539 100644 --- a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/BlacklistKotlinClosureTest.kt +++ b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/BlacklistKotlinClosureTest.kt @@ -7,15 +7,18 @@ import net.corda.core.flows.StartableByRPC import net.corda.core.messaging.startFlow import net.corda.core.serialization.CordaSerializable import net.corda.core.utilities.getOrThrow -import net.corda.testing.ALICE -import net.corda.testing.IntegrationTest +import net.corda.testing.* import net.corda.testing.driver.driver import org.assertj.core.api.Assertions.assertThatExceptionOfType +import org.junit.ClassRule import org.junit.Test class BlacklistKotlinClosureTest : IntegrationTest() { companion object { const val EVIL: Long = 666 + + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(ALICE.toDatabaseSchemaName(), DUMMY_NOTARY.toDatabaseSchemaName()) } @StartableByRPC diff --git a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt index 6aff9d5d2a..04ac286ead 100644 --- a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt +++ b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt @@ -28,6 +28,7 @@ import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.After import org.junit.Before +import org.junit.ClassRule import org.junit.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -49,6 +50,10 @@ class CordaRPCClientTest : NodeBasedTest(listOf("net.corda.finance.contracts", C private fun login(username: String, password: String, externalTrace: Trace? = null, impersonatedActor: Actor? = null) { connection = client.start(username, password, externalTrace, impersonatedActor) } + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(ALICE.toDatabaseSchemaName()) + } @Before override fun setUp() { diff --git a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/RPCStabilityTests.kt b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/RPCStabilityTests.kt index 6d49068c7a..48908ef7b1 100644 --- a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/RPCStabilityTests.kt +++ b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/RPCStabilityTests.kt @@ -12,14 +12,14 @@ import net.corda.core.serialization.serialize import net.corda.core.utilities.* import net.corda.node.services.messaging.RPCServerConfiguration import net.corda.nodeapi.RPCApi -import net.corda.testing.SerializationEnvironmentRule -import net.corda.testing.IntegrationTest +import net.corda.testing.* import net.corda.testing.driver.poll import net.corda.testing.internal.* import org.apache.activemq.artemis.api.core.SimpleString import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue +import org.junit.ClassRule import org.junit.Rule import org.junit.Test import rx.Observable @@ -39,6 +39,12 @@ class RPCStabilityTests : IntegrationTest() { pool.shutdown() } + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(ALICE, BOB, DUMMY_BANK_A) + .map { it.toDatabaseSchemaNames("","_10000","_10003","_10012") }.flatten().toTypedArray()) + } + object DummyOps : RPCOps { override val protocolVersion = 0 } diff --git a/docs/source/example-code/build.gradle b/docs/source/example-code/build.gradle index 6cad970f10..db3ad5da93 100644 --- a/docs/source/example-code/build.gradle +++ b/docs/source/example-code/build.gradle @@ -24,6 +24,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + resources { + srcDir file('../../testing/test-utils/src/main/resources') + } } } diff --git a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt index 95ffd9ef45..1cc97f86af 100644 --- a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt +++ b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt @@ -20,6 +20,9 @@ import org.junit.Test import kotlin.test.assertEquals class IntegrationTestingTutorial : IntegrationTest() { + override val databaseSchemas: MutableList + get() = listOf(ALICE, BOB, DUMMY_NOTARY).map { it.toDatabaseSchemaName() }.toMutableList() + @Test fun `alice bob cash exchange example`() { // START 1 diff --git a/finance/build.gradle b/finance/build.gradle index 662e7c9aa5..8bc6064930 100644 --- a/finance/build.gradle +++ b/finance/build.gradle @@ -17,6 +17,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + resources { + srcDir file('../../testing/test-utils/src/main/resources') + } } } diff --git a/finance/src/integration-test/kotlin/net/corda/finance/flows/CashConfigDataFlowTest.kt b/finance/src/integration-test/kotlin/net/corda/finance/flows/CashConfigDataFlowTest.kt index f67cc17a0e..071b4d775f 100644 --- a/finance/src/integration-test/kotlin/net/corda/finance/flows/CashConfigDataFlowTest.kt +++ b/finance/src/integration-test/kotlin/net/corda/finance/flows/CashConfigDataFlowTest.kt @@ -4,12 +4,18 @@ import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow import net.corda.finance.EUR import net.corda.finance.USD -import net.corda.testing.IntegrationTest +import net.corda.testing.* import net.corda.testing.driver.driver import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import org.junit.Test class CashConfigDataFlowTest : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(ALICE, BOB, DUMMY_BANK_A) + .map { it.toDatabaseSchemaNames("","_10000","_10003") }.flatten().toTypedArray()) + } @Test fun `issuable currencies are read in from node config`() { driver { diff --git a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionSQLServerImpl.kt b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionSQLServerImpl.kt index 4f89016fca..093d2ac41c 100644 --- a/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionSQLServerImpl.kt +++ b/finance/src/main/kotlin/net/corda/finance/contracts/asset/cash/selection/CashSelectionSQLServerImpl.kt @@ -14,7 +14,7 @@ import java.util.* /** * SQL Server / SQL Azure */ -class CashSelectionSQLServerImpl : AbstractCashSelection() { +class CashSelectionSQLServerImpl : AbstractCashSelection(maxRetries = 16, retrySleep = 1000, retryCap = 5000) { companion object { val JDBC_DRIVER_NAME = "Microsoft JDBC Driver 6.2 for SQL Server" diff --git a/node/build.gradle b/node/build.gradle index e300d238e5..94687cfbe9 100644 --- a/node/build.gradle +++ b/node/build.gradle @@ -35,6 +35,7 @@ sourceSets { } resources { srcDir file('src/integration-test/resources') + srcDir file('../../testing/test-utils/src/main/resources') } } } diff --git a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt index 43f9bcf20f..4bc031400d 100644 --- a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt @@ -9,18 +9,23 @@ import net.corda.core.utilities.getOrThrow import net.corda.node.internal.NodeStartup import net.corda.node.services.Permissions.Companion.startFlow import net.corda.nodeapi.User -import net.corda.testing.ALICE -import net.corda.testing.IntegrationTest +import net.corda.testing.* import net.corda.testing.common.internal.ProjectStructure.projectRootDir import net.corda.testing.driver.driver import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.ClassRule import org.junit.Test import java.io.* import java.nio.file.Files import kotlin.test.assertEquals class BootTests : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(ALICE, BOB, DUMMY_BANK_A) + .map { it.toDatabaseSchemaNames("", "_10000","_10003") }.flatten().toTypedArray()) + } @Test fun `java deserialization is disabled`() { diff --git a/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt b/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt index ff24a80bd6..57583b893a 100644 --- a/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt @@ -9,15 +9,18 @@ import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap import net.corda.node.services.Permissions.Companion.startFlow import net.corda.nodeapi.User -import net.corda.testing.ALICE -import net.corda.testing.BOB -import net.corda.testing.IntegrationTest -import net.corda.testing.chooseIdentity +import net.corda.testing.* import net.corda.testing.driver.driver import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import org.junit.Test class CordappScanningDriverTest : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(ALICE.toDatabaseSchemaName(), BOB.toDatabaseSchemaName()) + } + @Test fun `sub-classed initiated flow pointing to the same initiating flow as its super-class`() { val user = User("u", "p", setOf(startFlow())) diff --git a/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt b/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt index b7419b3fbf..925f14928e 100644 --- a/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt @@ -14,8 +14,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.startFlow import net.corda.nodeapi.User -import net.corda.testing.DUMMY_NOTARY -import net.corda.testing.IntegrationTest +import net.corda.testing.* import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver import net.corda.testing.node.NotarySpec @@ -24,6 +23,7 @@ import net.corda.testing.internal.performance.startPublishingFixedRateInjector import net.corda.testing.internal.performance.startReporter import net.corda.testing.internal.performance.startTightLoopInjector import org.junit.Before +import org.junit.ClassRule import org.junit.Ignore import org.junit.Test import java.lang.management.ManagementFactory @@ -40,6 +40,12 @@ private fun checkQuasarAgent() { @Ignore("Run these locally") class NodePerformanceTests : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*DUMMY_NOTARY.toDatabaseSchemaNames("_0", "_1", "_2").toTypedArray(), + DUMMY_BANK_A.toDatabaseSchemaName()) + } + @StartableByRPC class EmptyFlow : FlowLogic() { @Suspendable diff --git a/node/src/integration-test/kotlin/net/corda/node/NodeStartupPerformanceTests.kt b/node/src/integration-test/kotlin/net/corda/node/NodeStartupPerformanceTests.kt index 9b16610edf..a85edf5f45 100644 --- a/node/src/integration-test/kotlin/net/corda/node/NodeStartupPerformanceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/NodeStartupPerformanceTests.kt @@ -1,8 +1,9 @@ package net.corda.node import com.google.common.base.Stopwatch -import net.corda.testing.IntegrationTest +import net.corda.testing.* import net.corda.testing.driver.driver +import org.junit.ClassRule import org.junit.Ignore import org.junit.Test import java.util.* @@ -10,7 +11,10 @@ import java.util.concurrent.TimeUnit @Ignore("Only use locally") class NodeStartupPerformanceTests : IntegrationTest() { - + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(ALICE, BOB, DUMMY_BANK_A).map { it.toDatabaseSchemaName() }.toTypedArray()) + } // Measure the startup time of nodes. Note that this includes an RPC roundtrip, which causes e.g. Kryo initialisation. @Test fun `single node startup time`() { diff --git a/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt b/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt index 96c701f761..0fec826b96 100644 --- a/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt @@ -10,24 +10,29 @@ import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap import net.corda.nodeapi.User -import net.corda.testing.ALICE import net.corda.testing.driver.driver import org.bouncycastle.util.io.Streams import org.junit.Test import net.corda.node.services.Permissions.Companion.startFlow +import net.corda.testing.* import java.net.ConnectException import kotlin.test.assertTrue import kotlin.test.fail import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import java.util.regex.Pattern -class SSHServerTest { +class SSHServerTest : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(ALICE.toDatabaseSchemaName()) + } @Test() fun `ssh server does not start be default`() { val user = User("u", "p", setOf()) // The driver will automatically pick up the annotated flows below - driver() { + driver { val node = startNode(providedName = ALICE.name, rpcUsers = listOf(user)) node.getOrThrow() diff --git a/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt index 0c81dba7dd..1e36145857 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt @@ -20,7 +20,6 @@ import net.corda.node.internal.cordapp.CordappProviderImpl import net.corda.testing.* import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_NOTARY -import net.corda.testing.SerializationEnvironmentRule import net.corda.testing.IntegrationTest import net.corda.testing.driver.DriverDSLExposedInterface import net.corda.testing.driver.NodeHandle @@ -28,12 +27,14 @@ import net.corda.testing.driver.driver import net.corda.testing.node.MockServices import org.junit.Assert.assertEquals import org.junit.Before +import org.junit.ClassRule import org.junit.Test import java.net.URLClassLoader import java.nio.file.Files import kotlin.test.assertFailsWith class AttachmentLoadingTests : IntegrationTest() { + private class Services : MockServices() { private val provider = CordappProviderImpl(CordappLoader.createDevMode(listOf(isolatedJAR)), attachments) private val cordapp get() = provider.cordapps.first() @@ -43,6 +44,10 @@ class AttachmentLoadingTests : IntegrationTest() { } private companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(DUMMY_BANK_A, DUMMY_BANK_B, DUMMY_NOTARY) + .map { it.toDatabaseSchemaName() }.toTypedArray()) + private val logger = contextLogger() val isolatedJAR = AttachmentLoadingTests::class.java.getResource("isolated.jar")!! val ISOLATED_CONTRACT_ID = "net.corda.finance.contracts.isolated.AnotherDummyContract" diff --git a/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt index 2087937f8b..ad4816c57d 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt @@ -27,20 +27,27 @@ import net.corda.node.services.transactions.minCorrectReplicas import net.corda.node.utilities.ServiceIdentityGenerator import net.corda.testing.IntegrationTest import net.corda.testing.chooseIdentity +import net.corda.testing.* import net.corda.testing.contracts.DummyContract -import net.corda.testing.dummyCommand import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork.MockNode import net.corda.testing.node.MockNodeParameters import net.corda.testing.startFlow import org.junit.After import org.junit.Before +import org.junit.ClassRule import org.junit.Test import java.nio.file.Paths import kotlin.test.assertEquals import kotlin.test.assertTrue class BFTNotaryServiceTests : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas("node_0", "node_1", "node_2", "node_3", "node_4", "node_5", + "node_6", "node_7", "node_8", "node_9") + } + private lateinit var mockNet: MockNetwork private lateinit var notary: Party private lateinit var node: StartedNode diff --git a/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt index ea5b1f5399..2e51acbcb4 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt @@ -21,6 +21,7 @@ import net.corda.testing.driver.driver import net.corda.testing.node.ClusterSpec import net.corda.testing.node.NotarySpec import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import org.junit.Test import rx.Observable import java.util.* @@ -31,7 +32,11 @@ class DistributedServiceTests : IntegrationTest() { private lateinit var aliceProxy: CordaRPCOps private lateinit var raftNotaryIdentity: Party private lateinit var notaryStateMachines: Observable> - + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*DUMMY_NOTARY.toDatabaseSchemaNames("_0", "_1", "_2").toTypedArray(), + ALICE.toDatabaseSchemaName()) + } private fun setup(testBlock: () -> Unit) { val testUser = User("test", "test", permissions = setOf( startFlow(), diff --git a/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt index 9231d02380..53f59c1e13 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt @@ -12,22 +12,24 @@ import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.getOrThrow import net.corda.node.internal.StartedNode import net.corda.node.services.transactions.RaftValidatingNotaryService -import net.corda.testing.DUMMY_BANK_A -import net.corda.testing.IntegrationTest -import net.corda.testing.chooseIdentity +import net.corda.testing.* import net.corda.testing.contracts.DummyContract import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver -import net.corda.testing.dummyCommand -import net.corda.testing.startFlow import net.corda.testing.node.ClusterSpec import net.corda.testing.node.NotarySpec +import org.junit.ClassRule import org.junit.Test import java.util.* import kotlin.test.assertEquals import kotlin.test.assertFailsWith class RaftNotaryServiceTests : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas( "RAFTNotaryService_0", "RAFTNotaryService_1", "RAFTNotaryService_2", + DUMMY_BANK_A.toDatabaseSchemaName()) + } private val notaryName = CordaX500Name(RaftValidatingNotaryService.id, "RAFT Notary Service", "London", "GB") @Test diff --git a/node/src/integration-test/kotlin/net/corda/node/services/network/PersistentNetworkMapCacheTest.kt b/node/src/integration-test/kotlin/net/corda/node/services/network/PersistentNetworkMapCacheTest.kt index d4bdec79b7..702b894ebc 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/network/PersistentNetworkMapCacheTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/network/PersistentNetworkMapCacheTest.kt @@ -6,16 +6,18 @@ import net.corda.core.node.NodeInfo import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.internal.Node import net.corda.node.internal.StartedNode -import net.corda.testing.ALICE -import net.corda.testing.BOB -import net.corda.testing.DUMMY_REGULATOR -import net.corda.testing.chooseIdentity +import net.corda.testing.* import net.corda.testing.internal.NodeBasedTest import org.junit.Before +import org.junit.ClassRule import org.junit.Test import kotlin.test.assertEquals class PersistentNetworkMapCacheTest : NodeBasedTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(DUMMY_REGULATOR, ALICE, BOB).map { it.toDatabaseSchemaName() }.toTypedArray()) + } private val partiesList = listOf(DUMMY_REGULATOR, ALICE, BOB) private val addressesMap = HashMap() private val infos = HashSet() diff --git a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/FlowVersioningTest.kt b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/FlowVersioningTest.kt index 3396277518..9c48d2c2c0 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/FlowVersioningTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/FlowVersioningTest.kt @@ -7,15 +7,18 @@ import net.corda.core.flows.InitiatingFlow import net.corda.core.identity.Party import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap -import net.corda.testing.ALICE -import net.corda.testing.BOB -import net.corda.testing.chooseIdentity +import net.corda.testing.* import net.corda.testing.internal.NodeBasedTest -import net.corda.testing.startFlow import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import org.junit.Test class FlowVersioningTest : NodeBasedTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(ALICE.toDatabaseSchemaName(), BOB.toDatabaseSchemaName()) + } + @Test fun `getFlowContext returns the platform version for core flows`() { val alice = startNode(ALICE.name, platformVersion = 2) diff --git a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt index 757c943511..d2fbc59913 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt @@ -13,8 +13,7 @@ import net.corda.testing.* import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyState import net.corda.testing.driver.driver -import net.corda.testing.dummyCommand -import net.corda.testing.IntegrationTest +import org.junit.ClassRule import org.junit.Test import kotlin.test.assertEquals @@ -23,6 +22,11 @@ import kotlin.test.assertEquals * transaction size limit (which should only consider the hashes). */ class LargeTransactionsTest : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(ALICE, BOB, DUMMY_NOTARY).map { it.toDatabaseSchemaName() }.toTypedArray()) + } + @StartableByRPC @InitiatingFlow class SendLargeTransactionFlow(private val hash1: SecureHash, diff --git a/node/src/integration-test/kotlin/net/corda/node/services/vault/VaultQueryIntegrationTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/vault/VaultQueryIntegrationTests.kt new file mode 100644 index 0000000000..ec27c1fa3c --- /dev/null +++ b/node/src/integration-test/kotlin/net/corda/node/services/vault/VaultQueryIntegrationTests.kt @@ -0,0 +1,40 @@ +package net.corda.node.services.vault + + +import net.corda.testing.* +import org.junit.* + +class VaultQueryIntegrationTests : VaultQueryTests() { + + private val adapter = object: IntegrationTest() { + } + + @Before + override fun setUp() { + adapter.setUp() + super.setUp() + } + + @After + override fun tearDown() { + adapter.tearDown() + super.tearDown() + } + + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(MEGA_CORP.toDatabaseSchemaName()) + + @BeforeClass + @JvmStatic + fun globalSetUp() { + IntegrationTest.globalSetUp() + } + + @AfterClass + @JvmStatic + fun globalTearDown() { + IntegrationTest.globalTearDown() + } + } +} diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt index ecaa0032a0..17c3b36d90 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt @@ -31,8 +31,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQNonExistentQueueException import org.apache.activemq.artemis.api.core.ActiveMQSecurityException import org.apache.activemq.artemis.api.core.SimpleString import org.assertj.core.api.Assertions.assertThatExceptionOfType -import org.junit.After -import org.junit.Before +import org.junit.ClassRule import org.junit.Test import java.util.* import kotlin.test.assertEquals @@ -42,13 +41,17 @@ import kotlin.test.assertEquals * the attacker to [alice]. */ abstract class MQSecurityTest : NodeBasedTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(ALICE.toDatabaseSchemaName(), BOB.toDatabaseSchemaName()) + } val rpcUser = User("user1", "pass", permissions = emptySet()) lateinit var alice: StartedNode lateinit var attacker: SimpleMQClient private val clients = ArrayList() - @Before - fun start() { + override fun setUp() { + super.setUp() alice = startNode(ALICE.name, rpcUsers = extraRPCUsers + rpcUser) attacker = createAttacker() startAttacker(attacker) @@ -60,9 +63,10 @@ abstract class MQSecurityTest : NodeBasedTest() { abstract fun startAttacker(attacker: SimpleMQClient) - @After - fun stopClients() { + override fun tearDown() { + rpcConnections.forEach { it.forceClose() } clients.forEach { it.stop() } + super.tearDown() } @Test @@ -145,11 +149,6 @@ abstract class MQSecurityTest : NodeBasedTest() { return CordaRPCClient(target).start(rpcUser.username, rpcUser.password).also { rpcConnections.add(it) }.proxy } - @After - fun closeRPCConnections() { - rpcConnections.forEach { it.forceClose() } - } - fun loginToRPCAndGetClientQueue(): String { loginToRPC(alice.internals.configuration.rpcAddress!!, rpcUser) val clientQueueQuery = SimpleString("${RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX}.${rpcUser.username}.*") diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt index c0ac949582..588cb325f8 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt @@ -16,15 +16,14 @@ import net.corda.node.internal.Node import net.corda.node.internal.StartedNode import net.corda.node.services.messaging.* import net.corda.node.services.transactions.RaftValidatingNotaryService -import net.corda.testing.ALICE -import net.corda.testing.IntegrationTest -import net.corda.testing.chooseIdentity +import net.corda.testing.* import net.corda.testing.driver.DriverDSLExposedInterface import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver import net.corda.testing.node.ClusterSpec import net.corda.testing.node.NotarySpec import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import org.junit.Test import java.util.* import java.util.concurrent.CountDownLatch @@ -32,7 +31,10 @@ import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger class P2PMessagingTest : IntegrationTest() { - private companion object { + private companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(ALICE.toDatabaseSchemaName(), "DistributedService_0", "DistributedService_1") + val DISTRIBUTED_SERVICE_NAME = CordaX500Name(RaftValidatingNotaryService.id, "DistributedService", "London", "GB") } diff --git a/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt b/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt index 4966c0d592..5ecf515807 100644 --- a/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt @@ -20,10 +20,10 @@ import net.corda.core.utilities.getOrThrow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow import net.corda.nodeapi.User -import net.corda.testing.IntegrationTest -import net.corda.testing.chooseIdentity +import net.corda.testing.* import net.corda.testing.driver.driver import org.junit.Assume.assumeFalse +import org.junit.ClassRule import org.junit.Test import java.lang.management.ManagementFactory import javax.persistence.Column @@ -33,6 +33,12 @@ import kotlin.test.assertEquals import kotlin.test.assertNotNull class NodeStatePersistenceTests : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(ALICE, BOB, DUMMY_BANK_A) + .map { it.toDatabaseSchemaNames("", "_10000","_10003","_10006") }.flatten().toTypedArray(), + DUMMY_NOTARY.toDatabaseSchemaName()) + } @Test fun `persistent state survives node restart`() { // Temporary disable this test when executed on Windows. It is known to be sporadically failing. diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt index 0580cca49d..87cb6c5258 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt @@ -49,7 +49,7 @@ import java.time.ZoneOffset import java.time.temporal.ChronoUnit import java.util.* -class VaultQueryTests { +open class VaultQueryTests { @Rule @JvmField val testSerialization = SerializationEnvironmentRule() @@ -77,7 +77,7 @@ class VaultQueryTests { private val CASH_NOTARY_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CASH_NOTARY.nameOrNull(), CASH_NOTARY_KEY.public) @Before - fun setUp() { + open fun setUp() { // register additional identities val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MEGA_CORP_KEY, DUMMY_NOTARY_KEY), cordappPackages = cordappPackages) @@ -94,7 +94,7 @@ class VaultQueryTests { } @After - fun tearDown() { + open fun tearDown() { database.close() } @@ -1651,7 +1651,7 @@ class VaultQueryTests { @Test fun `unconsumed linear heads for linearId between two timestamps for a given external id`() { val start = Instant.now() - val end = start.plus(1, ChronoUnit.SECONDS) + val end = start.plus(3, ChronoUnit.SECONDS) database.transaction { vaultFiller.fillWithSomeTestLinearStates(1, "TEST1") diff --git a/samples/attachment-demo/build.gradle b/samples/attachment-demo/build.gradle index 93f10fefb1..78ddbefdbd 100644 --- a/samples/attachment-demo/build.gradle +++ b/samples/attachment-demo/build.gradle @@ -14,6 +14,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + resources { + srcDir file('../testing/test-utils/src/main/resources') + } } } diff --git a/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt b/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt index d4b0740ef6..d1196aee0d 100644 --- a/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt +++ b/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt @@ -5,15 +5,20 @@ import net.corda.core.utilities.getOrThrow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow import net.corda.nodeapi.User -import net.corda.testing.DUMMY_BANK_A -import net.corda.testing.DUMMY_BANK_B -import net.corda.testing.IntegrationTest +import net.corda.testing.* import net.corda.testing.driver.PortAllocation import net.corda.testing.driver.driver +import org.junit.ClassRule import org.junit.Test import java.util.concurrent.CompletableFuture.supplyAsync class AttachmentDemoTest : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(DUMMY_BANK_A, DUMMY_BANK_B, DUMMY_NOTARY) + .map { it.toDatabaseSchemaName() }.toTypedArray()) + } + // run with a 10,000,000 bytes in-memory zip file. In practice, a slightly bigger file will be used (~10,002,000 bytes). // Force INFO logging to prevent printing 10MB arrays in logfiles @Test diff --git a/samples/bank-of-corda-demo/build.gradle b/samples/bank-of-corda-demo/build.gradle index b496155694..1e674d2d2f 100644 --- a/samples/bank-of-corda-demo/build.gradle +++ b/samples/bank-of-corda-demo/build.gradle @@ -14,6 +14,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + resources { + srcDir file('../testing/test-utils/src/main/resources') + } } } diff --git a/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt b/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt index 76cb6ad06c..861b47f2b2 100644 --- a/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt +++ b/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt @@ -13,9 +13,16 @@ import net.corda.node.services.Permissions.Companion.startFlow import net.corda.nodeapi.User import net.corda.testing.* import net.corda.testing.driver.driver +import org.junit.ClassRule import org.junit.Test class BankOfCordaRPCClientTest : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(BOC.toDatabaseSchemaName(), DUMMY_NOTARY.toDatabaseSchemaName(), + BIGCORP_NAME.organisation) + } + @Test fun `issuer flow via RPC`() { val commonPermissions = setOf( diff --git a/samples/irs-demo/build.gradle b/samples/irs-demo/build.gradle index 5b5b51ecf9..bd5ba586d1 100644 --- a/samples/irs-demo/build.gradle +++ b/samples/irs-demo/build.gradle @@ -32,6 +32,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + resources { + srcDir file('../testing/test-utils/src/main/resources') + } } } diff --git a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt index f8f4bd77e0..9771098324 100644 --- a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt +++ b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt @@ -28,6 +28,7 @@ import net.corda.testing.http.HttpApi import net.corda.testing.node.NotarySpec import org.apache.commons.io.IOUtils import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import org.junit.Test import rx.Observable import java.time.Duration @@ -36,12 +37,16 @@ import java.time.LocalDate class IRSDemoTest : IntegrationTest() { companion object { private val log = contextLogger() + + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(DUMMY_BANK_A, DUMMY_BANK_B, DUMMY_NOTARY) + .map { it.toDatabaseSchemaName() }.toTypedArray()) } private val rpcUsers = listOf(User("user", "password", setOf("ALL"))) private val currentDate: LocalDate = LocalDate.now() private val futureDate: LocalDate = currentDate.plusMonths(6) - private val maxWaitTime: Duration = 60.seconds + private val maxWaitTime: Duration = 180.seconds @Test fun `runs IRS demo`() { diff --git a/samples/simm-valuation-demo/build.gradle b/samples/simm-valuation-demo/build.gradle index 832e2eb283..992ced76be 100644 --- a/samples/simm-valuation-demo/build.gradle +++ b/samples/simm-valuation-demo/build.gradle @@ -18,6 +18,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + resources { + srcDir file('../testing/test-utils/src/main/resources') + } } } diff --git a/samples/simm-valuation-demo/src/integration-test/kotlin/net/corda/vega/SimmValuationTest.kt b/samples/simm-valuation-demo/src/integration-test/kotlin/net/corda/vega/SimmValuationTest.kt index 19127e2fe7..808d28fcd6 100644 --- a/samples/simm-valuation-demo/src/integration-test/kotlin/net/corda/vega/SimmValuationTest.kt +++ b/samples/simm-valuation-demo/src/integration-test/kotlin/net/corda/vega/SimmValuationTest.kt @@ -3,9 +3,7 @@ package net.corda.vega import com.opengamma.strata.product.common.BuySell import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.getOrThrow -import net.corda.testing.DUMMY_BANK_A -import net.corda.testing.DUMMY_BANK_B -import net.corda.testing.IntegrationTest +import net.corda.testing.* import net.corda.testing.driver.driver import net.corda.testing.http.HttpApi import net.corda.vega.api.PortfolioApi @@ -13,6 +11,7 @@ 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.ClassRule import org.junit.Test import java.math.BigDecimal import java.time.LocalDate @@ -24,6 +23,10 @@ class SimmValuationTest : IntegrationTest() { val nodeALegalName = DUMMY_BANK_A.name val nodeBLegalName = DUMMY_BANK_B.name val testTradeId = "trade1" + + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(DUMMY_BANK_A, DUMMY_BANK_B, DUMMY_NOTARY) + .map { it.toDatabaseSchemaName() }.toTypedArray()) } @Test diff --git a/samples/trader-demo/build.gradle b/samples/trader-demo/build.gradle index 1a00d51bec..cbeab22e2f 100644 --- a/samples/trader-demo/build.gradle +++ b/samples/trader-demo/build.gradle @@ -14,6 +14,9 @@ sourceSets { runtimeClasspath += main.output + test.output srcDir file('src/integration-test/kotlin') } + resources { + srcDir file('../testing/test-utils/src/main/resources') + } } } diff --git a/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt b/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt index af253af527..dbfc45e894 100644 --- a/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt +++ b/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt @@ -9,10 +9,7 @@ import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.Permissions.Companion.startFlow import net.corda.nodeapi.User -import net.corda.testing.BOC -import net.corda.testing.DUMMY_BANK_A -import net.corda.testing.DUMMY_BANK_B -import net.corda.testing.chooseIdentity +import net.corda.testing.* import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver import net.corda.testing.driver.poll @@ -20,10 +17,16 @@ import net.corda.traderdemo.flow.BuyerFlow import net.corda.traderdemo.flow.CommercialPaperIssueFlow import net.corda.traderdemo.flow.SellerFlow import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import org.junit.Test import java.util.concurrent.Executors -class TraderDemoTest { +class TraderDemoTest : IntegrationTest() { + companion object { + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(DUMMY_BANK_A, DUMMY_BANK_B, BOC, DUMMY_NOTARY) + .map { it.toDatabaseSchemaName() }.toTypedArray()) + } @Test fun `runs trader demo`() { val demoUser = User("demo", "demo", setOf(startFlow(), all())) diff --git a/testing/node-driver/build.gradle b/testing/node-driver/build.gradle index 7dc2760f8f..c82b5bb2c2 100644 --- a/testing/node-driver/build.gradle +++ b/testing/node-driver/build.gradle @@ -19,6 +19,7 @@ sourceSets { } resources { srcDir file('src/integration-test/resources') + srcDir file('../testing/test-utils/src/main/resources') } } } diff --git a/testing/node-driver/src/integration-test/kotlin/net/corda/testing/driver/DriverTests.kt b/testing/node-driver/src/integration-test/kotlin/net/corda/testing/driver/DriverTests.kt index 9ec8cada53..2e8e748794 100644 --- a/testing/node-driver/src/integration-test/kotlin/net/corda/testing/driver/DriverTests.kt +++ b/testing/node-driver/src/integration-test/kotlin/net/corda/testing/driver/DriverTests.kt @@ -6,13 +6,11 @@ import net.corda.core.internal.list import net.corda.core.internal.readLines import net.corda.core.utilities.getOrThrow import net.corda.node.internal.NodeStartup -import net.corda.testing.DUMMY_BANK_A -import net.corda.testing.DUMMY_NOTARY -import net.corda.testing.DUMMY_REGULATOR +import net.corda.testing.* import net.corda.testing.common.internal.ProjectStructure.projectRootDir -import net.corda.testing.IntegrationTest import net.corda.testing.node.NotarySpec import org.assertj.core.api.Assertions.assertThat +import org.junit.ClassRule import org.junit.Test import java.util.concurrent.Executors import java.util.concurrent.ScheduledExecutorService @@ -32,6 +30,10 @@ class DriverTests : IntegrationTest() { // Check that the port is bound addressMustNotBeBound(executorService, hostAndPort) } + + @ClassRule @JvmField + val databaseSchemas = IntegrationTestSchemas(*listOf(DUMMY_BANK_A, DUMMY_NOTARY, DUMMY_REGULATOR) + .map { it.toDatabaseSchemaName() }.toTypedArray()) } @Test diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt index 13ccd7432c..007a78c542 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt @@ -20,6 +20,7 @@ import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.transactions.SignedTransaction import net.corda.node.VersionInfo import net.corda.node.internal.StateLoaderImpl +import net.corda.node.internal.configureDatabase import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.services.api.SchemaService import net.corda.node.services.api.StateMachineRecordedTransactionMappingStorage @@ -34,11 +35,17 @@ import net.corda.node.services.schema.HibernateObserver import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.transactions.InMemoryTransactionVerifierService import net.corda.node.services.vault.NodeVaultService -import net.corda.node.internal.configureDatabase import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.nodeapi.internal.persistence.HibernateConfiguration +import net.corda.nodeapi.internal.persistence.TransactionIsolationLevel import net.corda.testing.* +import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_CLASSNAME +import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_PASSWORD +import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_URL +import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_USER +import net.corda.testing.database.DatabaseConstants.SCHEMA +import net.corda.testing.database.DatabaseConstants.TRANSACTION_ISOLATION_LEVEL import org.bouncycastle.operator.ContentSigner import rx.Observable import rx.subjects.PublishSubject @@ -66,22 +73,37 @@ open class MockServices( @JvmStatic val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor") - private fun readDatabaseConfig(nodeName: String? = null, postifx: String? = null): Config { - val standarizedNodeName = if (nodeName!= null) nodeName.replace(" ", "").replace("-", "_") else null - //in case of H2, the same db instance runs for all integration tests, so adding additional variable postfix to use unique db user/schema each time - val h2InstanceName = if (postifx != null) standarizedNodeName + "_" + postifx else standarizedNodeName + private fun readDatabaseConfig(nodeName: String? = null, postfix: String? = null): Config { + val parseOptions = ConfigParseOptions.defaults() + + //read overrides from command line (passed by Gradle as system properties) + val dataSourceKeys = listOf(DATA_SOURCE_URL, DATA_SOURCE_CLASSNAME, DATA_SOURCE_USER, DATA_SOURCE_PASSWORD) + val dataSourceSystemProperties = Properties() + val allSystemProperties = System.getProperties().toList().map { it.first.toString() to it.second.toString() }.toMap() + dataSourceKeys.filter { allSystemProperties.containsKey(it) }.forEach { dataSourceSystemProperties.setProperty(it, allSystemProperties[it]) } + val systemConfigOverride = ConfigFactory.parseProperties(dataSourceSystemProperties, parseOptions) + + //read from db vendor specific configuration file val databaseConfig = ConfigFactory.parseResources(System.getProperty("databaseProvider") + ".conf", parseOptions.setAllowMissing(true)) val fixedOverride = ConfigFactory.parseString("baseDirectory = \"\"") - val nodeOrganizationNameConfig = if (standarizedNodeName != null) configOf("nodeOrganizationName" to standarizedNodeName) else ConfigFactory.empty() + + //implied property nodeOrganizationName to fill the potential placeholders in db schema/ db user properties + val standardizedNodeName = if (nodeName!= null) nodeName.replace(" ", "").replace("-", "_") else null + val nodeOrganizationNameConfig = if (standardizedNodeName != null) configOf("nodeOrganizationName" to standardizedNodeName) else ConfigFactory.empty() + + //defaults to H2 + //for H2 the same db instance runs for all integration tests, so adding additional variable postfix to use unique db user/schema each time + val h2InstanceName = if (postfix != null) standardizedNodeName + "_" + postfix else standardizedNodeName val defaultProps = Properties() - defaultProps.setProperty("dataSourceProperties.dataSourceClassName", "org.h2.jdbcx.JdbcDataSource") - defaultProps.setProperty("dataSourceProperties.dataSource.url", "jdbc:h2:mem:${h2InstanceName}_persistence;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE") - defaultProps.setProperty("dataSourceProperties.dataSource.user", "sa") - defaultProps.setProperty("dataSourceProperties.dataSource.password", "") + defaultProps.setProperty(DATA_SOURCE_CLASSNAME, "org.h2.jdbcx.JdbcDataSource") + defaultProps.setProperty(DATA_SOURCE_URL, "jdbc:h2:mem:${h2InstanceName}_persistence;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE") + defaultProps.setProperty(DATA_SOURCE_USER, "sa") + defaultProps.setProperty(DATA_SOURCE_PASSWORD, "") val defaultConfig = ConfigFactory.parseProperties(defaultProps, parseOptions) - return databaseConfig.withFallback(fixedOverride) + return systemConfigOverride.withFallback(databaseConfig) + .withFallback(fixedOverride) .withFallback(nodeOrganizationNameConfig) .withFallback(defaultConfig) .resolve() @@ -112,7 +134,10 @@ open class MockServices( @JvmStatic fun makeTestDatabaseProperties(nodeName: String? = null): DatabaseConfig { val config = readDatabaseConfig(nodeName) - return DatabaseConfig(schema = if (config.hasPath("database.schema")) config.getString("database.schema") else "") + val transactionIsolationLevel = if (config.hasPath(TRANSACTION_ISOLATION_LEVEL)) TransactionIsolationLevel.valueOf(config.getString(TRANSACTION_ISOLATION_LEVEL)) + else TransactionIsolationLevel.READ_COMMITTED + val schema = if (config.hasPath(SCHEMA)) config.getString(SCHEMA) else "" + return DatabaseConfig(transactionIsolationLevel = transactionIsolationLevel, schema = schema) } private fun makeTestIdentityService() = InMemoryIdentityService(MOCK_IDENTITIES, trustRoot = DEV_TRUST_ROOT) @@ -144,9 +169,9 @@ open class MockServices( cordappPackages: List = emptyList(), initialIdentityName: CordaX500Name): Pair { val cordappLoader = CordappLoader.createWithTestPackages(cordappPackages) - val dataSourceProps = makeTestDataSourceProperties() + val dataSourceProps = makeTestDataSourceProperties(initialIdentityName.organisation) val schemaService = NodeSchemaService(cordappLoader.cordappSchemas) - val database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(), identityService, schemaService) + val database = configureDatabase(dataSourceProps, makeTestDatabaseProperties(initialIdentityName.organisation), identityService, schemaService) val mockService = database.transaction { object : MockServices(cordappLoader, initialIdentityName = initialIdentityName, keys = *(keys.toTypedArray())) { override val identityService get() = identityService diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/IntegrationTest.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/IntegrationTest.kt index c01c74c0e6..39b693dd4d 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/IntegrationTest.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/IntegrationTest.kt @@ -1,10 +1,12 @@ package net.corda.testing +import net.corda.core.identity.Party import net.corda.testing.database.DbScriptRunner.runDbScript import org.junit.After import org.junit.AfterClass import org.junit.Before import org.junit.BeforeClass +import org.junit.rules.ExternalResource /** * Base class for all integration tests that require common setup and/or teardown. @@ -12,6 +14,8 @@ import org.junit.BeforeClass */ abstract class IntegrationTest { + open protected val databaseSchemas = Companion.databaseSchemas + // System properties set in main 'corda-project' build.gradle // Note: the database provider configuration file for integration tests should specify: // dataSource.user = ${nodeOrganizationName} @@ -22,19 +26,20 @@ abstract class IntegrationTest { private val dbProvider = System.getProperty(DATABASE_PROVIDER, "") private val TEST_DB_SCRIPT_DIR = "test.db.script.dir" private val testDbScriptDir = System.getProperty(TEST_DB_SCRIPT_DIR, "database-scripts") + var databaseSchemas = mutableListOf() @BeforeClass @JvmStatic fun globalSetUp() { if (dbProvider.isNotEmpty()) { - runDbScript(dbProvider,"$testDbScriptDir/db-global-setup-${this::class.simpleName}.sql") + runDbScript(dbProvider,"$testDbScriptDir/db-global-setup.sql", databaseSchemas) } } @AfterClass @JvmStatic fun globalTearDown() { if (dbProvider.isNotEmpty()) { - runDbScript(dbProvider,"$testDbScriptDir/db-global-cleanup-${this::class.simpleName}.sql") + runDbScript(dbProvider,"$testDbScriptDir/db-global-cleanup.sql", databaseSchemas) } } } @@ -43,15 +48,31 @@ abstract class IntegrationTest { @Throws(Exception::class) open fun setUp() { if (dbProvider.isNotEmpty()) { - runDbScript(dbProvider,"$testDbScriptDir/db-setup-${this::class.simpleName}.sql") + runDbScript(dbProvider,"$testDbScriptDir/db-setup.sql", databaseSchemas) } } @After open fun tearDown() { if (dbProvider.isNotEmpty()) { - runDbScript(dbProvider,"$testDbScriptDir/db-cleanup-${this::class.simpleName}.sql") + runDbScript(dbProvider,"$testDbScriptDir/db-cleanup.sql", databaseSchemas) } } +} +class IntegrationTestSchemas(vararg var list : String) : ExternalResource() { + + override fun before() { + IntegrationTest.Companion.databaseSchemas.addAll(list) + } + override fun after() { + IntegrationTest.Companion.databaseSchemas.clear() + } +} + +fun Party.toDatabaseSchemaName() = this.name.organisation.replace(" ", "").replace("-", "_") + +fun Party.toDatabaseSchemaNames(vararg postfixes: String): List { + val nodeName = this.toDatabaseSchemaName() + return postfixes.map { "$nodeName$it" } } \ No newline at end of file diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/database/DatabaseConstants.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/database/DatabaseConstants.kt new file mode 100644 index 0000000000..3313bd0ddd --- /dev/null +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/database/DatabaseConstants.kt @@ -0,0 +1,10 @@ +package net.corda.testing.database + +object DatabaseConstants { + const val DATA_SOURCE_URL = "dataSourceProperties.dataSource.url" + const val DATA_SOURCE_CLASSNAME = "dataSourceProperties.dataSourceClassName" + const val DATA_SOURCE_USER = "dataSourceProperties.dataSource.user" + const val DATA_SOURCE_PASSWORD = "dataSourceProperties.dataSource.password" + const val TRANSACTION_ISOLATION_LEVEL = "database.transactionIsolationLevel" + const val SCHEMA = "database.schema" +} \ No newline at end of file diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/database/DbScriptRunner.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/database/DbScriptRunner.kt index 10e3b1a1bf..06cd06fd39 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/database/DbScriptRunner.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/database/DbScriptRunner.kt @@ -3,10 +3,20 @@ package net.corda.testing.database import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigParseOptions import net.corda.core.utilities.loggerFor +import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_CLASSNAME +import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_PASSWORD +import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_URL +import net.corda.testing.database.DatabaseConstants.DATA_SOURCE_USER +import org.apache.commons.logging.LogFactory import org.springframework.core.io.ClassPathResource +import org.springframework.core.io.support.EncodedResource import org.springframework.jdbc.datasource.DriverManagerDataSource -import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils -import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator +import org.springframework.jdbc.datasource.init.* +import org.springframework.util.StringUtils +import java.sql.Connection +import java.sql.SQLException +import java.sql.SQLWarning +import java.util.* object DbScriptRunner { private val log = loggerFor() @@ -15,19 +25,106 @@ object DbScriptRunner { private const val TEST_DB_ADMIN_USER = "test.db.admin.user" private const val TEST_DB_ADMIN_PASSWORD = "test.db.admin.password" - fun runDbScript(dbProvider: String, initScript: String) { + private fun createDataSource(dbProvider: String) : DriverManagerDataSource { val parseOptions = ConfigParseOptions.defaults() - val databaseConfig = ConfigFactory.parseResources("$dbProvider.conf", parseOptions.setAllowMissing(false)) + val allSystemProperties = System.getProperties().toList().map { it.first.toString() to it.second.toString() }.toMap() + val dataSourceSystemProperties = Properties() + val dataSourceKeys = listOf(TEST_DB_ADMIN_USER, TEST_DB_ADMIN_PASSWORD, DATA_SOURCE_URL, DATA_SOURCE_CLASSNAME, + DATA_SOURCE_USER, DATA_SOURCE_PASSWORD) + dataSourceKeys.filter { allSystemProperties.containsKey(it) }.forEach { dataSourceSystemProperties.setProperty(it, allSystemProperties[it]) } + val databaseConfig = ConfigFactory.parseProperties(dataSourceSystemProperties, parseOptions) + .withFallback(ConfigFactory.parseResources("$dbProvider.conf", parseOptions.setAllowMissing(false))) + val dataSource = DriverManagerDataSource() - dataSource.setDriverClassName(databaseConfig.getString("dataSourceProperties.dataSourceClassName")) - dataSource.url = databaseConfig.getString("dataSourceProperties.dataSource.url") - dataSource.username = System.getProperty(TEST_DB_ADMIN_USER) - dataSource.password = System.getProperty(TEST_DB_ADMIN_PASSWORD) - val initSchema = ClassPathResource(initScript ) - if (initSchema.exists()) { - val databasePopulator = ResourceDatabasePopulator(false, true, null, initSchema) - DatabasePopulatorUtils.execute(databasePopulator, dataSource) + dataSource.setDriverClassName(databaseConfig.getString(DATA_SOURCE_CLASSNAME)) + dataSource.url = databaseConfig.getString(DATA_SOURCE_URL) + dataSource.username = databaseConfig.getString(TEST_DB_ADMIN_USER) + dataSource.password = databaseConfig.getString(TEST_DB_ADMIN_PASSWORD) + return dataSource + } + + fun runDbScript(dbProvider: String, initScript: String? = null, databaseSchemas: List = emptyList()) { + if (initScript != null) { + val initSchema = ClassPathResource(initScript) + if (initSchema.exists()) { + val encodedResource = EncodedResource(initSchema) + val inputString = encodedResource.inputStream.bufferedReader().use { it.readText().split("\n") } + val resolvedScripts = merge(inputString, databaseSchemas) + log.info("Executing DB Script for schemas $databaseSchemas with ${resolvedScripts.size} statements.") + DatabasePopulatorUtils.execute(ListPopulator(false, true, resolvedScripts), + createDataSource(dbProvider)) + } else log.warn("DB Script missing: $initSchema") + } + } + + fun merge(scripts: List, schema: String): List = + scripts.map { it.replace("\${schema}", schema) } + + fun merge(scripts: List, schemas: List): List = + if(schemas.isEmpty()) scripts else schemas.map { merge(scripts, it) }.flatten() +} + +//rewritten version of org.springframework.jdbc.datasource.init.ResourceDatabasePopulator +class ListPopulator(private val continueOnError: Boolean, + private val ignoreFailedDrops: Boolean, + private val statements: List) : DatabasePopulator { + private val logger = LogFactory.getLog(ScriptUtils::class.java) + + override fun populate(connection: Connection) { + try { + if (logger.isInfoEnabled) { + logger.info("Executing SQL script " ) + } + val startTime = System.currentTimeMillis() + val resource = statements.toString().substring(0,30) + " [...]" + var stmtNumber = 0 + val stmt = connection.createStatement() + try { + for (statement in statements) { + stmtNumber++ + try { + stmt.execute(statement) + val rowsAffected = stmt.updateCount + if (logger.isDebugEnabled) { + logger.debug(rowsAffected.toString() + " returned as update count for SQL: " + statement) + var warningToLog: SQLWarning? = stmt.warnings + while (warningToLog != null) { + logger.debug("SQLWarning ignored: SQL state '" + warningToLog.sqlState + + "', error code '" + warningToLog.errorCode + + "', message [" + warningToLog.message + "]") + warningToLog = warningToLog.nextWarning + } + } + } catch (ex: SQLException) { + val dropStatement = StringUtils.startsWithIgnoreCase(statement.trim { it <= ' ' }, "drop") + if (continueOnError || dropStatement && ignoreFailedDrops) { + if (logger.isDebugEnabled) { + logger.debug(ex) + } + } else { + throw ex + } + } + } + } finally { + try { + stmt.close() + } catch (ex: Throwable) { + logger.debug("Could not close JDBC Statement", ex) + } + } + + val elapsedTime = System.currentTimeMillis() - startTime + if (logger.isInfoEnabled) { + logger.info("Executed SQL script from $resource in $elapsedTime ms.") + } + logger.info("Executed SQL script $resource" ) + } catch (ex: Exception) { + if (ex is ScriptException) { + throw ex + } + throw UncategorizedScriptException( + "Failed to execute database script from resource [resource]", ex) } - else log.warn("DB Script missing: $initSchema") } } diff --git a/testing/test-utils/src/main/resources/database-scripts/sql-azure/db-setup.sql b/testing/test-utils/src/main/resources/database-scripts/sql-azure/db-setup.sql new file mode 100644 index 0000000000..d3c0065a79 --- /dev/null +++ b/testing/test-utils/src/main/resources/database-scripts/sql-azure/db-setup.sql @@ -0,0 +1,49 @@ +DROP TABLE IF EXISTS ${schema}.node_attachments; +DROP TABLE IF EXISTS ${schema}.node_checkpoints; +DROP TABLE IF EXISTS ${schema}.node_transactions; +DROP TABLE IF EXISTS ${schema}.node_message_retry; +DROP TABLE IF EXISTS ${schema}.node_message_ids; +DROP TABLE IF EXISTS ${schema}.vault_states; +DROP TABLE IF EXISTS ${schema}.node_our_key_pairs; +DROP TABLE IF EXISTS ${schema}.node_scheduled_states; +DROP TABLE IF EXISTS ${schema}.node_network_map_nodes; +DROP TABLE IF EXISTS ${schema}.node_network_map_subscribers; +DROP TABLE IF EXISTS ${schema}.node_notary_commit_log; +DROP TABLE IF EXISTS ${schema}.node_transaction_mappings; +DROP TABLE IF EXISTS ${schema}.vault_fungible_states_parts; +DROP TABLE IF EXISTS ${schema}.vault_linear_states_parts; +DROP TABLE IF EXISTS ${schema}.vault_fungible_states; +DROP TABLE IF EXISTS ${schema}.vault_linear_states; +DROP TABLE IF EXISTS ${schema}.node_bft_committed_states; +DROP TABLE IF EXISTS ${schema}.node_raft_committed_states; +DROP TABLE IF EXISTS ${schema}.vault_transaction_notes; +DROP TABLE IF EXISTS ${schema}.link_nodeinfo_party; +DROP TABLE IF EXISTS ${schema}.node_link_nodeinfo_party; +DROP TABLE IF EXISTS ${schema}.node_info_party_cert; +DROP TABLE IF EXISTS ${schema}.node_info_hosts; +DROP TABLE IF EXISTS ${schema}.node_infos; +DROP TABLE IF EXISTS ${schema}.cp_states; +DROP TABLE IF EXISTS ${schema}.node_contract_upgrades; +DROP TABLE IF EXISTS ${schema}.node_identities; +DROP TABLE IF EXISTS ${schema}.node_named_identities; +DROP TABLE IF EXISTS ${schema}.children; +DROP TABLE IF EXISTS ${schema}.parents; +DROP TABLE IF EXISTS ${schema}.contract_cash_states; +DROP TABLE IF EXISTS ${schema}.messages; +DROP TABLE IF EXISTS ${schema}.DummyDealStateSchemaV1$PersistentDummyDealState_participants; +DROP TABLE IF EXISTS ${schema}.DummyLinearStateSchemaV1$PersistentDummyLinearState_participants; +DROP TABLE IF EXISTS ${schema}.DummyLinearStateSchemaV2$PersistentDummyLinearState_participants; +DROP TABLE IF EXISTS ${schema}.SampleCashSchemaV2$PersistentCashState_participants; +DROP TABLE IF EXISTS ${schema}.SampleCashSchemaV3$PersistentCashState_participants; +DROP TABLE IF EXISTS ${schema}.SampleCommercialPaperSchemaV2$PersistentCommercialPaperState_participants; +DROP TABLE IF EXISTS ${schema}.cash_states_v2; +DROP TABLE IF EXISTS ${schema}.cash_states_v3; +DROP TABLE IF EXISTS ${schema}.cp_states_v2; +DROP TABLE IF EXISTS ${schema}.dummy_deal_states; +DROP TABLE IF EXISTS ${schema}.dummy_linear_states; +DROP TABLE IF EXISTS ${schema}.dummy_linear_states_v2; +DROP SEQUENCE IF EXISTS ${schema}.hibernate_sequence; +IF NOT EXISTS (SELECT schema_name FROM information_schema.schemata WHERE schema_name = '${schema}') EXEC('CREATE SCHEMA ${schema}'); +IF NOT EXISTS (SELECT * FROM sys.sysusers WHERE name='${schema}') CREATE USER ${schema} FOR LOGIN ${schema} WITH DEFAULT_SCHEMA = ${schema}; +GRANT ALTER, DELETE, EXECUTE, INSERT, REFERENCES, SELECT, UPDATE, VIEW DEFINITION ON SCHEMA::${schema} TO ${schema}; +GRANT CREATE TABLE, CREATE PROCEDURE, CREATE FUNCTION, CREATE VIEW TO ${schema}; \ No newline at end of file diff --git a/testing/test-utils/src/main/resources/database-scripts/sql-azure/master-user-setup.sql b/testing/test-utils/src/main/resources/database-scripts/sql-azure/master-user-setup.sql new file mode 100644 index 0000000000..a78bee4e1a --- /dev/null +++ b/testing/test-utils/src/main/resources/database-scripts/sql-azure/master-user-setup.sql @@ -0,0 +1,87 @@ +--once off script to run against master database (not a user database) +CREATE LOGIN AliceCorp WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER AliceCorp FROM LOGIN AliceCorp; +CREATE LOGIN AliceCorp_10000 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER AliceCorp_10000 FROM LOGIN AliceCorp_10003; +CREATE LOGIN AliceCorp_10003 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER AliceCorp_10003 FROM LOGIN AliceCorp_10003; +CREATE LOGIN AliceCorp_10006 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER AliceCorp_10006 FROM LOGIN AliceCorp_10006; +CREATE LOGIN BankA WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BankA FROM LOGIN BankA; +CREATE LOGIN BankA_10000 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BankA_10000 FROM LOGIN BankA_10000; +CREATE LOGIN BankA_10003 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BankA_10003 FROM LOGIN BankA_10003; +CREATE LOGIN BankA_10006 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BankA_10006 FROM LOGIN BankA_10006; +CREATE LOGIN BankB WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BankB FROM LOGIN BankB; +CREATE LOGIN BobPlc WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BobPlc FROM LOGIN BobPlc; +CREATE LOGIN BobPlc_10000 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BobPlc_10000 FROM LOGIN BobPlc_10000; +CREATE LOGIN BobPlc_10003 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BobPlc_10003 FROM LOGIN BobPlc_10003; +CREATE LOGIN BobPlc_10006 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BobPlc_10006 FROM LOGIN BobPlc_10006; +CREATE LOGIN CharlieLtd WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER CharlieLtd FROM LOGIN CharlieLtd; +CREATE LOGIN DistributedService_0 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER DistributedService_0 FROM LOGIN DistributedService_0; +CREATE LOGIN DistributedService_1 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER DistributedService_1 FROM LOGIN DistributedService_1; +CREATE LOGIN NetworkMapService WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER NetworkMapService FROM LOGIN NetworkMapService; +CREATE LOGIN Notary WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER Notary FROM LOGIN Notary; +CREATE LOGIN NotaryService WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER NotaryService FROM LOGIN NotaryService; +CREATE LOGIN NotaryService0 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER NotaryService0 FROM LOGIN NotaryService0; +CREATE LOGIN NotaryService1 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER NotaryService1 FROM LOGIN NotaryService1; +CREATE LOGIN NotaryService2 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER NotaryService2 FROM LOGIN NotaryService2; +CREATE LOGIN NotaryService_0 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER NotaryService_0 FROM LOGIN NotaryService_0; +CREATE LOGIN NotaryService_1 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER NotaryService_1 FROM LOGIN NotaryService_1; +CREATE LOGIN NotaryService_2 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER NotaryService_2 FROM LOGIN NotaryService_2; +CREATE LOGIN MegaCorp WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER MegaCorp FOR LOGIN MegaCorp; +CREATE LOGIN node_0 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_0 FOR LOGIN node_0; +CREATE LOGIN node_1 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_1 FOR LOGIN node_1; +CREATE LOGIN node_2 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_2 FOR LOGIN node_2; +CREATE LOGIN node_3 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_3 FOR LOGIN node_3; +CREATE LOGIN node_4 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_4 FOR LOGIN node_4; +CREATE LOGIN node_5 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_5 FOR LOGIN node_5; +CREATE LOGIN node_6 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_6 FOR LOGIN node_6; +CREATE LOGIN node_7 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_7 FOR LOGIN node_7; +CREATE LOGIN node_8 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_8 FOR LOGIN node_8; +CREATE LOGIN node_9 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER node_9 FOR LOGIN node_9; +CREATE LOGIN RAFTNotaryService_0 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER RAFTNotaryService_0 FROM LOGIN RAFTNotaryService_0; +CREATE LOGIN RAFTNotaryService_1 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER RAFTNotaryService_1 FROM LOGIN RAFTNotaryService_1; +CREATE LOGIN RAFTNotaryService_2 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER RAFTNotaryService_2 FROM LOGIN RAFTNotaryService_2; +CREATE LOGIN RegulatorA WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER RegulatorA FROM LOGIN RegulatorA; +CREATE LOGIN AliceCorp_10012 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER AliceCorp_10012 FROM LOGIN AliceCorp_10012; +CREATE LOGIN BobPlc_10012 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BobPlc_10012 FROM LOGIN BobPlc_10012; +CREATE LOGIN BankA_10012 WITH PASSWORD = 'yourStrong(!)Password'; +CREATE USER BankA_10012 FROM LOGIN BankA_10012; \ No newline at end of file diff --git a/testing/test-utils/src/main/resources/integration-sql-azure.conf b/testing/test-utils/src/main/resources/integration-sql-azure.conf new file mode 100644 index 0000000000..8c769a303c --- /dev/null +++ b/testing/test-utils/src/main/resources/integration-sql-azure.conf @@ -0,0 +1,11 @@ +dataSourceProperties = { + dataSourceClassName = "com.microsoft.sqlserver.jdbc.SQLServerDataSource" + dataSource.url = "jdbc:sqlserver://[HOST]:1433;databaseName=[DATABASE];encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30" + dataSource.user = ${nodeOrganizationName} + dataSource.password = "yourStrong(!)Password" +} +database = { + transactionIsolationLevel = READ_COMMITTED + initDatabase = true + schema = ${nodeOrganizationName} +} \ No newline at end of file diff --git a/testing/test-utils/src/main/resources/integration-sql-server.conf b/testing/test-utils/src/main/resources/integration-sql-server.conf new file mode 100644 index 0000000000..454f1d4442 --- /dev/null +++ b/testing/test-utils/src/main/resources/integration-sql-server.conf @@ -0,0 +1,11 @@ +dataSourceProperties = { + dataSourceClassName = "com.microsoft.sqlserver.jdbc.SQLServerDataSource" + dataSource.url = "jdbc:sqlserver://[HOST]:[PORT]" + dataSource.user = ${nodeOrganizationName} + dataSource.password = "yourStrong(!)Password" +} +database = { + transactionIsolationLevel = READ_COMMITTED + initDatabase = true + schema = ${nodeOrganizationName} +}