Skip to content

Commit abe8f20

Browse files
committed
restoring the KeY book example
1 parent e9eb1a5 commit abe8f20

File tree

7 files changed

+116
-27
lines changed

7 files changed

+116
-27
lines changed

key.core.testgen/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ description "Test Case Generation based on proof attempts."
33
dependencies {
44
implementation project(":key.core")
55
implementation("com.squareup:javapoet:1.13.0")
6+
7+
implementation "info.picocli:picocli:4.7.5"
68
}
9+

key.core.testgen/src/main/java/de/uka/ilkd/key/testgen/TGMain.java

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,114 @@
33
* SPDX-License-Identifier: GPL-2.0-only */
44
package de.uka.ilkd.key.testgen;
55

6+
import de.uka.ilkd.key.api.ProofManagementApi;
67
import de.uka.ilkd.key.control.KeYEnvironment;
78
import de.uka.ilkd.key.proof.Proof;
89
import de.uka.ilkd.key.proof.io.ProblemLoaderException;
910
import de.uka.ilkd.key.smt.solvertypes.SolverTypes;
11+
import de.uka.ilkd.key.speclang.Contract;
1012
import de.uka.ilkd.key.testgen.settings.TestGenerationSettings;
1113
import de.uka.ilkd.key.testgen.smt.testgen.TestGenerationLog;
1214
import org.slf4j.Logger;
1315
import org.slf4j.LoggerFactory;
16+
import picocli.CommandLine;
1417

1518
import java.io.File;
16-
import java.util.Objects;
19+
import java.util.ArrayList;
20+
import java.util.LinkedList;
21+
import java.util.List;
22+
import java.util.concurrent.Callable;
1723

