ENT-4652: Add unit tests for parsing attachment fix-up rules. (#5859)

This commit is contained in:
Chris Rankin 2020-01-16 17:19:58 +00:00 committed by Rick Parker
parent a7147c1ffd
commit f027fd5c77
2 changed files with 126 additions and 5 deletions

View File

@ -30,6 +30,7 @@ open class CordappProviderImpl(val cordappLoader: CordappLoader,
private val cordappConfigProvider: CordappConfigProvider,
private val attachmentStorage: AttachmentStorage) : SingletonSerializeAsToken(), CordappProviderInternal {
companion object {
const val COMMENT_MARKER = '#'
private val log = contextLogger()
}
@ -123,8 +124,8 @@ open class CordappProviderImpl(val cordappLoader: CordappLoader,
isValidFixup(fixupConnection.jarFile)
}.flatMapTo(ArrayList()) { fixupConnection ->
fixupConnection.inputStream.bufferedReader().useLines { lines ->
lines.filter(String::isNotBlank).map { line ->
val tokens = line.split("=>", limit = 2)
lines.map { it.substringBefore(COMMENT_MARKER) }.map(String::trim).filterNot(String::isEmpty).map { line ->
val tokens = line.split("=>")
require(tokens.size == 2) {
"Invalid fix-up line '$line' in '${fixupConnection.jarFile.name}'"
}
@ -148,9 +149,9 @@ open class CordappProviderImpl(val cordappLoader: CordappLoader,
}
private fun parseIds(ids: String): Set<AttachmentId> {
return ids.split(",").mapTo(LinkedHashSet()) {
AttachmentId.parse(it.trim())
}
return ids.split(",").map(String::trim)
.filterNot(String::isEmpty)
.mapTo(LinkedHashSet(), SecureHash.Companion::parse)
}
/**

View File

@ -2,6 +2,7 @@ package net.corda.node.internal.cordapp
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import net.corda.core.node.services.AttachmentId
import net.corda.core.node.services.AttachmentStorage
import net.corda.node.VersionInfo
import net.corda.testing.common.internal.testNetworkParameters
@ -11,7 +12,15 @@ import org.assertj.core.api.Assertions.assertThat
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import java.io.File
import java.io.FileOutputStream
import java.net.URL
import java.util.jar.JarOutputStream
import java.util.zip.Deflater.NO_COMPRESSION
import java.util.zip.ZipEntry
import java.util.zip.ZipEntry.DEFLATED
import java.util.zip.ZipEntry.STORED
import kotlin.test.assertFailsWith
class CordappProviderImplTests {
private companion object {
@ -21,9 +30,29 @@ class CordappProviderImplTests {
val emptyJAR: URL = this::class.java.getResource("empty.jar")
val validConfig: Config = ConfigFactory.parseString("key=value")
@JvmField
val ID1 = AttachmentId.randomSHA256()
@JvmField
val ID2 = AttachmentId.randomSHA256()
@JvmField
val ID3 = AttachmentId.randomSHA256()
@JvmField
val ID4 = AttachmentId.randomSHA256()
val stubConfigProvider = object : CordappConfigProvider {
override fun getConfigByName(name: String): Config = ConfigFactory.empty()
}
fun directoryEntry(internalName: String) = ZipEntry("$internalName/").apply {
method = STORED
compressedSize = 0
size = 0
crc = 0
}
fun fileEntry(internalName: String) = ZipEntry(internalName).apply {
method = DEFLATED
}
}
private lateinit var attachmentStore: AttachmentStorage
@ -84,6 +113,97 @@ class CordappProviderImplTests {
assertThat(expected.getString("key")).isEqualTo("value")
}
@Test
fun `test fixup rule that adds attachment`() {
val fixupJar = File.createTempFile("fixup", ".jar")
.writeFixupRules("$ID1 => $ID2, $ID3")
val fixedIDs = with(newCordappProvider(fixupJar.toURI().toURL())) {
start()
fixupAttachmentIds(listOf(ID1))
}
assertThat(fixedIDs).containsExactly(ID2, ID3)
}
@Test
fun `test fixup rule that deletes attachment`() {
val fixupJar = File.createTempFile("fixup", ".jar")
.writeFixupRules("$ID1 =>")
val fixedIDs = with(newCordappProvider(fixupJar.toURI().toURL())) {
start()
fixupAttachmentIds(listOf(ID1))
}
assertThat(fixedIDs).isEmpty()
}
@Test
fun `test fixup rule with blank LHS`() {
val fixupJar = File.createTempFile("fixup", ".jar")
.writeFixupRules(" => $ID2")
val ex = assertFailsWith<IllegalArgumentException> {
newCordappProvider(fixupJar.toURI().toURL()).start()
}
assertThat(ex).hasMessageContaining(
"Forbidden empty list of source attachment IDs in '${fixupJar.absolutePath}'"
)
}
@Test
fun `test fixup rule without arrows`() {
val rule = " $ID1 "
val fixupJar = File.createTempFile("fixup", ".jar")
.writeFixupRules(rule)
val ex = assertFailsWith<IllegalArgumentException> {
newCordappProvider(fixupJar.toURI().toURL()).start()
}
assertThat(ex).hasMessageContaining(
"Invalid fix-up line '${rule.trim()}' in '${fixupJar.absolutePath}'"
)
}
@Test
fun `test fixup rule with too many arrows`() {
val rule = " $ID1 => $ID2 => $ID3 "
val fixupJar = File.createTempFile("fixup", ".jar")
.writeFixupRules(rule)
val ex = assertFailsWith<IllegalArgumentException> {
newCordappProvider(fixupJar.toURI().toURL()).start()
}
assertThat(ex).hasMessageContaining(
"Invalid fix-up line '${rule.trim()}' in '${fixupJar.absolutePath}'"
)
}
@Test
fun `test fixup file containing multiple rules and comments`() {
val fixupJar = File.createTempFile("fixup", ".jar").writeFixupRules(
"# Whole line comment",
"\t$ID1,$ID2 => $ID2,, $ID3 # EOl comment",
" # Empty line with comment",
"",
"$ID3 => $ID4"
)
val fixedIDs = with(newCordappProvider(fixupJar.toURI().toURL())) {
start()
fixupAttachmentIds(listOf(ID2, ID1))
}
assertThat(fixedIDs).containsExactlyInAnyOrder(ID2, ID4)
}
private fun File.writeFixupRules(vararg lines: String): File {
JarOutputStream(FileOutputStream(this)).use { jar ->
jar.setMethod(DEFLATED)
jar.setLevel(NO_COMPRESSION)
jar.putNextEntry(directoryEntry("META-INF"))
jar.putNextEntry(fileEntry("META-INF/Corda-Fixups"))
for (line in lines) {
jar.write(line.toByteArray())
jar.write('\r'.toInt())
jar.write('\n'.toInt())
}
}
return this
}
private fun newCordappProvider(vararg urls: URL): CordappProviderImpl {
val loader = JarScanningCordappLoader.fromJarUrls(urls.toList(), VersionInfo.UNKNOWN)
return CordappProviderImpl(loader, stubConfigProvider, attachmentStore).apply { start() }