|
| 1 | +package org.usvm.checkers |
| 2 | + |
| 3 | +import org.jacodb.ets.model.EtsScene |
| 4 | +import org.jacodb.ets.utils.loadEtsFileAutoConvert |
| 5 | +import org.usvm.PathSelectionStrategy |
| 6 | +import org.usvm.UMachineOptions |
| 7 | +import org.usvm.api.targets.ReachabilityObserver |
| 8 | +import org.usvm.api.targets.TsReachabilityTarget |
| 9 | +import org.usvm.machine.TsMachine |
| 10 | +import org.usvm.machine.TsOptions |
| 11 | +import org.usvm.util.getResourcePath |
| 12 | +import kotlin.test.Test |
| 13 | +import kotlin.time.Duration.Companion.seconds |
| 14 | + |
| 15 | +class ReachabilityChecker { |
| 16 | + val scene = run { |
| 17 | + val name = "ReachabilityChecker.ts" |
| 18 | + val path = getResourcePath("/checkers/$name") |
| 19 | + val file = loadEtsFileAutoConvert(path) |
| 20 | + EtsScene(listOf(file)) |
| 21 | + } |
| 22 | + val options = UMachineOptions( |
| 23 | + stopOnTargetsReached = true, |
| 24 | + pathSelectionStrategies = listOf(PathSelectionStrategy.TARGETED), |
| 25 | + timeout = 15000000.seconds |
| 26 | + ) |
| 27 | + val tsOptions = TsOptions() |
| 28 | + |
| 29 | + @Test |
| 30 | + fun runReachabilityCheck() { |
| 31 | + val machine = TsMachine(scene, options, tsOptions, machineObserver = ReachabilityObserver()) |
| 32 | + val method = scene.projectClasses |
| 33 | + .flatMap { it.methods } |
| 34 | + .single { it.name == "simpleFunction" } |
| 35 | + |
| 36 | + val initialPoint = method.cfg.stmts.first { "if (" in it.toString() } |
| 37 | + val initialTarget = TsReachabilityTarget.InitialPoint(initialPoint) |
| 38 | + |
| 39 | + val intermediatePoint = method.cfg.stmts.filter { "if (" in it.toString() }[1] |
| 40 | + val intermediateTarget = TsReachabilityTarget.IntermediatePoint(intermediatePoint).also { |
| 41 | + initialTarget.addChild((it)) |
| 42 | + } |
| 43 | + val finalPoint = method.cfg.stmts.first { "return" in it.toString() } |
| 44 | + TsReachabilityTarget.FinalPoint(finalPoint).also { |
| 45 | + intermediateTarget.addChild(it) |
| 46 | + } |
| 47 | + |
| 48 | + val results = machine.analyze(listOf(method), listOf(initialTarget)) |
| 49 | + require(results.size == 1) { "Expected exactly one result, but got ${results.size}" } |
| 50 | + } |
| 51 | + |
| 52 | + @Test |
| 53 | + fun runReachabilityCheckForFirstInstruction() { |
| 54 | + val machine = TsMachine(scene, options, tsOptions, machineObserver = ReachabilityObserver()) |
| 55 | + val method = scene.projectClasses |
| 56 | + .flatMap { it.methods } |
| 57 | + .single { it.name == "simpleFunction" } |
| 58 | + |
| 59 | + val initialPoint = method.cfg.stmts.first() |
| 60 | + val initialTarget = TsReachabilityTarget.InitialPoint(initialPoint) |
| 61 | + |
| 62 | + val results = machine.analyze(listOf(method), listOf(initialTarget)) |
| 63 | + require(results.isEmpty()) { "Expected no analysis results, but got ${results.size}" } |
| 64 | + require(initialTarget.isRemoved) { "Expected initial target to be removed, but it was not" } |
| 65 | + } |
| 66 | +} |
0 commit comments