diff --git a/pom.xml b/pom.xml index ba3f38b8b3..1d807129af 100644 --- a/pom.xml +++ b/pom.xml @@ -27,10 +27,6 @@ We use these goals frequently to keep the dependencies and plugins up-to-date: Vavr (formerly called Javaslang) is an object-functional language extension to Java 8+. vavr - vavr-benchmark - vavr-match - vavr-match-processor - vavr-test https://vavr.io diff --git a/vavr-benchmark/pom.xml b/vavr-benchmark/pom.xml deleted file mode 100644 index 3b2cbf6a5f..0000000000 --- a/vavr-benchmark/pom.xml +++ /dev/null @@ -1,128 +0,0 @@ - - 4.0.0 - - io.vavr - vavr-parent - 0.10.6-SNAPSHOT - ../pom.xml - - vavr-benchmark - Vavr Benchmark - Benchmarks for Vavr. - https://vavr.io - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - ${project.groupId} - vavr - ${project.version} - - - org.scalaz - scalaz-core_2.12 - 7.3.8 - - - - org.clojure - clojure - 1.12.0 - - - org.pcollections - pcollections - 4.0.2 - - - org.functionaljava - functionaljava-java8 - 4.6 - - - org.eclipse.collections - eclipse-collections - 11.1.0 - - - io.usethesource - capsule - 0.6.1 - - - org.openjdk.jol - jol-core - 0.17 - - - org.jetbrains - annotations - 26.0.1 - - - org.junit.jupiter - junit-jupiter - test - - - org.openjdk.jmh - jmh-generator-annprocess - test - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven.surefire.version} - - - **/*Benchmark.java - - true - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - org.apache.maven.plugins - maven-install-plugin - - true - - - - org.sonatype.plugins - nexus-staging-maven-plugin - - true - - - - - - - usethesource - https://releases.usethesource.io/maven/ - - - diff --git a/vavr-benchmark/src/test/java/io/vavr/BenchmarkPerformanceReporter.java b/vavr-benchmark/src/test/java/io/vavr/BenchmarkPerformanceReporter.java deleted file mode 100644 index 300c457a61..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/BenchmarkPerformanceReporter.java +++ /dev/null @@ -1,514 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr; - -import io.vavr.collection.Array; -import io.vavr.collection.CharSeq; -import io.vavr.collection.Map; -import io.vavr.control.Option; -import org.openjdk.jmh.infra.BenchmarkParams; -import org.openjdk.jmh.results.BenchmarkResult; -import org.openjdk.jmh.results.Result; -import org.openjdk.jmh.results.RunResult; -import org.openjdk.jmh.util.ListStatistics; - -import java.text.DecimalFormat; -import java.util.Comparator; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class BenchmarkPerformanceReporter { - private static final Comparator TO_STRING_COMPARATOR = Comparator.comparing(String::length).thenComparing(Function.identity()); - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0.00"); - private static final DecimalFormat PERFORMANCE_FORMAT = new DecimalFormat("#0.00"); - private static final DecimalFormat PCT_FORMAT = new DecimalFormat("0.00%"); - - private final Array includeNames; - private final Array benchmarkClasses; - private final Array runResults; - private final String targetImplementation; - private final double outlierLowPct; - private final double outlierHighPct; - - public static BenchmarkPerformanceReporter of(Array includeNames, Array benchmarkClasses, Array runResults) { - return of(includeNames, benchmarkClasses, runResults, "vavr", 0.3, 0.05); - } - - public static BenchmarkPerformanceReporter of(Array includeNames, Array benchmarkClasses, Array runResults, String targetImplementation, double outlierLowPct, double outlierHighPct) { - return new BenchmarkPerformanceReporter(includeNames, benchmarkClasses, runResults, targetImplementation, outlierLowPct, outlierHighPct); - } - - /** - * This class prints performance reports about the execution of individual tests, comparing their performance - * against other implementations as required. - * - * @param benchmarkClasses The benchmarked source class names - * @param runResults The results - * @param targetImplementation The target implementation we want to focus on in the Ratio report. - * It is case insensitive. If we enter "vavr", it will match "VaVr" and "va_vr". - * @param outlierLowPct The percentage of samples on the lower end that will be ignored from the statistics - * @param outlierHighPct The percentage of samples on the higher end that will be ignored from the statistics - */ - private BenchmarkPerformanceReporter(Array includeNames, Array benchmarkClasses, Array runResults, String targetImplementation, double outlierLowPct, double outlierHighPct) { - this.includeNames = includeNames; - this.benchmarkClasses = benchmarkClasses; - this.runResults = runResults; - this.targetImplementation = targetImplementation; - this.outlierLowPct = outlierLowPct; - this.outlierHighPct = outlierHighPct; - } - - /** - * Prints all performance reports - */ - public void print() { - printDetailedPerformanceReport(); - printRatioPerformanceReport(); - } - - /** - * Prints the detail performance report for each individual test. - *
- * For each test it prints out: - *
    - *
  • Group
  • - *
  • Test Name
  • - *
  • Implementation - tests can have different implementations, e.g. Scala, Java, Vavr
  • - *
  • Parameters
  • - *
  • Score
  • - *
  • Error - 99% confidence interval expressed in % of the Score
  • - *
  • Unit - units for the Score
  • - *
  • Alternative implementations - compares performance of this test against alternative implementations
  • - *
