mps-coderules/reactor/Test/test/TestStoreAwareJournal.kt

241 lines
7.2 KiB
Kotlin

import jetbrains.mps.logic.reactor.core.*
import jetbrains.mps.logic.reactor.core.internal.*
import org.junit.Test
import org.junit.Assert.*
/*
* Copyright 2014-2019 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class TestStoreAwareJournal {
private class JournalDispatcherHelper(
dispatcher: Dispatcher,
val hist: MatchJournal = MatchJournal.forTest()
) {
val initialJournalSize = hist.view().chunks.size
var d: Dispatcher.DispatchingFront = dispatcher.front()
fun logExpand(occ: Occurrence) {
hist.logActivation(occ)
d = d.expand(occ)
}
fun logExpand(id: String, vararg args: Any) =
logExpand(justifiedOccurrence(id, hist, * args))
fun logFirstMatch() = hist.logMatch(d.matches().first())
// log and expand occurrence while tracking its justifications
fun logExpandJustified(id: String, vararg args: Any) =
logExpand(principalOccurrence(id, hist, * args))
}
@Test
fun testJustificationTracking() {
with(programWithRules(
rule("rule2",
headKept(
pconstraint("foo")
),
body(
pconstraint("bar")
)),
rule("rule3",
headKept(
pconstraint("foo")
),
body(
pconstraint("qux")
)),
rule("rule4",
headReplaced(
pconstraint("bar"),
pconstraint("qux")
),
body()
)))
{
with(JournalDispatcherHelper(Dispatcher(RuleIndex(rules)))) {
hist.justifications() shouldBe Justifications.of(0) // initial chunk
logExpand(principalOccurrenceInit("foo"))
val fooMatches = d.matches()
fooMatches.count() shouldBe 2
// log first 'foo' match
hist.logMatch(fooMatches.first())
hist.justifications() shouldBe Justifications.of(0,1)
logExpandJustified("bar")
d.matches().count() shouldBe 0
// log second 'foo' match
hist.logMatch(fooMatches.elementAt(1))
hist.justifications() shouldBe Justifications.of(0,2)
logExpandJustified("qux")
d.matches().count() shouldBe 1
logFirstMatch()
hist.justifications() shouldBe Justifications.of(0,1,2,3)
}
}
}
@Test
fun testFullReset() {
with(programWithRules(
rule("rule1",
headKept(
constraint("foo")
),
body(
pconstraint("bar")
)),
rule("rule2",
headReplaced(
pconstraint("bar"),
constraint("foo")
),
body(
pconstraint("qux")
))
))
{
with(JournalDispatcherHelper(Dispatcher(RuleIndex(rules)))) {
with(hist) {
view().chunks.size shouldBe initialJournalSize // only initial chunk
storeView().allOccurrences().count() shouldBe 0
}
val initialPos = hist.currentPos()
// execute program
logExpand("foo")
logFirstMatch()
logExpandJustified("bar")
logFirstMatch()
logExpandJustified("qux")
with(hist) {
view().chunks.size shouldBe 5 + initialJournalSize
storeView().allOccurrences().count() shouldBe 1 // only "qux"
// reset to the very beginning
reset(initialPos)
currentPos().chunk shouldBeSame initialPos.chunk
view().chunks.size shouldBe initialJournalSize
storeView().allOccurrences().count() shouldBe 0
}
}
}
}
@Test
fun testPushExecReset() {
with(programWithRules(
rule("rule2",
headKept(
pconstraint("foo")
),
body(
constraint("bar"),
constraint("bazz"),
pconstraint("qux")
)),
rule("rule3",
headReplaced(
constraint("bar"),
constraint("bazz")
),
body(
constraint("bazz")
)),
rule("rule4",
headKept(
pconstraint("qux"),
pconstraint("foo")
),
body(
pconstraint("last")
))
))
{
with(JournalDispatcherHelper(Dispatcher(RuleIndex(rules)))) {
logExpand(principalOccurrenceInit("foo"))
// rule2
logFirstMatch()
logExpand("bar")
logExpand("bazz")
// use this production later, but create it now to get relevant justs
val quxOcc = principalOccurrence("qux", hist)
val curChunk = hist.currentPos().chunk
// rule3
logFirstMatch()
logExpand("bazz")
// matched on rule with heads without justifications, should remain in the same chunk
// NB! the above no longer holds as the "principal" stuff has been phased out
// hist.currentPos().chunk shouldBeSame curChunk
// last production from rule2
logExpand(quxOcc)
// rule4
hist.view().chunks.size shouldBe 7 + initialJournalSize
logFirstMatch()
// match on the principal constraint must add the chunk
hist.view().chunks.size shouldBe 8 + initialJournalSize
val oldState = hist.view()
val oldStore = hist.storeView().allOccurrences()
val savedPos = hist.currentPos()
logExpandJustified("last")
hist.view().chunks.size shouldBe 9 + initialJournalSize
assertNotEquals(oldStore, hist.storeView().allOccurrences())
hist.reset(savedPos)
hist.view().chunks.size shouldBe oldState.chunks.size
hist.view().chunks shouldBe oldState.chunks
hist.storeView().allOccurrences() shouldBe oldStore
hist.currentPos() shouldBe savedPos
}
}
}
}