mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Universal: completed Cap unit test, full life cycle
This commit is contained in:
parent
2299b3beae
commit
c328655f68
@ -115,12 +115,16 @@ class UniversalContract : Contract {
|
||||
val nextStart = schedule.first()
|
||||
// todo: look into schedule for final dates
|
||||
|
||||
// todo: we may have to save original start date in order to roll out correctly
|
||||
val newRollOut = RollOut(nextStart, end, rollOut.frequency, rollOut.template)
|
||||
|
||||
val arr = replaceStartEnd(rollOut.template, start.toInstant(), nextStart.toInstant())
|
||||
|
||||
return replaceNext(arr, newRollOut )
|
||||
if (nextStart < end) {
|
||||
// todo: we may have to save original start date in order to roll out correctly
|
||||
val newRollOut = RollOut(nextStart, end, rollOut.frequency, rollOut.template)
|
||||
return replaceNext(arr, newRollOut )
|
||||
}
|
||||
else {
|
||||
return removeNext(arr)
|
||||
}
|
||||
}
|
||||
|
||||
fun<T> replaceStartEnd(p: Perceivable<T>, start: Instant, end: Instant) : Perceivable<T> =
|
||||
@ -156,6 +160,21 @@ class UniversalContract : Contract {
|
||||
else -> throw NotImplementedError("replaceNext " + arrangement.javaClass.name)
|
||||
}
|
||||
|
||||
fun removeNext(arrangement: Arrangement) : Arrangement =
|
||||
when (arrangement) {
|
||||
is Actions -> Actions(arrangement.actions.map { Action(it.name, it.condition, it.actors, removeNext(it.arrangement)) }.toSet())
|
||||
is And -> {
|
||||
val a = arrangement.arrangements.map { removeNext(it) }.filter { it != zero }
|
||||
if (a.count() > 1)
|
||||
And(a.toSet())
|
||||
else
|
||||
a.single()
|
||||
}
|
||||
is Transfer -> arrangement
|
||||
is Zero -> arrangement
|
||||
is Continuation -> zero
|
||||
else -> throw NotImplementedError("replaceNext " + arrangement.javaClass.name)
|
||||
}
|
||||
|
||||
override fun verify(tx: TransactionForContract) {
|
||||
|
||||
|
@ -23,8 +23,8 @@ class Cap {
|
||||
|
||||
val tradeDate: LocalDate = LocalDate.of(2016, 9, 1)
|
||||
|
||||
val contract = arrange {
|
||||
rollOut("2016-09-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
||||
val contractInitial = arrange {
|
||||
rollOut("2016-09-01".ld, "2017-09-01".ld, Frequency.SemiAnnual) {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
@ -43,14 +43,14 @@ class Cap {
|
||||
}
|
||||
}
|
||||
|
||||
val contractFixed = arrange {
|
||||
val contractAfterFixingFirst = arrange {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime() {
|
||||
val floating1 = interest(notional, "act/365", 1.0.bd, "2016-09-01", "2016-12-01")
|
||||
val fixed1 = interest(notional, "act/365", 0.5.bd, "2016-09-01", "2016-12-01")
|
||||
val floating1 = interest(notional, "act/365", 1.0.bd, "2016-09-01", "2017-03-01")
|
||||
val fixed1 = interest(notional, "act/365", 0.5.bd, "2016-09-01", "2017-03-01")
|
||||
highStreetBank.gives(acmeCorp, floating1 - fixed1, currency)
|
||||
rollOut("2016-12-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
||||
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.SemiAnnual) {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
@ -71,56 +71,7 @@ class Cap {
|
||||
}
|
||||
acmeCorp.may {
|
||||
"skip".anytime {
|
||||
rollOut("2016-12-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
|
||||
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
|
||||
highStreetBank.gives(acmeCorp, floating - fixed, currency)
|
||||
next()
|
||||
}
|
||||
}
|
||||
acmeCorp.may {
|
||||
"skip".anytime {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val contractFixed2 = arrange {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime() {
|
||||
val floating1 = interest(notional, "act/365", 1.0.bd, "2016-12-01", "2017-03-01")
|
||||
val fixed1 = interest(notional, "act/365", 0.5.bd, "2016-12-01", "2017-03-01")
|
||||
highStreetBank.gives(acmeCorp, floating1 - fixed1, currency)
|
||||
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
val floating = interest(notional, "act/365", fix("LIBOR", start, Tenor("3M")), start, end)
|
||||
val fixed = interest(notional, "act/365", 0.5.bd, start, end)
|
||||
highStreetBank.gives(acmeCorp, floating - fixed, currency)
|
||||
next()
|
||||
}
|
||||
}
|
||||
acmeCorp.may {
|
||||
"skip".anytime {
|
||||
next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
acmeCorp.may {
|
||||
"skip".anytime {
|
||||
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
||||
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.SemiAnnual) {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
@ -142,8 +93,24 @@ class Cap {
|
||||
}
|
||||
}
|
||||
|
||||
val contractAfterExecute = arrange {
|
||||
rollOut("2016-12-01".ld, "2017-09-01".ld, Frequency.Quarterly) {
|
||||
val contractAfterFixingFinal = arrange {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime() {
|
||||
val floating1 = interest(notional, "act/365", 1.0.bd, "2017-03-01", "2017-09-01")
|
||||
val fixed1 = interest(notional, "act/365", 0.5.bd, "2017-03-01", "2017-09-01")
|
||||
highStreetBank.gives(acmeCorp, floating1 - fixed1, currency)
|
||||
}
|
||||
}
|
||||
acmeCorp.may {
|
||||
"skip".anytime {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val contractAfterExecutionFirst = arrange {
|
||||
rollOut("2017-03-01".ld, "2017-09-01".ld, Frequency.SemiAnnual) {
|
||||
actions {
|
||||
(acmeCorp or highStreetBank).may {
|
||||
"exercise".anytime {
|
||||
@ -163,19 +130,21 @@ class Cap {
|
||||
}
|
||||
|
||||
val paymentFirst = arrange { highStreetBank.gives(acmeCorp, 250.K, EUR) }
|
||||
val paymentFinal = arrange { highStreetBank.gives(acmeCorp, 250.K, EUR) }
|
||||
|
||||
|
||||
val stateStart = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contract)
|
||||
val stateInitial = UniversalContract.State(listOf(DUMMY_NOTARY.owningKey), contractInitial)
|
||||
|
||||
val stateFixed = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractFixed)
|
||||
val stateAfterFixingFirst = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractAfterFixingFirst)
|
||||
|
||||
val stateAfterExecute = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractAfterExecute)
|
||||
val stateAfterExecutionFirst = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractAfterExecutionFirst)
|
||||
val statePaymentFirst = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), paymentFirst)
|
||||
|
||||
val stateFixed2 = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractFixed2)
|
||||
val stateAfterFixingFinal = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), contractAfterFixingFinal)
|
||||
val statePaymentFinal = UniversalContract.State( listOf(DUMMY_NOTARY.owningKey), paymentFinal)
|
||||
|
||||
val contractLimitedCap = arrange {
|
||||
rollOut("2016-04-01".ld, "2017-04-01".ld, Frequency.Quarterly, object {
|
||||
rollOut("2016-04-01".ld, "2017-04-01".ld, Frequency.SemiAnnual, object {
|
||||
val limit = variable(150.K)
|
||||
}) {
|
||||
actions {
|
||||
@ -200,7 +169,7 @@ class Cap {
|
||||
@Test
|
||||
fun issue() {
|
||||
transaction {
|
||||
output { stateStart }
|
||||
output { stateInitial }
|
||||
timestamp(TEST_TX_TIME_1)
|
||||
|
||||
this `fails with` "transaction has a single command"
|
||||
@ -219,8 +188,8 @@ class Cap {
|
||||
@Test
|
||||
fun `first fixing`() {
|
||||
transaction {
|
||||
input { stateStart }
|
||||
output { stateFixed }
|
||||
input { stateInitial }
|
||||
output { stateAfterFixingFirst }
|
||||
timestamp(TEST_TX_TIME_1)
|
||||
|
||||
tweak {
|
||||
@ -264,8 +233,8 @@ class Cap {
|
||||
@Test
|
||||
fun `first execute`() {
|
||||
transaction {
|
||||
input { stateFixed }
|
||||
output { stateAfterExecute }
|
||||
input { stateAfterFixingFirst }
|
||||
output { stateAfterExecutionFirst }
|
||||
output { statePaymentFirst }
|
||||
|
||||
timestamp(TEST_TX_TIME_1)
|
||||
@ -281,11 +250,30 @@ class Cap {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `final execute`() {
|
||||
transaction {
|
||||
input { stateAfterFixingFinal }
|
||||
output { statePaymentFinal }
|
||||
|
||||
timestamp(TEST_TX_TIME_1)
|
||||
|
||||
tweak {
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Action("some undefined name") }
|
||||
this `fails with` "action must be defined"
|
||||
}
|
||||
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Action("exercise") }
|
||||
|
||||
this.verifies()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `second fixing`() {
|
||||
transaction {
|
||||
input { stateAfterExecute }
|
||||
output { stateFixed2 }
|
||||
input { stateAfterExecutionFirst }
|
||||
output { stateAfterFixingFinal }
|
||||
timestamp(TEST_TX_TIME_1)
|
||||
|
||||
tweak {
|
||||
@ -295,32 +283,32 @@ class Cap {
|
||||
|
||||
tweak {
|
||||
// wrong source
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", BusinessCalendar.parseDateFromString("2016-12-01"), Tenor("3M")), 1.0.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBORx", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.0.bd))) }
|
||||
|
||||
this `fails with` "relevant fixing must be included"
|
||||
}
|
||||
|
||||
tweak {
|
||||
// wrong date
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2016-12-01").plusYears(1), Tenor("3M")), 1.0.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01").plusYears(1), Tenor("3M")), 1.0.bd))) }
|
||||
|
||||
this `fails with` "relevant fixing must be included"
|
||||
}
|
||||
|
||||
tweak {
|
||||
// wrong tenor
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2016-12-01"), Tenor("9M")), 1.0.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("9M")), 1.0.bd))) }
|
||||
|
||||
this `fails with` "relevant fixing must be included"
|
||||
}
|
||||
|
||||
tweak {
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2016-12-01"), Tenor("3M")), 1.5.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.5.bd))) }
|
||||
|
||||
this `fails with` "output state does not reflect fix command"
|
||||
}
|
||||
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2016-12-01"), Tenor("3M")), 1.0.bd))) }
|
||||
command(highStreetBank.owningKey) { UniversalContract.Commands.Fix(listOf(com.r3corda.core.contracts.Fix(FixOf("LIBOR", BusinessCalendar.parseDateFromString("2017-03-01"), Tenor("3M")), 1.0.bd))) }
|
||||
|
||||
this.verifies()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user