- */ - public void printDetailedPerformanceReport() { - final Array results = mapToTestExecutions(); - if (results.isEmpty()) { - return; - } - new DetailedPerformanceReport(results).print(); - } - - /** - * Prints the performance ratio report for each test, and compares the performance against different implementations - * of the same operation. - *
- * For each test it prints out: - *
    - *
  • Group
  • - *
  • Test Name
  • - *
  • Ratio - A/B means implementation A is compared against base implementation B
  • - *
  • Results - How many times faster implementation A is compared with B
  • - *
- */ - public void printRatioPerformanceReport() { - final Array results = mapToTestExecutions(); - if (results.isEmpty()) { - return; - } - new RatioPerformanceReport(results, targetImplementation).print(); - } - - private Array mapToTestExecutions() { - Array executions = Array.empty(); - for (RunResult runResult : runResults) { - executions = executions.append(TestExecution.of(runResult.getAggregatedResult(), outlierLowPct, outlierHighPct)); - } - return sort(executions, includeNames); - } - - private Array sort(Array results, Array includeNames) { - final Comparator comparator = Comparator - . comparing(t -> benchmarkClasses.indexWhere(c -> c.endsWith(t.getOperation()))) - .thenComparing(t -> includeNames.indexWhere(i -> t.getImplementation().startsWith(i))); - return results.sorted(comparator); - } - - private String padLeft(String str, int size) { - return str + CharSeq.repeat(' ', size - str.length()); - } - - private String padRight(String str, int size) { - return CharSeq.repeat(' ', size - str.length()) + str; - } - - private class DetailedPerformanceReport { - private final Array results; - private final Map> resultsByKey; - private final int paramKeySize; - private final int groupSize; - private final int nameSize; - private final int implSize; - private final int countSize; - private final int scoreSize; - private final int errorSize; - private final int unitSize; - private final Array alternativeImplementations; - - public DetailedPerformanceReport(Array results) { - this.results = results; - resultsByKey = results.groupBy(TestExecution::getTestNameParamKey); - paramKeySize = Math.max(results.map(r -> r.getParamKey().length()).max().get(), 10); - groupSize = Math.max(results.map(r -> r.getTarget().length()).max().get(), 10); - nameSize = Math.max(results.map(r -> r.getOperation().length()).max().get(), 10); - implSize = Math.max(results.map(r -> r.getImplementation().length()).max().get(), 10); - countSize = Math.max(results.map(r -> Long.toString(r.getSampleCount()).length()).max().get(), 5); - scoreSize = Math.max(results.map(r -> r.getScoreFormatted().length()).max().get(), 15); - errorSize = Math.max(results.map(r -> r.getScoreErrorPct().length()).max().get(), 10); - unitSize = Math.max(results.map(r -> r.getUnit().length()).max().get(), 7); - - alternativeImplementations = results.map(TestExecution::getImplementation).distinct(); - } - - public void print() { - printHeader(); - printDetails(); - } - - private void printHeader() { - final String alternativeImplHeader = alternativeImplementations.map(altImpl -> padRight(altImpl, altImplColSize(altImpl))).mkString(" "); - final String header = String.format("%s %s %s %s %s %s ±%s %s %s", - padLeft("Target", groupSize), - padLeft("Operation", nameSize), - padLeft("Impl", implSize), - padRight("Params", paramKeySize), - padRight("Count", countSize), - padRight("Score", scoreSize), - padRight("Error", errorSize), - padRight("Unit", unitSize), - alternativeImplHeader - ); - - System.out.println("\n\n\n"); - System.out.println("Detailed Performance Execution Report"); - System.out.println(CharSeq.of("=").repeat(header.length())); - System.out.println(" (Error: ±99% confidence interval, expressed as % of Score)"); - if (outlierLowPct > 0.0 && outlierHighPct > 0.0) { - System.out.println(String.format(" (Outliers removed: %s low end, %s high end)", PCT_FORMAT.format(outlierLowPct), PCT_FORMAT.format(outlierHighPct))); - } - if (!alternativeImplementations.isEmpty()) { - System.out.println(String.format(" (%s: read as current row implementation is x times faster than alternative implementation)", alternativeImplementations.mkString(", "))); - } - System.out.println(); - System.out.println(header); - } - - private void printDetails() { - for (TestExecution result : results) { - System.out.println(String.format("%s %s %s %s %s %s ±%s %s %s", - padLeft(result.getTarget(), groupSize), - padLeft(result.getOperation(), nameSize), - padLeft(result.getImplementation(), implSize), - padRight(result.getParamKey(), paramKeySize), - padRight(Long.toString(result.getSampleCount()), countSize), - padRight(result.getScoreFormatted(), scoreSize), - padRight(result.getScoreErrorPct(), errorSize), - padRight(result.getUnit(), unitSize), - calculatePerformanceStr(result, alternativeImplementations, resultsByKey) - )); - } - System.out.println("\n"); - } - - private int altImplColSize(String name) { - return Math.max(5, name.length()); - } - - private String calculatePerformanceStr(TestExecution result, Array alternativeImplementations, Map> resultsByKey) { - final String aggregateKey = result.getTestNameParamKey(); - final Array alternativeResults = resultsByKey.get(aggregateKey).getOrElse(Array::empty); - - return alternativeImplementations.map(altImpl -> Tuple.of(altImpl, alternativeResults.find(r -> altImpl.equals(r.getImplementation())))) - .map(alt -> Tuple.of(alt._1, calculateRatioStr(result, alt._2))) - .map(alt -> padRight(alt._2, altImplColSize(alt._1))) - .mkString(" "); - } - - private String calculateRatioStr(TestExecution baseResult, Option alternativeResult) { - if (!alternativeResult.isDefined()) { - return ""; - } - final double alternativeScore = alternativeResult.get().getScore(); - if (alternativeScore == 0.0) { - return ""; - } - final double ratio = baseResult.getScore() / alternativeScore; - return ratio == 1.0 ? "" : PERFORMANCE_FORMAT.format(ratio) + "×"; - } - } - - private class RatioPerformanceReport { - private final Map> resultsByKey; - private final int groupSize; - private final int nameSize; - private final Array paramKeys; - private final int paramKeySize; - private final Array alternativeImplementations; - private final int alternativeImplSize; - private final int ratioSize; - private final Array targetImplementations; - private final String targetImplementation; - - public RatioPerformanceReport(Array results, String targetImplementation) { - this.targetImplementation = targetImplementation; - - resultsByKey = results.groupBy(TestExecution::getTestNameKey); - groupSize = Math.max(results.map(r -> r.getTarget().length()).max().get(), 10); - nameSize = Math.max(results.map(r -> r.getOperation().length()).max().get(), 9); - - paramKeys = results.map(TestExecution::getParamKey).distinct().sorted(TO_STRING_COMPARATOR); - paramKeySize = Math.max(results.map(r -> r.getParamKey().length()).max().get(), 8); - - alternativeImplementations = results.map(TestExecution::getImplementation).distinct(); - targetImplementations = alternativeImplementations.filter(i -> i.toLowerCase().contains(targetImplementation.toLowerCase())); - alternativeImplSize = Math.max(alternativeImplementations.map(String::length).max().getOrElse(0), 10); - - final int targetImplSize = Math.max(targetImplementations.map(String::length).max().getOrElse(0), 10); - ratioSize = Math.max(targetImplSize + 1 + alternativeImplSize, 10); - } - - public void print() { - printHeader(); - printReport(); - } - - private void printHeader() { - System.out.println("\n\n"); - System.out.println("Performance Ratios"); - System.out.println(CharSeq.of("=").repeat(ratioHeaderNumerator().length())); - if (outlierLowPct > 0.0 && outlierHighPct > 0.0) { - System.out.println(String.format(" (Outliers removed: %s low end, %s high end)", PCT_FORMAT.format(outlierLowPct), PCT_FORMAT.format(outlierHighPct))); - } - } - - private String ratioHeaderNumerator() { - final String paramKeyHeader = paramKeys.map(type -> padRight(type, paramKeySize)).mkString(" "); - return String.format("%s %s %s %s ", - padLeft("Target", groupSize), - padLeft("Operation", nameSize), - padLeft("Ratio", ratioSize), - paramKeyHeader - ); - } - - private String ratioHeaderDenominator() { - final String paramKeyHeader = paramKeys.map(type -> padRight(type, paramKeySize)).mkString(" "); - return String.format("%s %s %s %s ", - padLeft("Target", groupSize), - padLeft("Operation", nameSize), - padRight("Ratio", ratioSize), - paramKeyHeader - ); - } - - private void printReport() { - if (alternativeImplementations.size() < 2) { - System.out.println("(nothing to report, you need at least two different implementation)"); - return; - } - - printTargetInDenominator(); - printTargetInNumerator(); - - System.out.println("\n"); - } - - @SuppressWarnings("Convert2MethodRef") - private void printTargetInNumerator() { - System.out.println(String.format("\nRatios %s / ", targetImplementation)); - System.out.println(ratioHeaderNumerator()); - for (String targetImpl : targetImplementations) { - for (Tuple2> execution : resultsByKey) { - printRatioForBaseType(targetImpl, execution._2, - (baseImpl, alternativeImpl) -> padLeft(String.format("%s/%s", baseImpl, alternativeImpl), ratioSize), - (baseExec, alternativeExec) -> calculateRatios(baseExec, alternativeExec)); - } - } - } - - private void printTargetInDenominator() { - System.out.println(String.format("\nRatios / %s", targetImplementation)); - System.out.println(ratioHeaderDenominator()); - for (String targetImpl : targetImplementations) { - for (Tuple2> execution : resultsByKey) { - printRatioForBaseType(targetImpl, execution._2, - (baseImpl, alternativeImpl) -> padRight(String.format("%s/%s", alternativeImpl, baseImpl), ratioSize), - (baseExec, alternativeExec) -> calculateRatios(alternativeExec, baseExec)); - } - } - } - - private void printRatioForBaseType(String baseType, Array testExecutions, - BiFunction ratioNamePrinter, - BiFunction, Array, String> ratioCalculator) { - final Array baseImplExecutions = testExecutions.filter(e -> e.getImplementation().equals(baseType)); - if (baseImplExecutions.isEmpty()) { - return; - } - final TestExecution baseTypeExecution = baseImplExecutions.head(); - - for (String alternativeImpl : alternativeImplementations) { - if (alternativeImpl.equals(baseType)) { - continue; - } - final Array alternativeExecutions = testExecutions.filter(e -> e.getImplementation().equals(alternativeImpl)); - if (alternativeExecutions.isEmpty()) { - continue; - } - System.out.println(String.format("%s %s %s %s", - padLeft(baseTypeExecution.getTarget(), groupSize), - padLeft(baseTypeExecution.getOperation(), nameSize), - ratioNamePrinter.apply(baseType, alternativeImpl), - ratioCalculator.apply(baseImplExecutions, alternativeExecutions))); - } - System.out.println(); - } - - private String calculateRatios(Array alternativeExecutions, Array baseImplExecutions) { - Array ratioStings = Array.empty(); - for (String paramKey : paramKeys) { - final Option alternativeExecution = alternativeExecutions.find(e -> e.getParamKey().equals(paramKey)); - final Option baseExecution = baseImplExecutions.find(e -> e.getParamKey().equals(paramKey)); - final String paramRatio = alternativeExecution.isEmpty() || baseExecution.isEmpty() || baseExecution.get().getScore() == 0.0 - ? "" - : PERFORMANCE_FORMAT.format(alternativeExecution.get().getScore() / baseExecution.get().getScore()) + "×"; - ratioStings = ratioStings.append(padRight(paramRatio, paramKeySize)); - } - return ratioStings.mkString(" "); - } - } - - public static class TestExecution implements Comparable { - private static double outlierLowPct; - private static double outlierHighPct; - private final String paramKey; - private final String fullName; - private final String target; - private final String operation; - private final String implementation; - private final long sampleCount; - private final double score; - private final double scoreError; - private final String unit; - - public static TestExecution of(BenchmarkResult benchmarkResult, double outlierLowPct, double outlierHighPct) { - TestExecution.outlierLowPct = outlierLowPct; - TestExecution.outlierHighPct = outlierHighPct; - return new TestExecution(benchmarkResult); - } - - public TestExecution(BenchmarkResult benchmark) { - final Result primaryResult = benchmark.getPrimaryResult(); - fullName = benchmark.getParams().getBenchmark(); - target = extractPart(fullName, 2); - operation = extractPart(fullName, 1); - implementation = extractPart(fullName, 0); - paramKey = getParameterKey(benchmark); - - final ListStatistics statistics = createStatisticsWithoutOutliers(benchmark, outlierLowPct, outlierHighPct); - sampleCount = statistics.getN(); - score = statistics.getMean(); - scoreError = statistics.getMeanErrorAt(0.999); - unit = primaryResult.getScoreUnit(); - } - - private ListStatistics createStatisticsWithoutOutliers(BenchmarkResult benchmark, double outlierLowPct, double outlierHighPct) { - Array results = benchmark.getIterationResults().stream() - .map(r -> r.getPrimaryResult().getScore()) - .collect(Array.collector()); - final int size = results.size(); - final int outliersLow = (int) (size * outlierLowPct); - final int outliersHigh = (int) (size * outlierHighPct); - results = results.drop(outliersLow).dropRight(outliersHigh); - return new ListStatistics(results.toJavaList().stream().mapToDouble(r -> r).toArray()); - } - - private String getParameterKey(BenchmarkResult benchmarkResult) { - final BenchmarkParams params = benchmarkResult.getParams(); - return params.getParamsKeys().stream().map(params::getParam).collect(Collectors.joining(";")); - } - - public String getTestNameParamKey() { - return target + ":" + operation + ":" + unit + ":" + paramKey; - } - - public String getTestNameKey() { - return target + ":" + operation + ":" + unit; - } - - private String extractPart(String fullyQualifiedName, int indexFromLast) { - final String[] parts = fullyQualifiedName.split("\\."); - return parts.length > indexFromLast ? parts[parts.length - indexFromLast - 1] : ""; - } - - public String getParamKey() { - return paramKey; - } - - public String getTarget() { - return target; - } - - public String getOperation() { - return operation; - } - - public String getImplementation() { - return implementation; - } - - public long getSampleCount() { - return sampleCount; - } - - public double getScore() { - return score; - } - - public String getScoreFormatted() { - return DECIMAL_FORMAT.format(score); - } - - public String getScoreErrorPct() { - return PCT_FORMAT.format(score == 0 ? 0 : scoreError / score); - } - - public String getUnit() { - return unit; - } - - @Override - public String toString() { - return String.format("%s %s %s %s -> %s (± %s)", paramKey, target, operation, implementation, getScoreFormatted(), getScoreErrorPct()); - } - - Comparator comparator = Comparator - .comparing(TestExecution::getUnit) - .thenComparing(TestExecution::getTarget) - .thenComparing(TestExecution::getParamKey) - .thenComparing(TestExecution::getOperation) - .thenComparing(TestExecution::getImplementation); - - @Override - public int compareTo(TestExecution o) { - return comparator.compare(this, o); - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/JmhRunner.java b/vavr-benchmark/src/test/java/io/vavr/JmhRunner.java deleted file mode 100644 index 1a55acf277..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/JmhRunner.java +++ /dev/null @@ -1,226 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr; - -import io.vavr.collection.*; -import io.vavr.control.LazyBenchmark; -import io.vavr.idiom.ForBenchmark; -import io.vavr.idiom.PatternMatchingBenchmark; -import io.vavr.idiom.TryBenchmark; -import io.vavr.idiom.TupleBenchmark; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.results.RunResult; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.ChainedOptionsBuilder; -import org.openjdk.jmh.runner.options.OptionsBuilder; -import org.openjdk.jmh.runner.options.TimeValue; -import org.openjdk.jmh.runner.options.VerboseMode; - -import java.util.Collection; -import java.util.Random; -import java.util.concurrent.TimeUnit; - -import static io.vavr.API.Array; - -public class JmhRunner { - /** - * Runs all the available benchmarks in precision mode. - * Note: it takes about 3 hours. - */ - public static void main(String[] args) { - final Array> CLASSES = Array( - ArrayBenchmark.class, - BitSetBenchmark.class, - CharSeqBenchmark.class, - HashSetBenchmark.class, - ListBenchmark.class, - MapBenchmark.class, - PriorityQueueBenchmark.class, - VectorBenchmark.class, - - LazyBenchmark.class, - - ForBenchmark.class, - PatternMatchingBenchmark.class, - TryBenchmark.class, - TupleBenchmark.class - ); - runDebugWithAsserts(CLASSES); - runSlowNoAsserts(CLASSES); - } - - public enum Includes { - JAVA("java"), - FUNCTIONAL_JAVA("fjava"), - PCOLLECTIONS("pcollections"), - ECOLLECTIONS("ecollections"), - CAPSULE("capsule"), - CLOJURE("clojure"), - SCALAZ("scalaz"), - SCALA("scala"), - VAVR("vavr"); - - private final String name; - - Includes(String name) { this.name = name; } - - @Override - public String toString() { return name; } - } - - /** enables debugging and assertions for benchmarks and production code - the speed results will be totally unreliable */ - public static void runDebugWithAsserts(Array> groups, Includes... includes) { - run(0, 1, 1, ForkJvm.DISABLE, VerboseMode.SILENT, Assertions.ENABLE, PrintInlining.DISABLE, groups, includes); - MemoryUsage.printAndReset(); - } - - @SuppressWarnings("unused") - public static void runQuickNoAsserts(Array> groups, Includes... includes) { - run(5, 5, 10, ForkJvm.ENABLE, VerboseMode.NORMAL, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print(); - } - - @SuppressWarnings("unused") - public static void runNormalNoAsserts(Array> groups, Includes... includes) { - run(7, 7, 300, ForkJvm.ENABLE, VerboseMode.NORMAL, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print(); - } - - @SuppressWarnings("unused") - public static void runSlowNoAsserts(Array> groups, Includes... includes) { - run(15, 15, 400, ForkJvm.ENABLE, VerboseMode.EXTRA, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print(); - } - - private static BenchmarkPerformanceReporter run(int warmupIterations, int measurementIterations, int millis, ForkJvm forkJvm, VerboseMode silent, Assertions assertions, PrintInlining printInlining, Array> groups, Includes[] includes) { - final Array includeNames = Array.of(includes.length == 0 ? Includes.values() : includes).map(Includes::toString); - final Array classNames = groups.map(Class::getCanonicalName); - final Array results = run(warmupIterations, measurementIterations, millis, forkJvm, silent, assertions, printInlining, classNames, includeNames); - return BenchmarkPerformanceReporter.of(includeNames, classNames, results); - } - - private static Array run(int warmupIterations, int measurementIterations, int millis, ForkJvm forkJvm, VerboseMode verboseMode, Assertions assertions, PrintInlining printInlining, Array classNames, Array includeNames) { - try { - final ChainedOptionsBuilder builder = new OptionsBuilder() - .shouldDoGC(true) - .verbosity(verboseMode) - .shouldFailOnError(true) - .mode(Mode.Throughput) - .timeUnit(TimeUnit.SECONDS) - .warmupTime(TimeValue.milliseconds(millis)) - .warmupIterations(warmupIterations) - .measurementTime(TimeValue.milliseconds(millis)) - .measurementIterations(measurementIterations) - .forks(forkJvm.forkCount) - /* We are using 4Gb and setting NewGen to 100% to avoid GC during testing. - Any GC during testing will destroy the iteration (i.e. introduce unreliable noise in the measurement), which should get ignored as an outlier */ - .jvmArgsAppend("-XX:+UseG1GC", "-Xss100m", "-Xms4g", "-Xmx4g", "-XX:MaxGCPauseMillis=1000", "-XX:+UnlockExperimentalVMOptions", "-XX:G1NewSizePercent=100", "-XX:G1MaxNewSizePercent=100", assertions.vmArg); - - final String includePattern = includeNames.mkString("\\..*?\\b(", "|", ")_"); - classNames.forEach(name -> builder.include(name + includePattern)); - - if (printInlining == PrintInlining.ENABLE) { - builder.jvmArgsAppend("-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining"); /* might help in deciding when the JVM is properly warmed up - or where to optimize the code */ - } - - return Array.ofAll(new Runner(builder.build()).run()); - } catch (RunnerException e) { - throw new RuntimeException(e); - } - } - - /* Options */ - private enum ForkJvm { - ENABLE(1), - DISABLE(0); - - final int forkCount; - - ForkJvm(int forkCount) { - this.forkCount = forkCount; - } - } - - private enum Assertions { - ENABLE("-enableassertions"), - DISABLE("-disableassertions"); - - final String vmArg; - - Assertions(String vmArg) { - this.vmArg = vmArg; - } - } - - private enum PrintInlining { - ENABLE, - DISABLE - } - - /* Helper methods */ - - public static Integer[] getRandomValues(int size, int seed) { - return getRandomValues(size, seed, false); - } - - public static Integer[] getRandomValues(int size, int seed, boolean nonNegative) { - return getRandomValues(size, nonNegative, new Random(seed)); - } - - public static Integer[] getRandomValues(int size, boolean nonNegative, Random random) { - final Integer[] results = new Integer[size]; - for (int i = 0; i < size; i++) { - final int value = random.nextInt(size) - (nonNegative ? 0 : (size / 2)); - results[i] = value; - } - return results; - } - - /** Randomly mutate array positions */ - public static int[] shuffle(int[] array, Random random) { - for (int i = array.length; i > 1; i--) { - swap(array, i - 1, random.nextInt(i)); - } - return array; - } - - static void swap(int[] array, int i, int j) { - final int temp = array[i]; - array[i] = array[j]; - array[j] = temp; - } - - /** used for dead code elimination and correctness assertion inside the benchmarks */ - public static int aggregate(int x, int y) { - return x ^ y; - } - - /** simplifies construction of immutable collections - with assertion and memory benchmarking */ - public static , R> R create(Function1 function, T source, Function1 assertion) { - return create(function, source, source.size(), assertion); - } - - @SuppressWarnings("unchecked") - public static R create(Function1 function, T source, int elementCount, Function1 assertion) { - final R result = function.apply(source); - assert assertion.apply(result); - - MemoryUsage.storeMemoryUsages(elementCount, result); - - return result; - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/MemoryUsage.java b/vavr-benchmark/src/test/java/io/vavr/MemoryUsage.java deleted file mode 100644 index 421d63678a..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/MemoryUsage.java +++ /dev/null @@ -1,82 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr; - -import io.vavr.collection.*; -import org.openjdk.jol.info.GraphLayout; - -import java.text.DecimalFormat; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -import static java.lang.Math.max; - -public class MemoryUsage { - private static final DecimalFormat FORMAT = new DecimalFormat("#,##0"); - private static Map>> memoryUsages = TreeMap.empty(); // if forked, this will be reset every time - - /** Calculate the occupied memory of different internals */ - static void printAndReset() { - for (Tuple2>> entry : memoryUsages) { - final Seq columnSizes = columnSizes(entry._1); - System.out.println(String.format("\nfor `%d` elements", entry._1)); - for (Seq stats : entry._2) { - final String format = String.format(" %s → %s bytes", - stats.get(0).padTo(columnSizes.get(0), ' '), - stats.get(1).leftPadTo(columnSizes.get(1), ' ') - ); - System.out.println(format); - } - } - - memoryUsages = memoryUsages.take(0); // reset - } - private static Seq columnSizes(int size) { - return memoryUsages.get(size) - .map(rows -> rows.map(row -> row.map(CharSeq::length))).get() - .reduce((row1, row2) -> row1.zip(row2).map(ts -> max(ts._1, ts._2))); - } - - static void storeMemoryUsages(int elementCount, Object target) { - memoryUsages = memoryUsages.put(elementCount, memoryUsages.get(elementCount).getOrElse(LinkedHashSet.empty()).add(Array.of( - toHumanReadableName(target), - toHumanReadableByteSize(target) - ).map(CharSeq::of))); - } - private static String toHumanReadableByteSize(Object target) { return FORMAT.format(byteSize(target)); } - private static long byteSize(Object target) { return GraphLayout.parseInstance(target).totalSize(); } - - private static HashMap, String> names = HashMap.ofEntries( - Tuple.of("^java\\.", "Java mutable @ "), - Tuple.of("^fj\\.", "Functional Java persistent @ "), - Tuple.of("^org\\.pcollections", "PCollections persistent @ "), - Tuple.of("^org\\.eclipse\\.collections", "Eclipse Collections persistent @ "), - Tuple.of("^clojure\\.", "Clojure persistent @ "), - Tuple.of("^scalaz\\.Heap", "Scalaz persistent @ "), - Tuple.of("^scala\\.collection.immutable", "Scala persistent @ "), - Tuple.of("^scala\\.collection.mutable", "Scala mutable @ "), - Tuple.of("^io\\.usethesource", "Capsule persistent @ "), - Tuple.of("^io\\.vavr\\.", "Vavr persistent @ ") - ).mapKeys(r -> Pattern.compile(r).asPredicate()); - private static String toHumanReadableName(Object target) { - final Class type = target.getClass(); - return prefix(type) + type.getSimpleName(); - } - private static String prefix(Class type) { return names.find(p -> p._1.test(type.getName())).get()._2; } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/ArrayBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/ArrayBenchmark.java deleted file mode 100644 index 3f93867697..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/ArrayBenchmark.java +++ /dev/null @@ -1,419 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import io.vavr.JmhRunner; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; - -import java.util.ArrayList; -import java.util.Objects; - -import static java.util.Arrays.asList; -import static io.vavr.JmhRunner.create; -import static io.vavr.JmhRunner.getRandomValues; -import static io.vavr.collection.Collections.areEqual; - -public class ArrayBenchmark { - static final Array> CLASSES = Array.of( - Create.class, - Head.class, - Tail.class, - Get.class, - Update.class, - Prepend.class, - Append.class, - Iterate.class - , Fill.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - @Param({"10", "100", "1000", "2500"}) - public int CONTAINER_SIZE; - - int EXPECTED_AGGREGATE; - Integer[] ELEMENTS; - - java.util.ArrayList javaMutable; - fj.data.Array fjavaMutable; - io.vavr.collection.Array vavrPersistent; - org.pcollections.PVector pcollVector; - - - @Setup - public void setup() { - ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); - EXPECTED_AGGREGATE = Iterator.of(ELEMENTS).reduce(JmhRunner::aggregate); - - javaMutable = create(java.util.ArrayList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); - fjavaMutable = create(fj.data.Array::array, ELEMENTS, ELEMENTS.length, v -> areEqual(v, asList(ELEMENTS))); - vavrPersistent = create(io.vavr.collection.Array::ofAll, javaMutable, v -> areEqual(v, javaMutable)); - pcollVector = create(org.pcollections.TreePVector::from, javaMutable, v -> areEqual(v, javaMutable)); - } - } - - public static class Create extends Base { - @Benchmark - public Object java_mutable() { - final ArrayList values = new ArrayList<>(javaMutable); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object fjava_persistent() { - final fj.data.Array values = fj.data.Array.iterableArray(javaMutable); - assert areEqual(values, fjavaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent() { - final io.vavr.collection.Array values = io.vavr.collection.Array.ofAll(javaMutable); - assert areEqual(values, vavrPersistent); - return values.head(); - } - - @Benchmark - public Object pcoll_vector() { - final org.pcollections.PVector values = org.pcollections.TreePVector.from(javaMutable); - assert areEqual(values, pcollVector); - return values; - } - } - - public static class Head extends Base { - @Benchmark - public Object java_mutable() { - final Object head = javaMutable.get(0); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object fjava_mutable() { - final Object head = fjavaMutable.get(0); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object vavr_persistent() { - final Object head = vavrPersistent.get(0); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object pcoll_vector() { - final Object head = pcollVector.get(0); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - } - - @SuppressWarnings("Convert2MethodRef") - public static class Tail extends Base { - @State(Scope.Thread) - public static class Initialized { - final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); - - @Setup(Level.Invocation) - public void initializeMutable(Base state) { - java.util.Collections.addAll(javaMutable, state.ELEMENTS); - assert areEqual(javaMutable, asList(state.ELEMENTS)); - } - - @TearDown(Level.Invocation) - public void tearDown() { - javaMutable.clear(); - } - } - - @Benchmark - public Object java_mutable(Initialized state) { - final java.util.ArrayList values = state.javaMutable; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values.remove(0); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Array values = vavrPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object pcoll_vector() { - org.pcollections.PVector values = pcollVector; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.minus(1); - } - assert values.isEmpty(); - return values; - } - } - - public static class Get extends Base { - @Benchmark - public int java_mutable() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= javaMutable.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int fjava_mutable() { - int aggregate = 0; - for (int i = 0; i < ELEMENTS.length; i++) { - aggregate ^= fjavaMutable.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= vavrPersistent.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public Object pcoll_vector() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= pcollVector.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } - - public static class Update extends Base { - @Benchmark - public Object java_mutable() { - final java.util.ArrayList values = javaMutable; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values.set(i, 0); - } - assert Iterator.ofAll(values).forAll(e -> e == 0); - return javaMutable; - } - - @Benchmark - public Object fjava_mutable() { - final fj.data.Array values = fjavaMutable; - for (int i = 0; i < ELEMENTS.length; i++) { - values.set(i, 0); - } - assert values.forall(e -> e == 0); - return fjavaMutable; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Array values = vavrPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.update(i, 0); - } - assert values.forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object pcoll_vector() { - org.pcollections.PVector values = pcollVector; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.with(i, 0); - } - assert Iterator.ofAll(values).forAll(e -> e == 0); - return values; - } - } - - public static class Prepend extends Base { - @Benchmark - public Object java_mutable() { - final java.util.ArrayList values = new java.util.ArrayList<>(CONTAINER_SIZE); - for (Integer element : ELEMENTS) { - values.add(0, element); - } - assert areEqual(List.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object fjava_mutable() { - fj.data.Array values = fj.data.Array.empty(); - for (Integer element : ELEMENTS) { - values = fj.data.Array.array(element).append(values); - } - assert areEqual(values.reverse(), javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Array values = io.vavr.collection.Array.empty(); - for (Integer element : ELEMENTS) { - values = values.prepend(element); - } - assert areEqual(values.reverse(), javaMutable); - return values; - } - - @Benchmark - public Object pcoll_vector() { - org.pcollections.PVector values = org.pcollections.TreePVector.empty(); - for (Integer element : ELEMENTS) { - values = values.plus(0, element); - } - assert areEqual(List.ofAll(values).reverse(), javaMutable); - return values; - } - } - - public static class Append extends Base { - @SuppressWarnings("ManualArrayToCollectionCopy") - @Benchmark - public Object java_mutable() { - final java.util.ArrayList values = new java.util.ArrayList<>(CONTAINER_SIZE); - for (Integer element : ELEMENTS) { - values.add(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object fjava_mutable() { - fj.data.Array values = fj.data.Array.empty(); - for (Integer element : ELEMENTS) { - values = values.append(fj.data.Array.array(element)); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Array values = io.vavr.collection.Array.empty(); - for (Integer element : ELEMENTS) { - values = values.append(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object pcoll_vector() { - org.pcollections.PVector values = org.pcollections.TreePVector.empty(); - for (Integer element : ELEMENTS) { - values = values.plus(element); - } - assert areEqual(values, javaMutable); - return values; - } - } - - @SuppressWarnings("ForLoopReplaceableByForEach") - public static class Iterate extends Base { - @Benchmark - public int java_mutable() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= javaMutable.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int fjava_mutable() { - int aggregate = 0; - for (final java.util.Iterator iterator = fjavaMutable.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (final Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int pcoll_vector() { - int aggregate = 0; - for (final java.util.Iterator iterator = pcollVector.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } - - public static class Fill extends Base { - @Benchmark - public Object vavr_persistent_constant_supplier() { - final io.vavr.collection.Array values = io.vavr.collection.Array.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); - final Integer head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object vavr_persistent_constant_object() { - final io.vavr.collection.Array values = io.vavr.collection.Array.fill(CONTAINER_SIZE, ELEMENTS[0]); - final Integer head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/BitSetBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/BitSetBenchmark.java deleted file mode 100644 index a519777dd8..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/BitSetBenchmark.java +++ /dev/null @@ -1,119 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import io.vavr.JmhRunner; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; - -import static io.vavr.JmhRunner.create; -import static io.vavr.JmhRunner.getRandomValues; -import static io.vavr.collection.Collections.areEqual; -import static scala.collection.JavaConverters.asJavaCollection; -import static scala.collection.JavaConverters.asScalaBuffer; - -public class BitSetBenchmark { - static final Array> CLASSES = Array.of( - AddAll.class, - Iterate.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - @Param({"10", "100", "1000", "2500"}) - public int CONTAINER_SIZE; - - int EXPECTED_AGGREGATE; - int[] ELEMENTS; - TreeSet DISTINCT; - - scala.collection.immutable.BitSet scalaPersistent; - io.vavr.collection.BitSet vavrPersistent; - - @Setup - @SuppressWarnings("RedundantCast") - public void setup() { - final Integer[] values = getRandomValues(CONTAINER_SIZE, 0, true); - ELEMENTS = new int[CONTAINER_SIZE]; - for (int i = 0; i < CONTAINER_SIZE; i++) { - ELEMENTS[i] = values[i]; - } - - DISTINCT = TreeSet.ofAll(ELEMENTS); - EXPECTED_AGGREGATE = DISTINCT.reduce(JmhRunner::aggregate); - - scalaPersistent = create(v -> (scala.collection.immutable.BitSet) scala.collection.immutable.BitSet$.MODULE$.apply(asScalaBuffer(v)), DISTINCT.toJavaList(), v -> areEqual(asJavaCollection(v), DISTINCT)); - vavrPersistent = create(io.vavr.collection.BitSet::ofAll, ELEMENTS, ELEMENTS.length, v -> areEqual(v, DISTINCT)); - } - } - - public static class AddAll extends Base { - @Benchmark - public Object scala_persistent() { - scala.collection.immutable.BitSet values = new scala.collection.immutable.BitSet.BitSet1(0L); - for (int element : ELEMENTS) { - values = values.$plus(element); - } - assert values.equals(scalaPersistent); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Set values = io.vavr.collection.BitSet.empty(); - for (Integer element : ELEMENTS) { - values = values.add(element); - } - assert values.equals(vavrPersistent); - return values; - } - } - - @SuppressWarnings("ForLoopReplaceableByForEach") - public static class Iterate extends Base { - @Benchmark - public int scala_persistent() { - int aggregate = 0; - for (final scala.collection.Iterator iterator = scalaPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= (Integer) iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (final io.vavr.collection.Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/CharSeqBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/CharSeqBenchmark.java deleted file mode 100644 index 5671dc3ca4..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/CharSeqBenchmark.java +++ /dev/null @@ -1,298 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import io.vavr.JmhRunner; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; - -import java.util.Objects; -import java.util.Random; - -import static java.lang.String.valueOf; -import static io.vavr.JmhRunner.create; -import static io.vavr.collection.Collections.areEqual; - -public class CharSeqBenchmark { - static final Array> CLASSES = Array.of( - Head.class, - Tail.class, - Get.class, - Update.class, - Repeat.class, - Prepend.class, - Append.class, - Iterate.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(java.lang.String... args) { - JmhRunner.runDebugWithAsserts(CLASSES); - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - @Param({"10", "100", "1000", "2500"}) - public int CONTAINER_SIZE; - - int EXPECTED_AGGREGATE; - char[] ELEMENTS; - - java.lang.String javaPersistent; - fj.data.LazyString fjavaPersistent; - io.vavr.collection.CharSeq vavrPersistent; - - @Setup - public void setup() { - final Random random = new Random(0); - ELEMENTS = new char[CONTAINER_SIZE]; - for (int i = 0; i < CONTAINER_SIZE; i++) { - ELEMENTS[i] = (char) random.nextInt(Character.MAX_VALUE); - } - EXPECTED_AGGREGATE = Iterator.ofAll(ELEMENTS).reduce((x, y) -> (char) JmhRunner.aggregate((int) x, (int) y)); - - javaPersistent = create(java.lang.String::new, ELEMENTS, ELEMENTS.length, v -> java.util.Arrays.equals(v.toCharArray(), ELEMENTS)); - fjavaPersistent = create(fj.data.LazyString::str, javaPersistent, javaPersistent.length(), v -> Objects.equals(v.toStringEager(), javaPersistent)); - vavrPersistent = create(io.vavr.collection.CharSeq::of, javaPersistent, javaPersistent.length(), v -> v.contentEquals(javaPersistent)); - } - } - - public static class Head extends Base { - @Benchmark - public Object java_persistent() { - final Object head = javaPersistent.charAt(0); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object fjava_persistent() { - final Object head = fjavaPersistent.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object vavr_persistent() { - final Object head = vavrPersistent.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - } - - @SuppressWarnings("Convert2MethodRef") - public static class Tail extends Base { - @Benchmark - public Object java_persistent() { - java.lang.String values = javaPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.substring(1); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.LazyString values = fjavaPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.CharSeq values = vavrPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert values.isEmpty(); - return values; - } - } - - public static class Get extends Base { - @Benchmark - public int java_persistent() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= javaPersistent.charAt(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int fjava_persistent() { - int aggregate = 0; - for (int i = 0; i < ELEMENTS.length; i++) { - aggregate ^= fjavaPersistent.charAt(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= vavrPersistent.charAt(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } - - public static class Update extends Base { - final char replacement = '❤'; - - @Benchmark - public Object java_persistent() { - java.lang.String values = javaPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.substring(0, i) + replacement + values.substring(i + 1); - } - assert Array.ofAll(values.toCharArray()).forAll(c -> c == replacement); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.CharSeq values = vavrPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.update(i, replacement); - } - assert values.forAll(c -> c == replacement); - return values; - } - } - - public static class Repeat extends Base { - final char value = '❤'; - - @Benchmark - public Object vavr_persistent() { - return CharSeq.of(value).repeat(CONTAINER_SIZE); - } - } - - public static class Prepend extends Base { - @Benchmark - public Object java_persistent() { - java.lang.String values = ""; - for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { - values = ELEMENTS[i] + values; - } - assert Objects.equals(values, javaPersistent); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.LazyString values = fj.data.LazyString.empty; - for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { - values = fj.data.LazyString.str(valueOf(ELEMENTS[i])).append(values); - } - assert Objects.equals(values.eval(), javaPersistent); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.CharSeq values = io.vavr.collection.CharSeq.empty(); - for (int i = CONTAINER_SIZE - 1; i >= 0; i--) { - values = values.prepend(ELEMENTS[i]); - } - assert values.contentEquals(vavrPersistent); - return values; - } - } - - public static class Append extends Base { - @Benchmark - public Object java_persistent() { - java.lang.String values = ""; - for (char c : ELEMENTS) { - values = values + c; - } - assert Objects.equals(values, javaPersistent); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.LazyString values = fj.data.LazyString.empty; - for (char c : ELEMENTS) { - values = values.append(valueOf(c)); - } - assert areEqual(values.toStream(), vavrPersistent); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.CharSeq values = io.vavr.collection.CharSeq.empty(); - for (char c : ELEMENTS) { - values = values.append(c); - } - assert values.contentEquals(vavrPersistent); - return values; - } - } - - @SuppressWarnings("ForLoopReplaceableByForEach") - public static class Iterate extends Base { - @Benchmark - public int java_persistent() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= javaPersistent.charAt(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int fjava_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = fjavaPersistent.toStream().iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (final Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/HashSetBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/HashSetBenchmark.java deleted file mode 100644 index fc237276fc..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/HashSetBenchmark.java +++ /dev/null @@ -1,190 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import io.vavr.JmhRunner; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; - -import static io.vavr.JmhRunner.create; -import static io.vavr.JmhRunner.getRandomValues; -import static scala.collection.JavaConverters.asScalaBuffer; - -public class HashSetBenchmark { - static final Array> CLASSES = Array.of( - Add.class, - Iterate.class, - Remove.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - @Param({ "10", "100", "1000", "2500" }) - public int CONTAINER_SIZE; - - int EXPECTED_AGGREGATE; - Integer[] ELEMENTS; - Set SET; - - scala.collection.immutable.Set scalaPersistent; - org.pcollections.PSet pcollectionsPersistent; - io.usethesource.capsule.Set.Immutable capsulePersistent; - io.vavr.collection.Set vavrPersistent; - - @Setup - @SuppressWarnings("unchecked") - public void setup() { - ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); - - SET = TreeSet.of(ELEMENTS); - EXPECTED_AGGREGATE = SET.reduce(JmhRunner::aggregate); - - scalaPersistent = create(v -> (scala.collection.immutable.Set) scala.collection.immutable.HashSet$.MODULE$.apply(asScalaBuffer(v)), SET.toJavaList(), SET.size(), v -> SET.forAll(v::contains)); - pcollectionsPersistent = create(org.pcollections.HashTreePSet::from, SET.toJavaList(), SET.size(), v -> SET.forAll(v::contains)); - capsulePersistent = create(io.usethesource.capsule.util.collection.AbstractSpecialisedImmutableSet::setOf, SET.toJavaSet(), SET.size(), v -> SET.forAll(v::contains)); - vavrPersistent = create(io.vavr.collection.HashSet::ofAll, SET, SET.size(), v -> SET.forAll(v::contains)); - } - } - - public static class Add extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PSet values = org.pcollections.HashTreePSet.empty(); - for (Integer element : ELEMENTS) { - values = values.plus(element); - } - assert SET.forAll(values::contains); - return values; - } - - @Benchmark - public Object scala_persistent() { - scala.collection.immutable.HashSet values = new scala.collection.immutable.HashSet<>(); - for (Integer element : ELEMENTS) { - values = values.$plus(element); - } - assert SET.forAll(values::contains); - return values; - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Set.Immutable values = io.usethesource.capsule.core.PersistentTrieSet.of(); - for (Integer element : ELEMENTS) { - values = values.__insert(element); - } - assert SET.forAll(values::contains); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Set values = io.vavr.collection.HashSet.empty(); - for (Integer element : ELEMENTS) { - values = values.add(element); - } - assert SET.forAll(values::contains); - return values; - } - } - - public static class Remove extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PSet values = pcollectionsPersistent; - for (Integer element : ELEMENTS) { - values = values.minus(element); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Set.Immutable values = capsulePersistent; - for (Integer element : ELEMENTS) { - values = values.__remove(element); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Set values = vavrPersistent; - for (Integer element : ELEMENTS) { - values = values.remove(element); - } - assert values.isEmpty(); - return values; - } - } - - @SuppressWarnings("ForLoopReplaceableByForEach") - public static class Iterate extends Base { - @Benchmark - public int scala_persistent() { - int aggregate = 0; - for (final scala.collection.Iterator iterator = scalaPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int pcollections_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = pcollectionsPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int capsule_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = capsulePersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (final io.vavr.collection.Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/IteratorBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/IteratorBenchmark.java deleted file mode 100644 index b6f36b287d..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/IteratorBenchmark.java +++ /dev/null @@ -1,126 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import io.vavr.JmhRunner; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Param; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.infra.Blackhole; - -import java.util.Random; - -import static io.vavr.JmhRunner.Includes.JAVA; -import static io.vavr.JmhRunner.Includes.SCALA; -import static io.vavr.JmhRunner.Includes.VAVR; -import static io.vavr.JmhRunner.getRandomValues; - -@SuppressWarnings({"ALL", "unchecked", "rawtypes"}) -public class IteratorBenchmark { - - static final Array> CLASSES = Array.of( - Sliding.class, - Concat.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runDebugWithAsserts(CLASSES); - JmhRunner.runNormalNoAsserts(CLASSES, JAVA, SCALA, VAVR); - } - - @State(Scope.Benchmark) - public static class Base { - @Param({"10", "100", "1000", "2500"}) - public int CONTAINER_SIZE; - - Integer[] ELEMENTS; - - scala.collection.Iterator scalaIterator; - io.vavr.collection.Iterator vavrIterator; - - @Setup - public void setup() { - final Random random = new Random(0); - ELEMENTS = getRandomValues(CONTAINER_SIZE, false, random); - scalaIterator = (scala.collection.Iterator) (Object) scala.collection.mutable.WrappedArray$.MODULE$.make(ELEMENTS) - .iterator(); - vavrIterator = Iterator.of(ELEMENTS); - } - } - - public static class Sliding extends Base { - - @Benchmark - public void scala_persistent(Blackhole bh) { - final scala.collection.Iterator.GroupedIterator values = scalaIterator.sliding(3, 1); - while (values.hasNext()) { - bh.consume(values.next()); - } - } - - @Benchmark - public void vavr_persistent(Blackhole bh) { - final Iterator> values = vavrIterator.sliding(3); - while (values.hasNext()) { - bh.consume(values.next()); - } - } - } - - @State(Scope.Benchmark) - public static class Concat { - - @Param({"10", "20", "100", "1000"}) - private int size; - - @Benchmark - public void vavr_persistent(Blackhole bh) { - Iterator iterator = Iterator.range(0, size) - .foldLeft(Iterator.empty(), (result, __) -> result.concat(Iterator.of(1))); - - long sum = 0; - while (iterator.hasNext()) { - sum += iterator.next(); - } - Assertions.assertEquals(size, sum); - } - - @Benchmark - public void scala_persistent(Blackhole bh) { - final scala.collection.Iterator iterator = scala.collection.Iterator.range(0, size) - .foldLeft((scala.collection.Iterator) (Object) scala.collection.Iterator.empty(), - (result, i) -> result.$plus$plus(() -> scala.collection.Iterator.single(1))); - - long sum = 0; - while (iterator.hasNext()) { - sum += iterator.next(); - } - Assertions.assertEquals(size, sum); - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/ListBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/ListBenchmark.java deleted file mode 100644 index de845a7bb3..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/ListBenchmark.java +++ /dev/null @@ -1,680 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import io.vavr.JmhRunner; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Objects; -import java.util.stream.Collectors; - -import static java.util.Arrays.asList; -import static io.vavr.JmhRunner.create; -import static io.vavr.JmhRunner.getRandomValues; -import static io.vavr.collection.Collections.areEqual; -import static scala.collection.JavaConverters.asJavaCollection; -import static scala.collection.JavaConverters.asScalaBuffer; - -public class ListBenchmark { - static final Array> CLASSES = Array.of( - Create.class, - Head.class, - Tail.class, - Get.class, - Update.class, - Prepend.class, - Append.class, - GroupBy.class, - Iterate.class - , Fill.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - @Param({"10", "100", "1000", "2500"}) - public int CONTAINER_SIZE; - - int EXPECTED_AGGREGATE; - Integer[] ELEMENTS; - - /* Only use these for non-mutating operations */ - java.util.ArrayList javaMutable; - java.util.LinkedList javaMutableLinked; - scala.collection.mutable.MutableList scalaMutable; - - fj.data.List fjavaPersistent; - org.pcollections.PStack pcollectionsPersistent; - scala.collection.immutable.List scalaPersistent; - clojure.lang.IPersistentList clojurePersistent; - io.vavr.collection.List vavrPersistent; - - @Setup - @SuppressWarnings("unchecked") - public void setup() { - ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); - EXPECTED_AGGREGATE = Iterator.of(ELEMENTS).reduce(JmhRunner::aggregate); - - javaMutable = create(java.util.ArrayList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); - javaMutableLinked = create(java.util.LinkedList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); - scalaMutable = create(v -> (scala.collection.mutable.MutableList) scala.collection.mutable.MutableList$.MODULE$.apply(asScalaBuffer(v)), asList(ELEMENTS), v -> areEqual(asJavaCollection(v), javaMutable)); - - scalaPersistent = JmhRunner., scala.collection.immutable.List> create( - v -> scala.collection.immutable.List$.MODULE$.apply(asScalaBuffer(v)), - javaMutable, - v -> areEqual(asJavaCollection(v), javaMutable) - ); - clojurePersistent = create(clojure.lang.PersistentList::create, javaMutable, v -> areEqual((Iterable) v, javaMutable)); - fjavaPersistent = create(v -> fj.data.List.fromIterator(v.iterator()), javaMutable, v -> areEqual(v, javaMutable)); - pcollectionsPersistent = create(org.pcollections.ConsPStack::from, javaMutable, v -> areEqual(v, javaMutable)); - vavrPersistent = create(io.vavr.collection.List::ofAll, javaMutable, v -> areEqual(v, javaMutable)); - } - } - - public static class Create extends Base { - @Benchmark - public Object java_mutable() { - final ArrayList values = new ArrayList<>(javaMutable); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object scala_persistent() { - final scala.collection.immutable.List values = scala.collection.immutable.List$.MODULE$.apply(scalaMutable); - assert Objects.equals(values, scalaPersistent); - return values; - } - - @Benchmark - public Object clojure_persistent() { - final clojure.lang.IPersistentStack values = clojure.lang.PersistentList.create(javaMutable); - assert Objects.equals(values, clojurePersistent); - return values; - } - - @Benchmark - public Object fjava_persistent() { - final fj.data.List values = fj.data.List.fromIterator(javaMutable.iterator()); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - final org.pcollections.PStack values = org.pcollections.ConsPStack.from(javaMutable); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent() { - final io.vavr.collection.List values = io.vavr.collection.List.ofAll(javaMutable); - assert areEqual(values, javaMutable); - return values.head(); - } - } - - public static class Head extends Base { - @Benchmark - public Object java_mutable() { - final Object head = javaMutable.get(0); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object scala_persistent() { - final Object head = scalaPersistent.head(); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object clojure_persistent() { - final Object head = clojurePersistent.peek(); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object fjava_persistent() { - final Object head = fjavaPersistent.head(); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object pcollections_persistent() { - final Object head = pcollectionsPersistent.get(0); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object vavr_persistent() { - final Object head = vavrPersistent.head(); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - } - - @SuppressWarnings("Convert2MethodRef") - public static class Tail extends Base { - @State(Scope.Thread) - public static class Initialized { - final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); - final java.util.LinkedList javaMutableLinked = new java.util.LinkedList<>(); - - @Setup(Level.Invocation) - public void initializeMutable(Base state) { - java.util.Collections.addAll(javaMutable, state.ELEMENTS); - javaMutableLinked.addAll(javaMutable); - assert areEqual(javaMutable, asList(state.ELEMENTS)) - && areEqual(javaMutableLinked, javaMutable); - } - - @TearDown(Level.Invocation) - public void tearDown() { - javaMutable.clear(); - javaMutableLinked.clear(); - } - } - - @Benchmark - public Object java_mutable(Initialized state) { - final java.util.ArrayList values = state.javaMutable; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values.remove(0); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object java_linked_mutable(Initialized state) { - final java.util.LinkedList values = state.javaMutableLinked; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values.remove(0); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - @SuppressWarnings({ "unchecked", "RedundantCast" }) - public Object scala_persistent() { - scala.collection.immutable.List values = scalaPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = (scala.collection.immutable.List) values.tail(); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object clojure_persistent() { - clojure.lang.IPersistentStack values = clojurePersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.pop(); - } - assert Objects.equals(values, clojure.lang.PersistentList.EMPTY); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.List values = fjavaPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PStack values = pcollectionsPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.minus(0); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.List values = vavrPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert values.isEmpty(); - return values; - } - } - - public static class Get extends Base { - @Benchmark - public int java_mutable() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= javaMutable.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int java_linked_mutable() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= javaMutableLinked.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int scala_persistent() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= scalaPersistent.apply(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int fjava_persistent() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= fjavaPersistent.index(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int pcollections_persistent() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= pcollectionsPersistent.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (int i = 0; i < CONTAINER_SIZE; i++) { - aggregate ^= vavrPersistent.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } - - public static class Update extends Base { - @State(Scope.Thread) - public static class Initialized { - final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); - final java.util.LinkedList javaMutableLinked = new java.util.LinkedList<>(); - final scala.collection.mutable.MutableList scalaMutable = new scala.collection.mutable.MutableList<>(); - - @Setup(Level.Invocation) - public void initializeMutable(Base state) { - java.util.Collections.addAll(javaMutable, state.ELEMENTS); - java.util.Collections.addAll(javaMutableLinked, state.ELEMENTS); - for (int i = state.CONTAINER_SIZE - 1; i >= 0; i--) { - scalaMutable.prependElem(state.ELEMENTS[i]); - } - - assert areEqual(javaMutable, asList(state.ELEMENTS)) - && areEqual(javaMutableLinked, javaMutable) - && areEqual(asJavaCollection(scalaMutable), javaMutable); - } - - @TearDown(Level.Invocation) - public void tearDown() { - javaMutable.clear(); - javaMutableLinked.clear(); - scalaMutable.clear(); - } - } - - @Benchmark - public Object java_mutable(Initialized state) { - final java.util.ArrayList values = state.javaMutable; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values.set(i, 0); - } - assert Array.ofAll(values).forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object java_linked_mutable(Initialized state) { - final java.util.LinkedList values = state.javaMutableLinked; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values.set(i, 0); - } - assert Array.ofAll(values).forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object scala_mutable(Initialized state) { - final scala.collection.mutable.MutableList values = state.scalaMutable; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values.update(i, 0); - } - assert Array.ofAll(asJavaCollection(values)).forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PStack values = pcollectionsPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.with(i, 0); - } - assert Array.ofAll(values).forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.List values = vavrPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.update(i, 0); - } - assert values.forAll(e -> e == 0); - return values; - } - } - - @SuppressWarnings("ManualArrayToCollectionCopy") - public static class Prepend extends Base { - @Benchmark - public Object java_mutable() { - final java.util.ArrayList values = new java.util.ArrayList<>(CONTAINER_SIZE); - for (Integer element : ELEMENTS) { - values.add(0, element); - } - assert areEqual(Array.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object java_linked_mutable() { - final java.util.LinkedList values = new java.util.LinkedList<>(); - for (Integer element : ELEMENTS) { - values.addFirst(element); - } - assert areEqual(Array.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object scala_mutable() { - final scala.collection.mutable.MutableList values = new scala.collection.mutable.MutableList<>(); - for (Integer element : ELEMENTS) { - values.prependElem(element); - } - assert areEqual(Array.ofAll(asJavaCollection(values)).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object scala_persistent() { - scala.collection.immutable.List values = scala.collection.immutable.List$.MODULE$.empty(); - for (Integer element : ELEMENTS) { - values = values.$colon$colon(element); - } - assert areEqual(Array.ofAll(asJavaCollection(values)).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.List values = fj.data.List.list(); - for (Integer element : ELEMENTS) { - values = values.cons(element); - } - assert areEqual(Array.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PStack values = org.pcollections.ConsPStack.empty(); - for (Integer element : ELEMENTS) { - values = values.plus(element); - } - assert areEqual(Array.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.List values = io.vavr.collection.List.empty(); - for (Integer element : ELEMENTS) { - values = values.prepend(element); - } - assert areEqual(values.reverse(), javaMutable); - return values; - } - } - - @SuppressWarnings("ManualArrayToCollectionCopy") - public static class Append extends Base { - @Benchmark - public Object java_mutable() { - final java.util.ArrayList values = new java.util.ArrayList<>(CONTAINER_SIZE); - for (Integer element : ELEMENTS) { - values.add(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object java_linked_mutable() { - final java.util.LinkedList values = new java.util.LinkedList<>(); - for (Integer element : ELEMENTS) { - values.addLast(element); - } - assert values.size() == CONTAINER_SIZE; - return values; - } - - @Benchmark - public Object scala_mutable() { - final scala.collection.mutable.MutableList values = new scala.collection.mutable.MutableList<>(); - for (Integer element : ELEMENTS) { - values.appendElem(element); - } - assert areEqual(asJavaCollection(values), javaMutable); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.List values = fj.data.List.list(); - for (Integer element : ELEMENTS) { - values = values.snoc(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PStack values = org.pcollections.ConsPStack.empty(); - for (Integer element : ELEMENTS) { - values = values.plus(values.size(), element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.List values = io.vavr.collection.List.empty(); - for (Integer element : ELEMENTS) { - values = values.append(element); - } - assert areEqual(values, javaMutable); - return values; - } - } - - public static class GroupBy extends Base { - @Benchmark - public Object java_mutable() { - return javaMutable.stream().collect(Collectors.groupingBy(Integer::bitCount)); - } - - @Benchmark - public Object scala_persistent() { - return scalaPersistent.groupBy(Integer::bitCount); - } - - @Benchmark - public Object fjava_persistent() { - return fjavaPersistent.groupBy(Integer::bitCount); - } - - @Benchmark - public Object vavr_persistent() { - return vavrPersistent.groupBy(Integer::bitCount); - } - } - - @SuppressWarnings("ForLoopReplaceableByForEach") - public static class Iterate extends Base { - @Benchmark - public int java_mutable() { - int aggregate = 0; - for (final java.util.Iterator iterator = javaMutable.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int java_linked_mutable() { - int aggregate = 0; - for (final java.util.Iterator iterator = javaMutableLinked.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int scala_mutable() { - int aggregate = 0; - for (final scala.collection.Iterator iterator = scalaMutable.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int scala_persistent() { - int aggregate = 0; - for (final scala.collection.Iterator iterator = scalaPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int fjava_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = fjavaPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int pcollections_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = pcollectionsPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } - - public static class Fill extends Base { - @Benchmark - public Object scala_persistent() { - final scala.collection.immutable.List values = scala.collection.immutable.List$.MODULE$.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); - final Object head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object vavr_persistent_constant_supplier() { - final io.vavr.collection.List values = io.vavr.collection.List.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); - final Integer head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object vavr_persistent_constant_object() { - final io.vavr.collection.List values = io.vavr.collection.List.fill(CONTAINER_SIZE, ELEMENTS[0]); - final Integer head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/MapBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/MapBenchmark.java deleted file mode 100644 index 9924c575c8..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/MapBenchmark.java +++ /dev/null @@ -1,771 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import io.vavr.Function1; -import io.vavr.JmhRunner; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.infra.Blackhole; - -import java.util.Arrays; -import java.util.Random; - -import static io.vavr.JmhRunner.create; -import static io.vavr.JmhRunner.getRandomValues; - -public class MapBenchmark { - static final Array> CLASSES = Array.of( - IterateKeys.class, - VavrKeys.class, - VavrValues.class, - IterateValues.class, - Get.class, - Miss.class, - PutOrdered.class, - PutShuffled.class, - ReplaceSingle.class, - ReplaceAll.class, - ReplaceAllOneByOne.class, - Remove.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - @Param({"10", "100", "1000", "2500"}) - public int CONTAINER_SIZE; - - int EXPECTED_AGGREGATE; - Integer[] ELEMENTS; - Integer[] KEYS; - Integer[] REMOVAL; - Map sampleTreeMap; - - // scala.collection.immutable.Map scalaPersistent; - org.pcollections.PMap pcollectionsPersistent; - io.usethesource.capsule.Map.Immutable capsulePersistent; - Map vavrHash; - Map vavrTreeMap; - Map vavrLinkedHash; - - @Setup - public void setup() { - ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); - sampleTreeMap = index(ELEMENTS); - KEYS = predicableShuffle(sampleTreeMap.keySet().toJavaArray(Integer[]::new)); - REMOVAL = predicableShuffle(KEYS.clone()); - EXPECTED_AGGREGATE = sampleTreeMap.values().reduce(JmhRunner::aggregate); - - pcollectionsPersistent = create( - org.pcollections.HashTreePMap::from, - sampleTreeMap.toJavaMap(), - sampleTreeMap.size(), - v -> sampleTreeMap.forAll((e) -> v.get(e._1).equals(e._2))); - capsulePersistent = create( - io.usethesource.capsule.util.collection.AbstractSpecialisedImmutableMap::mapOf, - sampleTreeMap.toJavaMap(), - sampleTreeMap.size(), - v -> sampleTreeMap.forAll((e) -> v.get(e._1).equals(e._2))); - vavrTreeMap = doCreateMap(TreeMap::ofAll, sampleTreeMap); - vavrHash = doCreateMap(HashMap::ofAll, sampleTreeMap); - vavrLinkedHash = doCreateMap(LinkedHashMap::ofAll, sampleTreeMap); - } - - private TreeMap index(Integer[] array) { - java.util.Map javaMap = new java.util.HashMap<>(); - for (int i = 0; i < array.length; i++) { - javaMap.put(i, array[i]); - } - return TreeMap.ofAll(javaMap); - } - - /** - * Shuffle the array. Use a random number generator with a fixed seed. - */ - private Integer[] predicableShuffle(Integer[] array) { - java.util.Collections.shuffle(Arrays.asList(array), new Random(42)); - return array; - } - - private > M doCreateMap(Function1, M> factory, M prototype) { - return create(factory, prototype.toJavaMap(), prototype.size(), v -> prototype.forAll(v::contains)); - } - } - - @SuppressWarnings("Duplicates") - public static class PutShuffled extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PMap values = org.pcollections.HashTreePMap.empty(); - Integer[] elements = ELEMENTS; - for (Integer key : KEYS) { - values = values.plus(key, elements[key]); - } - org.pcollections.PMap result = values; - assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); - return result; - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Map.Immutable values = io.usethesource.capsule.core.PersistentTrieMap.of(); - Integer[] elements = ELEMENTS; - for (Integer key : KEYS) { - values = values.__put(key, elements[key]); - } - io.usethesource.capsule.Map.Immutable result = values; - assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); - return result; - } - - @Benchmark - public Object vavr_tree() { - Map values = TreeMap.empty(); - Integer[] elements = ELEMENTS; - for (Integer key : KEYS) { - values = values.put(key, elements[key]); - } - assert vavrTreeMap.forAll(values::contains); - return values; - } - - @Benchmark - public Object vavr_hash() { - Map values = HashMap.empty(); - Integer[] elements = ELEMENTS; - for (Integer key : KEYS) { - values = values.put(key, elements[key]); - } - assert vavrTreeMap.forAll(values::contains); - return values; - } - - @Benchmark - public Object vavr_linked_hash() { - Map values = LinkedHashMap.empty(); - Integer[] elements = ELEMENTS; - for (Integer key : KEYS) { - values = values.put(key, elements[key]); - } - assert vavrTreeMap.forAll(values::contains); - return values; - } - } - - public static class PutOrdered extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PMap values = org.pcollections.HashTreePMap.empty(); - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.plus(i, elements[i]); - } - org.pcollections.PMap result = values; - assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); - return result; - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Map.Immutable values = io.usethesource.capsule.core.PersistentTrieMap.of(); - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.__put(i, elements[i]); - } - io.usethesource.capsule.Map.Immutable result = values; - assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); - return result; - } - - @Benchmark - public Object vavr_tree() { - Map values = TreeMap.empty(); - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.put(i, elements[i]); - } - assert vavrTreeMap.forAll(values::contains); - return values; - } - - @Benchmark - public Object vavr_hash() { - Map values = HashMap.empty(); - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.put(i, elements[i]); - } - assert vavrTreeMap.forAll(values::contains); - return values; - } - - @Benchmark - public Object vavr_linked_hash() { - Map values = LinkedHashMap.empty(); - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.put(i, elements[i]); - } - assert vavrTreeMap.forAll(values::contains); - return values; - } - } - - public static class Get extends Base { - @Benchmark - public void pcollections_persistent(Blackhole bh) { - org.pcollections.PMap values = pcollectionsPersistent; - for (Integer key : KEYS) { - bh.consume(values.get(key)); - } - } - - @Benchmark - public void capsule_persistent(Blackhole bh) { - io.usethesource.capsule.Map.Immutable values = capsulePersistent; - for (Integer key : KEYS) { - bh.consume(values.get(key)); - } - } - - @Benchmark - public void vavr_tree(Blackhole bh) { - Map values = vavrTreeMap; - Integer dflt = 1; - for (Integer key : KEYS) { - bh.consume(values.getOrElse(key, dflt)); - } - } - - @Benchmark - public void vavr_hash(Blackhole bh) { - Map values = vavrHash; - Integer dflt = 1; - for (Integer key : KEYS) { - bh.consume(values.getOrElse(key, dflt)); - } - } - - @Benchmark - public void vavr_linked_hash(Blackhole bh) { - Map values = vavrLinkedHash; - Integer dflt = 1; - for (Integer key : KEYS) { - bh.consume(values.getOrElse(key, dflt)); - } - } - } - - public static class Miss extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PMap values = pcollectionsPersistent; - return values.get(-1); - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Map.Immutable values = capsulePersistent; - return values.get(-1); - } - - @Benchmark - public Object vavr_tree() { - Map values = vavrTreeMap; - return values.get(-1); - } - - @Benchmark - public Object vavr_hash() { - Map values = vavrHash; - return values.get(-1); - } - - @Benchmark - public Object vavr_linked_hash() { - Map values = vavrLinkedHash; - return values.get(-1); - } - } - - public static class IterateKeys extends Base { - @Benchmark - public void pcollections_persistent(Blackhole bh) { - org.pcollections.PMap values = pcollectionsPersistent; - for (Integer integer : values.keySet()) { - bh.consume(integer); - } - } - - @Benchmark - public void capsule_persistent(Blackhole bh) { - io.usethesource.capsule.Map.Immutable values = capsulePersistent; - for (java.util.Iterator it = values.keyIterator(); it.hasNext(); ) { - bh.consume(it.next()); - } - } - - @Benchmark - public void vavr_tree(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.iterator((k, v) -> k)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_tree_keys(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.keysIterator()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_hash(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.iterator((k, v) -> k)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_hash_keys(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.keysIterator()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_linked_hash(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.iterator((k, v) -> k)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_linked_hash_keys(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.keysIterator()) { - bh.consume(integer); - } - } - } - - public static class VavrKeys extends Base { - @Benchmark - public void vavr_hash_keySet(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.keySet()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_hash_iterator(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.iterator((k, v) -> k)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_hash_keys(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.keysIterator()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_tree_keySet(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.keySet()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_tree_iterator(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.iterator((k, v) -> k)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_tree_keys(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.keysIterator()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_linked_hash_keySet(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.keySet()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_linked_hash_iterator(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.iterator((k, v) -> k)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_linked_hash_keys(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.keysIterator()) { - bh.consume(integer); - } - } - - } - - public static class VavrValues extends Base { - @Benchmark - public void vavr_hash_keySet(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.values()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_hash_iterator(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.iterator((k, v) -> v)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_hash_keys(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.valuesIterator()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_tree_keySet(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.values()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_tree_iterator(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.iterator((k, v) -> v)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_tree_keys(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.valuesIterator()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_linked_hash_keySet(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.values()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_linked_hash_iterator(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.iterator((k, v) -> v)) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_linked_hash_keys(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.valuesIterator()) { - bh.consume(integer); - } - } - - } - - public static class IterateValues extends Base { - @Benchmark - public void pcollections_persistent(Blackhole bh) { - org.pcollections.PMap values = pcollectionsPersistent; - for (Integer integer : values.values()) { - bh.consume(integer); - } - } - - @Benchmark - public void capsule_persistent(Blackhole bh) { - io.usethesource.capsule.Map.Immutable values = capsulePersistent; - for (java.util.Iterator it = values.valueIterator(); it.hasNext(); ) { - bh.consume(it.next()); - } - } - - @Benchmark - public void vavr_tree(Blackhole bh) { - Map values = vavrTreeMap; - for (Integer integer : values.valuesIterator()) { - bh.consume(integer); - } - } - - @Benchmark - public void vavr_hash(Blackhole bh) { - Map values = vavrHash; - for (Integer integer : values.valuesIterator()) { - bh.consume(integer); - } - - } - - @Benchmark - public void vavr_linked_hash(Blackhole bh) { - Map values = vavrLinkedHash; - for (Integer integer : values.valuesIterator()) { - bh.consume(integer); - } - } - } - - @SuppressWarnings("Duplicates") - public static class Remove extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PMap values = pcollectionsPersistent; - for (Integer removeMe : REMOVAL) { - values = values.minus(removeMe); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Map.Immutable values = capsulePersistent; - for (Integer removeMe : REMOVAL) { - values = values.__remove(removeMe); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object vavr_tree() { - Map values = vavrTreeMap; - for (Integer removeMe : REMOVAL) { - values = values.remove(removeMe); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object vavr_hash() { - Map values = vavrHash; - for (Integer removeMe : REMOVAL) { - values = values.remove(removeMe); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object vavr_linked_hash() { - Map values = vavrLinkedHash; - for (Integer removeMe : REMOVAL) { - values = values.remove(removeMe); - } - assert values.isEmpty(); - return values; - } - } - - @SuppressWarnings("Duplicates") - public static class ReplaceSingle extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PMap values = pcollectionsPersistent; - Integer key = REMOVAL[0]; - Integer newValue = ELEMENTS[key] + 1; - values = values.plus(key, newValue); - return values; - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Map.Immutable values = capsulePersistent; - Integer key = REMOVAL[0]; - Integer newValue = ELEMENTS[key] + 1; - values = values.__put(key, newValue); - return values; - } - - @Benchmark - public Object vavr_tree() { - Map values = vavrTreeMap; - Integer key = REMOVAL[0]; - Integer newValue = ELEMENTS[key] + 1; - values = values.put(key, newValue); - return values; - } - - @Benchmark - public Object vavr_hash() { - Map values = vavrHash; - Integer key = REMOVAL[0]; - Integer newValue = ELEMENTS[key] + 1; - values = values.put(key, newValue); - return values; - } - - @Benchmark - public Object vavr_linked_hash() { - Map values = vavrLinkedHash; - Integer key = REMOVAL[0]; - Integer newValue = ELEMENTS[key] + 1; - values = values.put(key, newValue); - return values; - } - } - - @SuppressWarnings("CollectionAddedToSelf") - public static class ReplaceAll extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PMap values = pcollectionsPersistent; - values = values.plusAll(values); - org.pcollections.PMap result = values; - assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); - return values; - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Map.Immutable values = capsulePersistent; - values = values.__putAll(values); - io.usethesource.capsule.Map.Immutable result = values; - assert vavrTreeMap.forAll((e) -> result.get(e._1).equals(e._2)); - return values; - } - - @Benchmark - public Object vavr_tree() { - Map values = vavrTreeMap; - values = values.merge(values, (l, r) -> r); - return values; - } - - @Benchmark - public Object vavr_hash() { - Map values = vavrHash; - values = values.merge(values, (l, r) -> r); - return values; - } - - @Benchmark - public Object vavr_linked_hash() { - Map values = vavrLinkedHash; - values = values.merge(values, (l, r) -> r); - return values; - } - } - - @SuppressWarnings("CollectionAddedToSelf") - public static class ReplaceAllOneByOne extends Base { - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PMap values = pcollectionsPersistent; - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.plus(i, elements[i] + 1); - } - return values; - } - - @Benchmark - public Object capsule_persistent() { - io.usethesource.capsule.Map.Immutable values = capsulePersistent; - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.__put(i, elements[i] + 1); - } - return values; - } - - @Benchmark - public Object vavr_tree() { - Map values = vavrTreeMap; - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.put(i, elements[i] + 1); - } - return values; - } - - @Benchmark - public Object vavr_hash() { - Map values = vavrHash; - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.put(i, elements[i] + 1); - } - return values; - } - - @Benchmark - public Object vavr_linked_hash() { - Map values = vavrLinkedHash; - Integer[] elements = ELEMENTS; - for (int i = 0; i < elements.length; i++) { - values = values.put(i, elements[i] + 1); - } - return values; - } - } - -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/PriorityQueueBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/PriorityQueueBenchmark.java deleted file mode 100644 index 12e33987c8..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/PriorityQueueBenchmark.java +++ /dev/null @@ -1,393 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import fj.P; -import io.vavr.JmhRunner; -import io.vavr.Tuple2; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; -import scala.math.Ordering; -import scala.math.Ordering$; -import scalaz.Heap; -import scalaz.Order; -import scalaz.Order$; - -import java.util.Collections; -import java.util.Objects; - -import static java.util.Arrays.asList; -import static io.vavr.JmhRunner.create; -import static io.vavr.JmhRunner.getRandomValues; -import static scala.collection.JavaConverters.asScalaBuffer; - -@SuppressWarnings({ "UnnecessaryFullyQualifiedName", "UnnecessarilyQualifiedInnerClassAccess" }) -public class PriorityQueueBenchmark { - static final Array> CLASSES = Array.of( - Enqueue.class, - Dequeue.class, - Sort.class - , Fill.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runDebugWithAsserts(CLASSES); - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - static final Ordering SCALA_ORDERING = Ordering$.MODULE$.comparatorToOrdering(Integer::compareTo); - static final Order SCALAZ_ORDER = Order$.MODULE$.fromScalaOrdering(SCALA_ORDERING); - - @Param({"10", "100", "1000", "2500"}) - public int CONTAINER_SIZE; - - int EXPECTED_AGGREGATE; - Integer[] ELEMENTS; - - scalaz.Heap scalazPersistent; - io.vavr.collection.PriorityQueue vavrPersistent; - fj.data.PriorityQueue fjava_persistent; - - @Setup - public void setup() { - ELEMENTS = getRandomValues(CONTAINER_SIZE, 0); - EXPECTED_AGGREGATE = Iterator.of(ELEMENTS).reduce(JmhRunner::aggregate); - - scalazPersistent = create(v -> scalaz.Heap.Empty$.MODULE$. apply().insertAll(asScalaBuffer(v), SCALAZ_ORDER), asList(ELEMENTS), v -> v.size() == CONTAINER_SIZE); - fjava_persistent = create(v -> fj.data.PriorityQueue. emptyInt().enqueue(v), List.of(ELEMENTS).map(v -> P.p(v, v)).toJavaList(), ELEMENTS.length, v -> v.toList().length() == CONTAINER_SIZE); - vavrPersistent = create(io.vavr.collection.PriorityQueue::of, ELEMENTS, ELEMENTS.length, v -> v.size() == CONTAINER_SIZE); - } - } - - public static class Enqueue extends Base { - @Benchmark - @SuppressWarnings({ "Convert2streamapi", "ManualArrayToCollectionCopy" }) - public Object java_mutable() { - final java.util.PriorityQueue values = new java.util.PriorityQueue<>(CONTAINER_SIZE); - for (Integer element : ELEMENTS) { - values.add(element); - } - assert values.size() == CONTAINER_SIZE; - return values; - } - - @Benchmark - @SuppressWarnings({ "Convert2streamapi", "ManualArrayToCollectionCopy" }) - public Object java_blocking_mutable() { - final java.util.concurrent.PriorityBlockingQueue values = new java.util.concurrent.PriorityBlockingQueue<>(CONTAINER_SIZE); - for (Integer element : ELEMENTS) { - values.add(element); - } - assert values.size() == CONTAINER_SIZE; - return values; - } - - @Benchmark - public Object scala_mutable() { - final scala.collection.mutable.PriorityQueue values = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING); - for (Integer element : ELEMENTS) { - values.$plus$eq(element); - } - assert values.size() == CONTAINER_SIZE; - return values; - } - - @Benchmark - public Object scalaz_persistent() { - scalaz.Heap values = scalaz.Heap.Empty$.MODULE$.apply(); - for (Integer element : ELEMENTS) { - values = values.insert(element, SCALAZ_ORDER); - } - assert values.size() == CONTAINER_SIZE; - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.PriorityQueue values = fj.data.PriorityQueue.emptyInt(); - for (Integer element : ELEMENTS) { - values = values.enqueue(element, element); - } - assert values.toList().length() == CONTAINER_SIZE; - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.PriorityQueue values = io.vavr.collection.PriorityQueue.empty(); - for (Integer element : ELEMENTS) { - values = values.enqueue(element); - } - assert values.size() == CONTAINER_SIZE; - return values; - } - } - - @SuppressWarnings("Convert2MethodRef") - public static class Dequeue extends Base { - @State(Scope.Thread) - public static class Initialized { - java.util.PriorityQueue javaMutable = new java.util.PriorityQueue<>(); - java.util.concurrent.PriorityBlockingQueue javaBlockingMutable = new java.util.concurrent.PriorityBlockingQueue<>(); - scala.collection.mutable.PriorityQueue scalaMutable = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING); - - @Setup(Level.Invocation) - public void initializeMutable(Base state) { - Collections.addAll(javaMutable, state.ELEMENTS); - Collections.addAll(javaBlockingMutable, state.ELEMENTS); - for (Integer element : state.ELEMENTS) { - scalaMutable.$plus$eq(element); - } - - assert (javaMutable.size() == state.CONTAINER_SIZE) - && (javaBlockingMutable.size() == state.CONTAINER_SIZE) - && (scalaMutable.size() == state.CONTAINER_SIZE); - } - - @TearDown(Level.Invocation) - public void tearDown() { - javaMutable.clear(); - javaBlockingMutable.clear(); - scalaMutable.clear(); - } - } - - @Benchmark - public Object java_mutable(Initialized state) { - final java.util.PriorityQueue values = state.javaMutable; - - int aggregate = 0; - for (; !values.isEmpty(); values.poll()) { - aggregate ^= values.peek(); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object java_blocking_mutable(Initialized state) { - final java.util.concurrent.PriorityBlockingQueue values = state.javaBlockingMutable; - - int aggregate = 0; - for (; !values.isEmpty(); values.poll()) { - aggregate ^= values.peek(); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object scala_mutable(Initialized state) { - final scala.collection.mutable.PriorityQueue values = state.scalaMutable; - - int aggregate = 0; - while (!values.isEmpty()) { - aggregate ^= values.dequeue(); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object scalaz_persistent() { - scalaz.Heap values = scalazPersistent; - - int aggregate = 0; - while (!values.isEmpty()) { - final scala.Tuple2> uncons = values.uncons().get(); - aggregate ^= uncons._1; - values = uncons._2; - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.PriorityQueue values = fjava_persistent; - - int aggregate = 0; - while (!values.isEmpty()) { - aggregate ^= values.top().some()._1(); - values = values.dequeue(); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.PriorityQueue values = vavrPersistent; - - int aggregate = 0; - while (!values.isEmpty()) { - final Tuple2> dequeue = values.dequeue(); - aggregate ^= dequeue._1; - values = dequeue._2; - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - } - - @SuppressWarnings("Convert2MethodRef") - public static class Sort extends Base { - @Benchmark - @SuppressWarnings("ManualArrayToCollectionCopy") - public Object java_mutable() { - final java.util.PriorityQueue values = new java.util.PriorityQueue<>(CONTAINER_SIZE); - for (Integer element : ELEMENTS) { - values.add(element); - } - assert values.size() == CONTAINER_SIZE; - int aggregate = 0; - for (; !values.isEmpty(); values.poll()) { - aggregate ^= values.peek(); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - @SuppressWarnings("ManualArrayToCollectionCopy") - public Object java_blocking_mutable() { - final java.util.concurrent.PriorityBlockingQueue values = new java.util.concurrent.PriorityBlockingQueue<>(CONTAINER_SIZE); - for (Integer element : ELEMENTS) { - values.add(element); - } - assert values.size() == CONTAINER_SIZE; - int aggregate = 0; - for (; !values.isEmpty(); values.poll()) { - aggregate ^= values.peek(); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - @SuppressWarnings("ManualArrayToCollectionCopy") - public Object java_treeset_mutable() { - io.vavr.collection.TreeMap> values = io.vavr.collection.TreeMap.empty(); - for (Integer element : ELEMENTS) { - final io.vavr.collection.List vs = values.get(element).getOrElse(io.vavr.collection.List.empty()).prepend(element); - values = values.put(element, vs); - } - assert values.values().map(Traversable::size).sum().intValue() == CONTAINER_SIZE; - int aggregate = 0; - while (!values.isEmpty()) { - final Tuple2> min = values.head(); - for (Integer integer : min._2) { - aggregate ^= integer; - } - values = values.remove(min._1); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object scala_mutable() { - scala.collection.mutable.PriorityQueue values = new scala.collection.mutable.PriorityQueue<>(SCALA_ORDERING); - for (Integer element : ELEMENTS) { - values = values.$plus$eq(element); - } - assert values.size() == CONTAINER_SIZE; - int aggregate = 0; - while (!values.isEmpty()) { - aggregate ^= values.dequeue(); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object scalaz_persistent() { - scalaz.Heap values = scalaz.Heap.Empty$.MODULE$.apply(); - for (Integer element : ELEMENTS) { - values = values.insert(element, SCALAZ_ORDER); - } - assert values.size() == CONTAINER_SIZE; - int aggregate = 0; - while (!values.isEmpty()) { - final scala.Tuple2> uncons = values.uncons().get(); - aggregate ^= uncons._1; - values = uncons._2; - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.PriorityQueue values = fj.data.PriorityQueue.emptyInt(); - for (Integer element : ELEMENTS) { - values = values.enqueue(element, element); - } - assert values.toList().length() == CONTAINER_SIZE; - - int aggregate = 0; - while (!values.isEmpty()) { - aggregate ^= values.top().some()._1(); - values = values.dequeue(); - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.PriorityQueue values = io.vavr.collection.PriorityQueue.of(ELEMENTS); - assert values.size() == CONTAINER_SIZE; - - int aggregate = 0; - while (!values.isEmpty()) { - final Tuple2> dequeue = values.dequeue(); - aggregate ^= dequeue._1; - values = dequeue._2; - } - assert values.isEmpty() && (aggregate == EXPECTED_AGGREGATE); - return values; - } - } - - public static class Fill extends Base { - @Benchmark - public Object vavr_persistent_constant_supplier() { - final io.vavr.collection.PriorityQueue values = io.vavr.collection.PriorityQueue.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); - final Integer head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object vavr_persistent_constant_object() { - final io.vavr.collection.PriorityQueue values = io.vavr.collection.PriorityQueue.fill(CONTAINER_SIZE, ELEMENTS[0]); - final Integer head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/collection/VectorBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/collection/VectorBenchmark.java deleted file mode 100644 index 7acbd0316a..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/collection/VectorBenchmark.java +++ /dev/null @@ -1,1066 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.collection; - -import io.vavr.JmhRunner; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.infra.Blackhole; -import scala.collection.generic.CanBuildFrom; -import scala.math.Ordering; -import scala.math.Ordering$; - -import java.util.Comparator; -import java.util.Objects; -import java.util.Random; - -import static java.util.Arrays.asList; -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.toList; -import static io.vavr.JmhRunner.Includes.*; -import static io.vavr.JmhRunner.*; -import static io.vavr.collection.Collections.areEqual; -import static io.vavr.collection.Vector.collector; -import static scala.collection.JavaConverters.asJavaCollection; -import static scala.collection.JavaConverters.asScalaBuffer; - -@SuppressWarnings({ "ALL", "unchecked", "rawtypes" }) -public class VectorBenchmark { - static final Array> CLASSES = Array.of( - Create.class, - Head.class, - Tail.class, - Get.class, - Update.class, - Map.class, - Filter.class, - Prepend.class, - PrependAll.class, - Append.class, - AppendAll.class, - Insert.class, - GroupBy.class, - Slice.class, - Sort.class, - Iterate.class - , Fill.class - ); - - @Test - public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } - - public static void main(String... args) { - JmhRunner.runDebugWithAsserts(CLASSES); - JmhRunner.runNormalNoAsserts(CLASSES, JAVA, FUNCTIONAL_JAVA, PCOLLECTIONS, ECOLLECTIONS, CLOJURE, SCALA, VAVR); - } - - @State(Scope.Benchmark) - public static class Base { - @Param({"10", "100", "1000", "1026", "2500"}) - public int CONTAINER_SIZE; - - int EXPECTED_AGGREGATE; - Integer[] ELEMENTS; - int[] INT_ELEMENTS; - int[] RANDOMIZED_INDICES; - - /* Only use this for non-mutating operations */ - java.util.ArrayList javaMutable; - - fj.data.Seq fjavaPersistent; - org.pcollections.PVector pCollectionsPersistent; - org.eclipse.collections.api.list.ImmutableList eCollectionsPersistent; - clojure.lang.PersistentVector clojurePersistent; - scala.collection.immutable.Vector scalaPersistent; - io.vavr.collection.Vector vavrPersistent; - io.vavr.collection.Vector vavrPersistentInt; - io.vavr.collection.Vector vavrPersistentByte; - - @Setup - public void setup() { - final Random random = new Random(0); - ELEMENTS = getRandomValues(CONTAINER_SIZE, false, random); - INT_ELEMENTS = ArrayType.asPrimitives(int.class, Array.of(ELEMENTS)); - RANDOMIZED_INDICES = shuffle(Array.range(0, CONTAINER_SIZE).toJavaStream().mapToInt(Integer::intValue).toArray(), random); - - EXPECTED_AGGREGATE = Array.of(ELEMENTS).reduce(JmhRunner::aggregate); - - javaMutable = create(java.util.ArrayList::new, asList(ELEMENTS), v -> areEqual(v, asList(ELEMENTS))); - fjavaPersistent = create(fj.data.Seq::fromJavaList, javaMutable, v -> areEqual(v, javaMutable)); - pCollectionsPersistent = create(org.pcollections.TreePVector::from, javaMutable, v -> areEqual(v, javaMutable)); - eCollectionsPersistent = create(org.eclipse.collections.impl.factory.Lists.immutable::ofAll, javaMutable, v -> areEqual(v, javaMutable)); - clojurePersistent = create(clojure.lang.PersistentVector::create, javaMutable, v -> areEqual(v, javaMutable)); - scalaPersistent = create(v -> (scala.collection.immutable.Vector) scala.collection.immutable.Vector$.MODULE$.apply(asScalaBuffer(v)), javaMutable, v -> areEqual(asJavaCollection(v), javaMutable)); - vavrPersistent = create(io.vavr.collection.Vector::ofAll, javaMutable, v -> areEqual(v, javaMutable)); - vavrPersistentInt = create(v -> io.vavr.collection.Vector.ofAll(INT_ELEMENTS), javaMutable, v -> areEqual(v, javaMutable) && (v.trie.type.type() == int.class)); - - final byte[] BYTE_ELEMENTS = new byte[CONTAINER_SIZE]; - random.nextBytes(BYTE_ELEMENTS); - vavrPersistentByte = create(v -> io.vavr.collection.Vector.ofAll(BYTE_ELEMENTS), javaMutable, v -> areEqual(v, Array.ofAll(BYTE_ELEMENTS)) && (v.trie.type.type() == byte.class)); - } - } - - /** Bulk creation from array based, boxed source */ - public static class Create extends Base { - @Benchmark - public Object java_mutable() { - final java.util.List values = new java.util.ArrayList<>(java.util.Arrays.asList(ELEMENTS)); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object java_mutable_boxed() { - final java.util.List values = new java.util.ArrayList<>(); - for (int i = 0; i < CONTAINER_SIZE; i++) { - values.add(INT_ELEMENTS[i]); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object java_mutable_boxed_stream() { - final java.util.List values = java.util.Arrays.stream(INT_ELEMENTS).boxed().collect(toList()); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object fjava_persistent() { - final fj.data.Seq values = fj.data.Seq.fromJavaList(javaMutable); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - final org.pcollections.PVector values = org.pcollections.TreePVector.from(javaMutable); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object ecollections_persistent() { - final org.eclipse.collections.api.list.ImmutableList values = org.eclipse.collections.impl.factory.Lists.immutable.ofAll(javaMutable); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object clojure_persistent() { - final clojure.lang.PersistentVector values = clojure.lang.PersistentVector.create(javaMutable); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object scala_persistent() { - final scala.collection.immutable.Vector values = scala.collection.immutable.Vector$.MODULE$.apply(scalaPersistent); - assert Objects.equals(values, scalaPersistent); - return values; - } - - @Benchmark - public Object vavr_persistent() { - final io.vavr.collection.Vector values = io.vavr.collection.Vector.ofAll(javaMutable); - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent_int() { - final io.vavr.collection.Vector values = io.vavr.collection.Vector.ofAll(INT_ELEMENTS); - assert (values.trie.type.type() == int.class) && areEqual(values, javaMutable); - return values; - } - } - - public static class Head extends Base { - @Benchmark - public Object java_mutable() { - final Object head = javaMutable.get(0); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object fjava_persistent() { - final Object head = fjavaPersistent.head(); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object pcollections_persistent() { - final Object head = pCollectionsPersistent.get(0); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object ecollections_persistent() { - final Object head = eCollectionsPersistent.getFirst(); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object clojure_persistent() { - final Object head = clojurePersistent.nth(0); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object scala_persistent() { - final Object head = scalaPersistent.head(); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - - @Benchmark - public Object vavr_persistent() { - final Object head = vavrPersistent.head(); - assert Objects.equals(head, javaMutable.get(0)); - return head; - } - } - - public static class Tail extends Base { - @State(Scope.Thread) - public static class Initialized { - final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); - - @Setup(Level.Invocation) - public void initializeMutable(Base state) { - java.util.Collections.addAll(javaMutable, state.ELEMENTS); - assert areEqual(javaMutable, asList(state.ELEMENTS)); - } - - @TearDown(Level.Invocation) - public void tearDown() { javaMutable.clear(); } - } - - @Benchmark - public Object java_mutable(Initialized state) { - java.util.List values = state.javaMutable; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.subList(1, values.size()); /* remove(0) would copy everything, but this will slow access down because of nesting */ - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.Seq values = fjavaPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PVector values = pCollectionsPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.minus(0); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object ecollections_persistent() { - org.eclipse.collections.api.list.ImmutableList values = eCollectionsPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.drop(1); - } - assert values.isEmpty() && (values != eCollectionsPersistent); - return values; - } - - @Benchmark - public void clojure_persistent(Blackhole bh) { /* stores the whole collection underneath */ - java.util.List values = clojurePersistent; - while (!values.isEmpty()) { - values = values.subList(1, values.size()); - bh.consume(values); - } - } - - @Benchmark - public Object scala_persistent() { - scala.collection.immutable.Vector values = scalaPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert ((scala.collection.immutable.Seq) values).isEmpty(); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Vector values = vavrPersistent; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert values.isEmpty(); - return values; - } - - @Benchmark - public Object vavr_persistent_int() { - io.vavr.collection.Vector values = vavrPersistentInt; - for (int i = 0; i < CONTAINER_SIZE; i++) { - values = values.tail(); - } - assert values.isEmpty(); - return values; - } - } - - /** Aggregated, randomized access to every element */ - public static class Get extends Base { - @Benchmark - public int java_mutable() { - int aggregate = 0; - for (int i : RANDOMIZED_INDICES) { - aggregate ^= javaMutable.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int fjava_persistent() { - int aggregate = 0; - for (int i : RANDOMIZED_INDICES) { - aggregate ^= fjavaPersistent.index(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int pcollections_persistent() { - int aggregate = 0; - for (int i : RANDOMIZED_INDICES) { - aggregate ^= pCollectionsPersistent.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int ecollections_persistent() { - int aggregate = 0; - for (int i : RANDOMIZED_INDICES) { - aggregate ^= eCollectionsPersistent.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int clojure_persistent() { - int aggregate = 0; - for (int i : RANDOMIZED_INDICES) { - aggregate ^= (int) clojurePersistent.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int scala_persistent() { - int aggregate = 0; - for (int i : RANDOMIZED_INDICES) { - aggregate ^= scalaPersistent.apply(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (int i : RANDOMIZED_INDICES) { - aggregate ^= vavrPersistent.get(i); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - } - - /** Randomized update of every element */ - public static class Update extends Base { - @State(Scope.Thread) - public static class Initialized { - final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); - - @Setup(Level.Invocation) - public void initializeMutable(Base state) { - java.util.Collections.addAll(javaMutable, state.ELEMENTS); - assert areEqual(javaMutable, asList(state.ELEMENTS)); - } - - @TearDown(Level.Invocation) - public void tearDown() { javaMutable.clear(); } - } - - @Benchmark - public Object java_mutable(Initialized state) { - final java.util.ArrayList values = state.javaMutable; - for (int i : RANDOMIZED_INDICES) { - values.set(i, 0); - } - assert Array.ofAll(values).forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.Seq values = fjavaPersistent; - for (int i : RANDOMIZED_INDICES) { - values = values.update(i, 0); - } - assert Array.ofAll(values).forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PVector values = pCollectionsPersistent; - for (int i : RANDOMIZED_INDICES) { - values = values.with(i, 0); - } - assert Array.ofAll(values).forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object ecollections_persistent() { - org.eclipse.collections.api.list.ImmutableList values = eCollectionsPersistent; - for (int i : RANDOMIZED_INDICES) { - final org.eclipse.collections.api.list.MutableList copy = values.toList(); - copy.set(i, 0); - values = copy.toImmutable(); - } - assert Array.ofAll(values).forAll(e -> e == 0) && (values != eCollectionsPersistent); - return values; - } - - @Benchmark - public Object clojure_persistent() { - clojure.lang.PersistentVector values = clojurePersistent; - for (int i : RANDOMIZED_INDICES) { - values = values.assocN(i, 0); - } - assert Array.of(values.toArray()).forAll(e -> Objects.equals(e, 0)); - return values; - } - - @Benchmark - public Object scala_persistent() { - scala.collection.immutable.Vector values = scalaPersistent; - for (int i : RANDOMIZED_INDICES) { - values = values.updateAt(i, 0); - } - assert Array.ofAll(asJavaCollection(values)).forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Vector values = vavrPersistent; - for (int i : RANDOMIZED_INDICES) { - values = values.update(i, 0); - } - assert values.forAll(e -> e == 0); - return values; - } - - @Benchmark - public Object vavr_persistent_int() { - io.vavr.collection.Vector values = vavrPersistentInt; - for (int i : RANDOMIZED_INDICES) { - values = values.update(i, 0); - } - assert (values.trie.type.type() == int.class) && values.forAll(e -> e == 0); - return values; - } - } - - public static class Map extends Base { - final CanBuildFrom canBuildFrom = scala.collection.immutable.Vector.canBuildFrom(); - private static int mapper(int i) { return i + 1; } - - @Benchmark - public Object java_mutable_loop() { - final Integer[] values = ELEMENTS.clone(); - for (int i = 0; i < CONTAINER_SIZE; i++) { - values[i] = mapper(values[i]); - } - assert areEqual(Array.of(values), Array.of(ELEMENTS).map(Map::mapper)); - return values; - } - - @Benchmark - public Object java_mutable() { - final java.util.List values = javaMutable.stream().map(Map::mapper).collect(toList()); - assert areEqual(values, Array.of(ELEMENTS).map(Map::mapper)); - return values; - } - - @Benchmark - public Object ecollections_persistent() { - final org.eclipse.collections.api.list.ImmutableList values = eCollectionsPersistent.collect(Map::mapper); - assert areEqual(values, Array.of(ELEMENTS).map(Map::mapper)); - return values; - } - - @Benchmark - public Object scala_persistent() { - final scala.collection.immutable.Vector values = (scala.collection.immutable.Vector) scalaPersistent.map(Map::mapper, canBuildFrom); - assert areEqual(asJavaCollection(values), Array.of(ELEMENTS).map(Map::mapper)); - return values; - } - - @Benchmark - public Object vavr_persistent() { - final io.vavr.collection.Vector values = vavrPersistent.map(Map::mapper); - assert areEqual(values, Array.of(ELEMENTS).map(Map::mapper)); - return values; - } - - @Benchmark - public Object vavr_persistent_int() { - final io.vavr.collection.Vector values = vavrPersistentInt.map(Map::mapper); - assert areEqual(values, Array.of(ELEMENTS).map(Map::mapper)); - return values; - } - } - - public static class Filter extends Base { - private static boolean isOdd(int i) { return (i & 1) == 1; } - - @Benchmark - public Object java_mutable() { - final java.util.List someValues = javaMutable.stream().filter(Filter::isOdd).collect(toList()); - assert areEqual(someValues, Array.of(ELEMENTS).filter(Filter::isOdd)); - return someValues; - } - - @Benchmark - public Object ecollections_persistent() { - final org.eclipse.collections.api.list.ImmutableList someValues = eCollectionsPersistent.select(Filter::isOdd); - assert areEqual(someValues, Array.of(ELEMENTS).filter(Filter::isOdd)); - return someValues; - } - - @Benchmark - public Object scala_persistent() { - final scala.collection.immutable.Vector someValues = (scala.collection.immutable.Vector) ((scala.collection.Traversable) scalaPersistent).filter(Filter::isOdd); - assert areEqual(asJavaCollection(someValues), Array.of(ELEMENTS).filter(Filter::isOdd)); - return someValues; - } - - @Benchmark - public Object vavr_persistent() { - final io.vavr.collection.Vector someValues = vavrPersistent.filter(Filter::isOdd); - assert areEqual(someValues, Array.of(ELEMENTS).filter(Filter::isOdd)); - return someValues; - } - - @Benchmark - public Object vavr_persistent_int() { - final io.vavr.collection.Vector someValues = vavrPersistentInt.filter(Filter::isOdd); - assert (someValues.trie.type.type() == int.class) && areEqual(someValues, Array.of(ELEMENTS).filter(Filter::isOdd)); - return someValues; - } - } - - public static class Prepend extends Base { - @Benchmark - public Object java_mutable() { - final java.util.ArrayList values = new java.util.ArrayList<>(); /* no initial value, as we're simulating dynamic usage */ - for (Integer element : ELEMENTS) { - values.add(0, element); - } - assert areEqual(Array.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.Seq values = fj.data.Seq.empty(); - for (Integer element : ELEMENTS) { - values = values.cons(element); - } - assert areEqual(Array.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PVector values = org.pcollections.TreePVector.empty(); - for (Integer element : ELEMENTS) { - values = values.plus(0, element); - } - assert areEqual(Array.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object ecollections_persistent() { - org.eclipse.collections.api.list.ImmutableList values = org.eclipse.collections.impl.factory.Lists.immutable.empty(); - for (Integer element : ELEMENTS) { - final org.eclipse.collections.api.list.MutableList copy = values.toList(); - copy.add(0, element); - values = copy.toImmutable(); - } - assert areEqual(values.toReversed(), javaMutable) && (values != eCollectionsPersistent); - return values; - } - - @Benchmark - public Object clojure_persistent() { - clojure.lang.PersistentVector values = clojure.lang.PersistentVector.EMPTY; - for (int i = 0; i < ELEMENTS.length; i++) { - clojure.lang.PersistentVector prepended = clojure.lang.PersistentVector.create(ELEMENTS[i]); - for (Object value : values) { - prepended = prepended.cons(value); /* rebuild everything via append */ - } - values = prepended; - } - assert areEqual(Array.ofAll(values).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object scala_persistent() { - scala.collection.immutable.Vector values = scala.collection.immutable.Vector$.MODULE$.empty(); - for (Integer element : ELEMENTS) { - values = values.appendFront(element); - } - assert areEqual(Array.ofAll(asJavaCollection(values)).reverse(), javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Vector values = io.vavr.collection.Vector.empty(); - for (Integer element : ELEMENTS) { - values = values.prepend(element); - } - assert areEqual(values.reverse(), javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent_int() { - io.vavr.collection.Vector values = io.vavr.collection.Vector.ofAll(ELEMENTS[0]); - for (int i = 1; i < ELEMENTS.length; i++) { - values = values.prepend(ELEMENTS[i]); - } - assert (values.trie.type.type() == int.class) && areEqual(values.reverse(), javaMutable); - return values; - } - } - - public static class PrependAll extends Base { - final CanBuildFrom canBuildFrom = scala.collection.immutable.Vector.canBuildFrom(); - - @Benchmark - public void scala_persistent(Blackhole bh) { - for (int i = 0; i < CONTAINER_SIZE; i++) { - final java.util.List front = javaMutable.subList(0, i); - final scala.collection.immutable.Vector back = scalaPersistent.slice(i, CONTAINER_SIZE); - - scala.collection.immutable.Vector values = back; - for (int j = front.size() - 1; j >= 0; j--) { - values = values.appendFront(front.get(j)); - } - assert areEqual(asJavaCollection(values), javaMutable); - bh.consume(values); - } - } - - @Benchmark - public void vavr_persistent(Blackhole bh) { - for (int i = 0; i < CONTAINER_SIZE; i++) { - final java.util.List front = javaMutable.subList(0, i); - final io.vavr.collection.Vector back = vavrPersistent.slice(i, CONTAINER_SIZE); - final io.vavr.collection.Vector values = back.prependAll(front); - assert areEqual(values, javaMutable); - bh.consume(values); - } - } - } - - /** Add all elements (one-by-one, as we're not testing bulk operations) */ - public static class Append extends Base { - @Benchmark - public Object java_mutable() { - final java.util.ArrayList values = new java.util.ArrayList<>(); /* no initial value as we're simulating dynamic usage */ - for (Integer element : ELEMENTS) { - values.add(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object fjava_persistent() { - fj.data.Seq values = fj.data.Seq.empty(); - for (Integer element : ELEMENTS) { - values = values.snoc(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object ecollections_persistent() { - org.eclipse.collections.api.list.ImmutableList values = org.eclipse.collections.impl.factory.Lists.immutable.empty(); - for (Integer element : ELEMENTS) { - final org.eclipse.collections.api.list.MutableList copy = values.toList(); - copy.add(element); - values = copy.toImmutable(); - } - assert areEqual(values, javaMutable) && (values != eCollectionsPersistent); - return values; - } - - @Benchmark - public Object pcollections_persistent() { - org.pcollections.PVector values = org.pcollections.TreePVector.empty(); - for (Integer element : ELEMENTS) { - values = values.plus(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object clojure_persistent() { - clojure.lang.PersistentVector values = clojure.lang.PersistentVector.EMPTY; - for (Integer element : ELEMENTS) { - values = values.cons(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object scala_persistent() { - scala.collection.immutable.Vector values = scala.collection.immutable.Vector$.MODULE$.empty(); - for (Integer element : ELEMENTS) { - values = values.appendBack(element); - } - assert areEqual(asJavaCollection(values), javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent() { - io.vavr.collection.Vector values = io.vavr.collection.Vector.empty(); - for (Integer element : ELEMENTS) { - values = values.append(element); - } - assert areEqual(values, javaMutable); - return values; - } - - @Benchmark - public Object vavr_persistent_int() { - io.vavr.collection.Vector values = io.vavr.collection.Vector.ofAll(INT_ELEMENTS[0]); - for (int i = 1; i < INT_ELEMENTS.length; i++) { - values = values.append(INT_ELEMENTS[i]); - } - assert (values.trie.type.type() == int.class) && areEqual(values, javaMutable); - return values; - } - } - - public static class AppendAll extends Base { - final CanBuildFrom canBuildFrom = scala.collection.immutable.Vector.canBuildFrom(); - - @Benchmark - public void scala_persistent(Blackhole bh) { - for (int i = 0; i < CONTAINER_SIZE; i++) { - final scala.collection.immutable.Vector front = scalaPersistent.slice(0, i); - final java.util.List back = javaMutable.subList(i, CONTAINER_SIZE); - final scala.collection.immutable.Vector values = front.$plus$plus(asScalaBuffer(back), (CanBuildFrom, Integer, scala.collection.immutable.Vector>) canBuildFrom); - assert areEqual(asJavaCollection(values), javaMutable); - bh.consume(values); - } - } - - @Benchmark - public void vavr_persistent(Blackhole bh) { - for (int i = 0; i < CONTAINER_SIZE; i++) { - final io.vavr.collection.Vector front = vavrPersistent.slice(0, i); - final java.util.List back = javaMutable.subList(i, CONTAINER_SIZE); - final io.vavr.collection.Vector values = front.appendAll(back); - assert areEqual(values, javaMutable); - bh.consume(values); - } - } - } - - public static class Insert extends Base { - @Benchmark - public void vavr_persistent(Blackhole bh) { - for (int i = 0; i < CONTAINER_SIZE; i++) { - final Vector values = vavrPersistent.insert(i, 0); - assert values.size() == CONTAINER_SIZE + 1; - bh.consume(values); - } - } - } - - public static class GroupBy extends Base { - @Benchmark - public Object java_mutable() { return javaMutable.stream().collect(groupingBy(Integer::bitCount)); } - - @Benchmark - public Object scala_persistent() { return scalaPersistent.groupBy(Integer::bitCount); } - - @Benchmark - public Object vavr_persistent() { return vavrPersistent.groupBy(Integer::bitCount); } - } - - /** Consume the vector one-by-one, from the front and back */ - public static class Slice extends Base { - @Benchmark - public void java_mutable(Blackhole bh) { /* stores the whole collection underneath */ - java.util.List values = javaMutable; - while (!values.isEmpty()) { - values = values.subList(1, values.size()); - values = values.subList(0, values.size() - 1); - bh.consume(values); - } - } - - @Benchmark - public void pcollections_persistent(Blackhole bh) { - org.eclipse.collections.api.list.ImmutableList values = eCollectionsPersistent; - for (int i = 1; !values.isEmpty(); i++) { - values = values.subList(1, values.size()); - values = values.subList(0, values.size() - 1); - bh.consume(values); - } - } - - @Benchmark - public void clojure_persistent(Blackhole bh) { /* stores the whole collection underneath */ - java.util.List values = clojurePersistent; - while (!values.isEmpty()) { - values = values.subList(1, values.size()); - values = values.subList(0, values.size() - 1); - bh.consume(values); - } - } - - @Benchmark - public void scala_persistent(Blackhole bh) { - scala.collection.immutable.Vector values = scalaPersistent; - while (!values.isEmpty()) { - values = values.slice(1, values.size()); - values = values.slice(0, values.size() - 1); - bh.consume(values); - } - } - - @Benchmark - public void vavr_persistent(Blackhole bh) { - io.vavr.collection.Vector values = vavrPersistent; - for (int i = 1; !values.isEmpty(); i++) { - values = values.slice(1, values.size()); - values = values.slice(0, values.size() - 1); - bh.consume(values); - } - } - - @Benchmark - public void vavr_persistent_int(Blackhole bh) { - io.vavr.collection.Vector values = this.vavrPersistentInt; - while (!values.isEmpty()) { - values = values.slice(1, values.size()); - values = values.slice(0, values.size() - 1); - bh.consume(values); - } - } - } - - public static class Sort extends Base { - static final Ordering SCALA_ORDERING = Ordering$.MODULE$.comparatorToOrdering(Integer::compareTo); - - @State(Scope.Thread) - public static class Initialized { - final java.util.ArrayList javaMutable = new java.util.ArrayList<>(); - - @Setup(Level.Invocation) - public void initializeMutable(Base state) { - java.util.Collections.addAll(javaMutable, state.ELEMENTS); - assert areEqual(javaMutable, asList(state.ELEMENTS)); - } - - @TearDown(Level.Invocation) - public void tearDown() { javaMutable.clear(); } - } - - @Benchmark - public Object java_mutable(Initialized state) { - state.javaMutable.sort(Comparator.naturalOrder()); - assert areEqual(state.javaMutable, vavrPersistent.sorted()); - return state.javaMutable; - } - - @Benchmark - public Object scala_persistent() { - final scala.collection.Seq results = ((scala.collection.Seq) scalaPersistent).sorted(SCALA_ORDERING); - assert areEqual(asJavaCollection(results), vavrPersistent.sorted()); - return results; - } - - @Benchmark - public Object vavr_persistent() { - final Vector results = vavrPersistent.sorted(); - assert areEqual(results, vavrPersistent.toJavaStream().sorted().collect(collector())); - return results; - } - } - - /** Sequential access for all elements */ - public static class Iterate extends Base { - @Benchmark - public int java_mutable() { - int aggregate = 0; - for (final java.util.Iterator iterator = javaMutable.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int fjava_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = fjavaPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int ecollections_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = eCollectionsPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int pcollections_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = pCollectionsPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int clojure_persistent() { - int aggregate = 0; - for (final java.util.Iterator iterator = clojurePersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int scala_persistent() { - int aggregate = 0; - for (final scala.collection.Iterator iterator = scalaPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent() { - int aggregate = 0; - for (final Iterator iterator = vavrPersistent.iterator(); iterator.hasNext(); ) { - aggregate ^= iterator.next(); - } - assert aggregate == EXPECTED_AGGREGATE; - return aggregate; - } - - @Benchmark - public int vavr_persistent_int() { - final int[] aggregate = { 0 }; - vavrPersistentInt.trie. visit((ordinal, leaf, start, end) -> { - for (int i = start; i < end; i++) { - aggregate[0] ^= leaf[i]; - } - return -1; - }); - assert aggregate[0] == EXPECTED_AGGREGATE; - return aggregate[0]; - } - } - - public static class Fill extends Base { - @Benchmark - public Object scala_persistent() { - final scala.collection.immutable.Vector values = scala.collection.immutable.Vector$.MODULE$.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); - final Object head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object vavr_persistent_constant_supplier() { - final io.vavr.collection.Vector values = io.vavr.collection.Vector.fill(CONTAINER_SIZE, () -> ELEMENTS[0]); - final Integer head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - - @Benchmark - public Object vavr_persistent_constant_object() { - final io.vavr.collection.Vector values = io.vavr.collection.Vector.fill(CONTAINER_SIZE, ELEMENTS[0]); - final Integer head = values.head(); - assert Objects.equals(head, ELEMENTS[0]); - return head; - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/control/LazyBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/control/LazyBenchmark.java deleted file mode 100644 index 074d70e25f..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/control/LazyBenchmark.java +++ /dev/null @@ -1,108 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.control; - -import io.vavr.JmhRunner; -import io.vavr.Lazy; -import io.vavr.collection.Array; -import io.vavr.collection.Iterator; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.infra.Blackhole; - -import static io.vavr.API.Array; -import static io.vavr.JmhRunner.Includes.JAVA; -import static io.vavr.JmhRunner.Includes.VAVR; - -public class LazyBenchmark { - static final Array> CLASSES = Array( - Get.class - ); - - @Test - public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); } - - public static void main(String... args) { - JmhRunner.runDebugWithAsserts(CLASSES, JAVA, VAVR); - JmhRunner.runSlowNoAsserts(CLASSES, JAVA, VAVR); - } - - @State(Scope.Benchmark) - public static class Base { - final int SIZE = 10; - - Integer[] EAGERS; - io.vavr.Lazy[] INITED_LAZIES; - - @Setup - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void setup() { - EAGERS = Iterator.range(0, SIZE).toJavaArray(Integer[]::new); - INITED_LAZIES = Iterator.of(EAGERS).map(i -> { - final Lazy lazy = Lazy.of(() -> i); - lazy.get(); - return lazy; - }).toJavaList().toArray(new Lazy[0]); - } - } - - @Threads(4) - @SuppressWarnings({ "WeakerAccess", "rawtypes" }) - public static class Get extends Base { - @State(Scope.Thread) - public static class Initialized { - io.vavr.Lazy[] LAZIES; - - @Setup(Level.Invocation) - @SuppressWarnings("unchecked") - public void initializeMutable(Base state) { - LAZIES = Iterator.of(state.EAGERS).map(i -> Lazy.of(() -> i)).toJavaList().toArray(new Lazy[0]); - } - } - - @Benchmark - public void java_eager(Blackhole bh) { - int size = SIZE; - Integer[] eagers = EAGERS; - for (int i = 0; i < size; i++) { - bh.consume(eagers[i]); - } - } - - @Benchmark - public void vavr_inited_lazy(Blackhole bh) { - int size = SIZE; - Lazy[] initedLazies = INITED_LAZIES; - for (int i = 0; i < size; i++) { - assert initedLazies[i].isEvaluated(); - bh.consume(initedLazies[i].get()); - } - } - - @Benchmark - public void vavr_lazy(Initialized state, Blackhole bh) { - int size = SIZE; - Lazy[] lazies = state.LAZIES; - for (int i = 0; i < size; i++) { - assert !lazies[i].isEvaluated(); - bh.consume(lazies[i].get()); - } - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/idiom/ForBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/idiom/ForBenchmark.java deleted file mode 100644 index 23ecb916b3..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/idiom/ForBenchmark.java +++ /dev/null @@ -1,101 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.idiom; - -import io.vavr.JmhRunner; -import io.vavr.collection.Array; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.BiFunction; - -import static java.util.stream.Collectors.toList; -import static io.vavr.API.*; -import static io.vavr.JmhRunner.getRandomValues; - -/** - * Benchmark for nested loops vs Vavr's For().yield comprehensions. - * - * @see For2 - */ -public class ForBenchmark { - static final Array> CLASSES = Array( - For.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - int CONTAINER_SIZE = 1000; - int AGGREGATE; - io.vavr.collection.List ELEMENTS; - - final BiFunction AGGREGATOR = (i, j) -> i ^ j; - - @Setup - public void setup() { - ELEMENTS = io.vavr.collection.List.ofAll(Arrays.stream(getRandomValues(CONTAINER_SIZE, 0, true))); - - AGGREGATE = 0; - for (Integer i : ELEMENTS) { - for (Integer j : ELEMENTS) { - AGGREGATE += AGGREGATOR.apply(i, j); - } - } - - } - } - - public static class For extends Base { - @Benchmark - public Object java_for() { - final List result = new ArrayList<>(CONTAINER_SIZE * CONTAINER_SIZE); - for (Integer i : ELEMENTS) { - for (Integer j : ELEMENTS) { - result.add(AGGREGATOR.apply(i, j)); - } - } - - assert Array(result).sum().intValue() == AGGREGATE; - return result; - } - - @Benchmark - public Object vavr_for() { - final List result = For(ELEMENTS, ELEMENTS).yield(AGGREGATOR).collect(toList()); - assert Array(result).sum().intValue() == AGGREGATE; - return result; - } - } - -} diff --git a/vavr-benchmark/src/test/java/io/vavr/idiom/PatternMatchingBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/idiom/PatternMatchingBenchmark.java deleted file mode 100644 index 3b063b09a6..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/idiom/PatternMatchingBenchmark.java +++ /dev/null @@ -1,108 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.idiom; - -import io.vavr.JmhRunner; -import io.vavr.collection.Array; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.infra.Blackhole; - -import java.util.Random; - -import static io.vavr.API.*; - -/** - * Benchmark for nested loops vs Vavr's For().yield comprehensions. - * - * @see For2 - */ -public class PatternMatchingBenchmark { - - static final Array> CLASSES = Array( - MatchVsSwitchIntValues.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class MatchVsSwitchIntValues { - - int[] VALUES; - - @Setup - public void setup() { - final int INSTANCES = 1000; - final int CASES = 5; - VALUES = Array.range(0, INSTANCES).map(i -> new Random(0).nextInt(CASES)).toJavaStream().mapToInt(i -> i).toArray(); - } - - @Benchmark - public void java_switch(Blackhole bh) { - for (int i : VALUES) { - final String result; - switch (i) { - case 0: - result = "0"; - break; - case 1: - result = "1"; - break; - case 2: - result = "2"; - break; - case 3: - result = "3"; - break; - default: - result = "4"; - break; - } - - assert String.valueOf(i).equals(result); - bh.consume(result); - } - } - - @Benchmark - public void vavr_match(Blackhole bh) { - for (int i : VALUES) { - final String result = Match(i).of( - Case($(0), "0"), - Case($(1), "1"), - Case($(2), "2"), - Case($(3), "3"), - Case($(), "4") - ); - assert String.valueOf(i).equals(result); - bh.consume(result); - } - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/idiom/TryBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/idiom/TryBenchmark.java deleted file mode 100644 index fa0627a1a0..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/idiom/TryBenchmark.java +++ /dev/null @@ -1,82 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.idiom; - -import io.vavr.JmhRunner; -import io.vavr.collection.Array; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.infra.Blackhole; - -import static io.vavr.API.Array; -import static io.vavr.API.Try; - -/** - * Benchmark for Try vs try/catch. - */ -public class TryBenchmark { - static final Array> CLASSES = Array( - Try.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - @State(Scope.Benchmark) - public static class Base { - int inverse(int divisor) throws ArithmeticException { return 1 / divisor; } - } - - public static class Try extends Base { - @Benchmark - public void java_try(Blackhole bh) { - for (int i = 0; i <= 1; i++) { - int result; - try { - result = inverse(i); - } catch (ArithmeticException e) { - result = 0; - } - assert result == i; - bh.consume(result); - } - } - - @Benchmark - public void vavr_try(Blackhole bh) { - for (int i = 0; i <= 1; i++) { - int i2 = i; - final int result = Try(() -> inverse(i2)) - .recover(ArithmeticException.class, 0) - .get(); - - assert result == i; - bh.consume(result); - } - } - } -} diff --git a/vavr-benchmark/src/test/java/io/vavr/idiom/TupleBenchmark.java b/vavr-benchmark/src/test/java/io/vavr/idiom/TupleBenchmark.java deleted file mode 100644 index 24a9f02673..0000000000 --- a/vavr-benchmark/src/test/java/io/vavr/idiom/TupleBenchmark.java +++ /dev/null @@ -1,74 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.idiom; - -import io.vavr.JmhRunner; -import io.vavr.Tuple; -import io.vavr.collection.Array; -import org.junit.jupiter.api.Test; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; - -import static io.vavr.API.Array; - -/** - * Benchmark for Tuple[2,4,8] vs an array. - */ -@State(Scope.Benchmark) -public class TupleBenchmark { - static final Array> CLASSES = Array( - Tuple2Benchmark.class, - Tuple4Benchmark.class, - Tuple8Benchmark.class - ); - - @Test - public void testAsserts() { - JmhRunner.runDebugWithAsserts(CLASSES); - } - - public static void main(String... args) { - JmhRunner.runNormalNoAsserts(CLASSES); - } - - public static class Tuple2Benchmark { - @Benchmark - public Object java_tuple() { return new Integer[] { 0, 1 }; } - - @Benchmark - public Object vavr_tuple() { return Tuple.of(0, 1); } - } - - public static class Tuple4Benchmark { - @Benchmark - public Object java_tuple() { return new Integer[] { 0, 1, 2 }; } - - @Benchmark - public Object vavr_tuple() { return Tuple.of(0, 1, 2, 3); } - } - - public static class Tuple8Benchmark { - @Benchmark - public Object java_tuple() { return new Integer[] { 0, 1, 2, 3, 4, 5, 6, 7 }; } - - @Benchmark - public Object vavr_tuple() { return Tuple.of(0, 1, 2, 3, 4, 5, 6, 7); } - } -} diff --git a/vavr-match-processor/pom.xml b/vavr-match-processor/pom.xml deleted file mode 100644 index 09e1ccd720..0000000000 --- a/vavr-match-processor/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - 4.0.0 - - io.vavr - vavr-parent - 0.10.6-SNAPSHOT - ../pom.xml - - vavr-match-processor - jar - Vavr Match Annotation Processor - Processor for structural pattern matching. - https://vavr.io - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - io.vavr - vavr-match - ${project.version} - - - - org.junit.jupiter - junit-jupiter - test - - - org.assertj - assertj-core - test - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - none - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.felix - maven-bundle-plugin - - - org.moditect - moditect-maven-plugin - - - add-module-infos - - add-module-info - - package - - 9 - - - module io.vavr.match.processor { - exports io.vavr.match; - exports io.vavr.match.generator; - exports io.vavr.match.model; - requires io.vavr.match; - } - - - true - - - - - - - diff --git a/vavr-match-processor/src/main/java/io/vavr/match/PatternsProcessor.java b/vavr-match-processor/src/main/java/io/vavr/match/PatternsProcessor.java deleted file mode 100644 index d7ebab5734..0000000000 --- a/vavr-match-processor/src/main/java/io/vavr/match/PatternsProcessor.java +++ /dev/null @@ -1,138 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match; - -import io.vavr.match.annotation.Patterns; -import io.vavr.match.annotation.Unapply; -import io.vavr.match.generator.Generator; -import io.vavr.match.model.ClassModel; -import io.vavr.match.model.MethodModel; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; -import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; -import java.io.IOException; -import java.io.Writer; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import static java.util.stream.Collectors.toList; - -/** - * A code generator for Vavr structural pattern matching patterns. - *

- * Note: - *

- * If javac complains {@code [WARNING] No processor claimed any of these annotations: ...} - * we need to provide the compiler arg {@code -Xlint:-processing}. - *

- * See JDK-6999068 bug. - * - * @author Daniel Dietrich - */ -// See Difference between Element, Type and Mirror: http://stackoverflow.com/a/2127320/1110815 -public class PatternsProcessor extends AbstractProcessor { - - @Override - public Set getSupportedAnnotationTypes() { - // we do not use @SupportedAnnotationTypes in order to be type-safe - return Collections.singleton(Patterns.class.getName()); - } - - @Override - public SourceVersion getSupportedSourceVersion() { - // intended to be used with Java 8+ - return SourceVersion.latestSupported(); - } - - /** - * Gathers annotated elements, transforms elements to a generator model and generates the model to code. - * - * @param annotations the annotation types requested to be processed - * @param roundEnv environment for information about the current and prior round - * @return whether or not the set of annotation types are claimed by this processor - */ - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - if (!annotations.isEmpty()) { - final Set typeElements = roundEnv.getElementsAnnotatedWith(Patterns.class).stream() - .filter(element -> element instanceof TypeElement) - .map(element -> (TypeElement) element) - .collect(Collectors.toSet()); - if (!typeElements.isEmpty()) { - final Set classModels = transform(typeElements); - if (!classModels.isEmpty()) { - generate(classModels); - } - } - } - return true; - } - - // Verify correct usage of annotations @Patterns and @Unapply - private Set transform(Set typeElements) { - final Set classModels = new HashSet<>(); - final javax.lang.model.util.Elements elementUtils = processingEnv.getElementUtils(); - final Messager messager = processingEnv.getMessager(); - for (TypeElement typeElement : typeElements) { - final ClassModel classModel = ClassModel.of(elementUtils, typeElement); - final List methodModels = classModel.getMethods().stream() - .filter(method -> method.isAnnotatedWith(Unapply.class)) - .collect(toList()); - if (methodModels.isEmpty()) { - messager.printMessage(Diagnostic.Kind.WARNING, "No @Unapply methods found.", classModel.typeElement()); - } else { - final boolean methodsValid = methodModels.stream().reduce(true, (bool, method) -> bool && UnapplyChecker.isValid(method.getExecutableElement(), messager), (b1, b2) -> b1 && b2); - if (methodsValid) { - classModels.add(classModel); - } - } - } - return classModels; - } - - // Expands all @Patterns classes - private void generate(Set classModels) { - final Filer filer = processingEnv.getFiler(); - for (ClassModel classModel : classModels) { - final String derivedClassName = deriveClassName(classModel); - final String code = Generator.generate(derivedClassName, classModel); - final String fqn = (classModel.hasDefaultPackage() ? "" : classModel.getPackageName() + ".") + derivedClassName; - try (final Writer writer = filer.createSourceFile(fqn, classModel.typeElement()).openWriter()) { - writer.write(code); - } catch (IOException x) { - throw new Error("Error writing " + fqn, x); - } - } - } - - private String deriveClassName(ClassModel classModel) { - final String name = classModel.getClassName(); - return ("$".equals(name) ? "" : name.endsWith(".$") ? name.substring(0, name.length() - 2) : name) - .replaceAll("\\.", "_") - + Patterns.class.getSimpleName(); - } -} diff --git a/vavr-match-processor/src/main/java/io/vavr/match/UnapplyChecker.java b/vavr-match-processor/src/main/java/io/vavr/match/UnapplyChecker.java deleted file mode 100644 index 53074ddb7a..0000000000 --- a/vavr-match-processor/src/main/java/io/vavr/match/UnapplyChecker.java +++ /dev/null @@ -1,75 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match; - -import javax.annotation.processing.Messager; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.type.TypeKind; -import javax.tools.Diagnostic; -import java.util.Arrays; -import java.util.Set; -import java.util.function.Supplier; - -import static javax.lang.model.element.Modifier.*; - -/** - * Checks if an {@link javax.lang.model.element.ExecutableElement} is a valid {@code @Unapply} method. - * - * @author Daniel Dietrich - */ -class UnapplyChecker { - - static boolean isValid(ExecutableElement elem, Messager messager) { - return ensure(elem, doesNotThrow(elem), messager, () -> "@" + "Unapply method should not throw (checked) exceptions.") && - ensure(elem, !elem.isDefault(), messager, () -> "@" + "Unapply method needs to be declared in a class, not an interface.") && - ensure(elem, !elem.isVarArgs(), messager, () -> "@" + "Unapply method has varargs.") && - ensure(elem, elem.getParameters().size() == 1, messager, () -> "Unapply method must have exactly one parameter of the object to be deconstructed.") && - ensure(elem, elem.getParameters().get(0).asType().getKind() == TypeKind.DECLARED, messager, () -> "Unapply method parameter must be a declared type.") && - ensure(elem, elem.getReturnType().toString().startsWith("io.vavr.Tuple"), messager, () -> "Return type of unapply method must be a Tuple.") && - ensure(elem, !elem.getReturnType().toString().endsWith("Tuple"), messager, () -> "Return type is no Tuple implementation.") && - ensure(elem, hasAll(elem, STATIC), messager, () -> "Unapply method needs to be static.") && - ensure(elem, hasNone(elem, PRIVATE, PROTECTED, ABSTRACT), messager, () -> "Unapply method may not be private or protected."); - } - - private static boolean ensure(ExecutableElement elem, boolean condition, Messager messager, Supplier msg) { - if (!condition) { - messager.printMessage(Diagnostic.Kind.ERROR, msg.get(), elem); - } - return condition; - } - - private static boolean hasAll(ExecutableElement elem, Modifier... modifiers) { - return elem.getModifiers().containsAll(Arrays.asList(modifiers)); - } - - private static boolean hasNone(ExecutableElement elem, Modifier... modifiers) { - final Set set = elem.getModifiers(); - for (Modifier modifier : modifiers) { - if (set.contains(modifier)) { - return false; - } - } - return true; - } - - private static boolean doesNotThrow(ExecutableElement elem) { - return elem.getThrownTypes().isEmpty(); - } -} diff --git a/vavr-match-processor/src/main/java/io/vavr/match/generator/Generator.java b/vavr-match-processor/src/main/java/io/vavr/match/generator/Generator.java deleted file mode 100644 index 2a6161f09d..0000000000 --- a/vavr-match-processor/src/main/java/io/vavr/match/generator/Generator.java +++ /dev/null @@ -1,182 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match.generator; - -import io.vavr.match.annotation.Unapply; -import io.vavr.match.model.ClassModel; -import io.vavr.match.model.MethodModel; -import io.vavr.match.model.TypeParameterModel; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.IntStream; - -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; - -/** - * Code generator for structural pattern matching patterns. - * - * @author Daniel Dietrich - */ -public class Generator { - - private Generator() { - } - - // ENTRY POINT: Expands one @Patterns class - public static String generate(String derivedClassName, ClassModel classModel) { - final List methodModels = classModel.getMethods().stream() - .filter(method -> method.isAnnotatedWith(Unapply.class)) - .collect(toList()); - final String _package = classModel.getPackageName(); - final ImportManager im = ImportManager.forClass(classModel, "io.vavr.API.Match"); - final String methods = generate(im, classModel, methodModels); - return "// @formatter:off\n" + - "// CHECKSTYLE:OFF\n" + - (_package.isEmpty() ? "" : "package " + _package + ";\n\n") + - im.getImports() + - "\n\n// GENERATED BY VAVR <<>> derived from " + classModel.getFullQualifiedName() + "\n\n" + - "@SuppressWarnings(\"deprecation\")\n" + - "public final class " + derivedClassName + " {\n\n" + - " private " + derivedClassName + "() {\n" + - " }\n\n" + - methods + - "}\n" + - "// CHECKSTYLE:ON\n" + - "// @formatter:on"; - } - - // Expands the @Unapply methods of a @Patterns class - private static String generate(ImportManager im, ClassModel classModel, List methodModels) { - final StringBuilder builder = new StringBuilder(); - for (MethodModel methodModel : methodModels) { - generate(im, classModel, methodModel, builder); - builder.append("\n"); - } - return builder.toString(); - } - - // Expands one @Unapply method - private static void generate(ImportManager im, ClassModel classModel, MethodModel methodModel, StringBuilder builder) { - final String paramTypeName = im.getType(methodModel.getParameter(0).getType()); - final String definedName = methodModel.getName(); - final String generatedName = "$" + definedName; - final int arity = Integer.parseInt(methodModel.getReturnType().getClassName().substring("Tuple".length())); - final String body; - if (arity == 0) { - body = pattern(im, 0) + ".of(" + paramTypeName + ".class)"; - } else { - final String args = IntStream.rangeClosed(1, arity).mapToObj(i -> "p" + i).collect(joining(", ")); - final String unapplyRef = classModel.getFullQualifiedName() + "::" + definedName; - body = String.format("%s.of(%s, %s, %s)", pattern(im, arity), paramTypeName + ".class", args, unapplyRef); - } - final List typeArgs = methodModel.getTypeParameters().stream() - .map(typeParameterModel -> mapToName(im, typeParameterModel)) - .collect(toList()); - final List upperBoundArgs = deriveUpperBounds(typeArgs, methodModel.getReturnType().getTypeParameters().size()); - final String returnType = genReturnType(im, methodModel, upperBoundArgs, arity); - final String method; - if (arity == 0 && methodModel.getTypeParameters().size() == 0) { - method = String.format("final %s %s = %s;", returnType, generatedName, body); - } else { - final String generics = genGenerics(im, methodModel, typeArgs, upperBoundArgs); - final String params = genParams(im, upperBoundArgs, arity); - method = String.format("%s %s %s(%s) {\n return %s;\n }", generics, returnType, generatedName, params, body); - } - builder.append(" public static ").append(method).append("\n"); - } - - // Introduces new upper generic type bounds for decomposed object parts - private static List deriveUpperBounds(List typeArgs, int count) { - final List result = new ArrayList<>(); - final Set knownTypeArgs = new HashSet<>(typeArgs); - for (int i = 0; i < count; i++) { - String typeArg = "_" + (i + 1); - while (knownTypeArgs.contains(typeArg)) { - typeArg = "_" + typeArg; - } - result.add(typeArg); - knownTypeArgs.add(typeArg); - } - return result; - } - - // Expands the generics part of a method declaration - private static String genGenerics(ImportManager im, MethodModel methodModel, List typeParameters, List upperBoundArgs) { - final List returnTypeArgs = methodModel.getReturnType().getTypeParameters(); - if (typeParameters.size() + returnTypeArgs.size() == 0) { - return ""; - } else { - final List result = new ArrayList<>(typeParameters); - for (int i = 0; i < returnTypeArgs.size(); i++) { - final String returnTypeArg = mapToName(im, returnTypeArgs.get(i)); - result.add(upperBoundArgs.get(i) + " extends " + returnTypeArg); - } - return result.stream().collect(joining(", ", "<", ">")); - } - } - - // Expands the return type of a method declaration - private static String genReturnType(ImportManager im, MethodModel methodModel, List upperBoundArgs, int arity) { - final List resultTypes = new ArrayList<>(); - final String type = mapToName(im, methodModel.getParameter(0).getType()); - resultTypes.add(type); - resultTypes.addAll(upperBoundArgs); - return pattern(im, arity) + resultTypes.stream().collect(joining(", ", "<", ">")); - } - - // Expands the parameters of a method declaration - private static String genParams(ImportManager im, List upperBoundArgs, int arity) { - final String patternType = im.getType("io.vavr", "API.Match.Pattern"); - return IntStream.range(0, arity) - .mapToObj(i -> patternType + "<" + upperBoundArgs.get(i) + ", ?> p" + (i + 1)) - .collect(joining(", ")); - } - - // Recursively maps generic type parameters to names according to their kind - private static String mapToName(ImportManager im, TypeParameterModel typeParameterModel) { - if (typeParameterModel.isType()) { - return mapToName(im, typeParameterModel.asType()); - } else if (typeParameterModel.isTypeVar()) { - return typeParameterModel.asTypeVar(); - } else { - throw new IllegalStateException("Unhandled type parameter: " + typeParameterModel.toString()); - } - } - - // Recursively maps class generics to names - private static String mapToName(ImportManager im, ClassModel classModel) { - final List typeParameters = classModel.getTypeParameters(); - final String simpleName = im.getType(classModel); - if (typeParameters.size() == 0) { - return simpleName; - } else { - return simpleName + classModel.getTypeParameters().stream() - .map(typeParam -> mapToName(im, typeParam)) - .collect(joining(", ", "<", ">")); - } - } - - private static String pattern(ImportManager im, int arity) { - return im.getType("io.vavr", "API.Match.Pattern" + arity); - } -} diff --git a/vavr-match-processor/src/main/java/io/vavr/match/generator/ImportManager.java b/vavr-match-processor/src/main/java/io/vavr/match/generator/ImportManager.java deleted file mode 100644 index 8866b293ff..0000000000 --- a/vavr-match-processor/src/main/java/io/vavr/match/generator/ImportManager.java +++ /dev/null @@ -1,188 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match.generator; - -import io.vavr.match.model.ClassModel; - -import java.util.*; - -import static java.util.stream.Collectors.joining; - -/** - * A stateful ImportManager which generates an import section of a Java class file. - * - * @author Daniel Dietrich - */ -class ImportManager { - - // properties - private final String packageNameOfClass; - private List directImports; - - // mutable state - private Map imports = new HashMap<>(); - - private ImportManager(String packageNameOfClass, List directImports) { - this.packageNameOfClass = packageNameOfClass; - this.directImports = directImports; - } - - // directImport FQN("io.vavr", "Match.API") will import "io.vavr.Match.API.Pattern0" - // otherwise "io.vavr.Match" is imported and "Match.API.Pattern0" is qualified - public static ImportManager forClass(ClassModel classModel, String... directImports) { - return new ImportManager(classModel.getPackageName(), reverseSort(directImports)); - } - - // used by generator to register non-static imports - public String getType(ClassModel classModel) { - final FQN fqn = new FQN(classModel.getPackageName(), classModel.getClassName()); - return getType(fqn, imports, packageNameOfClass, directImports); - } - - public String getType(String packageName, String className) { - final FQN fqn = new FQN(packageName, className); - return getType(fqn, imports, packageNameOfClass, directImports); - } - - // finally used by generator to get the import section - public String getImports() { - return optimizeImports(imports.values()); - } - - private static String getType(FQN fqn, Map imports, String packageNameOfClass, List directImports) { - if (fqn.packageName.isEmpty() && !packageNameOfClass.isEmpty()) { - throw new IllegalStateException("Can't import class '" + fqn.className + "' located in default package"); - } else if (fqn.packageName.equals(packageNameOfClass)) { - final Import _import = createImport(fqn, directImports); - if (_import.type.equals(fqn.className)) { - return fqn.className; - } else { - imports.put(fqn, _import); - return _import.type; - } - } else if (imports.containsKey(fqn)) { - return imports.get(fqn).type; - } else { - final Import _import = createImport(fqn, directImports); - imports.put(fqn, _import); - return _import.type; - } - } - - private static Import createImport(FQN fqn, List directImports) { - final String qualifiedName = fqn.qualifiedName(); - final Optional directImportOption = directImports.stream() - .filter(directImport -> qualifiedName.equals(directImport) || qualifiedName.startsWith(directImport + ".")) - .findFirst(); - if (directImportOption.isPresent()) { - final String directImport = directImportOption.get(); - if (qualifiedName.equals(directImport)) { - final String type = directImport.substring(directImport.lastIndexOf('.') + 1); - return new Import(directImport, type); - } else { - final String type = qualifiedName.substring(directImport.length() + 1); - final int index = type.indexOf("."); - final String firstSegment = (index < 0) ? type : type.substring(0, index); - return new Import(directImport + "." + firstSegment, type); - } - } else { - final int index = fqn.className.indexOf("."); - final String firstSegment = (index < 0) ? fqn.className : fqn.className.substring(0, index); - return new Import(fqn.packageName + "." + firstSegment, fqn.className); - } - } - - private static String optimizeImports(Collection imports) { - return imports.stream() - .filter(currentImport -> !currentImport.name.startsWith("java.lang.") || - imports.stream() - .filter(otherImport -> !otherImport.equals(currentImport)) - .map(otherImport -> otherImport.type) - .filter(otherType -> otherType.equals(currentImport.type)) - .findFirst().isPresent()) - .map(_import -> _import.name) - .distinct() - .sorted() - .map(s -> "import " + s + ";") - .collect(joining("\n")); - } - - private static List reverseSort(String[] strings) { - final String[] copy = new String[strings.length]; - System.arraycopy(strings, 0, copy, 0, strings.length); - Arrays.sort(copy, Comparator.reverseOrder()); - return Arrays.asList(copy); - } - - private static class FQN { - - private final String packageName; - private final String className; - - FQN(String packageName, String className) { - this.packageName = packageName; - this.className = className; - } - - String qualifiedName() { - return packageName.isEmpty() ? className : packageName + "." + className; - } - - @Override - public boolean equals(Object o) { - return (o == this) || (o instanceof FQN && qualifiedName().equals(((FQN) o).qualifiedName())); - } - - @Override - public int hashCode() { - return qualifiedName().hashCode(); - } - - @Override - public String toString() { - return "FQN(" + packageName + ", " + className + ")"; - } - } - - private static class Import { - - final String name; - final String type; - - Import(String name, String type) { - this.name = name; - this.type = type; - } - - @Override - public boolean equals(Object o) { - return (o == this) || (o instanceof Import && toString().equals(o.toString())); - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - @Override - public String toString() { - return "Import(" + name + ", " + type + ")"; - } - } -} diff --git a/vavr-match-processor/src/main/java/io/vavr/match/model/ClassModel.java b/vavr-match-processor/src/main/java/io/vavr/match/model/ClassModel.java deleted file mode 100644 index a0b2f97fdc..0000000000 --- a/vavr-match-processor/src/main/java/io/vavr/match/model/ClassModel.java +++ /dev/null @@ -1,100 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match.model; - -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.util.Elements; -import java.util.List; - -import static java.util.stream.Collectors.toList; - -/** - * Representation of a class. - * - * @author Daniel Dietrich - */ -public class ClassModel { - - private final Elements elementUtils; - private final DeclaredType declaredType; - - public static ClassModel of(Elements elementUtils, TypeElement typeElement) { - return new ClassModel(elementUtils, (DeclaredType) typeElement.asType()); - } - - public ClassModel(Elements elementUtils, DeclaredType declaredType) { - this.elementUtils = elementUtils; - this.declaredType = declaredType; - } - - public TypeElement typeElement() { - return (TypeElement) declaredType.asElement(); - } - - // returns the simple name for top level class and the combined class name for inner classes - public String getClassName() { - final String fqn = getFullQualifiedName(); - return hasDefaultPackage() ? fqn : fqn.substring(getPackageName().length() + 1); - } - - public String getFullQualifiedName() { - return typeElement().getQualifiedName().toString(); - } - - public List getMethods() { - return typeElement().getEnclosedElements().stream() - .filter(element -> { - final String name = element.getSimpleName().toString(); - return element instanceof ExecutableElement && !name.isEmpty() && !"".equals(name) && !"".equals(name); - }) - .map(element -> new MethodModel(elementUtils, (ExecutableElement) element)) - .collect(toList()); - } - - public String getPackageName() { - return elementUtils.getPackageOf(typeElement()).getQualifiedName().toString(); - } - - public List getTypeParameters() { - return declaredType.getTypeArguments().stream() - .map(typeMirror -> new TypeParameterModel(elementUtils, typeMirror)) - .collect(toList()); - } - - public boolean hasDefaultPackage() { - return elementUtils.getPackageOf(typeElement()).isUnnamed(); - } - - @Override - public boolean equals(Object o) { - return (o == this) || (o instanceof ClassModel && toString().equals(o.toString())); - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - @Override - public String toString() { - return declaredType.toString(); - } -} diff --git a/vavr-match-processor/src/main/java/io/vavr/match/model/MethodModel.java b/vavr-match-processor/src/main/java/io/vavr/match/model/MethodModel.java deleted file mode 100644 index b8ec6fe32c..0000000000 --- a/vavr-match-processor/src/main/java/io/vavr/match/model/MethodModel.java +++ /dev/null @@ -1,89 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match.model; - -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.util.Elements; -import java.lang.annotation.Annotation; -import java.util.List; - -import static java.util.stream.Collectors.toList; - -/** - * Representation of a method. - * - * @author Daniel Dietrich - */ -public class MethodModel { - - private final Elements elementUtils; - private final ExecutableElement executableElement; - - public MethodModel(Elements elementUtils, ExecutableElement executableElement) { - this.elementUtils = elementUtils; - this.executableElement = executableElement; - } - - public ExecutableElement getExecutableElement() { - return executableElement; - } - - public String getName() { - return executableElement.getSimpleName().toString(); - } - - public ParameterModel getParameter(int index) { - final List parameters = executableElement.getParameters(); - if (index < 0 || index > parameters.size()) { - throw new ArrayIndexOutOfBoundsException(index); - } - return new ParameterModel(elementUtils, parameters.get(index)); - } - - public ClassModel getReturnType() { - return new ClassModel(elementUtils, (DeclaredType) executableElement.getReturnType()); - } - - public List getTypeParameters() { - return executableElement.getTypeParameters().stream() - .map(typeParam -> new TypeParameterModel(elementUtils, typeParam.asType())) - .collect(toList()); - } - - public boolean isAnnotatedWith(Class annotationType) { - return executableElement.getAnnotationsByType(annotationType).length > 0; - } - - @Override - public boolean equals(Object o) { - return (o == this) || (o instanceof MethodModel && toString().equals(o.toString())); - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - @Override - public String toString() { - return executableElement.toString(); - } -} diff --git a/vavr-match-processor/src/main/java/io/vavr/match/model/ParameterModel.java b/vavr-match-processor/src/main/java/io/vavr/match/model/ParameterModel.java deleted file mode 100644 index db30c0bad9..0000000000 --- a/vavr-match-processor/src/main/java/io/vavr/match/model/ParameterModel.java +++ /dev/null @@ -1,58 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match.model; - -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.util.Elements; - -/** - * Representation of a method parameter. - * - * @author Daniel Dietrich - */ -public class ParameterModel { - - private final Elements elementUtils; - private final VariableElement variableElement; - - public ParameterModel(Elements elementUtils, VariableElement variableElement) { - this.elementUtils = elementUtils; - this.variableElement = variableElement; - } - - public ClassModel getType() { - return new ClassModel(elementUtils, (DeclaredType) variableElement.asType()); - } - - @Override - public boolean equals(Object o) { - return (o == this) || (o instanceof ParameterModel && toString().equals(o.toString())); - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - @Override - public String toString() { - return variableElement.toString(); - } -} diff --git a/vavr-match-processor/src/main/java/io/vavr/match/model/TypeParameterModel.java b/vavr-match-processor/src/main/java/io/vavr/match/model/TypeParameterModel.java deleted file mode 100644 index f1cc0614ab..0000000000 --- a/vavr-match-processor/src/main/java/io/vavr/match/model/TypeParameterModel.java +++ /dev/null @@ -1,78 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match.model; - -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Elements; - -import static javax.lang.model.type.TypeKind.DECLARED; -import static javax.lang.model.type.TypeKind.TYPEVAR; - -/** - * Representation of a generic type parameter. - * - * @author Daniel Dietrich - */ -public class TypeParameterModel { - - private final Elements elementUtils; - private final TypeMirror typeMirror; - - public TypeParameterModel(Elements elementUtils, TypeMirror typeMirror) { - this.elementUtils = elementUtils; - this.typeMirror = typeMirror; - } - - public ClassModel asType() { - return new ClassModel(elementUtils, (DeclaredType) typeMirror); - } - - public String asTypeVar() { - return typeMirror.toString(); - } - - public boolean isType() { - return isTypeKind(DECLARED); - } - - public boolean isTypeVar() { - return isTypeKind(TYPEVAR); - } - - private boolean isTypeKind(TypeKind typeKind) { - return typeMirror.getKind() == typeKind; - } - - @Override - public boolean equals(Object o) { - return (o == this) || (o instanceof TypeParameterModel && toString().equals(o.toString())); - } - - @Override - public int hashCode() { - return toString().hashCode(); - } - - @Override - public String toString() { - return typeMirror.toString(); - } -} diff --git a/vavr-match-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/vavr-match-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor deleted file mode 100644 index 64038365c2..0000000000 --- a/vavr-match-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ /dev/null @@ -1 +0,0 @@ -io.vavr.match.PatternsProcessor diff --git a/vavr-match/pom.xml b/vavr-match/pom.xml deleted file mode 100644 index d516103714..0000000000 --- a/vavr-match/pom.xml +++ /dev/null @@ -1,66 +0,0 @@ - - 4.0.0 - - io.vavr - vavr-parent - 0.10.6-SNAPSHOT - ../pom.xml - - vavr-match - jar - Vavr Match - Annotation for structural pattern matching. - https://vavr.io - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.felix - maven-bundle-plugin - - - org.moditect - moditect-maven-plugin - - - add-module-infos - - add-module-info - - package - - 9 - - - module io.vavr.match { - exports io.vavr.match.annotation; - } - - - true - - - - - - - diff --git a/vavr-match/src/main/java/io/vavr/match/annotation/Patterns.java b/vavr-match/src/main/java/io/vavr/match/annotation/Patterns.java deleted file mode 100644 index 0aaac2f798..0000000000 --- a/vavr-match/src/main/java/io/vavr/match/annotation/Patterns.java +++ /dev/null @@ -1,34 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Structural pattern matching annotation for pattern declarations. - * - * @author Daniel Dietrich - */ -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.CLASS) -public @interface Patterns { -} diff --git a/vavr-match/src/main/java/io/vavr/match/annotation/Unapply.java b/vavr-match/src/main/java/io/vavr/match/annotation/Unapply.java deleted file mode 100644 index baff111c03..0000000000 --- a/vavr-match/src/main/java/io/vavr/match/annotation/Unapply.java +++ /dev/null @@ -1,34 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.match.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Structural pattern matching annotation for unapply methods. - * - * @author Daniel Dietrich - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.CLASS) -public @interface Unapply { -} diff --git a/vavr-test/generator/Generator.scala b/vavr-test/generator/Generator.scala deleted file mode 100644 index 8c3fd0e7f1..0000000000 --- a/vavr-test/generator/Generator.scala +++ /dev/null @@ -1,1096 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// temporarily needed to circumvent https://issues.scala-lang.org/browse/SI-3772 (see case class Generics) -import Generator._ -import JavaGenerator._ - -import scala.language.implicitConversions - -val N = 8 -val TARGET_MAIN = s"${project.getBasedir()}/src-gen/main/java" -val TARGET_TEST = s"${project.getBasedir()}/src-gen/test/java" -val CHARSET = java.nio.charset.StandardCharsets.UTF_8 - -/** - * ENTRY POINT - */ -def run(): Unit = { - generateMainClasses() - generateTestClasses() -} - -/** - * Generate Vavr src-gen/main/java classes - */ -def generateMainClasses(): Unit = { - - // Workaround: Use /$** instead of /** in a StringContext when IntelliJ IDEA otherwise shows up errors in the editor - val javadoc = "**" - - genPropertyChecks() - - /** - * Generator of io.vavr.test.Property - */ - def genPropertyChecks(): Unit = { - - genVavrFile("io.vavr.test", "Property")(genProperty) - - def genProperty(im: ImportManager, packageName: String, className: String): String = xs""" - /** - * A property builder which provides a fluent API to build checkable properties. - * - * @author Daniel Dietrich - */ - public class $className { - - private final String name; - - private $className(String name) { - this.name = name; - } - - /** - * Defines a new Property. - * - * @param name property name - * @return a new {@code Property} - * @throws NullPointerException if name is null. - * @throws IllegalArgumentException if name is empty or consists of whitespace only - */ - public static Property def(String name) { - ${im.getType("java.util.Objects")}.requireNonNull(name, "name is null"); - if (name.trim().isEmpty()) { - throw new IllegalArgumentException("name is empty"); - } - return new Property(name); - } - - private static void logSatisfied(String name, int tries, long millis, boolean exhausted) { - if (exhausted) { - log(String.format("%s: Exhausted after %s tests in %s ms.", name, tries, millis)); - } else { - log(String.format("%s: OK, passed %s tests in %s ms.", name, tries, millis)); - } - } - - private static void logFalsified(String name, int currentTry, long millis) { - log(String.format("%s: Falsified after %s passed tests in %s ms.", name, currentTry - 1, millis)); - } - - private static void logErroneous(String name, int currentTry, long millis, String errorMessage) { - log(String.format("%s: Errored after %s passed tests in %s ms with message: %s", name, Math.max(0, currentTry - 1), millis, errorMessage)); - } - - private static void log(String msg) { - System.out.println(msg); - } - - /** - * Creates a CheckError caused by an exception when obtaining a generator. - * - * @param position The position of the argument within the argument list of the property, starting with 1. - * @param size The size hint passed to the {@linkplain Arbitrary} which caused the error. - * @param cause The error which occurred when the {@linkplain Arbitrary} tried to obtain the generator {@linkplain Gen}. - * @return a new CheckError instance. - */ - private static CheckError arbitraryError(int position, int size, Throwable cause) { - return new CheckError(String.format("Arbitrary %s of size %s: %s", position, size, cause.getMessage()), cause); - } - - /** - * Creates a CheckError caused by an exception when generating a value. - * - * @param position The position of the argument within the argument list of the property, starting with 1. - * @param size The size hint of the arbitrary which called the generator {@linkplain Gen} which caused the error. - * @param cause The error which occurred when the {@linkplain Gen} tried to generate a random value. - * @return a new CheckError instance. - */ - private static CheckError genError(int position, int size, Throwable cause) { - return new CheckError(String.format("Gen %s of size %s: %s", position, size, cause.getMessage()), cause); - } - - /** - * Creates a CheckError caused by an exception when testing a Predicate. - * - * @param cause The error which occurred when applying the {@linkplain java.util.function.Predicate}. - * @return a new CheckError instance. - */ - private static CheckError predicateError(Throwable cause) { - return new CheckError("Applying predicate: " + cause.getMessage(), cause); - } - - ${(1 to N).gen(i => { - val generics = (1 to i).gen(j => s"T$j")(", ") - val parameters = (1 to i).gen(j => s"a$j")(", ") - val parametersDecl = (1 to i).gen(j => s"Arbitrary a$j")(", ") - xs""" - /$javadoc - * Returns a logical for all quantor of $i given variables. - * - ${(1 to i).gen(j => s"* @param ${j.ordinal} variable type of this for all quantor")("\n")} - ${(1 to i).gen(j => s"* @param a$j ${j.ordinal} variable of this for all quantor")("\n")} - * @return a new {@code ForAll$i} instance of $i variables - */ - public <$generics> ForAll$i<$generics> forAll($parametersDecl) { - return new ForAll$i<>(name, $parameters); - } - """ - })("\n\n")} - - ${(1 to N).gen(i => { - val generics = (1 to i).gen(j => s"T$j")(", ") - val params = (name: String) => (1 to i).gen(j => s"$name$j")(", ") - val parametersDecl = (1 to i).gen(j => s"Arbitrary a$j")(", ") - xs""" - /$javadoc - * Represents a logical for all quantor. - * - ${(1 to i).gen(j => s"* @param ${j.ordinal} variable type of this for all quantor")("\n")} - * @author Daniel Dietrich - */ - public static class ForAll$i<$generics> { - - private final String name; - ${(1 to i).gen(j => xs""" - private final Arbitrary a$j; - """)("\n")} - - ForAll$i(String name, $parametersDecl) { - this.name = name; - ${(1 to i).gen(j => xs""" - this.a$j = a$j; - """)("\n")} - } - - /$javadoc - * Returns a checkable property that checks values of the $i variables of this {@code ForAll} quantor. - * - * @param predicate A $i-ary predicate - * @return a new {@code Property$i} of $i variables. - */ - public Property$i<$generics> suchThat(${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate) { - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Condition> proposition = (${params("t")}) -> new Condition(true, predicate.apply(${params("t")})); - return new Property$i<>(name, ${params("a")}, proposition); - } - } - """ - })("\n\n")} - - ${(1 to N).gen(i => { - - val checkedFunctionType = im.getType(s"io.vavr.CheckedFunction$i") - val optionType = im.getType("io.vavr.control.Option") - val randomType = im.getType("java.util.Random") - val tryType = im.getType("io.vavr.control.Try") - val checkException = "CheckException" - val tupleType = im.getType(s"io.vavr.Tuple") - - val generics = (1 to i).gen(j => s"T$j")(", ") - val params = (paramName: String) => (1 to i).gen(j => s"$paramName$j")(", ") - val parametersDecl = (1 to i).gen(j => s"Arbitrary a$j")(", ") - - xs""" - /$javadoc - * Represents a $i-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property$i<$generics> implements Checkable { - - private final String name; - ${(1 to i).gen(j => xs""" - private final Arbitrary a$j; - """)("\n")} - private final $checkedFunctionType<$generics, Condition> predicate; - - Property$i(String name, $parametersDecl, $checkedFunctionType<$generics, Condition> predicate) { - this.name = name; - ${(1 to i).gen(j => xs""" - this.a$j = a$j; - """)("\n")} - this.predicate = predicate; - } - - /$javadoc - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies($checkedFunctionType<$generics, Boolean> postcondition) { - final $checkedFunctionType<$generics, Condition> implication = (${params("t")}) -> { - final Condition precondition = predicate.apply(${params("t")}); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(${params("t")})); - } - }; - return new Property$i<>(name, ${params("a")}, implication); - } - - @Override - public CheckResult check($randomType random, int size, int tries) { - ${im.getType("java.util.Objects")}.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - ${(1 to i).gen(j => { - s"""final Gen gen$j = $tryType.of(() -> a$j.apply(size)).recover(x -> { throw arbitraryError($j, size, x); }).get();""" - })("\n")} - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - ${(1 to i).gen(j => { - s"""final T$j val$j = $tryType.of(() -> gen$j.apply(random)).recover(x -> { throw genError($j, size, x); }).get();""" - })("\n")} - try { - final Condition condition = $tryType.of(() -> predicate.apply(${(1 to i).gen(j => s"val$j")(", ")})).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, $tupleType.of(${(1 to i).gen(j => s"val$j")(", ")})); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, $optionType.some($tupleType.of(${(1 to i).gen(j => s"val$j")(", ")}))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, $optionType.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, $optionType.none()); - } - } - } - """ - })("\n\n")} - - /** - * Internally used to model conditions composed of pre- and post-condition. - */ - static class Condition { - - static final Condition EX_FALSO_QUODLIBET = new Condition(false, true); - - final boolean precondition; - final boolean postcondition; - - Condition(boolean precondition, boolean postcondition) { - this.precondition = precondition; - this.postcondition = postcondition; - } - - // ¬(p => q) ≡ ¬(¬p ∨ q) ≡ p ∧ ¬q - boolean isFalse() { - return precondition && !postcondition; - } - } - - /** - * Internally used to provide more specific error messages. - */ - static class CheckError extends Error { - - private static final long serialVersionUID = 1L; - - CheckError(String message, Throwable cause) { - super(message, cause); - } - } - } - """ - } -} - -/** - * Generate Vavr src-gen/test/java classes - */ -def generateTestClasses(): Unit = { - - genPropertyCheckTests() - - /** - * Generator of Property-check tests - */ - def genPropertyCheckTests(): Unit = { - genVavrFile("io.vavr.test", "PropertyTest", baseDir = TARGET_TEST)((im: ImportManager, packageName, className) => { - - // main classes - val list = im.getType("io.vavr.collection.List") - val predicate = im.getType("io.vavr.CheckedFunction1") - val random = im.getType("java.util.Random") - val tuple = im.getType("io.vavr.Tuple") - - // test classes - val test = im.getType("org.junit.jupiter.api.Test") - val assertThat = im.getStatic("org.assertj.core.api.Assertions.assertThat") - val assertThrows = im.getStatic("org.junit.jupiter.api.Assertions.assertThrows") - val woops = "yay! (this is a negative test)" - - xs""" - public class $className { - - static $predicate tautology() { - return any -> true; - } - - static $predicate falsum() { - return any -> false; - } - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @$test - public void shouldThrowWhenPropertyNameIsNull() { - $assertThrows(${im.getType("java.lang.NullPointerException")}.class, () -> Property.def(null)); - } - - @$test - public void shouldThrowWhenPropertyNameIsEmpty() { - $assertThrows(${im.getType("java.lang.IllegalArgumentException")}.class, () -> Property.def("")); - } - - // -- Property.check methods - - @$test - public void shouldCheckUsingDefaultConfiguration() { - final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(); - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - } - - @$test - public void shouldCheckGivenSizeAndTries() { - final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(0, 0); - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isTrue(); - } - - @$test - public void shouldThrowOnCheckGivenNegativeTries() { - $assertThrows(${im.getType("java.lang.IllegalArgumentException")}.class, () -> Property.def("test") - .forAll(OBJECTS) - .suchThat(tautology()) - .check(0, -1)); - } - - @$test - public void shouldCheckGivenRandomAndSizeAndTries() { - final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(new $random(), 0, 0); - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isTrue(); - } - - // -- satisfaction - - @$test - public void shouldCheckPythagoras() { - - final Arbitrary real = n -> Gen.choose(0, (double) n).filter(d -> d > .0d); - - // (∀a,b ∈ ℝ+ ∃c ∈ ℝ+ : a²+b²=c²) ≡ (∀a,b ∈ ℝ+ : √(a²+b²) ∈ ℝ+) - final Checkable property = Property.def("test").forAll(real, real).suchThat((a, b) -> Math.sqrt(a * a + b * b) > .0d); - final CheckResult result = property.check(); - - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - } - - @$test - public void shouldCheckZipAndThenUnzipIsIdempotentForListsOfSameLength() { - // ∀is,ss: length(is) = length(ss) → unzip(zip(is, ss)) = (is, ss) - final Arbitrary<$list> ints = Arbitrary.list(size -> Gen.choose(0, size)); - final Arbitrary<$list> strings = Arbitrary.list( - Arbitrary.string( - Gen.frequency( - Tuple.of(1, Gen.choose('A', 'Z')), - Tuple.of(1, Gen.choose('a', 'z')), - Tuple.of(1, Gen.choose('0', '9')) - ))); - final CheckResult result = Property.def("test") - .forAll(ints, strings) - .suchThat((is, ss) -> is.length() == ss.length()) - .implies((is, ss) -> is.zip(ss).unzip(t -> t).equals($tuple.of(is, ss))) - .check(); - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - } - - // -- exhausting - - @$test - public void shouldRecognizeExhaustedParameters() { - final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(falsum()).implies(tautology()).check(); - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isTrue(); - } - - // -- falsification - - @$test - public void shouldFalsifyFalseProperty() { - final Arbitrary ones = n -> random -> 1; - final CheckResult result = Property.def("test").forAll(ones).suchThat(one -> one == 2).check(); - $assertThat(result.isFalsified()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - $assertThat(result.count()).isEqualTo(1); - } - - // -- error detection - - @$test - public void shouldRecognizeArbitraryError() { - final Arbitrary arbitrary = n -> { throw new RuntimeException("$woops"); }; - final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check(); - $assertThat(result.isErroneous()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - $assertThat(result.count()).isEqualTo(0); - $assertThat(result.sample().isEmpty()).isTrue(); - } - - @$test - public void shouldRecognizeGenError() { - final Arbitrary arbitrary = Gen.fail("$woops").arbitrary(); - final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check(); - $assertThat(result.isErroneous()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - $assertThat(result.count()).isEqualTo(1); - $assertThat(result.sample().isEmpty()).isTrue(); - } - - @$test - public void shouldRecognizePropertyError() { - final Arbitrary a1 = n -> random -> 1; - final Arbitrary a2 = n -> random -> 2; - final CheckResult result = Property.def("test").forAll(a1, a2).suchThat((a, b) -> { - throw new RuntimeException("$woops"); - }).check(); - $assertThat(result.isErroneous()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - $assertThat(result.count()).isEqualTo(1); - $assertThat(result.sample().isDefined()).isTrue(); - $assertThat(result.sample().get()).isEqualTo(Tuple.of(1, 2)); - } - - // -- Property.and tests - - @$test - public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final CheckResult result = p1.and(p2).check(); - $assertThat(result.isSatisfied()).isTrue(); - } - - @$test - public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final CheckResult result = p1.and(p2).check(); - $assertThat(result.isSatisfied()).isFalse(); - } - - @$test - public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final CheckResult result = p1.and(p2).check(); - $assertThat(result.isSatisfied()).isFalse(); - } - - @$test - public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final CheckResult result = p1.and(p2).check(); - $assertThat(result.isSatisfied()).isFalse(); - } - - // -- Property.or tests - - @$test - public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final CheckResult result = p1.or(p2).check(); - $assertThat(result.isSatisfied()).isTrue(); - } - - @$test - public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final CheckResult result = p1.or(p2).check(); - $assertThat(result.isSatisfied()).isTrue(); - } - - @$test - public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final CheckResult result = p1.or(p2).check(); - $assertThat(result.isSatisfied()).isTrue(); - } - - @$test - public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final CheckResult result = p1.or(p2).check(); - $assertThat(result.isSatisfied()).isFalse(); - } - } - """ - }) - - for (i <- 1 to N) { - genVavrFile("io.vavr.test", s"PropertyCheck${i}Test", baseDir = TARGET_TEST)((im: ImportManager, packageName, className) => { - - val generics = (1 to i).gen(j => "Object")(", ") - val arbitraries = (1 to i).gen(j => "OBJECTS")(", ") - val arbitrariesMinus1 = (1 until i).gen(j => "OBJECTS")(", ") - val args = (1 to i).gen(j => s"o$j")(", ") - - // test classes - val test = im.getType("org.junit.jupiter.api.Test") - val assertThat = im.getStatic("org.assertj.core.api.Assertions.assertThat") - val assertThrows = im.getStatic("org.junit.jupiter.api.Assertions.assertThrows") - val woops = "yay! (this is a negative test)" - - xs""" - public class $className { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @$test - public void shouldApplyForAllOfArity$i() { - final Property.ForAll$i<${(1 to i).gen(j => "Object")(", ")}> forAll = Property.def("test").forAll(${(1 to i).gen(j => "null")(", ")}); - $assertThat(forAll).isNotNull(); - } - - @$test - public void shouldApplySuchThatOfArity$i() { - final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate = ($args) -> true; - final Property.Property$i<$generics> suchThat = forAll.suchThat(predicate); - $assertThat(suchThat).isNotNull(); - } - - @$test - public void shouldCheckTrueProperty$i() { - final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate = ($args) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - } - - @$test - public void shouldCheckFalseProperty$i() { - final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate = ($args) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - $assertThat(result.isFalsified()).isTrue(); - } - - @$test - public void shouldCheckErroneousProperty$i() { - final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> predicate = ($args) -> { throw new RuntimeException("$woops"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - $assertThat(result.isErroneous()).isTrue(); - } - - @$test - public void shouldCheckProperty${i}ImplicationWithTruePrecondition() { - final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> p1 = ($args) -> true; - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> p2 = ($args) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isFalse(); - } - - @$test - public void shouldCheckProperty${i}ImplicationWithFalsePrecondition() { - final Property.ForAll$i<$generics> forAll = Property.def("test").forAll($arbitraries); - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> p1 = ($args) -> false; - final ${im.getType(s"io.vavr.CheckedFunction$i")}<$generics, Boolean> p2 = ($args) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - $assertThat(result.isSatisfied()).isTrue(); - $assertThat(result.isExhausted()).isTrue(); - } - - @$test - public void shouldThrowOnProperty${i}CheckGivenNegativeTries() { - $assertThrows(${im.getType("java.lang.IllegalArgumentException")}.class, () -> Property.def("test") - .forAll($arbitraries) - .suchThat(($args) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @$test - public void shouldReturnErroneousProperty${i}CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("$woops").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen${(i > 1).gen(s", $arbitrariesMinus1")}) - .suchThat(($args) -> true) - .check(); - $assertThat(result.isErroneous()).isTrue(); - } - - @$test - public void shouldReturnErroneousProperty${i}CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("$woops"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary${(i > 1).gen(s", $arbitrariesMinus1")}) - .suchThat(($args) -> true) - .check(); - $assertThat(result.isErroneous()).isTrue(); - } - } - """ - }) - } - } -} - -/** - * Adds the Vavr header to generated classes. - * @param packageName Java package name - * @param className Simple java class name - * @param gen A generator which produces a String. - */ -def genVavrFile(packageName: String, className: String, baseDir: String = TARGET_MAIN)(gen: (ImportManager, String, String) => String, knownSimpleClassNames: List[String] = List()) = - genJavaFile(baseDir, packageName, className)(xraw""" - /* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - """)(gen)(CHARSET) - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - J A V A G E N E R A T O R F R A M E W O R K -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -object JavaGenerator { - - import java.nio.charset.{Charset, StandardCharsets} - - import Generator._ - - /** - * Generates a Java file. - * @param packageName Java package name - * @param className Simple java class name - * @param classHeader A class file header - * @param gen A generator which produces a String. - */ - def genJavaFile(baseDir: String, packageName: String, className: String)(classHeader: String)(gen: (ImportManager, String, String) => String, knownSimpleClassNames: List[String] = List())(implicit charset: Charset = StandardCharsets.UTF_8): Unit = { - - // DEV-NOTE: using File.separator instead of "/" does *not* work on windows! - val dirName = packageName.replaceAll("[.]", "/") - val fileName = className + ".java" - val importManager = new ImportManager(packageName, knownSimpleClassNames) - val classBody = gen.apply(importManager, packageName, className) - - genFile(baseDir, dirName, fileName)(xraw""" - $classHeader - package $packageName; - - /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D - \*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - - ${importManager.getImports} - - $classBody - """) - } - - /** - * A stateful ImportManager which generates an import section of a Java class file. - * @param packageNameOfClass package name of the generated class - * @param knownSimpleClassNames a list of class names which may not be imported from other packages - */ - class ImportManager(packageNameOfClass: String, knownSimpleClassNames: List[String], wildcardThreshold: Int = 5) { - - import scala.collection.mutable - - val nonStaticImports = new mutable.HashMap[String, String] - val staticImports = new mutable.HashMap[String, String] - - def getType(fullQualifiedName: String): String = simplify(fullQualifiedName, nonStaticImports) - - def getStatic(fullQualifiedName: String): String = simplify(fullQualifiedName, staticImports) - - def getImports: String = { - - def optimizeImports(imports: Seq[String], static: Boolean): String = { - val counts = imports.map(getPackageName).groupBy(s => s).map { case (s, list) => s -> list.length } - val directImports = imports.filter(s => counts(getPackageName(s)) <= wildcardThreshold) - val wildcardImports = counts.filter { case (_, count) => count > wildcardThreshold }.keySet.toIndexedSeq.map(s => s"$s.*") - (directImports ++ wildcardImports).sorted.map(fqn => s"import ${static.gen("static ")}$fqn;").mkString("\n") - } - - val staticImportSection = optimizeImports(staticImports.keySet.toIndexedSeq, static = true) - val nonStaticImportSection = optimizeImports(nonStaticImports.keySet.toIndexedSeq, static = false) - Seq(staticImportSection, nonStaticImportSection).mkString("\n\n") - } - - private def simplify(fullQualifiedName: String, imports: mutable.HashMap[String, String]): String = { - val simpleName = getSimpleName(fullQualifiedName) - val packageName = getPackageName(fullQualifiedName) - if (packageName.isEmpty && !packageNameOfClass.isEmpty) { - throw new IllegalStateException(s"Can't import class '$simpleName' located in default package") - } else if (packageName == packageNameOfClass) { - simpleName - } else if (imports.contains(fullQualifiedName)) { - imports(fullQualifiedName) - } else if (simpleName != "*" && (knownSimpleClassNames.contains(simpleName) || imports.values.exists(simpleName.equals(_)))) { - fullQualifiedName - } else { - imports += fullQualifiedName -> simpleName - simpleName - } - } - - private def getPackageName(fqn: String): String = fqn.substring(0, Math.max(fqn.lastIndexOf("."), 0)) - private def getSimpleName(fqn: String): String = fqn.substring(fqn.lastIndexOf(".") + 1) - } -} - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - C O R E G E N E R A T O R F R A M E W O R K -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -/** - * Core generator API - */ -object Generator { - - import java.nio.charset.{Charset, StandardCharsets} - import java.nio.file.{Files, Paths, StandardOpenOption} - - /** - * Generates a file by writing string contents to the file system. - * - * @param baseDir The base directory, e.g. src-gen - * @param dirName The directory relative to baseDir, e.g. main/java - * @param fileName The file name within baseDir/dirName - * @param createOption One of java.nio.file.{StandardOpenOption.CREATE_NEW, StandardOpenOption.CREATE}, default: CREATE_NEW - * @param contents The string contents of the file - * @param charset The charset, by default UTF-8 - */ - def genFile(baseDir: String, dirName: String, fileName: String, createOption: StandardOpenOption = StandardOpenOption.CREATE_NEW)(contents: => String)(implicit charset: Charset = StandardCharsets.UTF_8): Unit = { - - // println(s"Generating $dirName${File.separator}$fileName") - - Files.write( - Files.createDirectories(Paths.get(baseDir, dirName)).resolve(fileName), - contents.getBytes(charset), - createOption, StandardOpenOption.WRITE) - } - - implicit class IntExtensions(i: Int) { - - // returns i as ordinal, i.e. 1st, 2nd, 3rd, 4th, ... - def ordinal: String = - s"$i" + (if (i >= 4 && i <= 20) { - "th" - } else { - i % 10 match { - case 1 => "st" - case 2 => "nd" - case 3 => "rd" - case _ => "th" - } - }) - - // returns the grammatical number of a string, i.e. `i.numerus("name")` is - // 0: "no name", 1: "one name", 2: "two names", 3: "three names", 4: "4 names", ... - def numerus(noun: String): String = Math.abs(i) match { - case 0 => s"no ${noun}s" - case 1 => s"one $noun" - case 2 => s"two ${noun}s" - case 3 => s"three ${noun}s" - case _ => s"$i ${noun}s" - } - } - - implicit class StringExtensions(s: String) { - - // gets first char of s as string. throws if string is empty - def first: String = s.substring(0, 1) - - // converts first char of s to upper case. throws if string is empty - def firstUpper: String = s(0).toUpper + s.substring(1) - - // converts first char of s to lower case. throws if string is empty - def firstLower: String = s(0).toLower + s.substring(1) - } - - implicit class BooleanExtensions(condition: Boolean) { - def gen(s: => String): String = if (condition) s else "" - } - - implicit class OptionExtensions(option: Option[Any]) { - def gen(f: String => String): String = option.map(any => f.apply(any.toString)).getOrElse("") - def gen: String = option.map(any => any.toString).getOrElse("") - } - - /** - * Generates a String based on ints within a specific range. - * {{{ - * (1 to 3).gen(i => s"x$i")(", ") // x1, x2, x3 - * (1 to 3).reverse.gen(i -> s"x$i")(", ") // x3, x2, x1 - * }}} - * @param range A Range - */ - implicit class RangeExtensions(range: Range) { - def gen(f: Int => String = String.valueOf)(implicit delimiter: String = ""): String = - range map f mkString delimiter - } - - /** - * Generates a String based on an Iterable of objects. Objects are converted to Strings via toString. - * {{{ - * // val a = "A" - * // val b = "B" - * // val c = "C" - * Seq("a", "b", "c").gen(s => raw"""val $s = "${s.toUpperCase}"""")("\n") - * }}} - * - * @param iterable An Interable - */ - implicit class IterableExtensions(iterable: Iterable[Any]) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - iterable.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple1Extensions(tuple: Tuple1[Any]) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - f.apply(tuple._1.toString) mkString delimiter - } - - implicit class Tuple2Extensions(tuple: (Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - /** - * Generates a String based on a tuple of objects. Objects are converted to Strings via toString. - * {{{ - * // val seq = Seq("a", "1", "true") - * s"val seq = Seq(${("a", 1, true).gen(s => s""""$s"""")(", ")})" - * }}} - * @param tuple A Tuple - */ - implicit class Tuple3Extensions(tuple: (Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple4Extensions(tuple: (Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple5Extensions(tuple: (Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple6Extensions(tuple: (Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple7Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple8Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple9Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple10Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple11Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple12Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple13Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple14Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple15Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple16Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple17Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple18Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple19Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple20Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple21Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - implicit class Tuple22Extensions(tuple: (Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any)) { - def gen(f: String => String = identity)(implicit delimiter: String = ""): String = - tuple.productIterator.toList.map(x => f.apply(x.toString)) mkString delimiter - } - - /** - * Provides StringContext extensions, e.g. indentation of cascaded rich strings. - * @param sc Current StringContext - * @see this gist - */ - implicit class StringContextExtensions(sc: StringContext) { - - import scala.util.Properties.lineSeparator - - /** - * Formats escaped strings. - * @param args StringContext parts - * @return An aligned String - */ - def xs(args: Any*): String = align(sc.s, args) - - /** - * Formats raw/unescaped strings. - * @param args StringContext parts - * @return An aligned String - */ - def xraw(args: Any*): String = align(sc.raw, args) - - /** - * Indenting a rich string, removing first and last newline. - * A rich string consists of arguments surrounded by text parts. - */ - private def align(interpolator: Seq[Any] => String, args: Seq[Any]): String = { - - // indent embedded strings, invariant: parts.length = args.length + 1 - val indentedArgs = for { - (part, arg) <- sc.parts zip args.map(s => if (s == null) "" else s.toString) - } yield { - // get the leading space of last line of current part - val space = """([ \t]*)[^\s]*$""".r.findFirstMatchIn(part).map(_.group(1)).getOrElse("") - // add this leading space to each line (except the first) of current arg - arg.split("\r?\n") match { - case lines: Array[String] if lines.nonEmpty => lines reduce (_ + lineSeparator + space + _) - case whitespace => whitespace mkString "" - } - } - - // remove first and last newline and split string into separate lines - // adding termination symbol \u0000 in order to preserve empty strings between last newlines when splitting - val split = (interpolator(indentedArgs).replaceAll( """(^[ \t]*\r?\n)|(\r?\n[ \t]*$)""", "") + '\u0000').split("\r?\n") - - // find smallest indentation - val prefix = split filter (!_.trim().isEmpty) map { s => - """^\s+""".r.findFirstIn(s).getOrElse("") - } match { - case prefixes: Array[String] if prefixes.length > 0 => prefixes reduce { (s1, s2) => - if (s1.length <= s2.length) s1 else s2 - } - case _ => "" - } - - // align all lines - val aligned = split map { s => - if (s.startsWith(prefix)) s.substring(prefix.length) else s - } mkString lineSeparator dropRight 1 // dropping termination character \u0000 - - // combine multiple newlines to two - aligned.replaceAll("""[ \t]*\r?\n ([ \t]*\r?\n)+""", lineSeparator * 2) - } - } -} diff --git a/vavr-test/pom.xml b/vavr-test/pom.xml deleted file mode 100644 index 5978b3c1c6..0000000000 --- a/vavr-test/pom.xml +++ /dev/null @@ -1,99 +0,0 @@ - - 4.0.0 - - io.vavr - vavr-parent - 0.10.6-SNAPSHOT - ../pom.xml - - vavr-test - jar - Vavr Test - A property check framework for Vavr. - https://vavr.io - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - - - ${project.groupId} - vavr - ${project.version} - - - org.junit.jupiter - junit-jupiter - test - - - org.assertj - assertj-core - test - - - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-clean-plugin - - - net.alchim31.maven - scala-maven-plugin - - - org.codehaus.mojo - build-helper-maven-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-jar-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.felix - maven-bundle-plugin - - - org.moditect - moditect-maven-plugin - - - add-module-infos - - add-module-info - - package - - 9 - - - module io.vavr.test { - exports io.vavr.test; - requires io.vavr; - } - - - true - - - - - - - diff --git a/vavr-test/src-gen/main/java/io/vavr/test/Property.java b/vavr-test/src-gen/main/java/io/vavr/test/Property.java deleted file mode 100644 index 9d30db9bc7..0000000000 --- a/vavr-test/src-gen/main/java/io/vavr/test/Property.java +++ /dev/null @@ -1,1310 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import io.vavr.*; -import io.vavr.control.Option; -import io.vavr.control.Try; -import java.util.Objects; -import java.util.Random; - -/** - * A property builder which provides a fluent API to build checkable properties. - * - * @author Daniel Dietrich - */ -public class Property { - - private final String name; - - private Property(String name) { - this.name = name; - } - - /** - * Defines a new Property. - * - * @param name property name - * @return a new {@code Property} - * @throws NullPointerException if name is null. - * @throws IllegalArgumentException if name is empty or consists of whitespace only - */ - public static Property def(String name) { - Objects.requireNonNull(name, "name is null"); - if (name.trim().isEmpty()) { - throw new IllegalArgumentException("name is empty"); - } - return new Property(name); - } - - private static void logSatisfied(String name, int tries, long millis, boolean exhausted) { - if (exhausted) { - log(String.format("%s: Exhausted after %s tests in %s ms.", name, tries, millis)); - } else { - log(String.format("%s: OK, passed %s tests in %s ms.", name, tries, millis)); - } - } - - private static void logFalsified(String name, int currentTry, long millis) { - log(String.format("%s: Falsified after %s passed tests in %s ms.", name, currentTry - 1, millis)); - } - - private static void logErroneous(String name, int currentTry, long millis, String errorMessage) { - log(String.format("%s: Errored after %s passed tests in %s ms with message: %s", name, Math.max(0, currentTry - 1), millis, errorMessage)); - } - - private static void log(String msg) { - System.out.println(msg); - } - - /** - * Creates a CheckError caused by an exception when obtaining a generator. - * - * @param position The position of the argument within the argument list of the property, starting with 1. - * @param size The size hint passed to the {@linkplain Arbitrary} which caused the error. - * @param cause The error which occurred when the {@linkplain Arbitrary} tried to obtain the generator {@linkplain Gen}. - * @return a new CheckError instance. - */ - private static CheckError arbitraryError(int position, int size, Throwable cause) { - return new CheckError(String.format("Arbitrary %s of size %s: %s", position, size, cause.getMessage()), cause); - } - - /** - * Creates a CheckError caused by an exception when generating a value. - * - * @param position The position of the argument within the argument list of the property, starting with 1. - * @param size The size hint of the arbitrary which called the generator {@linkplain Gen} which caused the error. - * @param cause The error which occurred when the {@linkplain Gen} tried to generate a random value. - * @return a new CheckError instance. - */ - private static CheckError genError(int position, int size, Throwable cause) { - return new CheckError(String.format("Gen %s of size %s: %s", position, size, cause.getMessage()), cause); - } - - /** - * Creates a CheckError caused by an exception when testing a Predicate. - * - * @param cause The error which occurred when applying the {@linkplain java.util.function.Predicate}. - * @return a new CheckError instance. - */ - private static CheckError predicateError(Throwable cause) { - return new CheckError("Applying predicate: " + cause.getMessage(), cause); - } - - /** - * Returns a logical for all quantor of 1 given variables. - * - * @param 1st variable type of this for all quantor - * @param a1 1st variable of this for all quantor - * @return a new {@code ForAll1} instance of 1 variables - */ - public ForAll1 forAll(Arbitrary a1) { - return new ForAll1<>(name, a1); - } - - /** - * Returns a logical for all quantor of 2 given variables. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param a1 1st variable of this for all quantor - * @param a2 2nd variable of this for all quantor - * @return a new {@code ForAll2} instance of 2 variables - */ - public ForAll2 forAll(Arbitrary a1, Arbitrary a2) { - return new ForAll2<>(name, a1, a2); - } - - /** - * Returns a logical for all quantor of 3 given variables. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param a1 1st variable of this for all quantor - * @param a2 2nd variable of this for all quantor - * @param a3 3rd variable of this for all quantor - * @return a new {@code ForAll3} instance of 3 variables - */ - public ForAll3 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3) { - return new ForAll3<>(name, a1, a2, a3); - } - - /** - * Returns a logical for all quantor of 4 given variables. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param a1 1st variable of this for all quantor - * @param a2 2nd variable of this for all quantor - * @param a3 3rd variable of this for all quantor - * @param a4 4th variable of this for all quantor - * @return a new {@code ForAll4} instance of 4 variables - */ - public ForAll4 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4) { - return new ForAll4<>(name, a1, a2, a3, a4); - } - - /** - * Returns a logical for all quantor of 5 given variables. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param 5th variable type of this for all quantor - * @param a1 1st variable of this for all quantor - * @param a2 2nd variable of this for all quantor - * @param a3 3rd variable of this for all quantor - * @param a4 4th variable of this for all quantor - * @param a5 5th variable of this for all quantor - * @return a new {@code ForAll5} instance of 5 variables - */ - public ForAll5 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5) { - return new ForAll5<>(name, a1, a2, a3, a4, a5); - } - - /** - * Returns a logical for all quantor of 6 given variables. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param 5th variable type of this for all quantor - * @param 6th variable type of this for all quantor - * @param a1 1st variable of this for all quantor - * @param a2 2nd variable of this for all quantor - * @param a3 3rd variable of this for all quantor - * @param a4 4th variable of this for all quantor - * @param a5 5th variable of this for all quantor - * @param a6 6th variable of this for all quantor - * @return a new {@code ForAll6} instance of 6 variables - */ - public ForAll6 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6) { - return new ForAll6<>(name, a1, a2, a3, a4, a5, a6); - } - - /** - * Returns a logical for all quantor of 7 given variables. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param 5th variable type of this for all quantor - * @param 6th variable type of this for all quantor - * @param 7th variable type of this for all quantor - * @param a1 1st variable of this for all quantor - * @param a2 2nd variable of this for all quantor - * @param a3 3rd variable of this for all quantor - * @param a4 4th variable of this for all quantor - * @param a5 5th variable of this for all quantor - * @param a6 6th variable of this for all quantor - * @param a7 7th variable of this for all quantor - * @return a new {@code ForAll7} instance of 7 variables - */ - public ForAll7 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7) { - return new ForAll7<>(name, a1, a2, a3, a4, a5, a6, a7); - } - - /** - * Returns a logical for all quantor of 8 given variables. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param 5th variable type of this for all quantor - * @param 6th variable type of this for all quantor - * @param 7th variable type of this for all quantor - * @param 8th variable type of this for all quantor - * @param a1 1st variable of this for all quantor - * @param a2 2nd variable of this for all quantor - * @param a3 3rd variable of this for all quantor - * @param a4 4th variable of this for all quantor - * @param a5 5th variable of this for all quantor - * @param a6 6th variable of this for all quantor - * @param a7 7th variable of this for all quantor - * @param a8 8th variable of this for all quantor - * @return a new {@code ForAll8} instance of 8 variables - */ - public ForAll8 forAll(Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7, Arbitrary a8) { - return new ForAll8<>(name, a1, a2, a3, a4, a5, a6, a7, a8); - } - - /** - * Represents a logical for all quantor. - * - * @param 1st variable type of this for all quantor - * @author Daniel Dietrich - */ - public static class ForAll1 { - - private final String name; - private final Arbitrary a1; - - ForAll1(String name, Arbitrary a1) { - this.name = name; - this.a1 = a1; - } - - /** - * Returns a checkable property that checks values of the 1 variables of this {@code ForAll} quantor. - * - * @param predicate A 1-ary predicate - * @return a new {@code Property1} of 1 variables. - */ - public Property1 suchThat(CheckedFunction1 predicate) { - final CheckedFunction1 proposition = (t1) -> new Condition(true, predicate.apply(t1)); - return new Property1<>(name, a1, proposition); - } - } - - /** - * Represents a logical for all quantor. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @author Daniel Dietrich - */ - public static class ForAll2 { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - - ForAll2(String name, Arbitrary a1, Arbitrary a2) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - } - - /** - * Returns a checkable property that checks values of the 2 variables of this {@code ForAll} quantor. - * - * @param predicate A 2-ary predicate - * @return a new {@code Property2} of 2 variables. - */ - public Property2 suchThat(CheckedFunction2 predicate) { - final CheckedFunction2 proposition = (t1, t2) -> new Condition(true, predicate.apply(t1, t2)); - return new Property2<>(name, a1, a2, proposition); - } - } - - /** - * Represents a logical for all quantor. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @author Daniel Dietrich - */ - public static class ForAll3 { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - - ForAll3(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - } - - /** - * Returns a checkable property that checks values of the 3 variables of this {@code ForAll} quantor. - * - * @param predicate A 3-ary predicate - * @return a new {@code Property3} of 3 variables. - */ - public Property3 suchThat(CheckedFunction3 predicate) { - final CheckedFunction3 proposition = (t1, t2, t3) -> new Condition(true, predicate.apply(t1, t2, t3)); - return new Property3<>(name, a1, a2, a3, proposition); - } - } - - /** - * Represents a logical for all quantor. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @author Daniel Dietrich - */ - public static class ForAll4 { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - - ForAll4(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - } - - /** - * Returns a checkable property that checks values of the 4 variables of this {@code ForAll} quantor. - * - * @param predicate A 4-ary predicate - * @return a new {@code Property4} of 4 variables. - */ - public Property4 suchThat(CheckedFunction4 predicate) { - final CheckedFunction4 proposition = (t1, t2, t3, t4) -> new Condition(true, predicate.apply(t1, t2, t3, t4)); - return new Property4<>(name, a1, a2, a3, a4, proposition); - } - } - - /** - * Represents a logical for all quantor. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param 5th variable type of this for all quantor - * @author Daniel Dietrich - */ - public static class ForAll5 { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final Arbitrary a5; - - ForAll5(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.a5 = a5; - } - - /** - * Returns a checkable property that checks values of the 5 variables of this {@code ForAll} quantor. - * - * @param predicate A 5-ary predicate - * @return a new {@code Property5} of 5 variables. - */ - public Property5 suchThat(CheckedFunction5 predicate) { - final CheckedFunction5 proposition = (t1, t2, t3, t4, t5) -> new Condition(true, predicate.apply(t1, t2, t3, t4, t5)); - return new Property5<>(name, a1, a2, a3, a4, a5, proposition); - } - } - - /** - * Represents a logical for all quantor. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param 5th variable type of this for all quantor - * @param 6th variable type of this for all quantor - * @author Daniel Dietrich - */ - public static class ForAll6 { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final Arbitrary a5; - private final Arbitrary a6; - - ForAll6(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.a5 = a5; - this.a6 = a6; - } - - /** - * Returns a checkable property that checks values of the 6 variables of this {@code ForAll} quantor. - * - * @param predicate A 6-ary predicate - * @return a new {@code Property6} of 6 variables. - */ - public Property6 suchThat(CheckedFunction6 predicate) { - final CheckedFunction6 proposition = (t1, t2, t3, t4, t5, t6) -> new Condition(true, predicate.apply(t1, t2, t3, t4, t5, t6)); - return new Property6<>(name, a1, a2, a3, a4, a5, a6, proposition); - } - } - - /** - * Represents a logical for all quantor. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param 5th variable type of this for all quantor - * @param 6th variable type of this for all quantor - * @param 7th variable type of this for all quantor - * @author Daniel Dietrich - */ - public static class ForAll7 { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final Arbitrary a5; - private final Arbitrary a6; - private final Arbitrary a7; - - ForAll7(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.a5 = a5; - this.a6 = a6; - this.a7 = a7; - } - - /** - * Returns a checkable property that checks values of the 7 variables of this {@code ForAll} quantor. - * - * @param predicate A 7-ary predicate - * @return a new {@code Property7} of 7 variables. - */ - public Property7 suchThat(CheckedFunction7 predicate) { - final CheckedFunction7 proposition = (t1, t2, t3, t4, t5, t6, t7) -> new Condition(true, predicate.apply(t1, t2, t3, t4, t5, t6, t7)); - return new Property7<>(name, a1, a2, a3, a4, a5, a6, a7, proposition); - } - } - - /** - * Represents a logical for all quantor. - * - * @param 1st variable type of this for all quantor - * @param 2nd variable type of this for all quantor - * @param 3rd variable type of this for all quantor - * @param 4th variable type of this for all quantor - * @param 5th variable type of this for all quantor - * @param 6th variable type of this for all quantor - * @param 7th variable type of this for all quantor - * @param 8th variable type of this for all quantor - * @author Daniel Dietrich - */ - public static class ForAll8 { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final Arbitrary a5; - private final Arbitrary a6; - private final Arbitrary a7; - private final Arbitrary a8; - - ForAll8(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7, Arbitrary a8) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.a5 = a5; - this.a6 = a6; - this.a7 = a7; - this.a8 = a8; - } - - /** - * Returns a checkable property that checks values of the 8 variables of this {@code ForAll} quantor. - * - * @param predicate A 8-ary predicate - * @return a new {@code Property8} of 8 variables. - */ - public Property8 suchThat(CheckedFunction8 predicate) { - final CheckedFunction8 proposition = (t1, t2, t3, t4, t5, t6, t7, t8) -> new Condition(true, predicate.apply(t1, t2, t3, t4, t5, t6, t7, t8)); - return new Property8<>(name, a1, a2, a3, a4, a5, a6, a7, a8, proposition); - } - } - - /** - * Represents a 1-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property1 implements Checkable { - - private final String name; - private final Arbitrary a1; - private final CheckedFunction1 predicate; - - Property1(String name, Arbitrary a1, CheckedFunction1 predicate) { - this.name = name; - this.a1 = a1; - this.predicate = predicate; - } - - /** - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies(CheckedFunction1 postcondition) { - final CheckedFunction1 implication = (t1) -> { - final Condition precondition = predicate.apply(t1); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(t1)); - } - }; - return new Property1<>(name, a1, implication); - } - - @Override - public CheckResult check(Random random, int size, int tries) { - Objects.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); - try { - final Condition condition = Try.of(() -> predicate.apply(val1)).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, Tuple.of(val1)); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, Option.none()); - } - } - } - - /** - * Represents a 2-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property2 implements Checkable { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final CheckedFunction2 predicate; - - Property2(String name, Arbitrary a1, Arbitrary a2, CheckedFunction2 predicate) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.predicate = predicate; - } - - /** - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies(CheckedFunction2 postcondition) { - final CheckedFunction2 implication = (t1, t2) -> { - final Condition precondition = predicate.apply(t1, t2); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(t1, t2)); - } - }; - return new Property2<>(name, a1, a2, implication); - } - - @Override - public CheckResult check(Random random, int size, int tries) { - Objects.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); - final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); - final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); - try { - final Condition condition = Try.of(() -> predicate.apply(val1, val2)).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, Tuple.of(val1, val2)); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, Option.none()); - } - } - } - - /** - * Represents a 3-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property3 implements Checkable { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final CheckedFunction3 predicate; - - Property3(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, CheckedFunction3 predicate) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.predicate = predicate; - } - - /** - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies(CheckedFunction3 postcondition) { - final CheckedFunction3 implication = (t1, t2, t3) -> { - final Condition precondition = predicate.apply(t1, t2, t3); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(t1, t2, t3)); - } - }; - return new Property3<>(name, a1, a2, a3, implication); - } - - @Override - public CheckResult check(Random random, int size, int tries) { - Objects.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); - final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); - final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); - final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); - final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); - try { - final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3)).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3)); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, Option.none()); - } - } - } - - /** - * Represents a 4-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property4 implements Checkable { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final CheckedFunction4 predicate; - - Property4(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, CheckedFunction4 predicate) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.predicate = predicate; - } - - /** - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies(CheckedFunction4 postcondition) { - final CheckedFunction4 implication = (t1, t2, t3, t4) -> { - final Condition precondition = predicate.apply(t1, t2, t3, t4); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(t1, t2, t3, t4)); - } - }; - return new Property4<>(name, a1, a2, a3, a4, implication); - } - - @Override - public CheckResult check(Random random, int size, int tries) { - Objects.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); - final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); - final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); - final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); - final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); - final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); - final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); - try { - final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4)).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4)); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, Option.none()); - } - } - } - - /** - * Represents a 5-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property5 implements Checkable { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final Arbitrary a5; - private final CheckedFunction5 predicate; - - Property5(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, CheckedFunction5 predicate) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.a5 = a5; - this.predicate = predicate; - } - - /** - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies(CheckedFunction5 postcondition) { - final CheckedFunction5 implication = (t1, t2, t3, t4, t5) -> { - final Condition precondition = predicate.apply(t1, t2, t3, t4, t5); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(t1, t2, t3, t4, t5)); - } - }; - return new Property5<>(name, a1, a2, a3, a4, a5, implication); - } - - @Override - public CheckResult check(Random random, int size, int tries) { - Objects.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); - final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); - final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); - final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); - final Gen gen5 = Try.of(() -> a5.apply(size)).recover(x -> { throw arbitraryError(5, size, x); }).get(); - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); - final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); - final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); - final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); - final T5 val5 = Try.of(() -> gen5.apply(random)).recover(x -> { throw genError(5, size, x); }).get(); - try { - final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4, val5)).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4, val5)); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4, val5))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, Option.none()); - } - } - } - - /** - * Represents a 6-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property6 implements Checkable { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final Arbitrary a5; - private final Arbitrary a6; - private final CheckedFunction6 predicate; - - Property6(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, CheckedFunction6 predicate) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.a5 = a5; - this.a6 = a6; - this.predicate = predicate; - } - - /** - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies(CheckedFunction6 postcondition) { - final CheckedFunction6 implication = (t1, t2, t3, t4, t5, t6) -> { - final Condition precondition = predicate.apply(t1, t2, t3, t4, t5, t6); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(t1, t2, t3, t4, t5, t6)); - } - }; - return new Property6<>(name, a1, a2, a3, a4, a5, a6, implication); - } - - @Override - public CheckResult check(Random random, int size, int tries) { - Objects.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); - final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); - final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); - final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); - final Gen gen5 = Try.of(() -> a5.apply(size)).recover(x -> { throw arbitraryError(5, size, x); }).get(); - final Gen gen6 = Try.of(() -> a6.apply(size)).recover(x -> { throw arbitraryError(6, size, x); }).get(); - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); - final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); - final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); - final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); - final T5 val5 = Try.of(() -> gen5.apply(random)).recover(x -> { throw genError(5, size, x); }).get(); - final T6 val6 = Try.of(() -> gen6.apply(random)).recover(x -> { throw genError(6, size, x); }).get(); - try { - final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4, val5, val6)).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4, val5, val6)); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4, val5, val6))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, Option.none()); - } - } - } - - /** - * Represents a 7-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property7 implements Checkable { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final Arbitrary a5; - private final Arbitrary a6; - private final Arbitrary a7; - private final CheckedFunction7 predicate; - - Property7(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7, CheckedFunction7 predicate) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.a5 = a5; - this.a6 = a6; - this.a7 = a7; - this.predicate = predicate; - } - - /** - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies(CheckedFunction7 postcondition) { - final CheckedFunction7 implication = (t1, t2, t3, t4, t5, t6, t7) -> { - final Condition precondition = predicate.apply(t1, t2, t3, t4, t5, t6, t7); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(t1, t2, t3, t4, t5, t6, t7)); - } - }; - return new Property7<>(name, a1, a2, a3, a4, a5, a6, a7, implication); - } - - @Override - public CheckResult check(Random random, int size, int tries) { - Objects.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); - final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); - final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); - final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); - final Gen gen5 = Try.of(() -> a5.apply(size)).recover(x -> { throw arbitraryError(5, size, x); }).get(); - final Gen gen6 = Try.of(() -> a6.apply(size)).recover(x -> { throw arbitraryError(6, size, x); }).get(); - final Gen gen7 = Try.of(() -> a7.apply(size)).recover(x -> { throw arbitraryError(7, size, x); }).get(); - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); - final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); - final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); - final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); - final T5 val5 = Try.of(() -> gen5.apply(random)).recover(x -> { throw genError(5, size, x); }).get(); - final T6 val6 = Try.of(() -> gen6.apply(random)).recover(x -> { throw genError(6, size, x); }).get(); - final T7 val7 = Try.of(() -> gen7.apply(random)).recover(x -> { throw genError(7, size, x); }).get(); - try { - final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4, val5, val6, val7)).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4, val5, val6, val7)); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4, val5, val6, val7))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, Option.none()); - } - } - } - - /** - * Represents a 8-ary checkable property. - * - * @author Daniel Dietrich - */ - public static class Property8 implements Checkable { - - private final String name; - private final Arbitrary a1; - private final Arbitrary a2; - private final Arbitrary a3; - private final Arbitrary a4; - private final Arbitrary a5; - private final Arbitrary a6; - private final Arbitrary a7; - private final Arbitrary a8; - private final CheckedFunction8 predicate; - - Property8(String name, Arbitrary a1, Arbitrary a2, Arbitrary a3, Arbitrary a4, Arbitrary a5, Arbitrary a6, Arbitrary a7, Arbitrary a8, CheckedFunction8 predicate) { - this.name = name; - this.a1 = a1; - this.a2 = a2; - this.a3 = a3; - this.a4 = a4; - this.a5 = a5; - this.a6 = a6; - this.a7 = a7; - this.a8 = a8; - this.predicate = predicate; - } - - /** - * Returns an implication which composes this Property as pre-condition and a given post-condition. - * - * @param postcondition The postcondition of this implication - * @return A new Checkable implication - */ - public Checkable implies(CheckedFunction8 postcondition) { - final CheckedFunction8 implication = (t1, t2, t3, t4, t5, t6, t7, t8) -> { - final Condition precondition = predicate.apply(t1, t2, t3, t4, t5, t6, t7, t8); - if (precondition.isFalse()) { - return Condition.EX_FALSO_QUODLIBET; - } else { - return new Condition(true, postcondition.apply(t1, t2, t3, t4, t5, t6, t7, t8)); - } - }; - return new Property8<>(name, a1, a2, a3, a4, a5, a6, a7, a8, implication); - } - - @Override - public CheckResult check(Random random, int size, int tries) { - Objects.requireNonNull(random, "random is null"); - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - final long startTime = System.currentTimeMillis(); - try { - final Gen gen1 = Try.of(() -> a1.apply(size)).recover(x -> { throw arbitraryError(1, size, x); }).get(); - final Gen gen2 = Try.of(() -> a2.apply(size)).recover(x -> { throw arbitraryError(2, size, x); }).get(); - final Gen gen3 = Try.of(() -> a3.apply(size)).recover(x -> { throw arbitraryError(3, size, x); }).get(); - final Gen gen4 = Try.of(() -> a4.apply(size)).recover(x -> { throw arbitraryError(4, size, x); }).get(); - final Gen gen5 = Try.of(() -> a5.apply(size)).recover(x -> { throw arbitraryError(5, size, x); }).get(); - final Gen gen6 = Try.of(() -> a6.apply(size)).recover(x -> { throw arbitraryError(6, size, x); }).get(); - final Gen gen7 = Try.of(() -> a7.apply(size)).recover(x -> { throw arbitraryError(7, size, x); }).get(); - final Gen gen8 = Try.of(() -> a8.apply(size)).recover(x -> { throw arbitraryError(8, size, x); }).get(); - boolean exhausted = true; - for (int i = 1; i <= tries; i++) { - try { - final T1 val1 = Try.of(() -> gen1.apply(random)).recover(x -> { throw genError(1, size, x); }).get(); - final T2 val2 = Try.of(() -> gen2.apply(random)).recover(x -> { throw genError(2, size, x); }).get(); - final T3 val3 = Try.of(() -> gen3.apply(random)).recover(x -> { throw genError(3, size, x); }).get(); - final T4 val4 = Try.of(() -> gen4.apply(random)).recover(x -> { throw genError(4, size, x); }).get(); - final T5 val5 = Try.of(() -> gen5.apply(random)).recover(x -> { throw genError(5, size, x); }).get(); - final T6 val6 = Try.of(() -> gen6.apply(random)).recover(x -> { throw genError(6, size, x); }).get(); - final T7 val7 = Try.of(() -> gen7.apply(random)).recover(x -> { throw genError(7, size, x); }).get(); - final T8 val8 = Try.of(() -> gen8.apply(random)).recover(x -> { throw genError(8, size, x); }).get(); - try { - final Condition condition = Try.of(() -> predicate.apply(val1, val2, val3, val4, val5, val6, val7, val8)).recover(x -> { throw predicateError(x); }).get(); - if (condition.precondition) { - exhausted = false; - if (!condition.postcondition) { - logFalsified(name, i, System.currentTimeMillis() - startTime); - return new CheckResult.Falsified(name, i, Tuple.of(val1, val2, val3, val4, val5, val6, val7, val8)); - } - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.some(Tuple.of(val1, val2, val3, val4, val5, val6, val7, val8))); - } - } catch(CheckError err) { - logErroneous(name, i, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, i, err, Option.none()); - } - } - logSatisfied(name, tries, System.currentTimeMillis() - startTime, exhausted); - return new CheckResult.Satisfied(name, tries, exhausted); - } catch(CheckError err) { - logErroneous(name, 0, System.currentTimeMillis() - startTime, err.getMessage()); - return new CheckResult.Erroneous(name, 0, err, Option.none()); - } - } - } - - /** - * Internally used to model conditions composed of pre- and post-condition. - */ - static class Condition { - - static final Condition EX_FALSO_QUODLIBET = new Condition(false, true); - - final boolean precondition; - final boolean postcondition; - - Condition(boolean precondition, boolean postcondition) { - this.precondition = precondition; - this.postcondition = postcondition; - } - - // ¬(p => q) ≡ ¬(¬p ∨ q) ≡ p ∧ ¬q - boolean isFalse() { - return precondition && !postcondition; - } - } - - /** - * Internally used to provide more specific error messages. - */ - static class CheckError extends Error { - - private static final long serialVersionUID = 1L; - - CheckError(String message, Throwable cause) { - super(message, cause); - } - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck1Test.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck1Test.java deleted file mode 100644 index 1eb88198f9..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck1Test.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction1; -import java.lang.IllegalArgumentException; -import org.junit.jupiter.api.Test; - -public class PropertyCheck1Test { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldApplyForAllOfArity1() { - final Property.ForAll1 forAll = Property.def("test").forAll(null); - assertThat(forAll).isNotNull(); - } - - @Test - public void shouldApplySuchThatOfArity1() { - final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); - final CheckedFunction1 predicate = (o1) -> true; - final Property.Property1 suchThat = forAll.suchThat(predicate); - assertThat(suchThat).isNotNull(); - } - - @Test - public void shouldCheckTrueProperty1() { - final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); - final CheckedFunction1 predicate = (o1) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckFalseProperty1() { - final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); - final CheckedFunction1 predicate = (o1) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isFalsified()).isTrue(); - } - - @Test - public void shouldCheckErroneousProperty1() { - final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); - final CheckedFunction1 predicate = (o1) -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldCheckProperty1ImplicationWithTruePrecondition() { - final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); - final CheckedFunction1 p1 = (o1) -> true; - final CheckedFunction1 p2 = (o1) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckProperty1ImplicationWithFalsePrecondition() { - final Property.ForAll1 forAll = Property.def("test").forAll(OBJECTS); - final CheckedFunction1 p1 = (o1) -> false; - final CheckedFunction1 p2 = (o1) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnProperty1CheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS) - .suchThat((o1) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @Test - public void shouldReturnErroneousProperty1CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen) - .suchThat((o1) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldReturnErroneousProperty1CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary) - .suchThat((o1) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck2Test.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck2Test.java deleted file mode 100644 index e1d0a85a0a..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck2Test.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction2; -import java.lang.IllegalArgumentException; -import org.junit.jupiter.api.Test; - -public class PropertyCheck2Test { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldApplyForAllOfArity2() { - final Property.ForAll2 forAll = Property.def("test").forAll(null, null); - assertThat(forAll).isNotNull(); - } - - @Test - public void shouldApplySuchThatOfArity2() { - final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); - final CheckedFunction2 predicate = (o1, o2) -> true; - final Property.Property2 suchThat = forAll.suchThat(predicate); - assertThat(suchThat).isNotNull(); - } - - @Test - public void shouldCheckTrueProperty2() { - final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); - final CheckedFunction2 predicate = (o1, o2) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckFalseProperty2() { - final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); - final CheckedFunction2 predicate = (o1, o2) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isFalsified()).isTrue(); - } - - @Test - public void shouldCheckErroneousProperty2() { - final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); - final CheckedFunction2 predicate = (o1, o2) -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldCheckProperty2ImplicationWithTruePrecondition() { - final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); - final CheckedFunction2 p1 = (o1, o2) -> true; - final CheckedFunction2 p2 = (o1, o2) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckProperty2ImplicationWithFalsePrecondition() { - final Property.ForAll2 forAll = Property.def("test").forAll(OBJECTS, OBJECTS); - final CheckedFunction2 p1 = (o1, o2) -> false; - final CheckedFunction2 p2 = (o1, o2) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnProperty2CheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS, OBJECTS) - .suchThat((o1, o2) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @Test - public void shouldReturnErroneousProperty2CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen, OBJECTS) - .suchThat((o1, o2) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldReturnErroneousProperty2CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary, OBJECTS) - .suchThat((o1, o2) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck3Test.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck3Test.java deleted file mode 100644 index 898cf5905e..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck3Test.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction3; -import java.lang.IllegalArgumentException; -import org.junit.jupiter.api.Test; - -public class PropertyCheck3Test { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldApplyForAllOfArity3() { - final Property.ForAll3 forAll = Property.def("test").forAll(null, null, null); - assertThat(forAll).isNotNull(); - } - - @Test - public void shouldApplySuchThatOfArity3() { - final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction3 predicate = (o1, o2, o3) -> true; - final Property.Property3 suchThat = forAll.suchThat(predicate); - assertThat(suchThat).isNotNull(); - } - - @Test - public void shouldCheckTrueProperty3() { - final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction3 predicate = (o1, o2, o3) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckFalseProperty3() { - final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction3 predicate = (o1, o2, o3) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isFalsified()).isTrue(); - } - - @Test - public void shouldCheckErroneousProperty3() { - final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction3 predicate = (o1, o2, o3) -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldCheckProperty3ImplicationWithTruePrecondition() { - final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction3 p1 = (o1, o2, o3) -> true; - final CheckedFunction3 p2 = (o1, o2, o3) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckProperty3ImplicationWithFalsePrecondition() { - final Property.ForAll3 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction3 p1 = (o1, o2, o3) -> false; - final CheckedFunction3 p2 = (o1, o2, o3) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnProperty3CheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @Test - public void shouldReturnErroneousProperty3CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldReturnErroneousProperty3CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck4Test.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck4Test.java deleted file mode 100644 index 24d9255ab8..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck4Test.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction4; -import java.lang.IllegalArgumentException; -import org.junit.jupiter.api.Test; - -public class PropertyCheck4Test { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldApplyForAllOfArity4() { - final Property.ForAll4 forAll = Property.def("test").forAll(null, null, null, null); - assertThat(forAll).isNotNull(); - } - - @Test - public void shouldApplySuchThatOfArity4() { - final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction4 predicate = (o1, o2, o3, o4) -> true; - final Property.Property4 suchThat = forAll.suchThat(predicate); - assertThat(suchThat).isNotNull(); - } - - @Test - public void shouldCheckTrueProperty4() { - final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction4 predicate = (o1, o2, o3, o4) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckFalseProperty4() { - final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction4 predicate = (o1, o2, o3, o4) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isFalsified()).isTrue(); - } - - @Test - public void shouldCheckErroneousProperty4() { - final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction4 predicate = (o1, o2, o3, o4) -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldCheckProperty4ImplicationWithTruePrecondition() { - final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction4 p1 = (o1, o2, o3, o4) -> true; - final CheckedFunction4 p2 = (o1, o2, o3, o4) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckProperty4ImplicationWithFalsePrecondition() { - final Property.ForAll4 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction4 p1 = (o1, o2, o3, o4) -> false; - final CheckedFunction4 p2 = (o1, o2, o3, o4) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnProperty4CheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @Test - public void shouldReturnErroneousProperty4CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldReturnErroneousProperty4CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck5Test.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck5Test.java deleted file mode 100644 index 6ad8458efd..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck5Test.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction5; -import java.lang.IllegalArgumentException; -import org.junit.jupiter.api.Test; - -public class PropertyCheck5Test { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldApplyForAllOfArity5() { - final Property.ForAll5 forAll = Property.def("test").forAll(null, null, null, null, null); - assertThat(forAll).isNotNull(); - } - - @Test - public void shouldApplySuchThatOfArity5() { - final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction5 predicate = (o1, o2, o3, o4, o5) -> true; - final Property.Property5 suchThat = forAll.suchThat(predicate); - assertThat(suchThat).isNotNull(); - } - - @Test - public void shouldCheckTrueProperty5() { - final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction5 predicate = (o1, o2, o3, o4, o5) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckFalseProperty5() { - final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction5 predicate = (o1, o2, o3, o4, o5) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isFalsified()).isTrue(); - } - - @Test - public void shouldCheckErroneousProperty5() { - final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction5 predicate = (o1, o2, o3, o4, o5) -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldCheckProperty5ImplicationWithTruePrecondition() { - final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction5 p1 = (o1, o2, o3, o4, o5) -> true; - final CheckedFunction5 p2 = (o1, o2, o3, o4, o5) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckProperty5ImplicationWithFalsePrecondition() { - final Property.ForAll5 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction5 p1 = (o1, o2, o3, o4, o5) -> false; - final CheckedFunction5 p2 = (o1, o2, o3, o4, o5) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnProperty5CheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @Test - public void shouldReturnErroneousProperty5CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldReturnErroneousProperty5CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck6Test.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck6Test.java deleted file mode 100644 index 66c78f1226..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck6Test.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction6; -import java.lang.IllegalArgumentException; -import org.junit.jupiter.api.Test; - -public class PropertyCheck6Test { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldApplyForAllOfArity6() { - final Property.ForAll6 forAll = Property.def("test").forAll(null, null, null, null, null, null); - assertThat(forAll).isNotNull(); - } - - @Test - public void shouldApplySuchThatOfArity6() { - final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction6 predicate = (o1, o2, o3, o4, o5, o6) -> true; - final Property.Property6 suchThat = forAll.suchThat(predicate); - assertThat(suchThat).isNotNull(); - } - - @Test - public void shouldCheckTrueProperty6() { - final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction6 predicate = (o1, o2, o3, o4, o5, o6) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckFalseProperty6() { - final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction6 predicate = (o1, o2, o3, o4, o5, o6) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isFalsified()).isTrue(); - } - - @Test - public void shouldCheckErroneousProperty6() { - final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction6 predicate = (o1, o2, o3, o4, o5, o6) -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldCheckProperty6ImplicationWithTruePrecondition() { - final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction6 p1 = (o1, o2, o3, o4, o5, o6) -> true; - final CheckedFunction6 p2 = (o1, o2, o3, o4, o5, o6) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckProperty6ImplicationWithFalsePrecondition() { - final Property.ForAll6 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction6 p1 = (o1, o2, o3, o4, o5, o6) -> false; - final CheckedFunction6 p2 = (o1, o2, o3, o4, o5, o6) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnProperty6CheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @Test - public void shouldReturnErroneousProperty6CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldReturnErroneousProperty6CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck7Test.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck7Test.java deleted file mode 100644 index 223512e558..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck7Test.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction7; -import java.lang.IllegalArgumentException; -import org.junit.jupiter.api.Test; - -public class PropertyCheck7Test { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldApplyForAllOfArity7() { - final Property.ForAll7 forAll = Property.def("test").forAll(null, null, null, null, null, null, null); - assertThat(forAll).isNotNull(); - } - - @Test - public void shouldApplySuchThatOfArity7() { - final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction7 predicate = (o1, o2, o3, o4, o5, o6, o7) -> true; - final Property.Property7 suchThat = forAll.suchThat(predicate); - assertThat(suchThat).isNotNull(); - } - - @Test - public void shouldCheckTrueProperty7() { - final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction7 predicate = (o1, o2, o3, o4, o5, o6, o7) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckFalseProperty7() { - final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction7 predicate = (o1, o2, o3, o4, o5, o6, o7) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isFalsified()).isTrue(); - } - - @Test - public void shouldCheckErroneousProperty7() { - final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction7 predicate = (o1, o2, o3, o4, o5, o6, o7) -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldCheckProperty7ImplicationWithTruePrecondition() { - final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction7 p1 = (o1, o2, o3, o4, o5, o6, o7) -> true; - final CheckedFunction7 p2 = (o1, o2, o3, o4, o5, o6, o7) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckProperty7ImplicationWithFalsePrecondition() { - final Property.ForAll7 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction7 p1 = (o1, o2, o3, o4, o5, o6, o7) -> false; - final CheckedFunction7 p2 = (o1, o2, o3, o4, o5, o6, o7) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnProperty7CheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6, o7) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @Test - public void shouldReturnErroneousProperty7CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6, o7) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldReturnErroneousProperty7CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6, o7) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck8Test.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck8Test.java deleted file mode 100644 index 9b4e02bbff..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyCheck8Test.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction8; -import java.lang.IllegalArgumentException; -import org.junit.jupiter.api.Test; - -public class PropertyCheck8Test { - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldApplyForAllOfArity8() { - final Property.ForAll8 forAll = Property.def("test").forAll(null, null, null, null, null, null, null, null); - assertThat(forAll).isNotNull(); - } - - @Test - public void shouldApplySuchThatOfArity8() { - final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction8 predicate = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; - final Property.Property8 suchThat = forAll.suchThat(predicate); - assertThat(suchThat).isNotNull(); - } - - @Test - public void shouldCheckTrueProperty8() { - final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction8 predicate = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckFalseProperty8() { - final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction8 predicate = (o1, o2, o3, o4, o5, o6, o7, o8) -> false; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isFalsified()).isTrue(); - } - - @Test - public void shouldCheckErroneousProperty8() { - final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction8 predicate = (o1, o2, o3, o4, o5, o6, o7, o8) -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = forAll.suchThat(predicate).check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldCheckProperty8ImplicationWithTruePrecondition() { - final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction8 p1 = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; - final CheckedFunction8 p2 = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckProperty8ImplicationWithFalsePrecondition() { - final Property.ForAll8 forAll = Property.def("test").forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS); - final CheckedFunction8 p1 = (o1, o2, o3, o4, o5, o6, o7, o8) -> false; - final CheckedFunction8 p2 = (o1, o2, o3, o4, o5, o6, o7, o8) -> true; - final CheckResult result = forAll.suchThat(p1).implies(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnProperty8CheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6, o7, o8) -> true) - .check(Checkable.RNG.get(), 0, -1)); - } - - @Test - public void shouldReturnErroneousProperty8CheckResultIfGenFails() { - final Arbitrary failingGen = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test") - .forAll(failingGen, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6, o7, o8) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } - - @Test - public void shouldReturnErroneousProperty8CheckResultIfArbitraryFails() { - final Arbitrary failingArbitrary = size -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test") - .forAll(failingArbitrary, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS, OBJECTS) - .suchThat((o1, o2, o3, o4, o5, o6, o7, o8) -> true) - .check(); - assertThat(result.isErroneous()).isTrue(); - } -} \ No newline at end of file diff --git a/vavr-test/src-gen/test/java/io/vavr/test/PropertyTest.java b/vavr-test/src-gen/test/java/io/vavr/test/PropertyTest.java deleted file mode 100644 index 0fa1b7a28b..0000000000 --- a/vavr-test/src-gen/test/java/io/vavr/test/PropertyTest.java +++ /dev/null @@ -1,247 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*\ - G E N E R A T O R C R A F T E D -\*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import io.vavr.CheckedFunction1; -import io.vavr.Tuple; -import io.vavr.collection.List; -import java.lang.IllegalArgumentException; -import java.lang.NullPointerException; -import java.util.Random; -import org.junit.jupiter.api.Test; - -public class PropertyTest { - - static CheckedFunction1 tautology() { - return any -> true; - } - - static CheckedFunction1 falsum() { - return any -> false; - } - - static final Arbitrary OBJECTS = Gen.of(null).arbitrary(); - - @Test - public void shouldThrowWhenPropertyNameIsNull() { - assertThrows(NullPointerException.class, () -> Property.def(null)); - } - - @Test - public void shouldThrowWhenPropertyNameIsEmpty() { - assertThrows(IllegalArgumentException.class, () -> Property.def("")); - } - - // -- Property.check methods - - @Test - public void shouldCheckUsingDefaultConfiguration() { - final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckGivenSizeAndTries() { - final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(0, 0); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - @Test - public void shouldThrowOnCheckGivenNegativeTries() { - assertThrows(IllegalArgumentException.class, () -> Property.def("test") - .forAll(OBJECTS) - .suchThat(tautology()) - .check(0, -1)); - } - - @Test - public void shouldCheckGivenRandomAndSizeAndTries() { - final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(tautology()).check(new Random(), 0, 0); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - // -- satisfaction - - @Test - public void shouldCheckPythagoras() { - - final Arbitrary real = n -> Gen.choose(0, (double) n).filter(d -> d > .0d); - - // (∀a,b ∈ ℝ+ ∃c ∈ ℝ+ : a²+b²=c²) ≡ (∀a,b ∈ ℝ+ : √(a²+b²) ∈ ℝ+) - final Checkable property = Property.def("test").forAll(real, real).suchThat((a, b) -> Math.sqrt(a * a + b * b) > .0d); - final CheckResult result = property.check(); - - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - @Test - public void shouldCheckZipAndThenUnzipIsIdempotentForListsOfSameLength() { - // ∀is,ss: length(is) = length(ss) → unzip(zip(is, ss)) = (is, ss) - final Arbitrary> ints = Arbitrary.list(size -> Gen.choose(0, size)); - final Arbitrary> strings = Arbitrary.list( - Arbitrary.string( - Gen.frequency( - Tuple.of(1, Gen.choose('A', 'Z')), - Tuple.of(1, Gen.choose('a', 'z')), - Tuple.of(1, Gen.choose('0', '9')) - ))); - final CheckResult result = Property.def("test") - .forAll(ints, strings) - .suchThat((is, ss) -> is.length() == ss.length()) - .implies((is, ss) -> is.zip(ss).unzip(t -> t).equals(Tuple.of(is, ss))) - .check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - } - - // -- exhausting - - @Test - public void shouldRecognizeExhaustedParameters() { - final CheckResult result = Property.def("test").forAll(OBJECTS).suchThat(falsum()).implies(tautology()).check(); - assertThat(result.isSatisfied()).isTrue(); - assertThat(result.isExhausted()).isTrue(); - } - - // -- falsification - - @Test - public void shouldFalsifyFalseProperty() { - final Arbitrary ones = n -> random -> 1; - final CheckResult result = Property.def("test").forAll(ones).suchThat(one -> one == 2).check(); - assertThat(result.isFalsified()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - assertThat(result.count()).isEqualTo(1); - } - - // -- error detection - - @Test - public void shouldRecognizeArbitraryError() { - final Arbitrary arbitrary = n -> { throw new RuntimeException("yay! (this is a negative test)"); }; - final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check(); - assertThat(result.isErroneous()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - assertThat(result.count()).isEqualTo(0); - assertThat(result.sample().isEmpty()).isTrue(); - } - - @Test - public void shouldRecognizeGenError() { - final Arbitrary arbitrary = Gen.fail("yay! (this is a negative test)").arbitrary(); - final CheckResult result = Property.def("test").forAll(arbitrary).suchThat(tautology()).check(); - assertThat(result.isErroneous()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - assertThat(result.count()).isEqualTo(1); - assertThat(result.sample().isEmpty()).isTrue(); - } - - @Test - public void shouldRecognizePropertyError() { - final Arbitrary a1 = n -> random -> 1; - final Arbitrary a2 = n -> random -> 2; - final CheckResult result = Property.def("test").forAll(a1, a2).suchThat((a, b) -> { - throw new RuntimeException("yay! (this is a negative test)"); - }).check(); - assertThat(result.isErroneous()).isTrue(); - assertThat(result.isExhausted()).isFalse(); - assertThat(result.count()).isEqualTo(1); - assertThat(result.sample().isDefined()).isTrue(); - assertThat(result.sample().get()).isEqualTo(Tuple.of(1, 2)); - } - - // -- Property.and tests - - @Test - public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final CheckResult result = p1.and(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - } - - @Test - public void shouldCheckAndCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final CheckResult result = p1.and(p2).check(); - assertThat(result.isSatisfied()).isFalse(); - } - - @Test - public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final CheckResult result = p1.and(p2).check(); - assertThat(result.isSatisfied()).isFalse(); - } - - @Test - public void shouldCheckAndCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final CheckResult result = p1.and(p2).check(); - assertThat(result.isSatisfied()).isFalse(); - } - - // -- Property.or tests - - @Test - public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsTrue() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final CheckResult result = p1.or(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - } - - @Test - public void shouldCheckOrCombinationWhereFirstPropertyIsTrueAndSecondPropertyIsFalse() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final CheckResult result = p1.or(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - } - - @Test - public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsTrue() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(tautology()); - final CheckResult result = p1.or(p2).check(); - assertThat(result.isSatisfied()).isTrue(); - } - - @Test - public void shouldCheckOrCombinationWhereFirstPropertyIsFalseAndSecondPropertyIsFalse() { - final Checkable p1 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final Checkable p2 = Property.def("test").forAll(OBJECTS).suchThat(falsum()); - final CheckResult result = p1.or(p2).check(); - assertThat(result.isSatisfied()).isFalse(); - } -} \ No newline at end of file diff --git a/vavr-test/src/main/java/io/vavr/test/Arbitrary.java b/vavr-test/src/main/java/io/vavr/test/Arbitrary.java deleted file mode 100644 index bd7db486ba..0000000000 --- a/vavr-test/src/main/java/io/vavr/test/Arbitrary.java +++ /dev/null @@ -1,337 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -import io.vavr.collection.List; -import io.vavr.collection.Stream; - -import java.time.Duration; -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Comparator; -import java.util.Objects; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * Represents an arbitrary object of type T. - * - * @param The type of the arbitrary object. - * @author Daniel Dietrich - */ -@FunctionalInterface -public interface Arbitrary { - - /** - * Returns a generator for objects of type T. - * Use {@link Gen#map(Function)} and {@link Gen#flatMap(Function)} to - * combine object generators. - *

- * Example: - *

-     * 
-     * // represents arbitrary binary trees of a certain depth n
-     * final class ArbitraryTree implements Arbitrary<BinaryTree<Integer>> {
-     *     @Override
-     *     public Gen<BinaryTree<Integer>> apply(int n) {
-     *         return Gen.choose(-1000, 1000).flatMap(value -> {
-     *                  if (n == 0) {
-     *                      return Gen.of(BinaryTree.leaf(value));
-     *                  } else {
-     *                      return Gen.frequency(
-     *                              Tuple.of(1, Gen.of(BinaryTree.leaf(value))),
-     *                              Tuple.of(4, Gen.of(BinaryTree.branch(apply(n / 2).get(), value, apply(n / 2).get())))
-     *                      );
-     *                  }
-     *         });
-     *     }
-     * }
-     *
-     * // tree generator with a size hint of 10
-     * final Gen<BinaryTree<Integer>> treeGen = new ArbitraryTree().apply(10);
-     *
-     * // stream sum of tree node values to console for 100 arbitrary trees
-     * Stream.of(() -> treeGen.apply(RNG.get())).map(Tree::sum).take(100).stdout();
-     * 
-     * 
- * - * @param size A (not necessarily positive) size parameter which may be interpreted individually and is constant for all arbitrary objects regarding one property check. - * @return A generator for objects of type T. - */ - Gen apply(int size); - - /** - * Returns an Arbitrary based on this Arbitrary which produces unique values. - * - * @return A new generator - */ - default Arbitrary distinct() { - return distinctBy(Function.identity()); - } - - /** - * Returns an Arbitrary based on this Arbitrary which produces unique values based on the given comparator. - * - * @param comparator A comparator - * @return A new generator - */ - default Arbitrary distinctBy(Comparator comparator) { - Objects.requireNonNull(comparator, "comparator is null"); - final java.util.Set seen = new java.util.TreeSet<>(comparator); - return filter(seen::add); - } - - /** - * Returns an Arbitrary based on this Arbitrary which produces unique values based on the given function. - * - * @param key type - * @param keyExtractor A function - * @return A new generator - */ - default Arbitrary distinctBy(Function keyExtractor) { - Objects.requireNonNull(keyExtractor, "keyExtractor is null"); - final java.util.Set seen = new java.util.HashSet<>(); - return filter(t -> seen.add(keyExtractor.apply(t))); - } - - /** - * Returns an Arbitrary based on this Arbitrary which produces values that fulfill the given predicate. - * - * @param predicate A predicate - * @return A new generator - */ - default Arbitrary filter(Predicate predicate) { - return size -> apply(size).filter(predicate); - } - - /** - * Maps arbitrary objects T to arbitrary object U. - * - * @param mapper A function that maps arbitrary Ts to arbitrary Us given a mapper. - * @param New type of arbitrary objects - * @return A new Arbitrary - */ - default Arbitrary flatMap(Function> mapper) { - return size -> { - final Gen gen = apply(size); - return random -> mapper.apply(gen.apply(random)).apply(size).apply(random); - }; - } - - /** - * Intersperses values from this arbitrary instance with those of another. - * - * @param other another T arbitrary to accept values from. - * @return A new T arbitrary - */ - default Arbitrary intersperse(Arbitrary other) { - Objects.requireNonNull(other, "other is null"); - return size -> this.apply(size).intersperse(other.apply(size)); - } - - /** - * Maps arbitrary objects T to arbitrary object U. - * - * @param mapper A function that maps an arbitrary T to an object of type U. - * @param Type of the mapped object - * @return A new generator - */ - default Arbitrary map(Function mapper) { - Objects.requireNonNull(mapper, "mapper is null"); - return n -> { - final Gen generator = apply(n); - return random -> mapper.apply(generator.apply(random)); - }; - } - - default Arbitrary peek(Consumer action) { - return size -> apply(size).peek(action); - } - - /** - * Transforms this {@code Arbitrary}. - * - * @param f A transformation - * @param Type of transformation result - * @return An instance of type {@code U} - * @throws NullPointerException if {@code f} is null - */ - default U transform(Function, ? extends U> f) { - Objects.requireNonNull(f, "f is null"); - return f.apply(this); - } - - /** - * Generates an arbitrary value from a fixed set of values - * - * @param values A fixed set of values - * @param Type of generator value - * @return A new generator - */ - @SafeVarargs - @SuppressWarnings("varargs") - static Arbitrary of(U... values) { - return ofAll(Gen.choose(values)); - } - - /** - * Generates an arbitrary value from a given generator - * - * @param generator A generator to produce arbitrary values - * @param Type of generator value - * @return A new generator - */ - static Arbitrary ofAll(Gen generator) { - return size -> generator; - } - - /** - * Generates arbitrary integer values. - * - * @return A new Arbitrary of Integer - */ - static Arbitrary integer() { - return size -> Gen.choose(-size, size); - } - - /** - * Generates arbitrary {@link LocalDateTime}s with {@link LocalDateTime#now()} as {@code median} and - * {@link ChronoUnit#DAYS} as chronological unit. - * - * @return A new Arbitrary of LocalDateTime - * @see #localDateTime(LocalDateTime, ChronoUnit) - */ - static Arbitrary localDateTime() { - return localDateTime(ChronoUnit.DAYS); - } - - /** - * Generates arbitrary {@link LocalDateTime}s with {@link LocalDateTime#now()} as {@code median}. - * - * @param unit Chronological unit of {@code size} - * @return A new Arbitrary of LocalDateTime - * @see #localDateTime(LocalDateTime, ChronoUnit) - */ - static Arbitrary localDateTime(ChronoUnit unit) { - return localDateTime(LocalDateTime.now(), unit); - } - - /** - * Generates arbitrary {@link LocalDateTime}s. All generated values are drawn from a range with {@code median} - * as center and {@code median +/- size} as included boundaries. {@code unit} defines the chronological unit - * of {@code size}. - * - *

- * Example: - *

-     * 
-     * Arbitrary.localDateTime(LocalDateTime.now(), ChronoUnit.YEARS);
-     * 
-     * 
- * - * @param median Center of the LocalDateTime range - * @param unit Chronological unit of {@code size} - * @return A new Arbitrary of LocalDateTime - */ - static Arbitrary localDateTime(LocalDateTime median, ChronoUnit unit) { - Objects.requireNonNull(median, "median is null"); - Objects.requireNonNull(unit, "unit is null"); - return size -> { - if(size == 0) { - return Gen.of(median); - } - final LocalDateTime start = median.minus(size, unit); - final LocalDateTime end = median.plus(size, unit); - final long duration = Duration.between(start, end).toMillis(); - final Gen from = Gen.choose(0, duration); - return random -> start.plus(from.apply(random), ChronoUnit.MILLIS); - }; - } - - /** - * Generates arbitrary strings based on a given alphabet represented by gen. - *

- * Example: - *

-     * 
-     * Arbitrary.string(
-     *     Gen.frequency(
-     *         Tuple.of(1, Gen.choose('A', 'Z')),
-     *         Tuple.of(1, Gen.choose('a', 'z')),
-     *         Tuple.of(1, Gen.choose('0', '9'))));
-     * 
-     * 
- * - * @param gen A character generator - * @return a new Arbitrary of String - */ - static Arbitrary string(Gen gen) { - return size -> random -> Gen.choose(0, size).map(i -> { - final char[] chars = new char[i]; - for (int j = 0; j < i; j++) { - chars[j] = gen.apply(random); - } - return new String(chars); - }).apply(random); - } - - /** - * Generates arbitrary lists based on a given element generator arbitraryT. - *

- * Example: - *

-     * 
-     * Arbitrary.list(Arbitrary.integer());
-     * 
-     * 
- * - * @param arbitraryT Arbitrary elements of type T - * @param Component type of the List - * @return a new Arbitrary of List<T> - */ - static Arbitrary> list(Arbitrary arbitraryT) { - return size -> { - final Gen genT = arbitraryT.apply(size); - return random -> List.fill(Gen.choose(0, size).apply(random), () -> genT.apply(random)); - }; - } - - /** - * Generates arbitrary streams based on a given element generator arbitraryT. - *

- * Example: - *

-     * 
-     * Arbitrary.stream(Arbitrary.integer());
-     * 
-     * 
- * - * @param arbitraryT Arbitrary elements of type T - * @param Component type of the Stream - * @return a new Arbitrary of Stream<T> - */ - static Arbitrary> stream(Arbitrary arbitraryT) { - return size -> { - final Gen genT = arbitraryT.apply(size); - return random -> Stream.continually(() -> genT.apply(random)) - .take(Gen.choose(0, size).apply(random)); - }; - } -} diff --git a/vavr-test/src/main/java/io/vavr/test/CheckResult.java b/vavr-test/src/main/java/io/vavr/test/CheckResult.java deleted file mode 100644 index bd9b1101d7..0000000000 --- a/vavr-test/src/main/java/io/vavr/test/CheckResult.java +++ /dev/null @@ -1,411 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -import io.vavr.Tuple; -import io.vavr.control.Option; - -import java.io.Serializable; -import java.util.Objects; - -/** - * Represents the result of a property check which is - * - *
    - *
  • {@code Satisfied}, if all tests satisfied the given property
  • - *
  • {@code Falsified}, if a counter-example could be discovered that falsified the given property
  • - *
  • {@code Erroneous}, if an exception occurred executing the property check
  • - *
- * - * Please note that a {@code Satisfied} property check may be {@code Exhausted}, if the property is an implication - * and no sample could be found that satisfied the pre-condition. In this case the post-condition is satisfied by - * definition (see ex falso quodlibet). - * - * @author Daniel Dietrich - */ -public interface CheckResult { - - /** - * If this check result is satisfied as specified above. - * - * @return true, if this check result is satisfied, false otherwise - */ - boolean isSatisfied(); - - /** - * If this check result is falsified as specified above. - * - * @return true, if this check result is falsified, false otherwise - */ - boolean isFalsified(); - - /** - * If this check result is erroneous as specified above. - * - * @return true, if this check result is erroneous, false otherwise - */ - boolean isErroneous(); - - /** - * If this check result is exhausted as specified above. - * - * @return true, if this check result is exhausted, false otherwise - */ - boolean isExhausted(); - - /** - * The name of the checked property this result refers to. - * - * @return a property name - */ - String propertyName(); - - /** - * The number of checks performed using random generated input data. - * - * @return the number of checks performed - */ - int count(); - - /** - * An optional sample which falsified the property or which lead to an error. - * - * @return an optional sample - */ - Option sample(); - - /** - * An optional error. - * - * @return an optional error - */ - Option error(); - - /** - * Asserts that this CheckResult is satisfied. - * - * @throws AssertionError if this CheckResult is not satisfied. - */ - default void assertIsSatisfied() { - if (!isSatisfied()) { - throw new AssertionError("Expected satisfied check result but was " + this); - } - } - - /** - * Asserts that this CheckResult is satisfied with a given exhausted state. - * - * @param exhausted The exhausted state to be checked in the case of a satisfied CheckResult. - * @throws AssertionError if this CheckResult is not satisfied or the exhausted state does not match. - */ - default void assertIsSatisfiedWithExhaustion(boolean exhausted) { - if (!isSatisfied()) { - throw new AssertionError("Expected satisfied check result but was " + this); - } else if (isExhausted() != exhausted) { - throw new AssertionError("Expected satisfied check result to be " + (exhausted ? "" : "not ") + "exhausted but was: " + this); - } - } - - /** - * Asserts that this CheckResult is falsified. - * - * @throws AssertionError if this CheckResult is not falsified. - */ - default void assertIsFalsified() { - if (!isFalsified()) { - throw new AssertionError("Expected falsified check result but was " + this); - } - } - - /** - * Asserts that this CheckResult is erroneous. - * - * @throws AssertionError if this CheckResult is not erroneous. - */ - default void assertIsErroneous() { - if (!isErroneous()) { - throw new AssertionError("Expected erroneous check result but was " + this); - } - } - - /** - * Represents a satisfied property check. - */ - class Satisfied implements CheckResult, Serializable { - - private static final long serialVersionUID = 1L; - - private final String propertyName; - private final int count; - private final boolean exhausted; - - Satisfied(String propertyName, int count, boolean exhausted) { - this.propertyName = propertyName; - this.count = count; - this.exhausted = exhausted; - } - - @Override - public boolean isSatisfied() { - return true; - } - - @Override - public boolean isFalsified() { - return false; - } - - @Override - public boolean isErroneous() { - return false; - } - - @Override - public boolean isExhausted() { - return exhausted; - } - - @Override - public String propertyName() { - return propertyName; - } - - @Override - public int count() { - return count; - } - - @Override - public Option sample() { - return Option.none(); - } - - @Override - public Option error() { - return Option.none(); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } else if (o instanceof Satisfied) { - final Satisfied that = (Satisfied) o; - return Objects.equals(this.propertyName, that.propertyName) - && this.count == that.count - && this.exhausted == that.exhausted; - } else { - return false; - } - } - - @Override - public int hashCode() { - return Objects.hash(propertyName, count, exhausted); - } - - @Override - public String toString() { - return String.format("%s(propertyName = %s, count = %s, exhausted = %s)", getClass().getSimpleName(), propertyName, count, exhausted); - } - } - - /** - * Represents a falsified property check. - */ - class Falsified implements CheckResult, Serializable { - - private static final long serialVersionUID = 1L; - - private final String propertyName; - private final int count; - private final Tuple sample; - - Falsified(String propertyName, int count, Tuple sample) { - this.propertyName = propertyName; - this.count = count; - this.sample = sample; - } - - @Override - public boolean isSatisfied() { - return false; - } - - @Override - public boolean isFalsified() { - return true; - } - - @Override - public boolean isErroneous() { - return false; - } - - @Override - public boolean isExhausted() { - return false; - } - - @Override - public String propertyName() { - return propertyName; - } - - @Override - public int count() { - return count; - } - - @Override - public Option sample() { - return Option.some(sample); - } - - @Override - public Option error() { - return Option.none(); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } else if (o instanceof Falsified) { - final Falsified that = (Falsified) o; - return Objects.equals(this.propertyName, that.propertyName) - && this.count == that.count - && Objects.equals(this.sample, that.sample); - } else { - return false; - } - } - - @Override - public int hashCode() { - return Objects.hash(propertyName, count, sample); - } - - @Override - public String toString() { - return String.format("%s(propertyName = %s, count = %s, sample = %s)", getClass().getSimpleName(), propertyName, count, sample); - } - } - - /** - * Represents an erroneous property check. - */ - class Erroneous implements CheckResult, Serializable { - - private static final long serialVersionUID = 1L; - - private final String propertyName; - private final int count; - private final Error error; - private final Option sample; - - Erroneous(String propertyName, int count, Error error, Option sample) { - this.propertyName = propertyName; - this.count = count; - this.error = error; - this.sample = sample; - } - - @Override - public boolean isSatisfied() { - return false; - } - - @Override - public boolean isFalsified() { - return false; - } - - @Override - public boolean isErroneous() { - return true; - } - - @Override - public boolean isExhausted() { - return false; - } - - @Override - public String propertyName() { - return propertyName; - } - - @Override - public int count() { - return count; - } - - @Override - public Option sample() { - return sample; - } - - @Override - public Option error() { - return Option.some(error); - } - - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } else if (o instanceof Erroneous) { - final Erroneous that = (Erroneous) o; - return Objects.equals(this.propertyName, that.propertyName) - && this.count == that.count - && deepEquals(this.error, that.error) - && Objects.equals(this.sample, that.sample); - } else { - return false; - } - } - - boolean deepEquals(Throwable t1, Throwable t2) { - return (t1 == null && t2 == null) || ( - t1 != null && t2 != null - && Objects.equals(t1.getMessage(), t2.getMessage()) - && deepEquals(t1.getCause(), t2.getCause()) - ); - } - - @Override - public int hashCode() { - return Objects.hash(propertyName, count, deepHashCode(error), sample); - } - - int deepHashCode(Throwable t) { - if (t == null) { - return 0; - } else { - return Objects.hash(t.getMessage(), deepHashCode(t.getCause())); - } - } - - @Override - public String toString() { - return String.format("%s(propertyName = %s, count = %s, error = %s, sample = %s)", getClass().getSimpleName(), propertyName, count, error.getMessage(), sample); - } - } -} diff --git a/vavr-test/src/main/java/io/vavr/test/Checkable.java b/vavr-test/src/main/java/io/vavr/test/Checkable.java deleted file mode 100644 index 40beeddfb9..0000000000 --- a/vavr-test/src/main/java/io/vavr/test/Checkable.java +++ /dev/null @@ -1,119 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; -import java.util.function.Supplier; - -/** - * Interface for checkable properties, allowing composition via {@linkplain #and(Checkable)} and {@linkplain #or(Checkable)}. - * - * @author Daniel Dietrich - */ -@FunctionalInterface -public interface Checkable { - - /** - * A thread-safe, equally distributed random number generator. - */ - Supplier RNG = ThreadLocalRandom::current; - - /** - * Default size hint for generators: 100 - */ - int DEFAULT_SIZE = 100; - - /** - * Default tries to check a property: 1000 - */ - int DEFAULT_TRIES = 1000; - - /** - * Checks this property. - * - * @param randomNumberGenerator An implementation of {@link java.util.Random}. - * @param size A (not necessarily positive) size hint. - * @param tries A non-negative number of tries to falsify the given property. - * @return A {@linkplain CheckResult} - */ - CheckResult check(Random randomNumberGenerator, int size, int tries); - - /** - * Checks this property using the default random number generator {@link #RNG}. - * - * @param size A (not necessarily positive) size hint. - * @param tries A non-negative number of tries to falsify the given property. - * @return A {@linkplain CheckResult} - */ - default CheckResult check(int size, int tries) { - if (tries < 0) { - throw new IllegalArgumentException("tries < 0"); - } - return check(RNG.get(), size, tries); - } - - /** - * Checks this property using the default random number generator {@link #RNG} by calling {@link #check(int, int)}, - * where size is {@link #DEFAULT_SIZE} and tries is {@link #DEFAULT_TRIES}. - * - * @return A {@linkplain CheckResult} - */ - default CheckResult check() { - return check(RNG.get(), DEFAULT_SIZE, DEFAULT_TRIES); - } - - /** - * Returns a new Checkable which is satisfied if this Checkable and the given checkable are satisfied. - *

- * First this Checkable is checked. - * - * @param checkable A Checkable - * @return A new Checkable - */ - default Checkable and(Checkable checkable) { - return (rng, size, tries) -> { - final CheckResult result = check(rng, size, tries); - if (result.isSatisfied()) { - return checkable.check(rng, size, tries); - } else { - return result; - } - }; - } - - /** - * Returns a new Checkable which is satisfied if this Checkable or the given checkable are satisfied. - *

- * First this Checkable is checked. - * - * @param checkable A Checkable - * @return A new Checkable - */ - default Checkable or(Checkable checkable) { - return (rng, size, tries) -> { - final CheckResult result = check(rng, size, tries); - if (result.isSatisfied()) { - return result; - } else { - return checkable.check(rng, size, tries); - } - }; - } -} diff --git a/vavr-test/src/main/java/io/vavr/test/Gen.java b/vavr-test/src/main/java/io/vavr/test/Gen.java deleted file mode 100644 index bf824bac8f..0000000000 --- a/vavr-test/src/main/java/io/vavr/test/Gen.java +++ /dev/null @@ -1,450 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -import io.vavr.Tuple2; -import io.vavr.collection.Iterator; -import io.vavr.collection.List; -import io.vavr.collection.Stream; -import io.vavr.collection.Vector; - -import java.util.Objects; -import java.util.Random; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; - -/** - * Generators are the building blocks for providing arbitrary objects. - *

- * To ease the creation of Arbitraries, Gen is a FunctionalInterface which extends {@code Function}. - *

- * Gen objects are obtained via one of the methods {@code choose}, {@code fail}, {@code frequency}, {@code of} and - * {@code oneOf}. - *

- * Given Gen objects may be transformed using one of the methods {@code filter}, {@code map} and {@code flatMap}. - *

- * A simple way to obtain an Arbitrary of a Gen is to call {@linkplain Gen#arbitrary()}. - * This will ignore the size hint of Arbitrary. - * - * @param type of generated objects - * @author Daniel Dietrich - * @see Arbitrary - */ -@FunctionalInterface -public interface Gen { - - /** - * Functional interface of this generator. - * - * @param random a random number generator - * @return A generated value of type T. - */ - T apply(Random random); - - /** - * A generator which constantly returns t. - * - * @param t A value. - * @param Type of t. - * @return A new T generator - */ - static Gen of(T t) { - return ignored -> t; - } - - static Gen of(T seed, Function next) { - Objects.requireNonNull(next, "next is null"); - final Iterator iterator = Iterator.iterate(seed, next); - return ignored -> iterator.next(); - } - - /** - * Chooses an int between min and max, bounds inclusive and numbers distributed according to the distribution of - * the underlying random number generator. - *

- * Note: min and max are internally swapped if min > max. - * - * @param min lower bound - * @param max upper bound - * @return A new int generator - */ - static Gen choose(int min, int max) { - if (min == max) { - return ignored -> min; - } else { - final int _min = Math.min(min, max); - final int _max = Math.max(min, max); - return rng -> rng.nextInt(Math.abs(_max - _min) + 1) + _min; - } - } - - /** - * Chooses a long between min and max, bounds inclusive and numbers distributed according to the distribution of - * the underlying random number generator. - *

- * Note: min and max are internally swapped if min > max. - * - * @param min lower bound - * @param max upper bound - * @return A new long generator - */ - static Gen choose(long min, long max) { - if (min == max) { - return ignored -> min; - } else { - return random -> { - final double d = random.nextDouble(); - final long _min = Math.min(min, max); - final long _max = Math.max(min, max); - return (long) ((d * _max) + ((1.0 - d) * _min) + d); - }; - } - } - - /** - * Chooses a double between min and max, bounds inclusive and numbers distributed according to the distribution - * of the underlying random number generator. - *

- * Note: min and max are internally swapped if min > max. - * - * @param min lower bound - * @param max upper bound - * @return A new double generator - * @throws IllegalArgumentException if min or max is infinite, min or max is not a number (NaN) - */ - static Gen choose(double min, double max) { - if (Double.isInfinite(min)) { - throw new IllegalArgumentException("min is infinite"); - } - if (Double.isInfinite(max)) { - throw new IllegalArgumentException("max is infinite"); - } - if (Double.isNaN(min)) { - throw new IllegalArgumentException("min is not a number (NaN)"); - } - if (Double.isNaN(max)) { - throw new IllegalArgumentException("max is not a number (NaN)"); - } - if (min == max) { - return ignored -> min; - } else { - return random -> { - final double d = random.nextDouble(); - final double _min = Math.min(min, max); - final double _max = Math.max(min, max); - return d * _max + (1.0 - d) * _min; - }; - } - } - - /** - * Chooses a char between min and max, bounds inclusive and chars distributed according to the underlying random - * number generator. - *

- * Note: min and max are internally swapped if min > max. - * - * @param min lower bound - * @param max upper bound - * @return A new char generator - */ - static Gen choose(char min, char max) { - if (min == max) { - return ignored -> min; - } else { - return Gen.choose((int) min, (int) max).map(i -> (char) (int) i); - } - } - - /** - * Chooses a char from all chars in the array - * - * @param characters array with the characters to choose from - * @return A new array generator - */ - static Gen choose(char... characters) { - Objects.requireNonNull(characters, "characters is null"); - final Character[] validCharacters = List.ofAll(characters).toJavaArray(Character[]::new); - return choose(validCharacters); - } - - /** - * Chooses an enum value from all the enum constants defined in the enumerated type. - * - * @param clazz Enum class - * @param type of enum constants - * @return A new enum generator - */ - static > Gen choose(Class clazz) { - Objects.requireNonNull(clazz, "clazz is null"); - return Gen.choose(clazz.getEnumConstants()); - } - - /** - * Chooses a value from all values in the array. - * - * @param values array with the values to choose from - * @param value type - * @return A new array generator - */ - @SafeVarargs - @SuppressWarnings("varargs") - static Gen choose(T... values) { - Objects.requireNonNull(values, "values is null"); - if (values.length == 0) { - return Gen.fail("Empty array"); - } else { - return Gen.choose(0, values.length - 1).map(i -> values[i]); - } - } - - /** - * Chooses a value from all values in the iterable - * - * @param values iterable with the values to choose from. - * @param value type - * @return A new iterable generator - */ - static Gen choose(Iterable values) { - Objects.requireNonNull(values, "values is null"); - final Iterator iterator = Iterator.ofAll(values); - if (!iterator.hasNext()) { - throw new IllegalArgumentException("Empty iterable"); - } - @SuppressWarnings("unchecked") - final T[] array = (T[]) iterator.toJavaArray(); - return choose(array); - } - - /** - * A failing generator which throws a RuntimeException("failed"). - * - * @param Type of values theoretically generated. - * @return A new generator which always fails with the message "failed" - */ - static Gen fail() { - return fail("failed"); - } - - /** - * A failing generator which throws a RuntimeException. - * - * @param message Message thrown. - * @param Type of values theoretically generated. - * @return A new generator which always fails with the given message - */ - static Gen fail(String message) { - return ignored -> { - throw new RuntimeException(message); - }; - } - - /** - * Chooses one of the given generators according to their frequency. - * Only generators with positive frequencies are used in returned - * generator. - * - * @param generators A non-empty array of Tuples (frequency, generator) - * @param Type to be generated - * @return A new T generator - * @throws java.lang.NullPointerException if generators is null - * @throws java.lang.IllegalArgumentException if generators doesn't contain any generator with positive frequency - */ - @SuppressWarnings("varargs") - @SafeVarargs - static Gen frequency(Tuple2>... generators) { - Objects.requireNonNull(generators, "generators is null"); - if (generators.length == 0) { - throw new IllegalArgumentException("generators is empty"); - } - final Iterable>> iterable = Stream.of(generators); - return frequency(iterable); - } - - /** - * Chooses one of the given generators according to their frequency. - * Only generators with positive frequencies ares used in returned - * generator. - * - * @param generators A non-empty traversable of Tuples (frequency, generator) - * @param Type to be generated - * @return A new T generator - * @throws java.lang.NullPointerException if generators is null - * @throws java.lang.IllegalArgumentException if generators doesn't contain any generator with positive frequency - */ - static Gen frequency(Iterable>> generators) { - Objects.requireNonNull(generators, "generators is null"); - final Vector>> filtered = Iterator.ofAll(generators) - .filter(t -> t._1() > 0).toVector(); - if (filtered.isEmpty()) { - throw new IllegalArgumentException("no generator with positive weight"); - } - final int size = filtered.map(t -> t._1).sum().intValue(); - return choose(1, size).flatMap(n -> GenModule.frequency(n, filtered.iterator())); - } - - /** - * Intersperse values from this generator instance with those of another. - * - * @param other another T generator to accept values from. - * @return A new T generator - */ - default Gen intersperse(Gen other) { - final Iterator> iter = Iterator.continually(this).intersperse(other); - return random -> iter.get().apply(random); - } - - /** - * Randomly chooses one of the given generators. - * - * @param generators A non-empty array of generators - * @param Type to be generated - * @return A new T generator - * @throws java.lang.NullPointerException if generators is null - * @throws java.lang.IllegalArgumentException if generators is empty - */ - @SafeVarargs - static Gen oneOf(Gen... generators) { - Objects.requireNonNull(generators, "generators is null"); - if (generators.length == 0) { - throw new IllegalArgumentException("generators is empty"); - } - return choose(0, generators.length - 1).flatMap(i -> generators[i]); - } - - /** - * Randomly chooses one of the given generators. - * - * @param generators A non-empty Iterable of generators - * @param Type to be generated - * @return A new T generator - * @throws java.lang.NullPointerException if generators is null - * @throws java.lang.IllegalArgumentException if generators is empty - */ - static Gen oneOf(Iterable> generators) { - Objects.requireNonNull(generators, "generators is null"); - final Stream> stream = Stream.ofAll(generators); - if (stream.isEmpty()) { - throw new IllegalArgumentException("generators is empty"); - } - @SuppressWarnings("unchecked") - final Gen[] array = stream.toJavaArray(Gen[]::new); - return oneOf(array); - } - - /** - * Converts this Gen to an Arbitrary - * - * @return An arbitrary which returns this generator regardless of the provided size hint n - */ - default Arbitrary arbitrary() { - return n -> this; - } - - /** - * Returns a generator based on this generator which produces values that fulfill the given predicate. - * - * @param predicate A predicate - * @return A new generator - */ - default Gen filter(Predicate predicate) { - Objects.requireNonNull(predicate, "predicate is null"); - return random -> { - int count = 0; - final int filterThreshold = Integer.MAX_VALUE; - T t; - while (!predicate.test(t = apply(random))) { - // it may take a looooooong time to hit this condition! - if (++count == filterThreshold) { - throw new IllegalStateException("empty filter"); - } - } - return t; - }; - } - - /** - * Maps generated Ts to Us. - * - * @param mapper A function that maps a generated T to a new generator which generates objects of type U. - * @param Type of generated objects of the new generator - * @return A new generator - */ - default Gen flatMap(Function> mapper) { - Objects.requireNonNull(mapper, "mapper is null"); - return random -> mapper.apply(apply(random)).apply(random); - } - - /** - * Maps generated Ts to Us. - * - * @param mapper A function that maps a generated T to an object of type U. - * @param Type of the mapped object - * @return A new generator - */ - default Gen map(Function mapper) { - Objects.requireNonNull(mapper, "mapper is null"); - return random -> mapper.apply(apply(random)); - } - - default Gen peek(Consumer action) { - return random -> { - final T t = apply(random); - action.accept(t); - return t; - }; - } - - /** - * Transforms this {@code Gen}. - * - * @param f A transformation - * @param Type of transformation result - * @return An instance of type {@code U} - * @throws NullPointerException if {@code f} is null - */ - default U transform(Function, ? extends U> f) { - Objects.requireNonNull(f, "f is null"); - return f.apply(this); - } -} - -interface GenModule { - - /** - * Chooses a Gen according to the given frequencies. - * - * @param n a random value between 0 and sum(frequencies) - 1 - * @param iter a non-empty Iterator of (frequency, Gen) pairs - * @param type of generated values - * @return A value generator, choosen according to the given frequencies and the underlying n - */ - static Gen frequency(int n, java.util.Iterator>> iter) { - do { - final Tuple2> freqGen = iter.next(); - final int k = freqGen._1; - if (n <= k) { - return freqGen._2; - } else { - n = n - k; - } - } while (true); - } - -} diff --git a/vavr-test/src/main/java/io/vavr/test/package-info.java b/vavr-test/src/main/java/io/vavr/test/package-info.java deleted file mode 100644 index 9a2150e6e1..0000000000 --- a/vavr-test/src/main/java/io/vavr/test/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * A property check framework built around {@linkplain io.vavr.test.Property} which integrates well with unit test frameworks like junit. - */ -package io.vavr.test; diff --git a/vavr-test/src/test/java/io/vavr/test/ArbitraryTest.java b/vavr-test/src/test/java/io/vavr/test/ArbitraryTest.java deleted file mode 100644 index bb1433f51b..0000000000 --- a/vavr-test/src/test/java/io/vavr/test/ArbitraryTest.java +++ /dev/null @@ -1,353 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -import io.vavr.Function1; -import io.vavr.Tuple; -import io.vavr.collection.Iterator; -import io.vavr.collection.List; -import io.vavr.collection.Stream; -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Comparator; -import java.util.Random; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -public class ArbitraryTest { - - // equally distributed random number generator - private static final Random RANDOM = new Random(); - - // predictable random number generator (seed = 1) - private Random predictableRandom = new Random(1L); - // -- apply - - @Test - public void shouldApplyIntegerObject() { - final Gen> gen = new ArbitraryBinaryTree(0, 0).apply(0); - assertThat(gen).isNotNull(); - } - - // -- flatMap - - @Test - public void shouldFlatMapArbitrary() { - final Arbitrary arbitraryInt = size -> Gen.choose(-size, size); - final Arbitrary> arbitraryTree = arbitraryInt.flatMap(i -> new ArbitraryBinaryTree(-i, i)); - assertThat(arbitraryTree.apply(0).apply(RANDOM)).isNotNull(); - } - - // -- map - - @Test - public void shouldMapArbitrary() { - final Arbitrary arbitraryInt = size -> Gen.choose(-size, size); - final Arbitrary> arbitraryTree = arbitraryInt.map(BinaryTree::leaf); - assertThat(arbitraryTree.apply(0).apply(RANDOM)).isNotNull(); - } - - // -- filter - - @Test - public void shouldFilterArbitrary() { - final Arbitrary ints = Arbitrary.integer(); - final Arbitrary evenInts = ints.filter(i -> i % 2 == 0); - assertThat(evenInts.apply(10).apply(RANDOM)).isNotNull(); - } - - // -- peek - - @Test - public void shouldPeekArbitrary() { - final int[] actual = new int[] { Integer.MIN_VALUE }; - final int expected = Arbitrary.integer().peek(i -> actual[0] = i).apply(10).apply(RANDOM); - assertThat(actual[0]).isEqualTo(expected); - } - - // factory methods - - @Test - public void shouldCreateArbitraryInteger() { - final Arbitrary arbitrary = Arbitrary.integer(); - final Integer actual = arbitrary.apply(10).apply(RANDOM); - assertThat(actual).isNotNull(); - } - - @Test - public void shouldCreateArbitraryString() { - final Arbitrary arbitrary = Arbitrary.string(Gen.choose('a', 'z')); - final String actual = arbitrary.apply(10).apply(RANDOM); - assertThat(actual).isNotNull(); - } - - @Test - public void shouldCreateArbitraryList() { - final Arbitrary> arbitrary = Arbitrary.list(Arbitrary.integer()); - final List actual = arbitrary.apply(10).apply(RANDOM); - assertThat(actual).isNotNull(); - } - - @Test - public void shouldCreateArbitraryStream() { - final Arbitrary> arbitrary = Arbitrary.stream(Arbitrary.integer()); - final Stream actual = arbitrary.apply(10).apply(RANDOM); - assertThat(actual).isNotNull(); - } - - @Test - public void shouldCreateFixedContentArbitrary() { - final Gen arbitrary = Arbitrary.of("test", "content").apply(10); - for (int i = 0; i < 100; i++) { - assertThat(arbitrary.apply(RANDOM)).isIn("test", "content"); - } - } - - @Test - public void shouldCreateNonDistinctArbitrary() { - final Gen arbitrary = Arbitrary.string(Gen.choose('a', 'b')).apply(2); - List.range(0, 1000) - .map(i -> arbitrary.apply(RANDOM)) - .groupBy(Function1.identity()) - .forEach((key, value) -> assertThat(value.length()) - .describedAs(key) - .isGreaterThan(1)); - } - - @Test - public void shouldCreateDistinctArbitrary() { - final Gen distinctArbitrary = Arbitrary.string(Gen.choose('a', 'b')).distinct().apply(100); - List.range(0, 1000) - .map(i -> distinctArbitrary.apply(RANDOM)) - .groupBy(Function1.identity()) - .forEach((key, value) -> assertThat(value.length()) - .describedAs(key) - .isEqualTo(1)); - } - - @Test - public void shouldCreateDistinctByArbitrary() { - final Gen distinctByArbitrary = Arbitrary.string(Gen.choose('a', 'b')) - .distinctBy(Comparator.naturalOrder()).apply(100); - List.range(0, 10000) - .map(i -> distinctByArbitrary.apply(RANDOM)) - .groupBy(Function1.identity()) - .forEach((key, value) -> assertThat(value.length()) - .describedAs(key) - .isEqualTo(1)); - } - - @Test - public void shouldCreateInterspersedFixedContentArbitrary() { - final Gen arbitrary = Arbitrary.of("test") - .intersperse(Arbitrary.of("content")) - .apply(10); - for (int i = 0; i < 100; i++) { - assertThat(arbitrary.apply(RANDOM)).isIn("test", "content"); - } - } - - @Test - public void shouldCreateInterspersedFixedContentArbitraryWithConstantOrder() { - final Gen arbitrary = Arbitrary.of("test") - .intersperse(Arbitrary.of("content")) - .apply(10); - final Iterator> generatedStringPairs = Stream.range(0, 10) - .map(i -> arbitrary.apply(RANDOM)) - .grouped(2); - for (Stream stringPairs : generatedStringPairs) { - assertThat(stringPairs.mkString(",")).isEqualTo("test,content"); - } - - } - - @Test - public void shouldCreateCharArrayArbitrary() { - final Gen arbitrary = Arbitrary.string(Gen.choose("test".toCharArray())) - .filter(s -> !"".equals(s)) - .apply(1); - for (int i = 0; i < 100; i++) { - assertThat(arbitrary.apply(RANDOM)).isIn("t", "e", "s"); - } - } - - @Test - public void shouldCreateArbitraryStreamAndEvaluateAllElements() { - final Arbitrary> arbitrary = Arbitrary.stream(Arbitrary.integer()); - final Stream actual = arbitrary.apply(10).apply(new Random() { - private static final long serialVersionUID = 1L; - @Override - public int nextInt(int bound) { - return bound - 1; - } - }); - assertThat(actual.length()).isEqualTo(10); - } - - @Test - public void shouldCreateArbitraryLocalDateTime(){ - final Arbitrary date = Arbitrary.localDateTime(); - - assertThat(date).isNotNull(); - } - - - @Test - public void shouldNotAcceptNullMedianLocalDateTime(){ - assertThrows(NullPointerException.class, () -> Arbitrary.localDateTime(null, ChronoUnit.DAYS)); - } - - @Test - public void shouldNotAcceptNullChronoUnit(){ - assertThrows(NullPointerException.class, () -> Arbitrary.localDateTime(LocalDateTime.now(), null)); - } - - @Test - public void shouldCreateArbitraryLocalDateTimeAdjustedWithGivenChronoUnit(){ - final LocalDateTime median = LocalDateTime.of(2017, 2, 17, 3, 40); - final Arbitrary arbitrary = Arbitrary.localDateTime(median, ChronoUnit.YEARS); - - final LocalDateTime date = arbitrary.apply(100).apply(predictableRandom); - - assertThat(date).isEqualTo("2063-04-22T01:46:10.312"); - } - - @Test - public void shouldCreateMedianLocalDateTimeIfSizeIsZero(){ - final LocalDateTime median = LocalDateTime.now(); - - final Arbitrary arbitrary = Arbitrary.localDateTime(median, ChronoUnit.DAYS); - - final LocalDateTime date = arbitrary.apply(0).apply(RANDOM); - - assertThat(date).isEqualTo(median); - } - - @Test - public void shouldCreateDatesInInRangeOfSize(){ - final LocalDateTime median = LocalDateTime.now(); - final Arbitrary arbitrary = Arbitrary.localDateTime(median, ChronoUnit.DAYS); - - Property.def("With size of 100 days, dates should be in range of +/- 100 days") - .forAll(arbitrary) - .suchThat(d -> d.isAfter(median.minusDays(100)) && d.isBefore(median.plusDays(100))) - .check(100, 1000); - } - - @Test - public void shouldIgnoreNegativeSignInRangeOfDates(){ - final LocalDateTime median = LocalDateTime.now(); - final Arbitrary arbitrary = Arbitrary.localDateTime(median, ChronoUnit.DAYS); - - Property.def("With negative size of -100 days, dates should be in range of +/- 100 days") - .forAll(arbitrary) - .suchThat(d -> d.isAfter(median.minusDays(100)) && d.isBefore(median.plusDays(100))) - .check(-100, 1000); - } - - @Test - public void shouldGenerateTwoDifferentSuccessiveDates(){ - final Arbitrary dates = Arbitrary.localDateTime(); - final LocalDateTime firstDate = dates.apply(100).apply(RANDOM); - final LocalDateTime secondDate = dates.apply(100).apply(RANDOM); - - assertThat(firstDate).isNotEqualTo(secondDate); - } - - // -- transform - - @Test - public void shouldTransformArbitrary() { - final Arbitrary arbitrary = ignored -> Gen.of(1); - final String s = arbitrary.transform(a -> a.apply(0).apply(RANDOM).toString()); - assertThat(s).isEqualTo("1"); - } - - // helpers - - /** - * Represents arbitrary binary trees of a certain depth n with values of type int. - */ - static class ArbitraryBinaryTree implements Arbitrary> { - - final int minValue; - final int maxValue; - - ArbitraryBinaryTree(int minValue, int maxValue) { - this.minValue = Math.min(minValue, maxValue); - this.maxValue = Math.max(minValue, maxValue); - } - - @Override - public Gen> apply(int n) { - return random -> Gen.choose(minValue, maxValue).flatMap(value -> { - if (n == 0) { - return Gen.of(BinaryTree.leaf(value)); - } else { - return Gen.frequency( - Tuple.of(1, Gen.of(BinaryTree.leaf(value))), - Tuple.of(4, Gen.of(BinaryTree.branch(apply(n / 2).apply(random), value, apply(n / 2).apply(random)))) - ); - } - } - ).apply(random); - } - } - - interface BinaryTree { - - static Branch branch(BinaryTree left, T value, BinaryTree right) { - return new Branch<>(left, value, right); - } - - static Branch leaf(T value) { - return new Branch<>(empty(), value, empty()); - } - - static Empty empty() { - return Empty.instance(); - } - - class Branch implements BinaryTree { - - final BinaryTree left; - final T value; - final BinaryTree right; - - Branch(BinaryTree left, T value, BinaryTree right) { - this.left = left; - this.value = value; - this.right = right; - } - } - - class Empty implements BinaryTree { - - private static final Empty INSTANCE = new Empty<>(); - - @SuppressWarnings("unchecked") - static Empty instance() { - return (Empty) INSTANCE; - } - } - } -} diff --git a/vavr-test/src/test/java/io/vavr/test/CheckResultTest.java b/vavr-test/src/test/java/io/vavr/test/CheckResultTest.java deleted file mode 100644 index 32f9e49152..0000000000 --- a/vavr-test/src/test/java/io/vavr/test/CheckResultTest.java +++ /dev/null @@ -1,371 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -import io.vavr.Tuple; -import io.vavr.control.Option; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.Objects; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -public class CheckResultTest { - - static final CheckResult.Satisfied SATISFIED = new CheckResult.Satisfied("test", 0, false); - static final CheckResult.Falsified FALSIFIED = new CheckResult.Falsified("test", 0, Tuple.of(1)); - static final CheckResult.Erroneous ERRONEOUS = new CheckResult.Erroneous("test", 0, new Error("test"), Option.none()); - - // -- Satisfied - - @Test - public void shouldBeSatisfiedWhenIsSatisfied() { - assertThat(SATISFIED.isSatisfied()).isTrue(); - } - - @Test - public void shouldNotBeFalsifiedWhenIsSatisfied() { - assertThat(SATISFIED.isFalsified()).isFalse(); - } - - @Test - public void shouldNotBeErroneousWhenIsSatisfied() { - assertThat(SATISFIED.isErroneous()).isFalse(); - } - - @Test - public void shouldBeExhaustedWhenIsSatisfiedAndExhausted() { - Assertions.assertThat(new CheckResult.Satisfied("test", 0, true).isExhausted()).isTrue(); - } - - @Test - public void shouldNotBeExhaustedWhenIsSatisfiedAndNotExhausted() { - assertThat(SATISFIED.isExhausted()).isFalse(); - } - - @Test - public void shouldGetPropertyNameOfSatisfied() { - assertThat(SATISFIED.propertyName()).isEqualTo("test"); - } - - @Test - public void shouldGetCountOfSatisfied() { - assertThat(SATISFIED.count()).isEqualTo(0); - } - - @Test - public void shouldHaveNoSampleWhenIsSatisfied() { - assertThat(SATISFIED.sample()).isEqualTo(Option.none()); - } - - @Test - public void shouldHaveNoErrorWhenIsSatisfied() { - assertThat(SATISFIED.error()).isEqualTo(Option.none()); - } - - @Test - public void shouldIdentififyEqualSatisfiedObjectsWhenObjectsAreIdentical() { - final CheckResult.Satisfied satisfied = SATISFIED; - //noinspection EqualsWithItself - assertThat(satisfied.equals(satisfied)).isTrue(); - } - - @Test - public void shouldIdentififyEqualSatisfiedObjectsWhenObjectsHaveSameTypeAndEqualValues() { - final CheckResult.Satisfied satisfied1 = SATISFIED; - final CheckResult.Satisfied satisfied2 = new CheckResult.Satisfied("test", 0, false); - assertThat(satisfied1.equals(satisfied2)).isTrue(); - } - - @Test - public void shouldIdentififyUnequalSatisfiedObjectsWhenTypesAreUnequal() { - final CheckResult.Satisfied satisfied = SATISFIED; - assertThat(satisfied.equals(new Object())).isFalse(); - } - - @Test - public void shouldIdentififyUnequalSatisfiedObjectsWhenValuesAreUnequal() { - final CheckResult.Satisfied satisfied = new CheckResult.Satisfied("test", 1, true); - assertThat(satisfied.equals(new CheckResult.Satisfied("x", 1, true))).isFalse(); - assertThat(satisfied.equals(new CheckResult.Satisfied("test", -1, true))).isFalse(); - assertThat(satisfied.equals(new CheckResult.Satisfied("test", 1, false))).isFalse(); - } - - @Test - public void shouldComputeHashCodeOfSatisfied() { - assertThat(SATISFIED.hashCode()).isEqualTo(Objects.hash("test", 0, false)); - } - - @Test - public void shouldComputeToStringOfSatisfied() { - assertThat(SATISFIED.toString()).isEqualTo("Satisfied(propertyName = test, count = 0, exhausted = false)"); - } - - // -- Falsified - - @Test - public void shouldNotBeSatisfiedWhenIsFalsified() { - assertThat(FALSIFIED.isSatisfied()).isFalse(); - } - - @Test - public void shouldBeFalsifiedWhenIsFalsified() { - assertThat(FALSIFIED.isFalsified()).isTrue(); - } - - @Test - public void shouldNotBeErroneousWhenIsFalsified() { - assertThat(FALSIFIED.isErroneous()).isFalse(); - } - - @Test - public void shouldNotBeExhaustedWhenIsFalsified() { - assertThat(FALSIFIED.isExhausted()).isFalse(); - } - - @Test - public void shouldGetPropertyNameOfFalsified() { - assertThat(FALSIFIED.propertyName()).isEqualTo("test"); - } - - @Test - public void shouldGetCountOfFalsified() { - assertThat(FALSIFIED.count()).isEqualTo(0); - } - - @Test - public void shouldHaveASampleWhenIsFalsified() { - assertThat(FALSIFIED.sample().get()).isEqualTo(Tuple.of(1)); - } - - @Test - public void shouldHaveNoErrorWhenIsFalsified() { - assertThat(FALSIFIED.error()).isEqualTo(Option.none()); - } - - @Test - public void shouldIdentififyEqualFalsifiedObjectsWhenObjectsAreIdentical() { - final CheckResult.Falsified falsified = FALSIFIED; - //noinspection EqualsWithItself - assertThat(falsified.equals(falsified)).isTrue(); - } - - @Test - public void shouldIdentififyEqualFalsifiedObjectsWhenObjectsHaveSameTypeAndEqualValues() { - final CheckResult.Falsified falsified1 = FALSIFIED; - final CheckResult.Falsified falsified2 = new CheckResult.Falsified("test", 0, Tuple.of(1)); - assertThat(falsified1.equals(falsified2)).isTrue(); - } - - @Test - public void shouldIdentififyUnequalFalsifiedObjectsWhenTypesAreUnequal() { - final CheckResult.Falsified falsified = FALSIFIED; - assertThat(falsified.equals(new Object())).isFalse(); - } - - @Test - public void shouldIdentififyUnequalFalsifiedObjectsWhenValuesAreUnequal() { - final CheckResult.Falsified falsified = new CheckResult.Falsified("test", 1, Tuple.of(2)); - assertThat(falsified.equals(new CheckResult.Falsified("x", 1, Tuple.of(2)))).isFalse(); - assertThat(falsified.equals(new CheckResult.Falsified("test", -1, Tuple.of(2)))).isFalse(); - assertThat(falsified.equals(new CheckResult.Falsified("test", 1, Tuple.of(-1)))).isFalse(); - } - - @Test - public void shouldComputeHashCodeOfFalsified() { - assertThat(FALSIFIED.hashCode()).isEqualTo(Objects.hash("test", 0, Tuple.of(1))); - } - - @Test - public void shouldComputeToStringOfFalsified() { - assertThat(FALSIFIED.toString()).isEqualTo("Falsified(propertyName = test, count = 0, sample = (1))"); - } - - // -- Erroneous - - @Test - public void shouldNotBeSatisfiedWhenIsErroneous() { - assertThat(ERRONEOUS.isSatisfied()).isFalse(); - } - - @Test - public void shouldNotBeFalsifiedWhenIsErroneous() { - assertThat(ERRONEOUS.isFalsified()).isFalse(); - } - - @Test - public void shouldBeErroneousWhenIsErroneous() { - assertThat(ERRONEOUS.isErroneous()).isTrue(); - } - - @Test - public void shouldNotBeExhaustedWhenIsErroneous() { - assertThat(ERRONEOUS.isExhausted()).isFalse(); - } - - @Test - public void shouldGetPropertyNameOfErroneous() { - assertThat(ERRONEOUS.propertyName()).isEqualTo("test"); - } - - @Test - public void shouldGetCountOfErroneous() { - assertThat(ERRONEOUS.count()).isEqualTo(0); - } - - @Test - public void shouldHaveNoSampleWhenIsErroneousWithoutSample() { - assertThat(ERRONEOUS.sample()).isEqualTo(Option.none()); - } - - @Test - public void shouldHaveSampleWhenIsErroneousWithSample() { - final CheckResult.Erroneous erroneous = new CheckResult.Erroneous("test", 1, new Error("test"), Option.of(Tuple.of(1))); - assertThat(erroneous.sample().get()).isEqualTo(Tuple.of(1)); - } - - @Test - public void shouldHaveAnErrorWhenIsErroneous() { - assertThat(ERRONEOUS.error().get().getMessage()).isEqualTo("test"); - } - - @Test - public void shouldIdentififyEqualErroneousObjectsWhenObjectsAreIdentical() { - final CheckResult.Erroneous erroneous = ERRONEOUS; - //noinspection EqualsWithItself - assertThat(erroneous.equals(erroneous)).isTrue(); - } - - @Test - public void shouldIdentififyEqualErroneousObjectsWhenObjectsHaveSameTypeAndEqualValues() { - final CheckResult.Erroneous erroneous1 = ERRONEOUS; - final CheckResult.Erroneous erroneous2 = new CheckResult.Erroneous("test", 0, new Error("test"), Option.none()); - assertThat(erroneous1.equals(erroneous2)).isTrue(); - } - - @Test - public void shouldIdentififyUnequalErroneousObjectsWhenTypesAreUnequal() { - final CheckResult.Erroneous erroneous = ERRONEOUS; - assertThat(erroneous.equals(new Object())).isFalse(); - } - - @Test - public void shouldIdentififyUnequalErroneousObjectsWhenValuesAreUnequal() { - final CheckResult.Erroneous erroneous = new CheckResult.Erroneous("test", 1, new Error("error"), Option.none()); - assertThat(erroneous.equals(new CheckResult.Erroneous("x", 1, new Error("error"), Option.none()))).isFalse(); - assertThat(erroneous.equals(new CheckResult.Erroneous("test", -1, new Error("error"), Option.none()))).isFalse(); - assertThat(erroneous.equals(new CheckResult.Erroneous("test", 1, new Error("x"), Option.none()))).isFalse(); - assertThat(erroneous.equals(new CheckResult.Erroneous("test", 1, new Error("error"), Option.some(Tuple.of(1))))).isFalse(); - } - - @Test - public void shouldCheckDeepEqualityOfErroneousErrors() { - Assertions.assertThat(new CheckResult.Erroneous("test", 1, null, Option.none())).isEqualTo(new CheckResult.Erroneous("test", 1, null, Option.none())); - Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, null, Option.none())); - Assertions.assertThat(new CheckResult.Erroneous("test", 1, null, Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())); - Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())).isEqualTo(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())); - Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, new Error("x"), Option.none())); - Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test", new Error("test2")), Option.none())).isEqualTo(new CheckResult.Erroneous("test", 1, new Error("test", new Error("test2")), Option.none())); - Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test", new Error("test2")), Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, new Error("test"), Option.none())); - Assertions.assertThat(new CheckResult.Erroneous("test", 1, new Error("test", new Error("test2")), Option.none())).isNotEqualTo(new CheckResult.Erroneous("test", 1, new Error("test", new Error("x")), Option.none())); - } - - @Test - public void shouldComputeHashCodeOfErroneous() { - assertThat(ERRONEOUS.hashCode()).isEqualTo(Objects.hash("test", 0, ERRONEOUS.deepHashCode(new Error("test")), Option.none())); - } - - @Test - public void shouldComputeToStringOfErroneous() { - assertThat(ERRONEOUS.toString()).isEqualTo("Erroneous(propertyName = test, count = 0, error = test, sample = None)"); - } - - // Assertions - - // -- satisfied - - @Test - public void shouldAssertThatCheckResultIsSatisfied() { - new CheckResult.Satisfied("test", 0, false).assertIsSatisfied(); - } - - @Test - public void shouldThrowWhenAssertThatNonSatisfiedCheckResultIsSatisfied() { - assertThrows(AssertionError.class, () -> new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsSatisfied()); - } - - // -- satisfiedWithExhaustion - - @Test - public void shouldAssertThatCheckResultIsSatisfiedWithExhaustionTrue() { - new CheckResult.Satisfied("test", 0, true).assertIsSatisfiedWithExhaustion(true); - } - - @Test - public void shouldAssertThatCheckResultIsSatisfiedWithExhaustionFalse() { - new CheckResult.Satisfied("test", 0, false).assertIsSatisfiedWithExhaustion(false); - } - - @Test - public void shouldThrowWhenAssertThatNonSatisfiedCheckResultIsSatisfiedWithExhaustionTrue() { - assertThrows(AssertionError.class, () -> new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsSatisfiedWithExhaustion(true)); - } - - @Test - public void shouldThrowWhenAssertThatNonSatisfiedCheckResultIsSatisfiedWithExhaustionFalse() { - assertThrows(AssertionError.class, () -> new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsSatisfiedWithExhaustion(false)); - } - - @Test - public void shouldThrowWhenAssertThatSatisfiedNonExhaustedCheckResultIsSatisfiedWithExhaustionTrue() { - assertThrows(AssertionError.class, () -> new CheckResult.Satisfied("test", 0, false).assertIsSatisfiedWithExhaustion(true)); - } - - @Test - public void shouldThrowWhenAssertThatSatisfiedExhaustedCheckResultIsSatisfiedWithExhaustionFalse() { - assertThrows(AssertionError.class, () -> new CheckResult.Satisfied("test", 0, true).assertIsSatisfiedWithExhaustion(false)); - } - - // -- falsified - - @Test - public void shouldAssertThatCheckResultIsFalsified() { - new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsFalsified(); - } - - @Test - public void shouldThrowWhenAssertThatNonFalsifiedCheckResultIsFalsified() { - assertThrows(AssertionError.class, () -> new CheckResult.Satisfied("test", 0, false).assertIsFalsified()); - } - - // -- erroneous - - @Test - public void shouldAssertThatCheckResultIsErroneous() { - new CheckResult.Erroneous("test", 0, new Error(), Option.none()).assertIsErroneous(); - } - - @Test - public void shouldThrowWhenAssertThatNonErroneousCheckResultIsErroneous() { - assertThrows(AssertionError.class, () -> new CheckResult.Falsified("test", 0, Tuple.empty()).assertIsErroneous()); - } - -} diff --git a/vavr-test/src/test/java/io/vavr/test/ConditionTest.java b/vavr-test/src/test/java/io/vavr/test/ConditionTest.java deleted file mode 100644 index bf881c4f3c..0000000000 --- a/vavr-test/src/test/java/io/vavr/test/ConditionTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2018 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -import io.vavr.test.Property.Condition; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ConditionTest { - - /** - * Def: A 'Condition' is the result of {@code p => q} where {@code p} is a pre-condition and {@code q} is a post-condition. - *

- * The following holds: {@code p => q ≡ ¬p ∨ q} - */ - @Test - public void should() { - assertThat(cond(false, false)).isTrue(); - assertThat(cond(false, true)).isTrue(); - assertThat(cond(true, false)).isFalse(); - assertThat(cond(true, true)).isTrue(); - } - - private boolean cond(boolean p, boolean q) { - return !new Condition(p, q).isFalse(); - } -} diff --git a/vavr-test/src/test/java/io/vavr/test/GenTest.java b/vavr-test/src/test/java/io/vavr/test/GenTest.java deleted file mode 100644 index e2504d1a83..0000000000 --- a/vavr-test/src/test/java/io/vavr/test/GenTest.java +++ /dev/null @@ -1,401 +0,0 @@ -/* ____ ______________ ________________________ __________ - * \ \/ / \ \/ / __/ / \ \/ / \ - * \______/___/\___\______/___/_____/___/\___\______/___/\___\ - * - * Copyright 2014-2025 Vavr, https://vavr.io - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.vavr.test; - -import io.vavr.Tuple; -import io.vavr.collection.Stream; -import io.vavr.Tuple2; -import io.vavr.collection.List; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.Random; -import java.util.function.Predicate; -import java.util.function.Supplier; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -public class GenTest { - - // equally distributed random number generator - static final Random RANDOM = new Random(); - - // number of tries to assert a property - static final int TRIES = 1000; - - // -- of - - @Test - public void shouldIntersperseMultipleGeneratos() throws Exception { - Gen gen = Gen.of(0).intersperse(Gen.of(1)); - assertThat(gen.apply(RANDOM)).isEqualTo(0); - assertThat(gen.apply(RANDOM)).isEqualTo(1); - assertThat(gen.apply(RANDOM)).isEqualTo(0); - assertThat(gen.apply(RANDOM)).isEqualTo(1); - } - @Test - public void shouldCreateConstantGenOfElement() { - final Gen gen = Gen.of(1); - assertThat(gen.apply(RANDOM)).isEqualTo(1); - assertThat(gen.apply(RANDOM)).isEqualTo(1); - assertThat(gen.apply(RANDOM)).isEqualTo(1); - } - - @Test - public void shouldCreateGenOfSeedAndFunction() { - final Gen gen = Gen.of(1, i -> i + 1); - assertThat(gen.apply(RANDOM)).isEqualTo(1); - assertThat(gen.apply(RANDOM)).isEqualTo(2); - assertThat(gen.apply(RANDOM)).isEqualTo(3); - } - - // -- random number generator (rng) - - @Test - public void shouldUseCustomRandomNumberGenerator() { - final Random rng = new Random() { - private static final long serialVersionUID = 1L; - - @Override - public int nextInt(int bound) { - return 0; - } - }; - final Gen gen = Gen.choose(1, 2); - final Number actual = Stream.continually(() -> gen.apply(rng)).take(10).sum(); - assertThat(actual).isEqualTo(10L); - } - - // -- choose(int, int) - - @Test - public void shouldChooseIntBetweenMinMax() { - assertForAll(() -> Gen.choose(-1, 1).apply(RANDOM), i -> i >= -1 && i <= 1); - } - - @Test - public void shouldChooseIntWhenMinEqualsMax() { - assertForAll(() -> Gen.choose(0, 0).apply(RANDOM), i -> i == 0); - } - - // -- choose(long, long) - - @Test - public void shouldChooseLongBetweenMinMax() { - assertForAll(() -> Gen.choose(-1L, 1L).apply(RANDOM), l -> l >= -1L && l <= 1L); - } - - @Test - public void shouldChooseLongWhenMinEqualsMax() { - assertForAll(() -> Gen.choose(0L, 0L).apply(RANDOM), l -> l == 0L); - } - - // -- choose(double, double) - - @Test - public void shouldChooseDoubleBetweenMinMax() { - assertForAll(() -> Gen.choose(-1.0d, 1.0d).apply(RANDOM), d -> d >= -1.0d && d <= 1.0d); - } - - @Test - public void shouldChooseDoubleWhenMinEqualsMax() { - assertForAll(() -> Gen.choose(0.0d, 0.0d).apply(RANDOM), d -> d == 0.0d); - } - - @Test - public void shouldThrowWhenChooseDoubleAndMinIsNegativeInfinite() { - assertThrows(IllegalArgumentException.class, () -> Gen.choose(Double.NEGATIVE_INFINITY, 0.0d)); - } - - @Test - public void shouldThrowWhenChooseDoubleAndMinIsPositiveInfinite() { - assertThrows(IllegalArgumentException.class, () -> Gen.choose(Double.POSITIVE_INFINITY, 0.0d)); - } - - @Test - public void shouldThrowWhenChooseDoubleAndMinIsNotANumber() { - assertThrows(IllegalArgumentException.class, () -> Gen.choose(Double.NaN, 0.0d)); - } - - @Test - public void shouldThrowWhenChooseDoubleAndMaxIsNegativeInfinite() { - assertThrows(IllegalArgumentException.class, () -> Gen.choose(0.0d, Double.NEGATIVE_INFINITY)); - } - - @Test - public void shouldThrowWhenChooseDoubleAndMaxIsPositiveInfinite() { - assertThrows(IllegalArgumentException.class, () -> Gen.choose(0.0d, Double.POSITIVE_INFINITY)); - } - - @Test - public void shouldThrowWhenChooseDoubleAndMaxIsNotANumber() { - assertThrows(IllegalArgumentException.class, () -> Gen.choose(0.0d, Double.NaN)); - } - - // -- choose(char, char) - - @Test - public void shouldChooseCharBetweenMinMax() { - assertForAll(() -> Gen.choose('A', 'Z').apply(RANDOM), c -> c >= 'A' && c <= 'Z'); - } - - @Test - public void shouldChooseCharWhenMinEqualsMax() { - assertForAll(() -> Gen.choose('a', 'a').apply(RANDOM), c -> c == 'a'); - } - - // -- choose(array) - - @Test - public void shouldChooseFromASingleArray() throws Exception { - Integer[] i = { 1 }; - assertForAll(() -> Gen.choose(i).apply(RANDOM), c -> c == 1); - } - - @Test - public void shouldFailOnEmptyArray() throws Exception { - assertThrows(RuntimeException.class, () -> { - Integer[] i = {}; - Gen.choose(i).apply(RANDOM); - }); - } - - // -- Choose(enum) - - enum testEnum { - value1 - } - - @Test - public void shouldChooseFromEnum() throws Exception { - assertForAll(() -> Gen.choose(testEnum.class).apply(RANDOM), e -> Arrays.asList(testEnum.values()).contains(e)); - } - - // -- Choose(iterable) - @Test - public void shouldChooseFromIterable() throws Exception { - List i = List.of(1); - assertForAll(() -> Gen.choose(i).apply(RANDOM), c -> c == 1); - } - - @Test - public void shouldChooseFromIterableWithInstancesOfGenericInterface() { - List> i = List.of(() -> "test", () -> "test"); - - Supplier supplier = Gen.choose(i).apply(RANDOM); - - assertThat(supplier.get()).isEqualTo("test"); - } - - @Test - public void shouldFailOnEmptyIterable() { - assertThrows(RuntimeException.class, () -> { - List i = List.empty(); - Gen.choose(i).apply(RANDOM); - }); - } - - // -- fail - - @Test - public void shouldFailAlwaysWhenCallingFailingGen() { - assertThrows(RuntimeException.class, () -> Gen.fail().apply(RANDOM)); - } - - // -- frequency(VarArgs) - - @Test - public void shouldThrowWhenCallingFrequencyOfVarArgsAndArgIsNull() { - assertThrows(NullPointerException.class, () -> Gen.frequency((Tuple2>) null)); - } - - @Test - public void shouldThrowWhenCallingFrequencyOfVarArgsAndArgIsEmpty() { - assertThrows(IllegalArgumentException.class, () -> { - @SuppressWarnings("unchecked") final Tuple2>[] empty = (Tuple2>[]) new Tuple2[0]; - Gen.frequency(empty); - }); - } - - @Test - public void shouldThrowWhenCallingFrequencyOfVarArgsAndAllFrequenciesAreNonPositive() { - assertThrows(IllegalArgumentException.class, () -> { - final Gen gen = Gen.frequency(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0))); - gen.apply(RANDOM); - }); - } - - @Test - public void shouldIgnoreGeneratorsWithNonPositiveFrequency() { - final Gen gen = Gen.frequency(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0)), Tuple.of(1, Gen.of(1))); - assertForAll(() -> gen.apply(RANDOM), i -> i == 1); - } - - @Test - public void shouldGenerateElementsAccordingToFrequencyGivenVarArgs() { - final Gen gen = Gen.frequency(Tuple.of(0, Gen.of(-1)), Tuple.of(1, Gen.of(1))); - assertForAll(() -> gen.apply(RANDOM), i -> i != -1); - } - - // -- frequency(Iterable) - - @Test - public void shouldThrowWhenCallingFrequencyOfIterableAndArgIsNull() { - assertThrows(NullPointerException.class, () -> Gen.frequency((Iterable>>) null)); - } - - @Test - public void shouldThrowWhenCallingFrequencyOfIterableAndArgIsEmpty() { - assertThrows(IllegalArgumentException.class, () -> Gen.frequency(List.empty())); - } - - @Test - public void shouldThrowWhenCallingFrequencyOfIterableAndAllFrequenciesAreNonPositive() { - assertThrows(IllegalArgumentException.class, () -> { - final Gen gen = Gen.frequency(List.of(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0)))); - gen.apply(RANDOM); - }); - } - - @Test - public void shouldGenerateElementsAccordingToFrequencyGivenAnIterable() { - final Gen gen = Gen.frequency(List.of(Tuple.of(0, Gen.of(-1)), Tuple.of(1, Gen.of(1)))); - assertForAll(() -> gen.apply(RANDOM), i -> i != -1); - } - - // -- oneOf(VarArgs) - - @Test - public void shouldThrowWhenCallingOneOfAndVarArgsIsNull() { - assertThrows(NullPointerException.class, () -> Gen.oneOf((Gen[]) null)); - } - - @Test - public void shouldThrowWhenCallingOneOfAndVarArgsIsEmpty() { - assertThrows(IllegalArgumentException.class, () -> { - @SuppressWarnings("unchecked") - final Gen[] empty = (Gen[]) new Gen[0]; - Gen.oneOf(empty); - }); - } - - @Test - public void shouldReturnOneOfGivenVarArgs() { - final Gen gen = Gen.oneOf(Gen.of(1), Gen.of(2)); - assertForAll(() -> gen.apply(RANDOM), i -> i == 1 || i == 2); - } - - // -- oneOf(Iterable) - - @Test - public void shouldThrowWhenCallingOneOfAndIterableIsNull() { - assertThrows(NullPointerException.class, () ->Gen.oneOf((Iterable>) null)); - } - - @Test - public void shouldThrowWhenCallingOneOfAndIterableIsEmpty() { - assertThrows(IllegalArgumentException.class, () ->Gen.oneOf(List.empty())); - } - - @Test - public void shouldReturnOneOfGivenIterable() { - final Gen gen = Gen.oneOf(List.of(Gen.of(1), Gen.of(2))); - assertForAll(() -> gen.apply(RANDOM), i -> i == 1 || i == 2); - } - - // -- arbitrary - - @Test - public void shouldConvertGenToArbitrary() { - assertThat(Gen.of(1).arbitrary()).isInstanceOf(Arbitrary.class); - } - - // -- map - - @Test - public void shouldThrowWhenCallingMapWithNullArg() { - assertThrows(NullPointerException.class, () -> Gen.of(1).map(null)); - } - - @Test - public void shouldMapGen() { - final Gen gen = Gen.of(1).map(i -> i * 2); - assertForAll(() -> gen.apply(RANDOM), i -> i % 2 == 0); - } - - // -- flatMap - - @Test - public void shouldThrowWhenCallingFlatMapWithNullArg() { - assertThrows(NullPointerException.class, () -> Gen.of(1).flatMap(null)); - } - - @Test - public void shouldFlatMapGen() { - final Gen gen = Gen.of(1).flatMap(i -> Gen.of(i * 2)); - assertForAll(() -> gen.apply(RANDOM), i -> i % 2 == 0); - } - - // -- filter - - @Test - public void shouldThrowWhenCallingFilterWithNullArg() { - assertThrows(NullPointerException.class, () -> Gen.of(1).filter(null)); - } - - @Test - public void shouldFilterGenerator() { - final Gen gen = Gen.choose(1, 2).filter(i -> i % 2 == 0); - assertForAll(() -> gen.apply(RANDOM), i -> i == 2); - } - - @Test - public void shouldDetectEmptyFilter() { - assertThrows(IllegalStateException.class, () -> Gen.of(1).filter(ignored -> false).apply(RANDOM)); - } - - // -- peek - - @Test - public void shouldPeekArbitrary() { - final int[] actual = new int[] { -1 }; - final int expected = Gen.of(1).peek(i -> actual[0] = i).apply(new Random()); - assertThat(actual[0]).isEqualTo(expected); - } - - // -- transform - - @Test - public void shouldTransformGen() { - final String s = Gen.of(1).transform(gen -> gen.apply(RANDOM).toString()); - assertThat(s).isEqualTo("1"); - } - - // helpers - - void assertForAll(Supplier supplier, Predicate property) { - for (int i = 0; i < TRIES; i++) { - final T element = supplier.get(); - if (!property.test(element)) { - throw new AssertionError("predicate did not hold for " + element); - } - } - } -} diff --git a/vavr/pom.xml b/vavr/pom.xml index a9f2dfcd40..48564cf62d 100644 --- a/vavr/pom.xml +++ b/vavr/pom.xml @@ -14,7 +14,7 @@ The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt + https://www.apache.org/licenses/LICENSE-2.0.txt repo @@ -22,13 +22,13 @@ ${project.groupId} vavr-match - ${project.version} + 0.10.5 ${project.groupId} vavr-match-processor - ${project.version} + 0.10.5 true