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.
This commit is contained in:
szymonsztuka 2018-11-21 18:36:30 +00:00 committed by GitHub
parent 489e719b54
commit 014f71d36a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 9 deletions

View File

@ -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<PublicKey>, jarManifestAttributes: Map<String,String>){
attachment((services.cordappProvider as MockCordappProvider).addMockCordapp(contractClassName, services.attachments as MockAttachmentStorage, attachmentId, signers, jarManifestAttributes))
}
}
data class TestLedgerDSLInterpreter private constructor(

View File

@ -97,6 +97,15 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup {
* @param attachmentId The attachment
*/
fun _attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List<PublicKey>)
/**
* 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<PublicKey>, jarManifestAttributes: Map<String,String>)
}
/**
@ -203,7 +212,7 @@ class TransactionDSL<out T : TransactionDSLInterpreter>(interpreter: T, private
*/
fun attachment(contractClassName: ContractClassName) = _attachment(contractClassName)
fun attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List<PublicKey>) = _attachment(contractClassName, attachmentId, signers)
fun attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List<PublicKey>, jarManifestAttributes: Map<String,String> = 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) }

View File

@ -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 <reified T : Any> 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<String,String> = 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()

View File

@ -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<Pair<Cordapp, AttachmentId>>()
fun addMockCordapp(contractClassName: ContractClassName, attachments: MockAttachmentStorage, contractHash: AttachmentId? = null, signers: List<PublicKey> = emptyList()): AttachmentId {
fun addMockCordapp(contractClassName: ContractClassName, attachments: MockAttachmentStorage, contractHash: AttachmentId? = null, signers: List<PublicKey> = emptyList(), jarManifestAttributes: Map<String,String> = 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<String, ByteArray>()
private fun fakeAttachmentCached(contractClass: String): ByteArray = attachmentsCache.computeIfAbsent(contractClass) {
fakeAttachment(contractClass, contractClass)
private fun fakeAttachmentCached(contractClass: String, manifestAttributes: Map<String,String> = emptyMap()): ByteArray = attachmentsCache.computeIfAbsent(contractClass + manifestAttributes.toSortedMap()) {
fakeAttachment(contractClass, contractClass, manifestAttributes)
}
}