Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test suite minimization #98

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class RunnerCmdConfig(args: Array<String>) : AbstractCmdConfig("kex-runner", arg
}")
mode.isRequired = false
options += mode

options
})

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.vorpal.research.kex.jacoco.minimization

import java.nio.file.Path

interface TestReduction

private class Test(
val reqs: List<Int>
) {
var power: Int = reqs.size
}

private class Requirement {
private val satisfyTests: MutableList<Path> =mutableListOf<Path>()
private var visited = false

fun addTest(testName: Path) {
satisfyTests.add(testName)
}

fun visit(tests: MutableMap<Path, Test>) {
if (visited) return
satisfyTests.forEach{ tests[it]!!.power-- }
visited = true
}
}

class GreedyTestReductionImpl (
testCoverage: TestwiseCoverageInfo
) :TestReduction{
private var tests: MutableMap<Path, Test> = mutableMapOf()
private var requirements: MutableMap<Int, Requirement> = mutableMapOf()

init {
testCoverage.req.forEach{ requirements[it] = Requirement() }
for (test in testCoverage.tests) {
tests[test.testName] = Test(test.satisfize)
for (requirement in test.satisfize)
requirements[requirement]!!.addTest(test.testName)
}
}

fun minimized(): List<Path> {
val requestSet = mutableSetOf<Int>()
for (test in tests) {
test.value.reqs.forEach { requestSet.add(it) }
}

var satisfiedReq = 0
val importantTests = emptyList<Path>().toMutableList()
while (satisfiedReq < requestSet.size) {
var maxTest: Path? = null
tests.forEach { if (it.value.power > (tests[maxTest]?.power ?: -1)) maxTest = it.key }
if ((tests[maxTest]?.power ?: 0) == 0) break

satisfiedReq += tests[maxTest]!!.power
tests[maxTest]!!.reqs.forEach { requirements[it]!!.visit(tests) }
importantTests.add(importantTests.size, maxTest!!)
}

val allTests = tests.keys.toList()
return allTests.subtract(importantTests.toSet()).toList()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.vorpal.research.kex.jacoco.minimization

import org.vorpal.research.kex.launcher.AnalysisLevel
import org.vorpal.research.kfg.ClassManager
import org.vorpal.research.kfg.container.Container
import java.nio.file.Path

class TestCoverageInfo(
val testName: Path,
val satisfize: List<Int>
) {
}

class TestwiseCoverageInfo(
val req: List<Int>,
val tests: List<TestCoverageInfo>
)

class Minimizer(
private val jar: List<Container>,
val cm: ClassManager,
private val analysisLevel: AnalysisLevel
) {
fun execute(report: Boolean = false, mode: String = "symbolic") {
val testWiseCoverage = TestwiseCoverage(jar)
val testCoverage = testWiseCoverage.execute(analysisLevel)
val excessTests = GreedyTestReductionImpl(testCoverage).minimized()

for (classPath in excessTests) {
val classFile = classPath.toFile()
if (classFile.exists()) {
classFile.delete()
} else {
org.vorpal.research.kthelper.logging.log.error("nonexistent class in Minimizer: $classFile")
}
}

if (report) { testWiseCoverage.reportCoverage(cm, analysisLevel, mode) }
}
}
Loading
Loading