Universal: completed Cap unit test, full life cycle

This commit is contained in:
sofusmortensen 2016-09-19 00:06:42 +02:00
parent 2299b3beae
commit c328655f68
2 changed files with 86 additions and 79 deletions

View File

@ -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) {

View File

@ -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()
}