From 014f71d36aaf4f000daa00427f521acf83d8e4e5 Mon Sep 17 00:00:00 2001 From: szymonsztuka Date: Wed, 21 Nov 2018 18:36:30 +0000 Subject: [PATCH] CORDA-2150 testing infrastructure for non downgrade contract version rule - TestDSL creates Jar with manifest file (#4274) This is preliminary addition to test "Implementation-Version" entry from META-INF/MANIFEST.MF in TestDSL.kt. MockCordappProvider was creating JAR without manifest file. Added the manifest file with the obligatory (by JAR spec) attribute "Manifest-Version", other attributes can be added. --- .../main/kotlin/net/corda/testing/dsl/TestDSL.kt | 4 ++++ .../corda/testing/dsl/TransactionDSLInterpreter.kt | 11 ++++++++++- .../net/corda/testing/internal/InternalTestUtils.kt | 8 ++++++-- .../corda/testing/internal/MockCordappProvider.kt | 13 +++++++------ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TestDSL.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TestDSL.kt index c98a026365..77a243c8dc 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TestDSL.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TestDSL.kt @@ -155,6 +155,10 @@ data class TestTransactionDSLInterpreter private constructor( attachment((services.cordappProvider as MockCordappProvider).addMockCordapp(contractClassName, services.attachments as MockAttachmentStorage, attachmentId, signers)) } + override fun _attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List, jarManifestAttributes: Map){ + attachment((services.cordappProvider as MockCordappProvider).addMockCordapp(contractClassName, services.attachments as MockAttachmentStorage, attachmentId, signers, jarManifestAttributes)) + } + } data class TestLedgerDSLInterpreter private constructor( diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TransactionDSLInterpreter.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TransactionDSLInterpreter.kt index e47a8037e5..e7ccdafb86 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TransactionDSLInterpreter.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/dsl/TransactionDSLInterpreter.kt @@ -97,6 +97,15 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup { * @param attachmentId The attachment */ fun _attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List) + + /** + * Attaches an attachment containing the named contract to the transaction. + * @param contractClassName The contract class to attach. + * @param attachmentId The attachment. + * @param signers The signers. + * @param jarManifestAttributes The JAR manifest file attributes. + */ + fun _attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List, jarManifestAttributes: Map) } /** @@ -203,7 +212,7 @@ class TransactionDSL(interpreter: T, private */ fun attachment(contractClassName: ContractClassName) = _attachment(contractClassName) - fun attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List) = _attachment(contractClassName, attachmentId, signers) + fun attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List, jarManifestAttributes: Map = emptyMap()) = _attachment(contractClassName, attachmentId, signers, jarManifestAttributes) fun attachment(contractClassName: ContractClassName, attachmentId: AttachmentId) = _attachment(contractClassName, attachmentId, emptyList()) fun attachments(vararg contractClassNames: ContractClassName) = contractClassNames.forEach { attachment(it) } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/InternalTestUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/InternalTestUtils.kt index 5f044339b6..5da0c03c48 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/InternalTestUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/InternalTestUtils.kt @@ -14,6 +14,7 @@ import net.corda.core.node.NodeInfo import net.corda.core.schemas.MappedSchema import net.corda.core.transactions.WireTransaction import net.corda.core.utilities.loggerFor +import net.corda.node.internal.cordapp.set import net.corda.node.internal.createCordaPersistence import net.corda.node.internal.security.RPCSecurityManagerImpl import net.corda.node.internal.startHikariPool @@ -41,6 +42,7 @@ import java.util.* import java.util.jar.JarOutputStream import java.util.zip.ZipEntry import javax.security.auth.x500.X500Principal +import java.util.jar.Manifest @Suppress("unused") inline fun T.kryoSpecific(reason: String, function: () -> Unit) = if (!AMQP_ENABLED) { @@ -180,9 +182,11 @@ fun configureDatabase(hikariProperties: Properties, /** * Convenience method for creating a fake attachment containing a file with some content. */ -fun fakeAttachment(filePath: String, content: String): ByteArray { +fun fakeAttachment(filePath: String, content: String, manifestAttributes: Map = emptyMap()): ByteArray { val bs = ByteArrayOutputStream() - JarOutputStream(bs).use { js -> + val manifest = Manifest() + manifestAttributes.forEach{ manifest[it.key] = it.value} //adding manually instead of putAll, as it requires typed keys, not strings + JarOutputStream(bs, manifest).use { js -> js.putNextEntry(ZipEntry(filePath)) js.writer().apply { append(content); flush() } js.closeEntry() diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt index 3b87150155..63af2c3106 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/MockCordappProvider.kt @@ -3,7 +3,6 @@ package net.corda.testing.internal import net.corda.core.contracts.ContractClassName import net.corda.core.cordapp.Cordapp import net.corda.core.crypto.SecureHash -import net.corda.core.identity.Party import net.corda.core.internal.DEPLOYED_CORDAPP_UPLOADER import net.corda.core.internal.cordapp.CordappImpl import net.corda.core.node.services.AttachmentId @@ -13,7 +12,7 @@ import net.corda.node.internal.cordapp.CordappProviderImpl import net.corda.testing.services.MockAttachmentStorage import java.nio.file.Paths import java.security.PublicKey -import java.util.* +import java.util.jar.Attributes class MockCordappProvider( cordappLoader: CordappLoader, @@ -23,7 +22,7 @@ class MockCordappProvider( private val cordappRegistry = mutableListOf>() - fun addMockCordapp(contractClassName: ContractClassName, attachments: MockAttachmentStorage, contractHash: AttachmentId? = null, signers: List = emptyList()): AttachmentId { + fun addMockCordapp(contractClassName: ContractClassName, attachments: MockAttachmentStorage, contractHash: AttachmentId? = null, signers: List = emptyList(), jarManifestAttributes: Map = emptyMap()): AttachmentId { val cordapp = CordappImpl( contractClassNames = listOf(contractClassName), initiatedFlows = emptyList(), @@ -38,8 +37,10 @@ class MockCordappProvider( info = CordappImpl.Info.UNKNOWN, allFlows = emptyList(), jarHash = SecureHash.allOnesHash) + val jarManifestAttributesWithObligatoryElement = jarManifestAttributes.toMutableMap() + jarManifestAttributesWithObligatoryElement.putIfAbsent(Attributes.Name.MANIFEST_VERSION.toString(), "1.0") if (cordappRegistry.none { it.first.contractClassNames.contains(contractClassName) && it.second == contractHash }) { - cordappRegistry.add(Pair(cordapp, findOrImportAttachment(listOf(contractClassName), fakeAttachmentCached(contractClassName), attachments, contractHash, signers))) + cordappRegistry.add(Pair(cordapp, findOrImportAttachment(listOf(contractClassName), fakeAttachmentCached(contractClassName, jarManifestAttributesWithObligatoryElement), attachments, contractHash, signers))) } return cordappRegistry.findLast { contractClassName in it.first.contractClassNames }?.second!! } @@ -59,7 +60,7 @@ class MockCordappProvider( } private val attachmentsCache = mutableMapOf() - private fun fakeAttachmentCached(contractClass: String): ByteArray = attachmentsCache.computeIfAbsent(contractClass) { - fakeAttachment(contractClass, contractClass) + private fun fakeAttachmentCached(contractClass: String, manifestAttributes: Map = emptyMap()): ByteArray = attachmentsCache.computeIfAbsent(contractClass + manifestAttributes.toSortedMap()) { + fakeAttachment(contractClass, contractClass, manifestAttributes) } }