From ae2b96df41675f55cd96346e14e11e4b93c5c6a9 Mon Sep 17 00:00:00 2001 From: szymonsztuka Date: Fri, 21 Sep 2018 15:03:46 +0100 Subject: [PATCH] Fix integration tests in database mode (#1401) Add SQL setup in new test classes which were missing it. Ignoring H2 tests when running against standalone database. Revert datasource Enterprise specific configuration for RaftTransactionCommitLogTests.kt test, and mark it as required for test in database mode. --- .../kotlin/net/corda/node/BootTests.kt | 4 +++- .../net/corda/node/ExternalBrokerTests.kt | 9 +++++++++ .../node/flows/AsymmetricCorDappsTests.kt | 3 +-- .../corda/node/persistence/H2SecurityTests.kt | 13 ++++++++++++- .../RaftTransactionCommitLogTests.kt | 6 ++++-- .../messaging/AdditionP2PAddressModeTest.kt | 18 +++++++++++++----- .../corda/services/vault/VaultRestartTest.kt | 12 +++++++++++- .../net/corda/testing/driver/DriverTests.kt | 2 ++ .../corda/testing/database/DbScriptRunner.kt | 8 +++++--- 9 files changed, 60 insertions(+), 15 deletions(-) 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 e63f12f885..a223462d8f 100644 --- a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt @@ -16,6 +16,7 @@ import net.corda.nodeapi.exceptions.InternalNodeException import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.BOB_NAME import net.corda.testing.core.DUMMY_BANK_A_NAME +import net.corda.testing.core.DUMMY_NOTARY_NAME import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeParameters @@ -38,7 +39,8 @@ class BootTests : IntegrationTest() { companion object { @ClassRule @JvmField - val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), DUMMY_BANK_A_NAME.toDatabaseSchemaName()) + val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), + DUMMY_BANK_A_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName()) } @Test fun `java deserialization is disabled`() { diff --git a/node/src/integration-test/kotlin/net/corda/node/ExternalBrokerTests.kt b/node/src/integration-test/kotlin/net/corda/node/ExternalBrokerTests.kt index 68bc780293..116a7211ba 100644 --- a/node/src/integration-test/kotlin/net/corda/node/ExternalBrokerTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/ExternalBrokerTests.kt @@ -11,14 +11,18 @@ import net.corda.node.services.config.* import net.corda.node.services.messaging.ArtemisMessagingServer import net.corda.nodeapi.internal.config.ExternalBrokerConnectionConfiguration import net.corda.testing.core.ALICE_NAME +import net.corda.testing.core.DUMMY_NOTARY_NAME import net.corda.testing.core.MAX_MESSAGE_SIZE import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.PortAllocation import net.corda.testing.driver.driver import net.corda.testing.internal.IntegrationTest +import net.corda.testing.internal.IntegrationTestSchemas import net.corda.testing.internal.rigorousMock import net.corda.testing.internal.stubs.CertificateStoreStubs +import net.corda.testing.internal.toDatabaseSchemaName import net.corda.testing.node.User +import org.junit.ClassRule import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder @@ -28,6 +32,11 @@ import kotlin.test.assertEquals import kotlin.test.fail class ExternalBrokertests : IntegrationTest() { + companion object { + @ClassRule + @JvmField + val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName()) + } @Rule @JvmField diff --git a/node/src/integration-test/kotlin/net/corda/node/flows/AsymmetricCorDappsTests.kt b/node/src/integration-test/kotlin/net/corda/node/flows/AsymmetricCorDappsTests.kt index 3d4611bc9a..d310a17f23 100644 --- a/node/src/integration-test/kotlin/net/corda/node/flows/AsymmetricCorDappsTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/flows/AsymmetricCorDappsTests.kt @@ -24,8 +24,7 @@ class AsymmetricCorDappsTests : IntegrationTest() { companion object { @ClassRule @JvmField - val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), - DUMMY_BANK_A_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName()) + val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName()) } @StartableByRPC diff --git a/node/src/integration-test/kotlin/net/corda/node/persistence/H2SecurityTests.kt b/node/src/integration-test/kotlin/net/corda/node/persistence/H2SecurityTests.kt index 57dad79ea5..9e42212053 100644 --- a/node/src/integration-test/kotlin/net/corda/node/persistence/H2SecurityTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/persistence/H2SecurityTests.kt @@ -11,7 +11,9 @@ import net.corda.nodeapi.internal.persistence.CouldNotCreateDataSourceException import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.PortAllocation import net.corda.testing.driver.driver +import net.corda.testing.internal.IntegrationTest import net.corda.testing.node.User +import org.junit.Assume.assumeTrue import org.junit.Test import java.net.InetAddress import java.sql.DriverManager @@ -29,6 +31,7 @@ class H2SecurityTests { @Test fun `h2 server starts when h2Settings are set`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database driver(DriverParameters(inMemoryDB = false, startNodesInProcess = isQuasarAgentSpecified(), notarySpecs = emptyList())) { val port = getFreePort() startNode(customOverrides = mapOf(h2AddressKey to "localhost:$port")).getOrThrow() @@ -40,6 +43,7 @@ class H2SecurityTests { @Test fun `h2 server on the host name requires non-default database password`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database driver(DriverParameters(inMemoryDB = false, startNodesInProcess = isQuasarAgentSpecified(), notarySpecs = emptyList())) { assertFailsWith(CouldNotCreateDataSourceException::class) { startNode(customOverrides = mapOf(h2AddressKey to "${InetAddress.getLocalHost().hostName}:${getFreePort()}")).getOrThrow() @@ -48,7 +52,8 @@ class H2SecurityTests { } @Test - fun `h2 server on the external host IP requires non-default database password`() { + fun `h2 server on the external host IP requires non-default database password`(){ + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database driver(DriverParameters(inMemoryDB = false, startNodesInProcess = isQuasarAgentSpecified(), notarySpecs = emptyList())) { assertFailsWith(CouldNotCreateDataSourceException::class) { startNode(customOverrides = mapOf(h2AddressKey to "${InetAddress.getLocalHost().hostAddress}:${getFreePort()}")).getOrThrow() @@ -58,6 +63,7 @@ class H2SecurityTests { @Test fun `h2 server on host name requires non-blank database password`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database driver(DriverParameters(inMemoryDB = false, startNodesInProcess = isQuasarAgentSpecified(), notarySpecs = emptyList())) { assertFailsWith(CouldNotCreateDataSourceException::class) { startNode(customOverrides = mapOf(h2AddressKey to "${InetAddress.getLocalHost().hostName}:${getFreePort()}", @@ -68,6 +74,7 @@ class H2SecurityTests { @Test fun `h2 server on external host IP requires non-blank database password`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database driver(DriverParameters(inMemoryDB = false, startNodesInProcess = isQuasarAgentSpecified(), notarySpecs = emptyList())) { assertFailsWith(CouldNotCreateDataSourceException::class) { startNode(customOverrides = mapOf(h2AddressKey to "${InetAddress.getLocalHost().hostAddress}:${getFreePort()}", @@ -78,6 +85,7 @@ class H2SecurityTests { @Test fun `h2 server on localhost runs with the default database password`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database driver(DriverParameters(inMemoryDB = false, startNodesInProcess = false, notarySpecs = emptyList())) { startNode(customOverrides = mapOf(h2AddressKey to "localhost:${getFreePort()}")).getOrThrow() } @@ -85,6 +93,7 @@ class H2SecurityTests { @Test fun `h2 server to loopback IP runs with the default database password`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database driver(DriverParameters(inMemoryDB = false, startNodesInProcess = isQuasarAgentSpecified(), notarySpecs = emptyList())) { startNode(customOverrides = mapOf(h2AddressKey to "127.0.0.1:${getFreePort()}")).getOrThrow() } @@ -92,6 +101,7 @@ class H2SecurityTests { @Test fun `remote code execution via h2 server is disabled`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database driver(DriverParameters(inMemoryDB = false, startNodesInProcess = false, notarySpecs = emptyList())) { val port = getFreePort() startNode(customOverrides = mapOf(h2AddressKey to "localhost:$port", dbPasswordKey to "x")).getOrThrow() @@ -107,6 +117,7 @@ class H2SecurityTests { @Test fun `malicious flow tries to enable remote code execution via h2 server`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test where running against remote database val user = User("mark", "dadada", setOf(Permissions.startFlow())) driver(DriverParameters(inMemoryDB = false, startNodesInProcess = false, notarySpecs = emptyList())) { val port = getFreePort() diff --git a/node/src/integration-test/kotlin/net/corda/node/services/transactions/RaftTransactionCommitLogTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/transactions/RaftTransactionCommitLogTests.kt index 3edb3d3f3e..a4eccadef5 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/transactions/RaftTransactionCommitLogTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/transactions/RaftTransactionCommitLogTests.kt @@ -1,5 +1,6 @@ package net.corda.node.services.transactions +import com.typesafe.config.ConfigFactory import io.atomix.catalyst.transport.Address import io.atomix.copycat.client.ConnectionStrategies import io.atomix.copycat.client.CopycatClient @@ -22,7 +23,7 @@ import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.driver.PortAllocation import net.corda.testing.internal.LogHelper -import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties +import net.corda.testing.node.internal.makeInternalTestDataSourceProperties import org.hamcrest.Matchers.instanceOf import org.junit.After import org.junit.Assert.assertThat @@ -153,7 +154,8 @@ class RaftTransactionCommitLogTests { private fun createReplica(myAddress: NetworkHostAndPort, clusterAddress: NetworkHostAndPort? = null): CompletableFuture { val storage = Storage.builder().withStorageLevel(StorageLevel.MEMORY).build() val address = Address(myAddress.host, myAddress.port) - val database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(), { null }, { null }, NodeSchemaService(includeNotarySchemas = true)) + // Enterprise - OS difference: below configureDatabase parameters differs with OS intentionally to be able run test in remote database + val database = configureDatabase(makeInternalTestDataSourceProperties( configSupplier = { ConfigFactory.empty() }), DatabaseConfig(runMigration = true), { null }, { null }, NodeSchemaService(includeNotarySchemas = true)) databases.add(database) val stateMachineFactory = { RaftTransactionCommitLog(database, Clock.systemUTC(), RaftUniquenessProvider.Companion::createMap) } diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/AdditionP2PAddressModeTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/AdditionP2PAddressModeTest.kt index e4087fe3f7..f102cc077d 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/AdditionP2PAddressModeTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/AdditionP2PAddressModeTest.kt @@ -12,18 +12,26 @@ import net.corda.finance.DOLLARS import net.corda.finance.contracts.asset.Cash import net.corda.finance.flows.CashIssueAndPaymentFlow import net.corda.node.services.Permissions.Companion.all -import net.corda.testing.core.DUMMY_BANK_A_NAME -import net.corda.testing.core.DUMMY_BANK_B_NAME -import net.corda.testing.core.expect -import net.corda.testing.core.expectEvents +import net.corda.testing.core.* import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.PortAllocation import net.corda.testing.driver.driver +import net.corda.testing.internal.IntegrationTest +import net.corda.testing.internal.IntegrationTestSchemas +import net.corda.testing.internal.toDatabaseSchemaName import net.corda.testing.node.User +import org.junit.ClassRule import org.junit.Test import java.util.* -class AdditionP2PAddressModeTest { +class AdditionP2PAddressModeTest : IntegrationTest() { + companion object { + @ClassRule + @JvmField + val databaseSchemas = IntegrationTestSchemas(DUMMY_BANK_A_NAME.toDatabaseSchemaName(), DUMMY_BANK_B_NAME.toDatabaseSchemaName(), + DUMMY_NOTARY_NAME.toDatabaseSchemaName()) + } + private val portAllocation = PortAllocation.Incremental(27182) @Test fun `runs nodes with one configured to use additionalP2PAddresses`() { diff --git a/node/src/integration-test/kotlin/net/corda/services/vault/VaultRestartTest.kt b/node/src/integration-test/kotlin/net/corda/services/vault/VaultRestartTest.kt index a7d5650f2e..d97ba3c3a5 100644 --- a/node/src/integration-test/kotlin/net/corda/services/vault/VaultRestartTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/vault/VaultRestartTest.kt @@ -10,13 +10,23 @@ import net.corda.finance.DOLLARS import net.corda.finance.contracts.asset.Cash import net.corda.finance.flows.CashIssueFlow import net.corda.testing.core.DUMMY_BANK_A_NAME +import net.corda.testing.core.DUMMY_NOTARY_NAME import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.OutOfProcess import net.corda.testing.driver.driver +import net.corda.testing.internal.IntegrationTest +import net.corda.testing.internal.IntegrationTestSchemas +import net.corda.testing.internal.toDatabaseSchemaName import org.assertj.core.api.Assertions +import org.junit.ClassRule import org.junit.Test -class VaultRestartTest { +class VaultRestartTest : IntegrationTest() { + companion object { + @ClassRule + @JvmField + val databaseSchemas = IntegrationTestSchemas(DUMMY_BANK_A_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName()) + } @Test fun `restart and query vault after adding some cash states`() { 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 5f07b942dc..e3686e72c2 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 @@ -27,6 +27,7 @@ import net.corda.testing.node.internal.addressMustNotBeBound import net.corda.testing.node.internal.internalDriver import org.assertj.core.api.Assertions.* import org.json.simple.JSONObject +import org.junit.Assume.assumeTrue import org.junit.ClassRule import org.junit.Test import java.util.* @@ -156,6 +157,7 @@ class DriverTests : IntegrationTest() { @Test fun `driver rejects multiple nodes with the same organisation name`() { + assumeTrue(!IntegrationTest.isRemoteDatabaseMode()) // Enterprise only - disable test, Liquibase doesn't quote schema name with all uppercase or lowercase letters driver(DriverParameters(startNodesInProcess = true, notarySpecs = emptyList())) { newNode(CordaX500Name(commonName = "Notary", organisation = "R3CEV", locality = "New York", country = "US"))().getOrThrow() assertThatIllegalArgumentException().isThrownBy { 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 ce6564993d..7e1b03f620 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 @@ -65,7 +65,7 @@ object DbScriptRunner { if (schemas.isEmpty()) scripts else schemas.map { merge(scripts, it) }.flatten() } -//rewritten version of org.springframework.jdbc.datasource.init.ResourceDatabasePopulator +// Rewritten version of org.springframework.jdbc.datasource.init.ResourceDatabasePopulator class ListPopulator(private val continueOnError: Boolean, private val ignoreFailedDrops: Boolean, private val statements: List) : DatabasePopulator { @@ -94,9 +94,11 @@ class ListPopulator(private val continueOnError: Boolean, } } catch (ex: SQLException) { val dropStatement = StringUtils.startsWithIgnoreCase(statement.trim { it <= ' ' }, "drop") - if ((continueOnError || dropStatement && ignoreFailedDrops)) { + // Ignore exception on Oracle db, as the user from the previous test maybe still logged in, and cannot be dropped + val createUser = StringUtils.startsWithIgnoreCase(statement.trim { it <= ' ' },"CREATE USER") + if ((continueOnError || dropStatement && ignoreFailedDrops) || createUser) { val dropUserStatement = StringUtils.startsWithIgnoreCase(statement.trim { it <= ' ' }, "drop user ") - if (dropUserStatement) { // log to help spotting a node still logged on database after test has finished (happens on Oracle db) + if (dropUserStatement || createUser) { // log to help spotting a node still logged on database after test has finished (happens on Oracle db) logger.warn("SQLException for $statement: SQL state '" + ex.sqlState + "', error code '" + ex.errorCode + "', message [" + ex.message + "]")