mirror of
https://github.com/corda/corda.git
synced 2025-06-17 14:48:16 +00:00
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:
@ -155,6 +155,10 @@ data class TestTransactionDSLInterpreter private constructor(
|
|||||||
attachment((services.cordappProvider as MockCordappProvider).addMockCordapp(contractClassName, services.attachments as MockAttachmentStorage, attachmentId, signers))
|
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(
|
data class TestLedgerDSLInterpreter private constructor(
|
||||||
|
@ -97,6 +97,15 @@ interface TransactionDSLInterpreter : Verifies, OutputStateLookup {
|
|||||||
* @param attachmentId The attachment
|
* @param attachmentId The attachment
|
||||||
*/
|
*/
|
||||||
fun _attachment(contractClassName: ContractClassName, attachmentId: AttachmentId, signers: List<PublicKey>)
|
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) = _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 attachment(contractClassName: ContractClassName, attachmentId: AttachmentId) = _attachment(contractClassName, attachmentId, emptyList())
|
||||||
|
|
||||||
fun attachments(vararg contractClassNames: ContractClassName) = contractClassNames.forEach { attachment(it) }
|
fun attachments(vararg contractClassNames: ContractClassName) = contractClassNames.forEach { attachment(it) }
|
||||||
|
@ -14,6 +14,7 @@ import net.corda.core.node.NodeInfo
|
|||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
|
import net.corda.node.internal.cordapp.set
|
||||||
import net.corda.node.internal.createCordaPersistence
|
import net.corda.node.internal.createCordaPersistence
|
||||||
import net.corda.node.internal.security.RPCSecurityManagerImpl
|
import net.corda.node.internal.security.RPCSecurityManagerImpl
|
||||||
import net.corda.node.internal.startHikariPool
|
import net.corda.node.internal.startHikariPool
|
||||||
@ -41,6 +42,7 @@ import java.util.*
|
|||||||
import java.util.jar.JarOutputStream
|
import java.util.jar.JarOutputStream
|
||||||
import java.util.zip.ZipEntry
|
import java.util.zip.ZipEntry
|
||||||
import javax.security.auth.x500.X500Principal
|
import javax.security.auth.x500.X500Principal
|
||||||
|
import java.util.jar.Manifest
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
inline fun <reified T : Any> T.kryoSpecific(reason: String, function: () -> Unit) = if (!AMQP_ENABLED) {
|
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.
|
* 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()
|
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.putNextEntry(ZipEntry(filePath))
|
||||||
js.writer().apply { append(content); flush() }
|
js.writer().apply { append(content); flush() }
|
||||||
js.closeEntry()
|
js.closeEntry()
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.testing.internal
|
|||||||
import net.corda.core.contracts.ContractClassName
|
import net.corda.core.contracts.ContractClassName
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
import net.corda.core.crypto.SecureHash
|
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.DEPLOYED_CORDAPP_UPLOADER
|
||||||
import net.corda.core.internal.cordapp.CordappImpl
|
import net.corda.core.internal.cordapp.CordappImpl
|
||||||
import net.corda.core.node.services.AttachmentId
|
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 net.corda.testing.services.MockAttachmentStorage
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.util.*
|
import java.util.jar.Attributes
|
||||||
|
|
||||||
class MockCordappProvider(
|
class MockCordappProvider(
|
||||||
cordappLoader: CordappLoader,
|
cordappLoader: CordappLoader,
|
||||||
@ -23,7 +22,7 @@ class MockCordappProvider(
|
|||||||
|
|
||||||
private val cordappRegistry = mutableListOf<Pair<Cordapp, AttachmentId>>()
|
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(
|
val cordapp = CordappImpl(
|
||||||
contractClassNames = listOf(contractClassName),
|
contractClassNames = listOf(contractClassName),
|
||||||
initiatedFlows = emptyList(),
|
initiatedFlows = emptyList(),
|
||||||
@ -38,8 +37,10 @@ class MockCordappProvider(
|
|||||||
info = CordappImpl.Info.UNKNOWN,
|
info = CordappImpl.Info.UNKNOWN,
|
||||||
allFlows = emptyList(),
|
allFlows = emptyList(),
|
||||||
jarHash = SecureHash.allOnesHash)
|
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 }) {
|
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!!
|
return cordappRegistry.findLast { contractClassName in it.first.contractClassNames }?.second!!
|
||||||
}
|
}
|
||||||
@ -59,7 +60,7 @@ class MockCordappProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val attachmentsCache = mutableMapOf<String, ByteArray>()
|
private val attachmentsCache = mutableMapOf<String, ByteArray>()
|
||||||
private fun fakeAttachmentCached(contractClass: String): ByteArray = attachmentsCache.computeIfAbsent(contractClass) {
|
private fun fakeAttachmentCached(contractClass: String, manifestAttributes: Map<String,String> = emptyMap()): ByteArray = attachmentsCache.computeIfAbsent(contractClass + manifestAttributes.toSortedMap()) {
|
||||||
fakeAttachment(contractClass, contractClass)
|
fakeAttachment(contractClass, contractClass, manifestAttributes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user