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

Commit

Permalink
Finish STDIN support and test.
Browse files Browse the repository at this point in the history
  • Loading branch information
gchallen committed Sep 5, 2022
1 parent 4dff5f3 commit 4880ca6
Show file tree
Hide file tree
Showing 11 changed files with 358 additions and 89 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.8.0"
version = "2022.9.0"
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
Expand Down
8 changes: 4 additions & 4 deletions lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ dependencies {
implementation("org.ow2.asm:asm:9.3")

api("com.beyondgrader.resource-agent:agent:2022.6.6")
api("com.github.cs125-illinois.jeed:core:2022.8.0")
api("com.github.cs125-illinois:jenisol:2022.8.0")
api("io.kotest:kotest-runner-junit5:5.4.1")
api("com.github.cs125-illinois.jeed:core:2022.9.0")
api("com.github.cs125-illinois:jenisol:2022.9.0")
api("io.kotest:kotest-runner-junit5:5.4.2")
api("com.google.truth:truth:1.1.3")
api("com.github.cs125-illinois:libcs1:2022.7.0")
api("com.github.cs125-illinois:libcs1:2022.9.0")
}
tasks {
val sourcesJar by creating(Jar::class) {
Expand Down
36 changes: 28 additions & 8 deletions lib/src/main/kotlin/QuestionHelpers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -394,23 +394,43 @@ class InvertingClassLoader(
}
}

class ResettingInputStream : InputStream() {
private var currentInputStream: ByteArrayInputStream = ByteArrayInputStream("".toByteArray())
set(value) {
currentInputStream.close()
field = value
class BumpingInputStream : InputStream() {
private var stream = ByteArrayInputStream("".toByteArray())
private lateinit var inputs: List<ByteArray>

private var index = 0
private var usedIndex = false

fun setInputs(_inputs: List<ByteArray>) {
index = 0
usedIndex = false
inputs = _inputs
stream = ByteArrayInputStream(inputs.getOrNull(index) ?: "".toByteArray())
}

fun bump() {
if (usedIndex) {
index++
stream = ByteArrayInputStream(inputs.getOrNull(index) ?: "".toByteArray())
usedIndex = false
}
}

override fun read(): Int {
return currentInputStream.read()
usedIndex = true
return stream.read()
}
}

fun bindJeedCaptureOutputControlInput(stdinStream: ResettingInputStream): CaptureOutputControlInput {
fun bindJeedCaptureOutputControlInput(stdinStream: BumpingInputStream): CaptureOutputControlInput {
return fun(stdin: List<String>, run: () -> Any?): CapturedResult {
stdinStream.setInputs(stdin.map { "$it\n".toByteArray() })

val outputListener = object : Sandbox.OutputListener {
override fun stdout(int: Int) {
stdinStream.bump()
}
override fun stderr(int: Int) {}
override fun stdout(int: Int) {}
}
var resourceUsage: ResourceMonitoringCheckpoint? = null
val jeedOutput = Sandbox.redirectOutput(outputListener) {
Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/kotlin/TestQuestion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ suspend fun Question.test(
minTestCount = settings.minTestCount,
maxTestCount = settings.maxTestCount
)
val systemInStream = ResettingInputStream()
val systemInStream = BumpingInputStream()
val executionArguments = Sandbox.ExecutionArguments(
timeout = settings.timeout.toLong(),
classLoaderConfiguration = classLoaderConfiguration,
Expand Down
8 changes: 8 additions & 0 deletions lib/src/test/kotlin/TestValidation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,12 @@ class TestValidation : StringSpec({
report!!.requiredTestCount shouldBeGreaterThan 0
}
}
"stdin interleaving should work" {
validator.validate("Input Interleaving Test", force = true, testing = true)
.also { (question, report) ->
question.validated shouldBe true
report shouldNotBe null
report!!.requiredTestCount shouldBeGreaterThan 0
}
}
})
240 changes: 236 additions & 4 deletions lib/src/test/resources/questions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1965,12 +1965,244 @@
},
"fauxStatic": false
},
"Input Interleaving Test": {
"name": "Input Interleaving Test",
"type": "KLASS",
"klass": "Question",
"metadata": {
"contentHash": "07f28386753a725afce9dc22bdad83f0",
"packageName": "com.examples.inputinterleavingtest",
"version": "2022.9.0",
"author": "[email protected]",
"javaDescription": "<p>Testing STDIN generation and interleaving.</p>",
"kotlinDescription": "<p>Testing STDIN generation and interleaving. In Kotlin!</p>",
"usedFiles": [
"/Users/challen/code/questioner-problems/src/main/java/com/examples/inputinterleavingtest/correct/kotlin/Question.kt"
],
"focused": false
},
"annotatedControls": {},
"question": {
"klass": "Question",
"contents": "import java.util.Arrays;\nimport java.util.Random;\nimport java.util.Scanner;\nimport edu.illinois.cs.cs125.jenisol.core.EdgeType;\nimport edu.illinois.cs.cs125.jenisol.core.Limit;\nimport edu.illinois.cs.cs125.jenisol.core.ProvideSystemIn;\nimport edu.illinois.cs.cs125.jenisol.core.RandomType;\nimport edu.illinois.cs.cs125.jenisol.core.SimpleType;\nimport edu.illinois.cs.cs125.jenisol.core.generators.SystemIn;\nimport edu.illinois.cs.cs125.questioner.lib.Correct;\n\n/*\n * Testing STDIN generation and interleaving.\n */\n\n@SuppressWarnings(\"StringOperationCanBeSimplified\")\n@Correct(name = \"Input Interleaving Test\", version = \"2022.9.0\", author = \"[email protected]\")\npublic class Question {\n @ProvideSystemIn\n @Limit(1)\n public static void echo() {\n System.out.println(\"Hello!\");\n Scanner scanner = new Scanner(System.in);\n String first = scanner.nextLine();\n System.out.println(\"First: \" + first);\n String second = scanner.nextLine();\n System.out.println(\"Second: \" + second);\n }\n\n @SimpleType\n private static final SystemIn[] SIMPLE =\n new SystemIn[] {new SystemIn(Arrays.asList(\"Test\", \"Me\"))};\n\n @EdgeType private static final SystemIn[] EDGE = new SystemIn[] {};\n\n @RandomType\n private static SystemIn randomInput(Random random) {\n return new SystemIn(\n Arrays.asList(new String(\"\" + random.nextInt()), new String(\"\" + random.nextInt())));\n }\n}",
"language": "java",
"path": "/Users/challen/code/questioner-problems/src/main/java/com/examples/inputinterleavingtest/Question.java"
},
"correct": {
"klass": "Question",
"contents": "import java.util.Scanner;\n\npublic class Question {\n public static void echo() {\n System.out.println(\"Hello!\");\n Scanner scanner = new Scanner(System.in);\n String first = scanner.nextLine();\n System.out.println(\"First: \" + first);\n String second = scanner.nextLine();\n System.out.println(\"Second: \" + second);\n }\n}\n",
"language": "java",
"path": "/Users/challen/code/questioner-problems/src/main/java/com/examples/inputinterleavingtest/Question.java",
"complexity": 1,
"features": {
"featureMap": {
"LOCAL_VARIABLE_DECLARATIONS": 3,
"VARIABLE_ASSIGNMENTS": 3,
"ARITHMETIC_OPERATORS": 2,
"METHOD": 1,
"STRING": 2,
"CLASS": 1,
"NEW_KEYWORD": 1,
"VISIBILITY_MODIFIERS": 2,
"STATIC_METHOD": 1,
"IMPORT": 1,
"PRINT_STATEMENTS": 3,
"DOT_NOTATION": 3,
"DOTTED_METHOD_CALL": 2,
"DOTTED_VARIABLE_ACCESS": 1
},
"importList": [
"java.util.Scanner"
],
"typeList": [
"Scanner",
"String"
],
"identifierList": [
"scanner",
"first",
"second"
],
"dottedMethodList": [
"println",
"nextLine"
]
},
"lineCount": {
"source": 11,
"comment": 0,
"blank": 2
},
"expectedDeadCount": 1
},
"alternativeSolutions": [
{
"klass": "QuestionKt",
"contents": "import java.util.Scanner\n\n\nfun echo() {\n println(\"Hello!\")\n val scanner = Scanner(System.`in`)\n val first = scanner.nextLine()\n println(\"First: $first\")\n val second = scanner.nextLine()\n println(\"Second: $second\")\n}",
"language": "kotlin",
"path": "/Users/challen/code/questioner-problems/src/main/java/com/examples/inputinterleavingtest/correct/kotlin/Question.kt",
"complexity": 1,
"features": {
"featureMap": {
"LOCAL_VARIABLE_DECLARATIONS": 3,
"VARIABLE_ASSIGNMENTS": 3,
"METHOD": 1,
"IMPORT": 1,
"PRINT_STATEMENTS": 3,
"DOT_NOTATION": 3,
"DOTTED_METHOD_CALL": 2,
"DOTTED_VARIABLE_ACCESS": 1
},
"importList": [
"java.util.Scanner"
],
"typeList": [],
"identifierList": [],
"dottedMethodList": [
"nextLine"
]
},
"lineCount": {
"source": 9,
"comment": 0,
"blank": 2
}
}
],
"incorrect": [],
"common": [],
"importWhitelist": [],
"importBlacklist": [],
"slug": "input-interleaving-test",
"kotlinSolution": {
"klass": "QuestionKt",
"contents": "import java.util.Scanner\n\n\nfun echo() {\n println(\"Hello!\")\n val scanner = Scanner(System.`in`)\n val first = scanner.nextLine()\n println(\"First: $first\")\n val second = scanner.nextLine()\n println(\"Second: $second\")\n}",
"language": "kotlin",
"path": "/Users/challen/code/questioner-problems/src/main/java/com/examples/inputinterleavingtest/correct/kotlin/Question.kt",
"complexity": 1,
"features": {
"featureMap": {
"LOCAL_VARIABLE_DECLARATIONS": 3,
"VARIABLE_ASSIGNMENTS": 3,
"METHOD": 1,
"IMPORT": 1,
"PRINT_STATEMENTS": 3,
"DOT_NOTATION": 3,
"DOTTED_METHOD_CALL": 2,
"DOTTED_VARIABLE_ACCESS": 1
},
"importList": [
"java.util.Scanner"
],
"typeList": [],
"identifierList": [],
"dottedMethodList": [
"nextLine"
]
},
"lineCount": {
"source": 9,
"comment": 0,
"blank": 2
}
},
"hasKotlin": true,
"published": {
"name": "Input Interleaving Test",
"type": "KLASS",
"path": "input-interleaving-test",
"author": "[email protected]",
"version": "2022.9.0",
"packageName": "com.examples.inputinterleavingtest",
"languages": [
"java",
"kotlin"
],
"descriptions": {
"java": "<p>Testing STDIN generation and interleaving.</p>",
"kotlin": "<p>Testing STDIN generation and interleaving. In Kotlin!</p>"
},
"complexity": {
"java": 1,
"kotlin": 1
},
"features": {
"java": {
"featureMap": {
"LOCAL_VARIABLE_DECLARATIONS": 3,
"VARIABLE_ASSIGNMENTS": 3,
"ARITHMETIC_OPERATORS": 2,
"METHOD": 1,
"STRING": 2,
"CLASS": 1,
"NEW_KEYWORD": 1,
"VISIBILITY_MODIFIERS": 2,
"STATIC_METHOD": 1,
"IMPORT": 1,
"PRINT_STATEMENTS": 3,
"DOT_NOTATION": 3,
"DOTTED_METHOD_CALL": 2,
"DOTTED_VARIABLE_ACCESS": 1
},
"importList": [
"java.util.Scanner"
],
"typeList": [
"Scanner",
"String"
],
"identifierList": [
"scanner",
"first",
"second"
],
"dottedMethodList": [
"println",
"nextLine"
]
},
"kotlin": {
"featureMap": {
"LOCAL_VARIABLE_DECLARATIONS": 3,
"VARIABLE_ASSIGNMENTS": 3,
"METHOD": 1,
"IMPORT": 1,
"PRINT_STATEMENTS": 3,
"DOT_NOTATION": 3,
"DOTTED_METHOD_CALL": 2,
"DOTTED_VARIABLE_ACCESS": 1
},
"importList": [
"java.util.Scanner"
],
"typeList": [],
"identifierList": [],
"dottedMethodList": [
"nextLine"
]
}
},
"lineCounts": {
"java": {
"source": 11,
"comment": 0,
"blank": 2
},
"kotlin": {
"source": 9,
"comment": 0,
"blank": 2
}
}
},
"fauxStatic": false
},
"With Imports": {
"name": "With Imports",
"type": "KLASS",
"klass": "Question",
"metadata": {
"contentHash": "cb19a8122edb12c3937dd28e4820ca15",
"contentHash": "28944ac134c1b61f898a4d9596831bb7",
"packageName": "com.examples.withimports",
"version": "2022.7.0",
"author": "[email protected]",
Expand All @@ -1984,7 +2216,7 @@
"annotatedControls": {},
"question": {
"klass": "Question",
"contents": "import edu.illinois.cs.cs125.questioner.lib.Correct;\n\nimport java.util.Arrays;\nimport java.util.List;\n\n/*\n * Example to test use of import statements.\n */\n\n@Correct(name = \"With Imports\", version = \"2022.7.0\", author = \"[email protected]\")\npublic class Question {\n public static List<Integer> max(int first, int second) {\n return Arrays.asList(first, second);\n }\n}",
"contents": "import edu.illinois.cs.cs125.questioner.lib.Correct;\nimport java.util.Arrays;\nimport java.util.List;\n\n/*\n * Example to test use of import statements.\n */\n\n@Correct(name = \"With Imports\", version = \"2022.7.0\", author = \"[email protected]\")\npublic class Question {\n public static List<Integer> max(int first, int second) {\n return Arrays.asList(first, second);\n }\n}",
"language": "java",
"path": "/Users/challen/code/questioner-problems/src/main/java/com/examples/withimports/Question.java"
},
Expand Down Expand Up @@ -2612,7 +2844,7 @@
"type": "METHOD",
"klass": "Question",
"metadata": {
"contentHash": "7265340f9d922ca3dfe7ff222f5a309d",
"contentHash": "f53448151d802ca1846e2f5c3475f44d",
"packageName": "com.examples.withfeaturecheck",
"version": "2022.7.0",
"author": "[email protected]",
Expand All @@ -2628,7 +2860,7 @@
"annotatedControls": {},
"question": {
"klass": "Question",
"contents": "import edu.illinois.cs.cs125.jeed.core.Features;\nimport edu.illinois.cs.cs125.jenisol.core.BoundComplexity;\nimport edu.illinois.cs.cs125.jenisol.core.FilterParameters;\nimport edu.illinois.cs.cs125.jenisol.core.SkipTest;\nimport edu.illinois.cs.cs125.questioner.lib.CheckFeatures;\nimport edu.illinois.cs.cs125.questioner.lib.Correct;\nimport edu.illinois.cs.cs125.questioner.lib.FeatureCheckException;\nimport edu.illinois.cs.cs125.questioner.lib.Wrap;\nimport edu.illinois.cs.cs125.questioner.lib.features.FeatureHelpers;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/*\n * Test whether feature checking works.\n */\n\n@Correct(name = \"With Feature Check\", author = \"[email protected]\", version = \"2022.7.0\")\n@Wrap\npublic class Question {\n @FilterParameters\n private static void filterParameters(int range) {\n if (range < 0) {\n throw new SkipTest();\n }\n if (range > 1024) {\n throw new BoundComplexity();\n }\n }\n\n int sumTo(int range) {\n return (range * (range + 1)) / 2;\n }\n\n @CheckFeatures\n private static List<String> checkFeatures(Features solution, Features submission) {\n if (FeatureHelpers.usesLoop(submission)) {\n throw new FeatureCheckException(\"Submission uses a loop\");\n }\n return new ArrayList<>();\n }\n}",
"contents": "import edu.illinois.cs.cs125.jeed.core.Features;\nimport edu.illinois.cs.cs125.jenisol.core.BoundComplexity;\nimport edu.illinois.cs.cs125.jenisol.core.FilterParameters;\nimport edu.illinois.cs.cs125.jenisol.core.SkipTest;\nimport edu.illinois.cs.cs125.questioner.lib.CheckFeatures;\nimport edu.illinois.cs.cs125.questioner.lib.Correct;\nimport edu.illinois.cs.cs125.questioner.lib.FeatureCheckException;\nimport edu.illinois.cs.cs125.questioner.lib.Wrap;\nimport edu.illinois.cs.cs125.questioner.lib.features.FeatureHelpers;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/*\n * Test whether feature checking works.\n */\n\n@Correct(name = \"With Feature Check\", author = \"[email protected]\", version = \"2022.7.0\")\n@Wrap\npublic class Question {\n @FilterParameters\n private static void filterParameters(int range) {\n if (range < 0) {\n throw new SkipTest();\n }\n if (range > 1024) {\n throw new BoundComplexity();\n }\n }\n\n int sumTo(int range) {\n return (range * (range + 1)) / 2;\n }\n\n @CheckFeatures\n private static List<String> checkFeatures(Features solution, Features submission) {\n if (FeatureHelpers.usesLoop(submission)) {\n throw new FeatureCheckException(\"Submission uses a loop\");\n }\n return new ArrayList<>();\n }\n}",
"language": "java",
"path": "/Users/challen/code/questioner-problems/src/main/java/com/examples/withfeaturecheck/Question.java"
},
Expand Down
8 changes: 4 additions & 4 deletions plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
id("com.google.devtools.ksp")
}
dependencies {
antlr("org.antlr:antlr4:4.10.1")
antlr("org.antlr:antlr4:4.11.1")

implementation("org.jetbrains.kotlin:kotlin-reflect:1.7.10")
implementation(gradleApi())
Expand All @@ -20,12 +20,12 @@ dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
implementation("com.google.googlejavaformat:google-java-format:1.15.0")
implementation("com.google.guava:guava:31.1-jre")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.3")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.3")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.13.4")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4")
implementation("com.github.slugify:slugify:3.0.2")
implementation("org.apache.httpcomponents.client5:httpclient5-fluent:5.1.3")

testImplementation("io.kotest:kotest-runner-junit5:5.4.1")
testImplementation("io.kotest:kotest-runner-junit5:5.4.2")
}
tasks.compileKotlin {
dependsOn(tasks.generateGrammarSource)
Expand Down
Loading

0 comments on commit 4880ca6

Please sign in to comment.