-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
final field code validator and tests
thanks to Richard for hinting at the needed infrastructure
- Loading branch information
1 parent
ea6e9ca
commit e46b239
Showing
10 changed files
with
216 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
key.core/src/test/java/de/uka/ilkd/key/proof/init/FinalFieldCodeValidatorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package de.uka.ilkd.key.proof.init; | ||
|
||
import de.uka.ilkd.key.control.DefaultUserInterfaceControl; | ||
import de.uka.ilkd.key.control.KeYEnvironment; | ||
import de.uka.ilkd.key.java.abstraction.KeYJavaType; | ||
import de.uka.ilkd.key.logic.op.ProgramMethod; | ||
import de.uka.ilkd.key.proof.io.ProblemLoaderException; | ||
import de.uka.ilkd.key.proof.mgt.SpecificationRepository; | ||
import de.uka.ilkd.key.speclang.Contract; | ||
import de.uka.ilkd.key.util.KeYTypeUtil; | ||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.api.DynamicTest; | ||
import org.junit.jupiter.api.TestFactory; | ||
|
||
import java.io.File; | ||
import java.net.URL; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.stream.Stream; | ||
|
||
class FinalFieldCodeValidatorTest { | ||
|
||
@TestFactory | ||
public Stream<DynamicTest> testCodeValidatorParse() throws ProblemLoaderException { | ||
return testContracts(false, "final/shouldparse"); | ||
} | ||
|
||
//@TestFactory | ||
public Stream<DynamicTest> testCodeValidatorFail() throws ProblemLoaderException { | ||
return testContracts(true, "final/shouldfail"); | ||
} | ||
|
||
private Stream<DynamicTest> testContracts(boolean shouldfail, String directory) throws ProblemLoaderException { | ||
URL url = getClass().getResource(directory); | ||
assert url != null : directory + " not found."; | ||
assert "file".equals(url.getProtocol()): "Test cases must be in file system"; | ||
File dir = new File(url.getPath()); | ||
KeYEnvironment<DefaultUserInterfaceControl> env = KeYEnvironment.load(dir, null, null, null); | ||
|
||
Set<KeYJavaType> kjts = env.getJavaInfo().getAllKeYJavaTypes(); | ||
Set<Contract> contracts = new HashSet<>(); | ||
for (KeYJavaType type : kjts) { | ||
if (!KeYTypeUtil.isLibraryClass(type)) { | ||
SpecificationRepository specRepo = env.getSpecificationRepository(); | ||
for(Contract c: specRepo.getAllContracts()) { | ||
var target = c.getTarget(); | ||
if (target instanceof ProgramMethod pm && | ||
pm.isConstructor() && | ||
!KeYTypeUtil.isLibraryClass(pm.getContainerType())) { | ||
contracts.add(c); | ||
} | ||
} | ||
} | ||
} | ||
if(shouldfail) | ||
return contracts.stream().map(c -> DynamicTest.dynamicTest("Illegal constructor " + c.getName(), | ||
() -> Assertions.assertThrowsExactly(FinalFieldCodeValidator.FinalViolationException.class, | ||
() -> testConstructor(c, env)))); | ||
else return contracts.stream().map(c -> DynamicTest.dynamicTest("Legal constructor " + c.getName(), | ||
()->testConstructor(c, env))); | ||
} | ||
|
||
private void testConstructor(Contract c, KeYEnvironment<?> env) throws ProofInputException { | ||
try { | ||
// System.out.println("Contract id: " + c.getName()); | ||
ContractPO po = c.createProofObl(env.getInitConfig()); | ||
env.createProof(po); | ||
} catch(FinalFieldCodeValidator.FinalViolationException fex) { | ||
System.err.println("Position: " + fex.getPosition()); | ||
fex.printStackTrace(); | ||
throw fex; | ||
} | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
key.core/src/test/resources/de/uka/ilkd/key/proof/init/final/shouldfail/FinalProblem1.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
class FinalReadBeforeWriteIndirect { | ||
final int finalField; | ||
|
||
//@ ensures b; | ||
FinalReadBeforeWriteIndirect(boolean b) { | ||
int before = getFinalField(); | ||
finalField = 42; | ||
int after = getFinalField(); | ||
} | ||
|
||
/*@ normal_behaviour | ||
@ ensures \result == finalField; | ||
@*/ | ||
private int getFinalField() { | ||
return finalField; | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
...t/resources/de/uka/ilkd/key/proof/init/final/shouldfail/FinalReadBeforeWriteIndirect.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
class FinalReadBeforeWriteIndirect { | ||
final int finalField; | ||
|
||
//@ ensures b; | ||
FinalReadBeforeWriteIndirect(boolean b) { | ||
int before = getFinalField(); | ||
finalField = 42; | ||
int after = getFinalField(); | ||
} | ||
|
||
/*@ normal_behaviour | ||
@ ensures \result == finalField; | ||
@*/ | ||
private int getFinalField() { | ||
return finalField; | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
key.core/src/test/resources/de/uka/ilkd/key/proof/init/final/shouldfail/LeakThis1.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
class LeakThis1 { | ||
final int finalField; | ||
|
||
//@ ensures b; | ||
LeakThis1(boolean b) { | ||
int before = getFinalField(this); | ||
finalField = 42; | ||
int after = getFinalField(this); | ||
} | ||
|
||
/*@ normal_behaviour | ||
@ ensures \result == x.finalField; | ||
@*/ | ||
private int getFinalField(LeakThis1 x) { | ||
return x.finalField; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
key.core/src/test/resources/de/uka/ilkd/key/proof/init/final/shouldfail/LeakThis2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class LeakThis2 { | ||
final int finalField; | ||
LeakThis2 other; | ||
|
||
//@ ensures b; | ||
LeakThis2(boolean b) { | ||
leakThis(); | ||
int before = getFinalField(); | ||
finalField = 42; | ||
int after = getFinalField(); | ||
} | ||
|
||
private LeakThis2 leakThis() { | ||
other = true ? this : this; | ||
} | ||
|
||
/*@ normal_behaviour | ||
@ ensures \result == finalField; | ||
@*/ | ||
int getFinalField() { | ||
return other.finalField; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
key.core/src/test/resources/de/uka/ilkd/key/proof/init/final/shouldfail/Subclass.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class Subclass { | ||
final int finalField; | ||
|
||
//@ ensures b; | ||
Subclass(boolean b) { | ||
int before = getFinalField(); | ||
finalField = 42; | ||
int after = getFinalField(); | ||
} | ||
|
||
int getFinalField() { | ||
return 0; | ||
} | ||
} | ||
|
||
class Subsubclass extends Subclass { | ||
/*@ normal_behaviour | ||
@ ensures \result == finalField; | ||
@*/ | ||
int getFinalField() { | ||
return finalField; | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
...src/test/resources/de/uka/ilkd/key/proof/init/final/shouldparse/SecondaryConstructor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class SecondaryConstructor { | ||
final int finalField; | ||
|
||
boolean b; | ||
|
||
//@ ensures b; | ||
SecondaryConstructor(int v) { | ||
finalField = v; | ||
} | ||
|
||
SecondaryCosntructor() { | ||
this(42); | ||
int x = finalField; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters