mirror of
https://github.com/corda/corda.git
synced 2025-06-01 23:20:54 +00:00
CORDA-1497 replace missing validation (#4349)
This commit is contained in:
parent
9232b3637b
commit
c2986ca31d
@ -53,7 +53,7 @@ data class EnumTransforms(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun validate(constants: Map<String, Int>): EnumTransforms {
|
private fun validate(constants: Map<String, Int>): EnumTransforms {
|
||||||
validateNoCycles()
|
validateNoCycles(constants)
|
||||||
|
|
||||||
// For any name in the enum's constants, get all its previous names
|
// For any name in the enum's constants, get all its previous names
|
||||||
fun renameChain(newName: String): Sequence<String> = generateSequence(newName) { renames[it] }
|
fun renameChain(newName: String): Sequence<String> = generateSequence(newName) { renames[it] }
|
||||||
@ -85,12 +85,16 @@ data class EnumTransforms(
|
|||||||
*
|
*
|
||||||
* By detecting each condition, and updating the chains accordingly, we can perform cycle-detection in O(n) time.
|
* By detecting each condition, and updating the chains accordingly, we can perform cycle-detection in O(n) time.
|
||||||
*/
|
*/
|
||||||
private fun validateNoCycles() {
|
private fun validateNoCycles(constants: Map<String, Int>) {
|
||||||
// We keep track of chains in both directions
|
// We keep track of chains in both directions
|
||||||
val chainStartsToEnds = mutableMapOf<String, String>()
|
val chainStartsToEnds = mutableMapOf<String, String>()
|
||||||
val chainEndsToStarts = mutableMapOf<String, String>()
|
val chainEndsToStarts = mutableMapOf<String, String>()
|
||||||
|
|
||||||
for ((from, to) in renames) {
|
for ((to, from) in renames) {
|
||||||
|
if (from in constants) {
|
||||||
|
throw InvalidEnumTransformsException("Rename from $from to $to would rename existing constant in $constants.keys")
|
||||||
|
}
|
||||||
|
|
||||||
// If there is an existing chain, starting at the "to" node of this edge, then there is a chain from this edge's
|
// If there is an existing chain, starting at the "to" node of this edge, then there is a chain from this edge's
|
||||||
// "from" to that chain's end.
|
// "from" to that chain's end.
|
||||||
val newEnd = chainStartsToEnds[to] ?: to
|
val newEnd = chainStartsToEnds[to] ?: to
|
||||||
@ -105,13 +109,17 @@ data class EnumTransforms(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Either update, or create, the chains in both directions.
|
// Either update, or create, the chains in both directions.
|
||||||
chainStartsToEnds[from] = newEnd
|
|
||||||
chainEndsToStarts[to] = newStart
|
|
||||||
|
|
||||||
// If we have joined two previously unconnected chains, update their starts and ends accordingly.
|
|
||||||
chainStartsToEnds[newStart] = newEnd
|
chainStartsToEnds[newStart] = newEnd
|
||||||
chainEndsToStarts[newEnd] = newStart
|
chainEndsToStarts[newEnd] = newStart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure that every rename chain ends with a known constant.
|
||||||
|
for ((chainStart, chainEnd) in chainStartsToEnds) {
|
||||||
|
if (chainEnd !in constants) {
|
||||||
|
throw InvalidEnumTransformsException(
|
||||||
|
"Rename chain from $chainStart to $chainEnd does not end with a known constant in ${constants.keys}")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,6 +51,36 @@ class EnumTransformationTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CordaSerializationTransformRenames(
|
||||||
|
CordaSerializationTransformRename(from = "P", to = "Q"),
|
||||||
|
CordaSerializationTransformRename(from = "Q", to = "R")
|
||||||
|
)
|
||||||
|
enum class DanglingRenames { A, B, C }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun renameCycleDoesNotTerminateInConstant() {
|
||||||
|
assertFailsWith<InvalidEnumTransformsException> {
|
||||||
|
EnumTransforms.build(
|
||||||
|
TransformsAnnotationProcessor.getTransformsSchema(DanglingRenames::class.java),
|
||||||
|
DanglingRenames::class.java.constants)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@CordaSerializationTransformRenames(
|
||||||
|
CordaSerializationTransformRename(from = "P", to = "Q"),
|
||||||
|
CordaSerializationTransformRename(from = "Q", to = "R")
|
||||||
|
)
|
||||||
|
enum class RenamesExisting { Q, R, S }
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun renamesRenameExistingConstant() {
|
||||||
|
assertFailsWith<InvalidEnumTransformsException> {
|
||||||
|
EnumTransforms.build(
|
||||||
|
TransformsAnnotationProcessor.getTransformsSchema(RenamesExisting::class.java),
|
||||||
|
RenamesExisting::class.java.constants)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val Class<*>.constants: Map<String, Int> get() =
|
private val Class<*>.constants: Map<String, Int> get() =
|
||||||
enumConstants.asSequence().mapIndexed { index, constant -> constant.toString() to index }.toMap()
|
enumConstants.asSequence().mapIndexed { index, constant -> constant.toString() to index }.toMap()
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user