Skip to content
This repository has been archived by the owner on Jan 5, 2023. It is now read-only.

Commit

Permalink
Promote mutation count, fix mutation shuffling.
Browse files Browse the repository at this point in the history
  • Loading branch information
gchallen committed Sep 30, 2022
1 parent 255d945 commit 3cb46f1
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 24 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}
subprojects {
group = "com.github.cs125-illinois.questioner"
version = "2022.9.10"
version = "2022.9.11"
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
Expand Down
3 changes: 1 addition & 2 deletions lib/src/main/kotlin/Annotations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ annotation class Correct(
val maxTimeout: Int = Question.TestingControl.DEFAULT_MAX_TIMEOUT,
val timeoutMultiplier: Int = Question.TestingControl.DEFAULT_TIMEOUT_MULTIPLIER,
val minMutationCount: Int = Question.TestingControl.DEFAULT_MIN_MUTATION_COUNT,
val maxMutationCount: Int = Question.TestingControl.DEFAULT_MAX_MUTATION_COUNT,
val maxMutationCount: Int = -1,
val outputMultiplier: Int = Question.TestingControl.DEFAULT_OUTPUT_MULTIPLIER,
val maxExtraComplexity: Int = Question.TestingControl.DEFAULT_MAX_EXTRA_COMPLEXITY,
val maxDeadCode: Int = Question.TestingControl.DEFAULT_MAX_DEAD_CODE,
Expand Down Expand Up @@ -78,7 +78,6 @@ annotation class CheckFeatures {
"@$name methods must return List<String>!"
}
(method.genericReturnType as ParameterizedType).also { collectionType ->
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
check(collectionType.rawType == java.util.List::class.java) {
"@$name methods must return List<String>"
}
Expand Down
3 changes: 1 addition & 2 deletions lib/src/main/kotlin/Question.kt
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,6 @@ data class Question(
const val DEFAULT_MAX_TIMEOUT = 2048
const val DEFAULT_TIMEOUT_MULTIPLIER = 32
const val DEFAULT_MIN_MUTATION_COUNT = 0
const val DEFAULT_MAX_MUTATION_COUNT = 32
const val DEFAULT_OUTPUT_MULTIPLIER = 8
const val DEFAULT_MAX_EXTRA_COMPLEXITY = 2
const val DEFAULT_MAX_DEAD_CODE = 0
Expand All @@ -212,7 +211,7 @@ data class Question(
DEFAULT_MAX_TIMEOUT,
DEFAULT_TIMEOUT_MULTIPLIER,
DEFAULT_MIN_MUTATION_COUNT,
DEFAULT_MAX_MUTATION_COUNT,
null,
DEFAULT_OUTPUT_MULTIPLIER,
DEFAULT_MAX_EXTRA_COMPLEXITY,
DEFAULT_MAX_DEAD_CODE,
Expand Down
5 changes: 5 additions & 0 deletions lib/src/main/kotlin/QuestionHelpers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import edu.illinois.cs.cs125.jeed.core.fromTemplates
import edu.illinois.cs.cs125.jeed.core.kompile
import edu.illinois.cs.cs125.jeed.core.ktLint
import edu.illinois.cs.cs125.jeed.core.moshi.CompiledSourceResult
import edu.illinois.cs.cs125.jeed.core.stripComments
import edu.illinois.cs.cs125.jenisol.core.CaptureOutputControlInput
import edu.illinois.cs.cs125.jenisol.core.CapturedResult
import edu.illinois.cs.cs125.jenisol.core.unwrap
Expand Down Expand Up @@ -238,6 +239,10 @@ fun Question.mutations(seed: Int, count: Int) = templateSubmission(
}
// Templated questions sometimes will mutate the template
.filter { (contents, _) -> contents != correct.contents }
.distinctBy { (contents, _) ->
contents.stripComments(Source.FileType.JAVA).hashCode()
}
.shuffled(random = Random(seed))
.take(count)
.map { (contents, source) ->
Question.IncorrectFile(
Expand Down
4 changes: 2 additions & 2 deletions lib/src/main/kotlin/Validation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ data class CorrectResults(val incorrect: Question.FlatFile, val results: TestRes
data class IncorrectResults(val incorrect: Question.IncorrectFile, val results: TestResults)

@Suppress("LongMethod", "ComplexMethod")
suspend fun Question.validate(defaultSeed: Int): ValidationReport {
suspend fun Question.validate(defaultSeed: Int, maxMutationCount: Int): ValidationReport {

val seed = if (control.seed!! != -1) {
control.seed!!
Expand Down Expand Up @@ -267,7 +267,7 @@ suspend fun Question.validate(defaultSeed: Int): ValidationReport {
val bootstrapLength = Instant.now().toEpochMilli() - bootStrapStart.toEpochMilli()

val mutationStart = Instant.now()
val mutations = mutations(seed, control.maxMutationCount!!).also {
val mutations = mutations(seed, control.maxMutationCount ?: maxMutationCount).also {
if (it.size < control.minMutationCount!!) {
throw TooFewMutations(correct, it.size, control.minMutationCount!!)
}
Expand Down
17 changes: 14 additions & 3 deletions lib/src/main/kotlin/Validator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,25 @@ package edu.illinois.cs.cs125.questioner.lib
import java.io.File

@Suppress("unused")
class Validator(questionsFile: File, private val sourceDir: String, private val seed: Int) {
class Validator(
questionsFile: File,
private val sourceDir: String,
private val seed: Int,
private val maxMutationCount: Int
) {
private val unvalidatedQuestions = loadFromPath(questionsFile, sourceDir).also {
assert(it.isNotEmpty())
}
private val questions = loadFromPath(questionsFile, sourceDir).also {
assert(it.isNotEmpty())
}
suspend fun validate(name: String, verbose: Boolean = false, force: Boolean = false, testing: Boolean = false): Pair<Question, ValidationReport?> {

suspend fun validate(
name: String,
verbose: Boolean = false,
force: Boolean = false,
testing: Boolean = false
): Pair<Question, ValidationReport?> {
val question = if (force) {
unvalidatedQuestions[name]
} else {
Expand All @@ -27,7 +38,7 @@ class Validator(questionsFile: File, private val sourceDir: String, private val
question.reportFile(sourceDir).delete()
}
try {
question.validate(seed).also { report ->
question.validate(seed, maxMutationCount).also { report ->
if (!testing) {
println("$name: ${report.summary}")
question.validationFile(sourceDir)
Expand Down
3 changes: 2 additions & 1 deletion lib/src/test/kotlin/TestTestTesting.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import kotlin.system.measureTimeMillis
private val validator = Validator(
Path.of(object {}::class.java.getResource("/questions.json")!!.toURI()).toFile(),
"",
seed = 124
seed = 124,
maxMutationCount = 64
)

const val JAVA_EMPTY_SUITE_CLASS = """
Expand Down
3 changes: 2 additions & 1 deletion lib/src/test/kotlin/TestValidation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import java.nio.file.Path
private val validator = Validator(
Path.of(object {}::class.java.getResource("/questions.json")!!.toURI()).toFile(),
"",
seed = 124
seed = 124,
maxMutationCount = 64
)

class TestValidation : StringSpec({
Expand Down
53 changes: 42 additions & 11 deletions plugin/src/main/kotlin/GenerateMetatests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ abstract class GenerateMetatests : DefaultTask() {
@get:Input
abstract var seed: Int

@get:Input
abstract var maxMutationCount: Int

@InputFiles
val inputFiles = project.extensions.getByType(JavaPluginExtension::class.java)
.sourceSets.getByName("main").allSource.filter { it.name == ".validation.json" }
Expand Down Expand Up @@ -51,7 +54,15 @@ abstract class GenerateMetatests : DefaultTask() {
tests.first().let { (packageName, questions) ->
project.file("src/test/kotlin/TestAllQuestions.kt").also {
it.parentFile.mkdirs()
it.writeText(questions.generateTest(packageName, "TestAllQuestions", sourceRoot, seed))
it.writeText(
questions.generateTest(
packageName,
"TestAllQuestions",
sourceRoot,
seed,
maxMutationCount
)
)
}
project.file("src/test/kotlin/TestUnvalidatedQuestions.kt").also {
it.parentFile.mkdirs()
Expand All @@ -61,6 +72,7 @@ abstract class GenerateMetatests : DefaultTask() {
"TestUnvalidatedQuestions",
sourceRoot,
seed,
maxMutationCount,
onlyNotValidated = true
)
)
Expand All @@ -73,6 +85,7 @@ abstract class GenerateMetatests : DefaultTask() {
"TestFocusedQuestions",
sourceRoot,
seed,
maxMutationCount,
onlyFocused = true
)
)
Expand Down Expand Up @@ -107,6 +120,7 @@ fun List<Question>.generateTest(
klass: String,
sourceRoot: File,
seed: Int,
maxMutationCount: Int,
onlyNotValidated: Boolean = false,
onlyFocused: Boolean = false
): String {
Expand Down Expand Up @@ -149,39 +163,56 @@ fun List<Question>.generateTest(
}
return """$packageNameBlock@file:Suppress("SpellCheckingInspection", "UnusedImport", "unused")
${if (!isBlank) {
${
if (!isBlank) {
"""import edu.illinois.cs.cs125.jeed.core.warm
import edu.illinois.cs.cs125.questioner.lib.Validator
"""
} else {""}}import io.kotest.core.spec.style.StringSpec
${if (!isBlank) {
} else {
""
}
}import io.kotest.core.spec.style.StringSpec
${
if (!isBlank) {
"""import kotlinx.coroutines.runBlocking
import java.nio.file.Path
"""
} else {""}}
} else {
""
}
}
/*
* THIS FILE IS AUTOGENERATED. DO NOT EDIT BY HAND.
*/
/* ktlint-disable max-line-length */${if (!isBlank) {
/* ktlint-disable max-line-length */${
if (!isBlank) {
"""
private val validator = Validator(
Path.of(object {}::class.java.getResource("/questions.json")!!.toURI()).toFile(),
${"\"\"\"" + sourceRoot.path.replace("/", System.getProperty("file.separator")) + "\"\"\"" },
seed = $seed
${"\"\"\"" + sourceRoot.path.replace("/", System.getProperty("file.separator")) + "\"\"\""},
seed = $seed,
maxMutationCount = $maxMutationCount
)
"""
} else {""}}
} else {
""
}
}
@Suppress("MaxLineLength", "LargeClass")
class $klass : StringSpec({${if (!isBlank) {
class $klass : StringSpec({${
if (!isBlank) {
"""
beforeSpec {
runBlocking {
warm(failLint = false, quiet = true, useDocker = false)
}
}"""
} else {""}}
} else {
""
}
}
$testBlock
})
/* ktlint-enable max-line-length */
Expand Down
1 change: 1 addition & 0 deletions plugin/src/main/kotlin/QuestionerConfigExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ package edu.illinois.cs.cs125.questioner.plugin

open class QuestionerConfigExtension {
var seed: Int = 124
var maxMutationCount: Int = 32
}
2 changes: 2 additions & 0 deletions plugin/src/main/kotlin/QuestionerPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ class QuestionerPlugin : Plugin<Project> {
generateMetatests.dependsOn(project.tasks.getByName("processResources"))
project.afterEvaluate {
project.tasks.getByName("processResources").dependsOn(saveQuestions)

generateMetatests.seed = config.seed
generateMetatests.maxMutationCount = config.maxMutationCount

project.configurations.getByName("runtimeClasspath") { conf ->
val agentJarPath = conf.resolvedConfiguration.resolvedArtifacts.find {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=2022.9.10
version=2022.9.11

0 comments on commit 3cb46f1

Please sign in to comment.