diff --git a/build.gradle.kts b/build.gradle.kts index 8f40380..cd7675d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ import java.util.Properties import org.jetbrains.kotlin.gradle.tasks.KotlinCompile group = "com.github.cs125-illinois" -version = "2022.9.4" +version = "2022.10.0" plugins { kotlin("jvm") version "1.7.20" diff --git a/src/main/kotlin/Solution.kt b/src/main/kotlin/Solution.kt index 1d15368..0bae858 100644 --- a/src/main/kotlin/Solution.kt +++ b/src/main/kotlin/Solution.kt @@ -4,6 +4,7 @@ package edu.illinois.cs.cs125.jenisol.core import com.rits.cloning.Cloner import edu.illinois.cs.cs125.jenisol.core.generators.GeneratorFactory +import edu.illinois.cs.cs125.jenisol.core.generators.Parameters import edu.illinois.cs.cs125.jenisol.core.generators.boxType import edu.illinois.cs.cs125.jenisol.core.generators.getArrayDimension import edu.illinois.cs.cs125.jenisol.core.generators.getArrayType @@ -164,17 +165,19 @@ class Solution(val solution: Class<*>) { } else if (fauxStatic) { 1 } else { - receiverGenerators.sumOf { - generatorFactory.get(Random, Cloner.shared())[it]!!.fixed.size - } * 2 + receiverGenerators.sumOf { generator -> + generatorFactory.get(Random, Cloner.shared())[generator]!!.fixed.filter { + it.type == Parameters.Type.SIMPLE || it.type == Parameters.Type.FIXED_FIELD + }.size * 2 + } } private val defaultMethodCount = ( - (allExecutables - receiverGenerators).sumOf { - if (it.receiverParameter()) { + (allExecutables - receiverGenerators).sumOf { generator -> + if (generator.receiverParameter()) { defaultReceiverCount } else { - generatorFactory.get(Random, Cloner.shared())[it]!!.fixed.size.coerceAtLeast(1) + - if (receiverGenerators.isNotEmpty() && it.objectParameter()) { + generatorFactory.get(Random, Cloner.shared())[generator]!!.fixed.size.coerceAtLeast(1) + + if (receiverGenerators.isNotEmpty() && generator.objectParameter()) { defaultReceiverCount } else { 0 @@ -218,7 +221,7 @@ class Solution(val solution: Class<*>) { check(settings.shrink != null) { "shrink setting must be specified" } - val testCount = if (settings.testCount != -1) { + var testCount = if (settings.testCount != -1) { check(settings.minTestCount == -1 && settings.maxTestCount == -1) { "Can't set testCount and minTestCount or maxTestCount" } @@ -253,6 +256,20 @@ class Solution(val solution: Class<*>) { } else { -1 } + if (receiverCount != -1) { + if (settings.testCount != -1) { + check(testCount >= receiverCount * 2) { + "Not enough tests to test all receivers: ${settings.testCount}" + } + } else { + testCount = testCount.coerceAtLeast(receiverCount * 2) + if (settings.maxTestCount != -1) { + check(testCount <= settings.maxTestCount) { + "Can't test all receivers without exceeding maxTestCount: $testCount ${settings.maxTestCount}" + } + } + } + } return settings.copy(testCount = testCount, methodCount = methodCount, receiverCount = receiverCount) } diff --git a/src/main/kotlin/Submission.kt b/src/main/kotlin/Submission.kt index ad54c96..9f93b44 100644 --- a/src/main/kotlin/Submission.kt +++ b/src/main/kotlin/Submission.kt @@ -579,8 +579,7 @@ class Submission(val solution: Solution, val submission: Class<*>) { } while (totalCount < settings.testCount) { - val createdCount = runners.createdCount() - val finishedReceivers = createdCount >= neededReceivers + val finishedReceivers = runners.createdCount() >= neededReceivers if (Thread.interrupted()) { return runners.toResults( diff --git a/src/main/kotlin/generators/Receiver.kt b/src/main/kotlin/generators/Receiver.kt index bc0806a..4b2a93d 100644 --- a/src/main/kotlin/generators/Receiver.kt +++ b/src/main/kotlin/generators/Receiver.kt @@ -26,15 +26,6 @@ class ReceiverGenerator( override val simple: Set> get() = receivers .filter { it.complexity.level == 0 } - .onEach { - check(it.solution::class.java == submission.solution.solution) - check(it.solutionCopy::class.java == submission.solution.solution) - check(it.submission::class.java == submission.submission) - check(it.submissionCopy::class.java == submission.submission) - check(it.unmodifiedCopy::class.java == submission.submission) - check(it.solution !== it.solutionCopy) - check(it.submission !== it.submissionCopy) - } .toSet() override val edge: Set> @@ -45,14 +36,6 @@ class ReceiverGenerator( simple.shuffled(random).first() } else { receivers.findWithComplexity(complexity, random) - }.also { - check(it.solution::class.java == submission.solution.solution) - check(it.solutionCopy::class.java == submission.solution.solution) - check(it.submission::class.java == submission.submission) - check(it.submissionCopy::class.java == submission.submission) - check(it.unmodifiedCopy::class.java == submission.submission) - check(it.solution !== it.solutionCopy) - check(it.submission !== it.submissionCopy) } } diff --git a/src/main/resources/edu.illinois.cs.cs125.jenisol.core.version b/src/main/resources/edu.illinois.cs.cs125.jenisol.core.version index de9c1bc..cbe5ac6 100644 --- a/src/main/resources/edu.illinois.cs.cs125.jenisol.core.version +++ b/src/main/resources/edu.illinois.cs.cs125.jenisol.core.version @@ -1 +1 @@ -version=2022.9.4 \ No newline at end of file +version=2022.10.0 \ No newline at end of file diff --git a/src/test/java/edu/illinois/cs/cs125/jenisol/core/Helpers.kt b/src/test/java/edu/illinois/cs/cs125/jenisol/core/Helpers.kt index d6ff31e..caf94ea 100644 --- a/src/test/java/edu/illinois/cs/cs125/jenisol/core/Helpers.kt +++ b/src/test/java/edu/illinois/cs/cs125/jenisol/core/Helpers.kt @@ -78,14 +78,15 @@ suspend fun Solution.fullTest( klass: Class<*>, seed: Int, isCorrect: Boolean, - solutionResults: TestResults? = null + solutionResults: TestResults? = null, + overrideMaxCount: Int = 0 ): Pair { val baseSettings = Settings( shrink = true, seed = seed, testing = true, - minTestCount = 64.coerceAtMost(maxCount), - maxTestCount = 1024.coerceAtMost(maxCount) + minTestCount = 64.coerceAtMost(maxCount).coerceAtLeast(overrideMaxCount), + maxTestCount = 1024.coerceAtMost(maxCount).coerceAtLeast(overrideMaxCount) ) @Suppress("RethrowCaughtException") @@ -136,7 +137,7 @@ suspend fun Solution.fullTest( if (!isCorrect) { first.indexOfFirst { it.failed } shouldBe first.size - 1 - failingTestCount = original.size + failingTestCount = original.size.coerceAtLeast(first.settings.receiverCount * 2) } first.size shouldBe second.size @@ -195,12 +196,17 @@ suspend fun Solution.fullTest( return Pair(original, first) } -@Suppress("NestedBlockDepth", "ComplexMethod") -suspend fun Class<*>.test() = this.testingClasses().apply { +@Suppress("NestedBlockDepth", "ComplexMethod", "LongMethod") +suspend fun Class<*>.test(overrideMaxCount: Int = 0) = this.testingClasses().apply { solution(primarySolution).apply { val (_, solutionResults) = submission(primarySolution).let { if (!primarySolution.isDesignOnly()) { - fullTest(primarySolution, seed = 124, isCorrect = true).also { (results) -> + fullTest( + primarySolution, + seed = 124, + isCorrect = true, + overrideMaxCount = overrideMaxCount + ).also { (results) -> check(results.succeeded) { "Solution did not pass testing: ${results.explain()}" } } } else { @@ -214,7 +220,8 @@ suspend fun Class<*>.test() = this.testingClasses().apply { correct, seed = 124, isCorrect = true, - solutionResults = solutionResults + solutionResults = solutionResults, + overrideMaxCount = overrideMaxCount ).first.also { results -> check(!results.timeout) check(results.succeeded) { @@ -240,7 +247,8 @@ suspend fun Class<*>.test() = this.testingClasses().apply { incorrect, seed = 124, isCorrect = false, - solutionResults = solutionResults + solutionResults = solutionResults, + overrideMaxCount = overrideMaxCount ).first.also { results -> results.threw shouldBe null results.timeout shouldBe false diff --git a/src/test/java/edu/illinois/cs/cs125/jenisol/core/TestJavaExamples.kt b/src/test/java/edu/illinois/cs/cs125/jenisol/core/TestJavaExamples.kt index efaedf4..1e3b65a 100644 --- a/src/test/java/edu/illinois/cs/cs125/jenisol/core/TestJavaExamples.kt +++ b/src/test/java/edu/illinois/cs/cs125/jenisol/core/TestJavaExamples.kt @@ -381,6 +381,9 @@ class TestJavaExamples : StringSpec( examples.java.receiver.timeouttest.Correct::class.java.also { "${it.testName()}" { it.test() } } + examples.java.receiver.tripleequalswithasserts.Correct::class.java.also { + "${it.testName()}" { it.test() } + } // Tests that should fail examples.java.noreceiver.filternotnullwithrandomgeneratesnull.Correct::class.java.also { "${it.testName()}" { diff --git a/src/test/java/examples/java/receiver/completethreefields/Correct.java b/src/test/java/examples/java/receiver/completethreefields/Correct.java index 17d37d2..c73327c 100644 --- a/src/test/java/examples/java/receiver/completethreefields/Correct.java +++ b/src/test/java/examples/java/receiver/completethreefields/Correct.java @@ -1,9 +1,5 @@ package examples.java.receiver.completethreefields; -import edu.illinois.cs.cs125.jenisol.core.FixedParameters; -import edu.illinois.cs.cs125.jenisol.core.Three; -import java.util.Arrays; -import java.util.List; import java.util.Objects; public class Correct { @@ -42,14 +38,4 @@ public boolean equals(Object o) { Correct correct = (Correct) o; return Objects.equals(name, correct.name) && Objects.equals(artist, correct.artist); } - - @FixedParameters - private static final List> FIXED = - Arrays.asList( - new Three<>("Test", "Me", 1988), - new Three<>("Test", "Me", 1987), - new Three<>("Testing", "Me", 1988), - new Three<>("Test", "You", 1988), - new Three<>(null, "Me", 1988), - new Three<>("Test", null, 1988)); } diff --git a/src/test/java/examples/java/receiver/tripleequalswithasserts/Correct.java b/src/test/java/examples/java/receiver/tripleequalswithasserts/Correct.java new file mode 100644 index 0000000..002b0a1 --- /dev/null +++ b/src/test/java/examples/java/receiver/tripleequalswithasserts/Correct.java @@ -0,0 +1,42 @@ +package examples.java.receiver.tripleequalswithasserts; + +import edu.illinois.cs.cs125.jenisol.core.EdgeType; +import edu.illinois.cs.cs125.jenisol.core.RandomType; +import edu.illinois.cs.cs125.jenisol.core.SimpleType; +import java.util.Random; + +public class Correct { + private final String string; + private final double first; + private final double second; + + public Correct(String setString, double setFirst, double setSecond) { + assert setString != null; + assert setFirst >= -90.0 && setFirst <= 90.0; + assert setSecond >= -180.0 && setSecond <= 180.0; + string = setString; + first = setFirst; + second = setSecond; + } + + @SimpleType private static final double[] SIMPLE_DOUBLES = new double[] {8.8}; + + @EdgeType + private static final double[] EDGE_DOUBLES = + new double[] { + -180.1, -180.0, -179.9, -90.1, -90.0, -89.9, 89.9, 90.0, 90.1, 179.9, 180.0, 180.1 + }; + + @RandomType + private static double randomPosition(Random random) { + return (random.nextDouble() * 179.8) - 89.9; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Correct correct)) { + return false; + } + return first == correct.first && second == correct.second; + } +} diff --git a/src/test/java/examples/java/receiver/tripleequalswithasserts/Incorrect0.java b/src/test/java/examples/java/receiver/tripleequalswithasserts/Incorrect0.java new file mode 100644 index 0000000..53b243d --- /dev/null +++ b/src/test/java/examples/java/receiver/tripleequalswithasserts/Incorrect0.java @@ -0,0 +1,24 @@ +package examples.java.receiver.tripleequalswithasserts; + +public class Incorrect0 { + private final String string; + private final double first; + private final double second; + + public Incorrect0(String setString, double setFirst, double setSecond) { + assert setString != null; + assert setFirst >= -90.0 && setFirst <= 90.0; + assert setSecond >= -180.0 && setSecond <= 180.0; + string = setString; + first = setFirst; + second = setSecond; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof Incorrect0 correct)) { + return true; + } + return first == correct.first && second == correct.second; + } +}