18-
public class TGMain {
24+
@CommandLine.Command(name = "tcgen", mixinStandardHelpOptions = true,
25+
description = "Generator of Testcases based on Proof Attempts")
26+
public class TGMain implements Callable<Integer> {
1927
private final static Logger LOGGER = LoggerFactory.getLogger("main");
2028

2129
public static void main(String[] args) throws ProblemLoaderException, InterruptedException {
30+
int exitCode = new CommandLine(new TGMain()).execute(args);
31+
System.exit(exitCode);
32+
}
33+
34+
@CommandLine.Parameters(description = "KeY or Java file.", arity = "1..*")
35+
private List<File> files = new LinkedList<>();
36+
37+
@CommandLine.Option(names = {"-s", "--symbex"},
38+
description = "apply symbex", negatable = true)
39+
private boolean symbex;
40+
41+
@CommandLine.Option(names = {"-c", "--contract"},
42+
arity = "*",
43+
description = "name of the contract to be loaded in the Java environment")
44+
private List<String> contractNames = new ArrayList<>();
45+
46+
@CommandLine.Option(names = {"--all-contracts"},
47+
description = "name of the contract to be loaded in the Java environment")
48+
private boolean allContracts = false;
49+
50+
51+
@CommandLine.Option(names = {"-o", "--output"}, description = "Output folder")
52+
private File outputFolder = new File("out");
53+
54+
@CommandLine.Option(names = {"-r", "--rfl"}, description = "Use Reflection class", negatable = true)
55+
private boolean useReflection = false;
56+
57+
@CommandLine.Option(names = {"-f", "--format"}, description = "Use Reflection class")
58+
private Format format = Format.JUnit4;
59+
60+
61+
@CommandLine.Option(names = {"--max-unwinds"}, description = "max unwinds")
62+
private int maxUnwinds = 10;
63+
@CommandLine.Option(names = {"--dups"}, description = "remove duplicates", negatable = true)
64+
private boolean removeDuplicates;
65+
66+
@Override
67+
public Integer call() throws Exception {
2268
if (SolverTypes.Z3_CE_SOLVER.checkForSupport()) {
2369
LOGGER.error("Z3 not found! Bye.");
24-
System.exit(1);
25-
return;
70+
return 1;
2671
} else {
2772
LOGGER.info("Z3 found; Version {}", SolverTypes.Z3_CE_SOLVER.getInstalledVersion());
2873
}
2974

30-
3175
var settings = new TestGenerationSettings();
32-
String fileName = null;
33-
for (int i = 0; i < args.length; i++) {
34-
var a = args[i];
35-
if (a.startsWith("--")) {
36-
switch (a) {
37-
case "--output" -> settings.setOutputPath(args[++i]);
38-
case "--rfl" -> settings.setRFL(true);
39-
case "--format" -> settings.setFormat(Format.valueOf(args[++i]));
76+
TestGenerationLog log = new SysoutTestGenerationLog();
77+
settings.setOutputPath(outputFolder.getAbsolutePath());
78+
settings.setRFL(useReflection);
79+
settings.setFormat(format);
80+
settings.setApplySymbolicExecution(symbex);
81+
settings.setMaxUnwinds(maxUnwinds);
82+
settings.setRemoveDuplicates(removeDuplicates);
83+
84+
for (File file : files) {
85+
List<Proof> proofs = new LinkedList<>();
86+
var env = KeYEnvironment.load(file);
87+
Proof proof = env.getLoadedProof();
88+
if (proof == null) { // non-key file
89+
var print = contractNames.isEmpty();
90+
final var api = new ProofManagementApi(env);
91+
var contracts = api.getProofContracts();
92+
for (Contract contract : contracts) {
93+
final var name = contract.getName();
94+
if (print) {
95+
LOGGER.info("Contract found: {}", name);
96+
}
97+
98+
if (allContracts || contractNames.contains(name)) {
99+
proofs.add(api.startProof(contract).getProof());
100+
}
40101
}
41-
} else {
42-
fileName = a;
102+
} else { // key file
103+
proofs = List.of(proof);
43104
}
44-
}
45105

46-
var env = KeYEnvironment.load(new File(Objects.requireNonNull(fileName)));
47-
TestGenerationLog log = new SysoutTestGenerationLog();
48-
Proof proof = env.getLoadedProof();
49-
TestgenFacade.generateTestcases(env, proof, settings, log);
106+
for (Proof p : proofs) {
107+
TestgenFacade.generateTestcases(env, p, settings, log);
108+
p.dispose();
109+
}
110+
111+
env.dispose();
112+
}
113+
return 0;
50114
}
51115

52116
private static class SysoutTestGenerationLog implements TestGenerationLog {

key.core.testgen/src/test/java/de/uka/ilkd/key/testcase/TestcaseGenerationE2ETest.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,16 @@ public class TestcaseGenerationE2ETest {
1212
@Test
1313
public void binarySearch() throws ProblemLoaderException, InterruptedException {
1414
TGMain.main(new String[]{
15-
"--output", "testcases/binarysearch/actual", "testcases/binarysearch/attempt.proof"
15+
"--output", "testcases/binarysearch/actual", "testcases/binarysearch/attempt.proof"
16+
});
17+
}
18+
19+
@Test
20+
public void arrayUtil() throws ProblemLoaderException, InterruptedException {
21+
TGMain.main(new String[]{
22+
"--all-contracts",
23+
"--output", "testcases/arrayutil/actual",
24+
"testcases/arrayutil/src/"
1625
});
1726
}
1827
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/** From the second KeY book.
2+
* https://link.springer.com/chapter/10.1007/978-3-319-49812-6_12
3+
* Listing 12.1
4+
*/
5+
public class ArrayUtils {
6+
/*@ public normal_behavior
7+
@ ensures (\forall int i; 0<=i && i<a.length; a[i]==b[i]);
8+
@*/
9+
public void arrCopy(int[] a, int[] b) {
10+
for (int i = 0; i < a.length; i++) {
11+
b[i] = a[i];
12+
}
13+
}
14+
}

key.util/src/main/java/org/key_project/util/collection/ImmutableMap.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* SPDX-License-Identifier: GPL-2.0-only */
44
package org.key_project.util.collection;
55

6+
import org.jspecify.annotations.Nullable;
7+
68
import java.util.Iterator;
79

810

key.util/src/main/java/org/key_project/util/collection/ImmutableMapEntry.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
* SPDX-License-Identifier: GPL-2.0-only */
44
package org.key_project.util.collection;
55

6+
import org.jspecify.annotations.Nullable;
7+
68
/**
79
* This interface declares a tupel of two values. The first one is of type <S> and named key, the
810
* second one is of type <T> and named value
911
*/
1012

11-
public interface ImmutableMapEntry<S, T> extends java.io.Serializable {
13+
public interface ImmutableMapEntry<S extends @Nullable Object, T extends @Nullable Object> extends java.io.Serializable {
1214

1315
/** @return the first part of the tupel */
1416
S key();

keyext.ui.testgen/src/main/java/de/uka/ilkd/key/gui/testgen/TGInfoDialog.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,6 @@ public void actionPerformed(ActionEvent e) {
6666
};
6767

6868
private final TestGenerationLog logger = new TestGenerationLog() {
69-
@Override
70-
public void write(String t) {
71-
textArea.append(t);
72-
}
73-
7469
@Override
7570
public void writeln(String line) {
7671
ThreadUtilities.invokeOnEventQueue(() -> textArea.append(line + "\n"));

0 commit comments

Comments
 (0)