diff --git a/.ci/dev/compatibility/JenkinsfileJDK11Azul b/.ci/dev/compatibility/JenkinsfileJDK11Azul index 999072ae9f..96396ca2c0 100644 --- a/.ci/dev/compatibility/JenkinsfileJDK11Azul +++ b/.ci/dev/compatibility/JenkinsfileJDK11Azul @@ -12,7 +12,7 @@ pipeline { } environment { - DOCKER_TAG_TO_USE = "${env.GIT_COMMIT.subSequence(0, 8)}" + DOCKER_TAG_TO_USE = "${env.GIT_COMMIT.subSequence(0, 8)}JDK11" EXECUTOR_NUMBER = "${env.EXECUTOR_NUMBER}" BUILD_ID = "${env.BUILD_ID}-${env.JOB_NAME}" ARTIFACTORY_CREDENTIALS = credentials('artifactory-credentials') diff --git a/.ci/dev/smoke/Jenkinsfile b/.ci/dev/smoke/Jenkinsfile deleted file mode 100644 index 3ddc3cdce8..0000000000 --- a/.ci/dev/smoke/Jenkinsfile +++ /dev/null @@ -1,101 +0,0 @@ -@Library('corda-shared-build-pipeline-steps') -import static com.r3.build.BuildControl.killAllExistingBuildsForJob - -killAllExistingBuildsForJob(env.JOB_NAME, env.BUILD_NUMBER.toInteger()) - -pipeline { - agent { label 'k8s' } - options { - timestamps() - overrideIndexTriggers(false) - timeout(time: 3, unit: 'HOURS') - } - - triggers { - issueCommentTrigger('.*smoke tests.*') - } - - environment { - EXECUTOR_NUMBER = "${env.EXECUTOR_NUMBER}" - } - - stages { - stage('Corda Smoke Tests') { - steps { - script { - if (currentBuildTriggeredByComment()) { - stage('Run Smoke Tests') { - script { - pullRequest.createStatus(status: 'pending', - context: 'continuous-integration/jenkins/pr-merge/smokeTest', - description: 'Smoke Tests Running', - targetUrl: "${env.JOB_URL}") - } - - withCredentials([string(credentialsId: 'container_reg_passwd', variable: 'DOCKER_PUSH_PWD')]) { - sh "./gradlew " + - "-Dkubenetize=true " + - "-Ddocker.push.password=\"\${DOCKER_PUSH_PWD}\" " + - "-Ddocker.work.dir=\"/tmp/\${EXECUTOR_NUMBER}\" " + - " clean allParallelSmokeTest --stacktrace" - } - } - - } - } - } - } - } - - post { - always { - script { - if (currentBuildTriggeredByComment()) { - archiveArtifacts artifacts: '**/pod-logs/**/*.log', fingerprint: false - junit '**/build/test-results-xml/**/*.xml' - } - } - } - - - success { - script { - if (currentBuildTriggeredByComment()) { - pullRequest.createStatus(status: 'success', - context: 'continuous-integration/jenkins/pr-merge/smokeTest', - description: 'Smoke Tests Passed', - targetUrl: "${env.BUILD_URL}testResults") - } - } - } - - failure { - script { - if (currentBuildTriggeredByComment()) { - pullRequest.createStatus(status: 'failure', - context: 'continuous-integration/jenkins/pr-merge/smokeTest', - description: 'Smoke Tests Failed', - targetUrl: "${env.BUILD_URL}testResults") - } - } - } - - cleanup { - deleteDir() /* clean up our workspace */ - } - } -} - -@NonCPS -def currentBuildTriggeredByComment() { - def triggerCause = currentBuild.rawBuild.getCause(org.jenkinsci.plugins.pipeline.github.trigger.IssueCommentCause) - if (triggerCause) { - echo("Build was started by ${triggerCause.userLogin}, who wrote: " + - "\"${triggerCause.comment}\", which matches the " + - "\"${triggerCause.triggerPattern}\" trigger pattern.") - } else { - echo('Build was not started by a trigger') - } - - return triggerCause != null -} diff --git a/common/logging/src/main/resources/error-codes/cordapp-invalid-version-identifier.properties b/common/logging/src/main/resources/error-codes/cordapp-invalid-version-identifier.properties index 64f4416164..ac5e328311 100644 --- a/common/logging/src/main/resources/error-codes/cordapp-invalid-version-identifier.properties +++ b/common/logging/src/main/resources/error-codes/cordapp-invalid-version-identifier.properties @@ -1,4 +1,4 @@ errorTemplate = Version identifier ({0}) for attribute {1} must be a whole number starting from 1. shortDescription = A version attribute with an invalid value was specified in the manifest of the CorDapp JAR. The version attribute value must be a whole number that is greater than or equal to 1. actionsToFix = Investigate the logs to find the invalid version attribute, and change its value to a valid one (a whole number greater than or equal to 1). -aliases = \ No newline at end of file +aliases = 1nskd37 \ No newline at end of file diff --git a/common/logging/src/main/resources/error-codes/cordapp-invalid-version-identifier_en_US.properties b/common/logging/src/main/resources/error-codes/cordapp-invalid-version-identifier_en_US.properties index 64f4416164..f8a32f64bd 100644 --- a/common/logging/src/main/resources/error-codes/cordapp-invalid-version-identifier_en_US.properties +++ b/common/logging/src/main/resources/error-codes/cordapp-invalid-version-identifier_en_US.properties @@ -1,4 +1,3 @@ errorTemplate = Version identifier ({0}) for attribute {1} must be a whole number starting from 1. shortDescription = A version attribute with an invalid value was specified in the manifest of the CorDapp JAR. The version attribute value must be a whole number that is greater than or equal to 1. -actionsToFix = Investigate the logs to find the invalid version attribute, and change its value to a valid one (a whole number greater than or equal to 1). -aliases = \ No newline at end of file +actionsToFix = Investigate the logs to find the invalid version attribute, and change its value to a valid one (a whole number greater than or equal to 1). \ No newline at end of file diff --git a/common/logging/src/main/resources/error-codes/cordapp-missing-version-attribute.properties b/common/logging/src/main/resources/error-codes/cordapp-missing-version-attribute.properties index b820268356..6598d8c263 100644 --- a/common/logging/src/main/resources/error-codes/cordapp-missing-version-attribute.properties +++ b/common/logging/src/main/resources/error-codes/cordapp-missing-version-attribute.properties @@ -1,4 +1,4 @@ errorTemplate = Target versionId attribute {0} not specified. Please specify a whole number starting from 1. shortDescription = A required version attribute was not specified in the manifest of the CorDapp JAR. actionsToFix = Investigate the logs to find out which version attribute was not specified, and add that version attribute to the CorDapp manifest. -aliases = \ No newline at end of file +aliases = 1nskd37 \ No newline at end of file diff --git a/common/logging/src/main/resources/error-codes/cordapp-missing-version-attribute_en_US.properties b/common/logging/src/main/resources/error-codes/cordapp-missing-version-attribute_en_US.properties index b820268356..8504d2632b 100644 --- a/common/logging/src/main/resources/error-codes/cordapp-missing-version-attribute_en_US.properties +++ b/common/logging/src/main/resources/error-codes/cordapp-missing-version-attribute_en_US.properties @@ -1,4 +1,3 @@ errorTemplate = Target versionId attribute {0} not specified. Please specify a whole number starting from 1. shortDescription = A required version attribute was not specified in the manifest of the CorDapp JAR. -actionsToFix = Investigate the logs to find out which version attribute was not specified, and add that version attribute to the CorDapp manifest. -aliases = \ No newline at end of file +actionsToFix = Investigate the logs to find out which version attribute was not specified, and add that version attribute to the CorDapp manifest. \ No newline at end of file diff --git a/core-tests/src/test/kotlin/net/corda/coretests/flows/FlowIsKilledTest.kt b/core-tests/src/test/kotlin/net/corda/coretests/flows/FlowIsKilledTest.kt index 0f496d6364..14a2607b26 100644 --- a/core-tests/src/test/kotlin/net/corda/coretests/flows/FlowIsKilledTest.kt +++ b/core-tests/src/test/kotlin/net/corda/coretests/flows/FlowIsKilledTest.kt @@ -20,10 +20,7 @@ import net.corda.testing.core.CHARLIE_NAME import net.corda.testing.core.singleIdentity import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.driver -import org.apache.logging.log4j.Level -import org.apache.logging.log4j.core.config.Configurator import org.assertj.core.api.Assertions.assertThatExceptionOfType -import org.junit.Before import org.junit.Test import java.util.concurrent.Semaphore import kotlin.test.assertEquals @@ -36,11 +33,6 @@ class FlowIsKilledTest { const val EXCEPTION_MESSAGE = "Goodbye, cruel world!" } - @Before - fun setup() { - Configurator.setLevel("net.corda.node.services.statemachine", Level.DEBUG) - } - @Test(timeout = 300_000) fun `manually handle the isKilled check`() { driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) { @@ -111,7 +103,6 @@ class FlowIsKilledTest { assertFailsWith { handle.returnValue.getOrThrow(1.minutes) } - assertTrue(AFlowThatGetsMurderedByItsFriend.receivedKilledException) assertEquals(11, AFlowThatGetsMurderedByItsFriendResponder.position) val aliceCheckpoints = alice.rpc.startFlow(::GetNumberOfCheckpointsFlow).returnValue.getOrThrow(20.seconds) assertEquals(1, aliceCheckpoints) @@ -121,7 +112,7 @@ class FlowIsKilledTest { } @Test(timeout = 300_000) - fun `manually handle killed flows using checkForIsNotKilled`() { + fun `manually handle killed flows using checkFlowIsNotKilled`() { driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) { val alice = startNode(providedName = ALICE_NAME).getOrThrow() alice.rpc.let { rpc -> @@ -140,7 +131,7 @@ class FlowIsKilledTest { } @Test(timeout = 300_000) - fun `manually handle killed flows using checkForIsNotKilled with lazy message`() { + fun `manually handle killed flows using checkFlowIsNotKilled with lazy message`() { driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) { val alice = startNode(providedName = ALICE_NAME).getOrThrow() alice.rpc.let { rpc -> @@ -192,6 +183,7 @@ class FlowIsKilledTest { companion object { val lockA = Semaphore(0) val lockB = Semaphore(0) + var isKilled = false var position = 0 } @@ -208,6 +200,7 @@ class FlowIsKilledTest { position = i logger.info("i = $i") if (isKilled) { + AFlowThatWantsToDieAndKillsItsFriends.isKilled = true throw KilledFlowException(runId, EXCEPTION_MESSAGE) } @@ -244,6 +237,9 @@ class FlowIsKilledTest { } catch (e: UnexpectedFlowEndException) { receivedKilledExceptions[ourIdentity.name] = true locks[ourIdentity.name]!!.release() + require(AFlowThatWantsToDieAndKillsItsFriends.isKilled) { + "The initiator must be killed when this exception is received" + } throw e } } @@ -253,19 +249,16 @@ class FlowIsKilledTest { @InitiatingFlow class AFlowThatGetsMurderedByItsFriend(private val party: Party) : FlowLogic() { - companion object { - var receivedKilledException = false - } - @Suspendable override fun call() { val sessionOne = initiateFlow(party) - // trigger sessions with 2 counter parties - sessionOne.sendAndReceive("what is up") try { + sessionOne.sendAndReceive("what is up") sessionOne.receive() } catch (e: UnexpectedFlowEndException) { - receivedKilledException = true + require(AFlowThatGetsMurderedByItsFriendResponder.isKilled) { + "The responder must be killed when this exception is received" + } throw e } } @@ -277,6 +270,7 @@ class FlowIsKilledTest { companion object { val lockA = Semaphore(0) val lockB = Semaphore(0) + var isKilled = false var flowId: StateMachineRunId? = null var position = 0 } @@ -289,6 +283,7 @@ class FlowIsKilledTest { for (i in 0..100) { position = i if (isKilled) { + AFlowThatGetsMurderedByItsFriendResponder.isKilled = true throw KilledFlowException(runId, EXCEPTION_MESSAGE) } diff --git a/core-tests/src/test/kotlin/net/corda/coretests/flows/FlowSleepTest.kt b/core-tests/src/test/kotlin/net/corda/coretests/flows/FlowSleepTest.kt index c2ce0b66d9..0c4a197d58 100644 --- a/core-tests/src/test/kotlin/net/corda/coretests/flows/FlowSleepTest.kt +++ b/core-tests/src/test/kotlin/net/corda/coretests/flows/FlowSleepTest.kt @@ -17,9 +17,6 @@ import net.corda.testing.core.BOB_NAME import net.corda.testing.core.singleIdentity import net.corda.testing.driver.DriverParameters import net.corda.testing.driver.driver -import org.apache.logging.log4j.Level -import org.apache.logging.log4j.core.config.Configurator -import org.junit.Before import org.junit.Test import java.time.Duration import java.time.Instant @@ -27,11 +24,6 @@ import kotlin.test.assertTrue class FlowSleepTest { - @Before - fun setup() { - Configurator.setLevel("net.corda.node.services.statemachine", Level.DEBUG) - } - @Test(timeout = 300_000) fun `flow can sleep`() { driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) { diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/AMQPClient.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/AMQPClient.kt index 561119b4f5..4551608054 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/AMQPClient.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/protonwrapper/netty/AMQPClient.kt @@ -113,7 +113,7 @@ class AMQPClient(val targets: List, override fun operationComplete(future: ChannelFuture) { amqpActive = false if (!future.isSuccess) { - log.info("Failed to connect to $currentTarget") + log.info("Failed to connect to $currentTarget", future.cause()) if (started) { workerGroup?.schedule({ diff --git a/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt b/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt index 9e95ace917..1fd59b9704 100644 --- a/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt @@ -9,6 +9,7 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.internal.div import net.corda.core.toFuture import net.corda.core.utilities.NetworkHostAndPort +import net.corda.core.utilities.contextLogger import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.config.configureWithDevSSLCertificate import net.corda.node.services.messaging.ArtemisMessagingServer @@ -51,7 +52,11 @@ class ProtonWrapperTests { @JvmField val temporaryFolder = TemporaryFolder() - private val portAllocation = incrementalPortAllocation() // use 15000 to move us out of harms way + companion object { + private val log = contextLogger() + } + + private val portAllocation = incrementalPortAllocation() private val serverPort = portAllocation.nextPort() private val serverPort2 = portAllocation.nextPort() private val artemisPort = portAllocation.nextPort() @@ -350,7 +355,8 @@ class ProtonWrapperTests { val connection2ID = CordaX500Name.build(connection2.remoteCert!!.subjectX500Principal) assertEquals("client 1", connection2ID.organisationUnit) val source2 = connection2.remoteAddress - // Stopping one shouldn't disconnect the other + + log.info("Stopping one shouldn't disconnect the other") amqpClient1.stop() val connection3 = connectionEvents.next() assertEquals(false, connection3.connected) @@ -358,14 +364,16 @@ class ProtonWrapperTests { assertEquals(false, amqpClient1.connected) client2Connected.get(60, TimeUnit.SECONDS) assertEquals(true, amqpClient2.connected) - // Now shutdown both + + log.info("Now shutdown both") amqpClient2.stop() val connection4 = connectionEvents.next() assertEquals(false, connection4.connected) assertEquals(source2, connection4.remoteAddress) assertEquals(false, amqpClient1.connected) assertEquals(false, amqpClient2.connected) - // Now restarting one should work + + log.info("Now restarting one should work") val client1Connected = amqpClient1.onConnection.toFuture() amqpClient1.start() val connection5 = connectionEvents.next() @@ -375,7 +383,8 @@ class ProtonWrapperTests { client1Connected.get(60, TimeUnit.SECONDS) assertEquals(true, amqpClient1.connected) assertEquals(false, amqpClient2.connected) - // Cleanup + + log.info("Cleanup") amqpClient1.stop() sharedThreads.shutdownGracefully() sharedThreads.terminationFuture().sync() diff --git a/node/src/integration-test/kotlin/net/corda/node/flows/KillFlowTest.kt b/node/src/integration-test/kotlin/net/corda/node/flows/KillFlowTest.kt index 59ed762343..0dc0c0d995 100644 --- a/node/src/integration-test/kotlin/net/corda/node/flows/KillFlowTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/flows/KillFlowTest.kt @@ -34,10 +34,7 @@ import net.corda.testing.driver.NodeParameters import net.corda.testing.driver.OutOfProcess import net.corda.testing.driver.driver import net.corda.testing.node.internal.FINANCE_CORDAPPS -import org.apache.logging.log4j.Level -import org.apache.logging.log4j.core.config.Configurator import org.assertj.core.api.Assertions -import org.junit.Before import org.junit.Test import java.time.Duration import java.util.concurrent.Semaphore @@ -50,11 +47,6 @@ import kotlin.test.assertTrue class KillFlowTest { - @Before - fun setup() { - Configurator.setLevel("net.corda.node.services.statemachine", Level.DEBUG) - } - @Test(timeout = 300_000) fun `a killed flow will end when it reaches the next suspension point`() { driver(DriverParameters(notarySpecs = emptyList(), startNodesInProcess = true)) { diff --git a/node/src/main/kotlin/net/corda/node/services/vault/HibernateQueryCriteriaParser.kt b/node/src/main/kotlin/net/corda/node/services/vault/HibernateQueryCriteriaParser.kt index 91d53eb51f..c26c414019 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/HibernateQueryCriteriaParser.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/HibernateQueryCriteriaParser.kt @@ -761,8 +761,14 @@ class HibernateQueryCriteriaParser(val contractStateType: Class) .values.map { participant -> (participant as LiteralExpression<*>).literal } log.warn("Adding new participants: $participants to existing participants: $existingParticipants") - commonPredicates.replace(predicateID, criteriaBuilder.and( - getPersistentPartyRoot().get("x500Name").`in`(existingParticipants + participants))) + commonPredicates.replace( + predicateID, + checkIfListIsEmpty( + args = existingParticipants + participants, + criteriaBuilder = criteriaBuilder, + predicate = criteriaBuilder.and(getPersistentPartyRoot().get("x500Name").`in`(existingParticipants + participants)) + ) + ) } else { // Get the persistent party entity. @@ -791,12 +797,18 @@ class HibernateQueryCriteriaParser(val contractStateType: Class("stateRef"), - subRoot.get("compositeKey").get("stateRef"))), - criteriaBuilder.not(subRoot.get("x500Name").`in`(exactParticipants))) - val subQueryNotExistsPredicate = criteriaBuilder.and(criteriaBuilder.not(criteriaBuilder.exists(subQueryNotExists))) - constraintPredicates.add(subQueryNotExistsPredicate) + + //if the list of exact participants is empty, we return nothing with 1=0 + if (exactParticipants.isEmpty()) { + constraintPredicates.add(criteriaBuilder.and(criteriaBuilder.equal(criteriaBuilder.literal(1), 0))) + } else { + subQueryNotExists.where(criteriaBuilder.and( + criteriaBuilder.equal(vaultStates.get("stateRef"), + subRoot.get("compositeKey").get("stateRef"))), + criteriaBuilder.not(subRoot.get("x500Name").`in`(exactParticipants))) + val subQueryNotExistsPredicate = criteriaBuilder.and(criteriaBuilder.not(criteriaBuilder.exists(subQueryNotExists))) + constraintPredicates.add(subQueryNotExistsPredicate) + } // join with transactions for each matching participant (only required where more than one) if (exactParticipants.size > 1) 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 407b09be53..2a5f12e994 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 @@ -249,6 +249,27 @@ abstract class VaultQueryTestsBase : VaultQueryParties { } } + @Test(timeout=300_000) + fun `returns zero states when exact participants list is empty`() { + database.transaction { + identitySvc.verifyAndRegisterIdentity(BIG_CORP_IDENTITY) + vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP)) + vaultFiller.fillWithDummyState(participants = listOf(MEGA_CORP, BIG_CORP)) + + val criteria = VaultQueryCriteria(exactParticipants = emptyList()) + val results = vaultService.queryBy(criteria) + assertThat(results.states).hasSize(0) + + val criteriaWithOneExactParticipant = VaultQueryCriteria(exactParticipants = listOf(MEGA_CORP)) + val resultsWithOneExactParticipant = vaultService.queryBy(criteriaWithOneExactParticipant) + assertThat(resultsWithOneExactParticipant.states).hasSize(1) + + val criteriaWithMoreExactParticipants = VaultQueryCriteria(exactParticipants = listOf(MEGA_CORP, BIG_CORP)) + val resultsWithMoreExactParticipants = vaultService.queryBy(criteriaWithMoreExactParticipants) + assertThat(resultsWithMoreExactParticipants.states).hasSize(1) + } + } + @Test(timeout=300_000) fun `unconsumed base contract states for two participants`() { database.transaction {