mirror of
https://gitlab.kit.edu/uskyk/typicalc.git
synced 2024-11-08 10:20:41 +00:00
Fuzzing setup + documentation
This commit is contained in:
parent
bd8a7a26cf
commit
3f07a6d234
2
.gitignore
vendored
2
.gitignore
vendored
@ -18,3 +18,5 @@ drivers/
|
||||
# Error screenshots generated by TestBench for failed integration tests
|
||||
error-screenshots/
|
||||
webpack.generated.js
|
||||
|
||||
/fuzz-results
|
||||
|
45
README.md
45
README.md
@ -1,11 +1,11 @@
|
||||
# Typicalc
|
||||
|
||||
The project is a standard Maven project, so you can import it to your IDE of choice. [Read more how to set up a development environment](https://vaadin.com/docs/v14/flow/installing/installing-overview.html) for Vaadin projects (Windows, Linux, macOS).
|
||||
The project is a standard Maven project, so you can import it to your IDE of choice.
|
||||
[Read more how to set up a development environment](https://vaadin.com/docs/v18/flow/installing/installing-overview.html) for Vaadin projects (Windows, Linux, macOS).
|
||||
|
||||
[To Vaadin documentation](https://vaadin.com/docs-beta/latest/flow/overview/)
|
||||
|
||||
|
||||
## Running and debugging the applcation
|
||||
## Running and debugging the application
|
||||
|
||||
### Running the application from the command line.
|
||||
To run from the command line, use `mvn` and open http://localhost:8080 in your browser.
|
||||
@ -15,7 +15,7 @@ To run from the command line, use `mvn` and open http://localhost:8080 in your b
|
||||
- Right click on the Application class
|
||||
- Select "Debug 'Application.main()'" from the list
|
||||
|
||||
After the application has started, you can view your it at http://localhost:8080/ in your browser.
|
||||
After the application has started, you can view it at http://localhost:8080/ in your browser.
|
||||
You can now also attach break points in code for debugging purposes, by clicking next to a line number in any source file.
|
||||
|
||||
### Running and debugging the application in Eclipse
|
||||
@ -27,13 +27,29 @@ Do not worry if the debugger breaks at a `SilentExitException`. This is a Spring
|
||||
After the application has started, you can view your it at http://localhost:8080/ in your browser.
|
||||
You can now also attach break points in code for debugging purposes, by clicking next to a line number in any source file.
|
||||
|
||||
## What next?
|
||||
## Fuzzing with [JQF](https://github.com/rohanpadhye/JQF)
|
||||
|
||||
[vaadin.com](https://vaadin.com) has lots of material to help you get you started:
|
||||
### [Zest](https://github.com/rohanpadhye/JQF/wiki/Fuzzing-with-Zest)
|
||||
|
||||
- Follow the tutorials in [vaadin.com/tutorials](https://vaadin.com/tutorials). Especially [vaadin.com/tutorials/getting-started-with-flow](https://vaadin.com/tutorials/getting-started-with-flow) is good for getting a grasp of the basic Vaadin concepts.
|
||||
- Read the documentation in [vaadin.com/docs](https://vaadin.com/docs).
|
||||
- For a bigger Vaadin application example, check out the Full Stack App starter from [vaadin.com/start](https://vaadin.com/start).
|
||||
Run:
|
||||
```
|
||||
mvn test-compile jqf:fuzz -Dclass=edu.kit.typicalc.model.parser.LambdaParserFuzzTest -Dmethod=testInference
|
||||
```
|
||||
|
||||
This will use the `LambdaTermGenerator` to create random lambda terms that are then passed to the `ModelImpl`.
|
||||
|
||||
### [AFL](https://lcamtuf.coredump.cx/afl/)
|
||||
|
||||
First install the necessary JQF tools: https://github.com/rohanpadhye/jqf/wiki/Fuzzing-with-AFL
|
||||
|
||||
Remove the `@Ignore` annotation in `LambdaParserFuzzTest` and run:
|
||||
```
|
||||
mvn test-compile
|
||||
jqf-afl-fuzz -c target/test-classes:target/classes -i src/test/resources/terms/ edu.kit.typicalc.model.parser.LambdaParserFuzzTest testLambdaParserAFL
|
||||
```
|
||||
|
||||
Generated inputs are stored in `fuzz-results/queue/`.
|
||||
More samples can be added to `src/test/resources/terms/` to speed up the process.
|
||||
|
||||
## Deploying using Docker
|
||||
|
||||
@ -48,3 +64,14 @@ Once the Docker image is correctly built, you can test it locally using
|
||||
```
|
||||
docker run -p 8080:8080 myapp:latest
|
||||
```
|
||||
|
||||
## Deploying using a JAR
|
||||
|
||||
First build the project:
|
||||
```
|
||||
mvn package -Pproduction
|
||||
```
|
||||
Then run the server:
|
||||
```
|
||||
java -jar target/typicalc-1.0-SNAPSHOT.jar
|
||||
```
|
||||
|
11
pom.xml
11
pom.xml
@ -92,6 +92,12 @@
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.berkeley.cs.jqf</groupId>
|
||||
<artifactId>jqf-fuzz</artifactId>
|
||||
<version>1.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-testbench</artifactId>
|
||||
@ -159,6 +165,11 @@
|
||||
<build>
|
||||
<defaultGoal>spring-boot:run</defaultGoal>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>edu.berkeley.cs.jqf</groupId>
|
||||
<artifactId>jqf-maven-plugin</artifactId>
|
||||
<version>1.6</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
|
@ -1,6 +1,5 @@
|
||||
server.port=${PORT:8080}
|
||||
server.servlet.session.persistent=false
|
||||
logging.level.org.atmosphere = warn
|
||||
spring.mustache.check-template-location = false
|
||||
spring.devtools.add-properties = false
|
||||
|
||||
# vaadin.whitelisted-packages= org/vaadin/example
|
||||
|
@ -0,0 +1,65 @@
|
||||
package edu.kit.typicalc.model.parser;
|
||||
|
||||
import edu.berkeley.cs.jqf.fuzz.Fuzz;
|
||||
import edu.berkeley.cs.jqf.fuzz.JQF;
|
||||
import edu.kit.typicalc.model.Model;
|
||||
import edu.kit.typicalc.model.ModelImpl;
|
||||
import edu.kit.typicalc.model.TypeInfererInterface;
|
||||
import edu.kit.typicalc.model.step.InferenceStep;
|
||||
import edu.kit.typicalc.model.term.LambdaTerm;
|
||||
import edu.kit.typicalc.util.Result;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.pholser.junit.quickcheck.*;
|
||||
|
||||
@RunWith(JQF.class)
|
||||
public class LambdaParserFuzzTest {
|
||||
/**
|
||||
* Runs the type inference algorithm and gets the first inference step.
|
||||
* Only validates that the algorithm produced something.
|
||||
*
|
||||
* @param term lambda term
|
||||
*/
|
||||
@Fuzz
|
||||
public void testInference(@From(LambdaTermGenerator.class) String term) {
|
||||
Model model = new ModelImpl();
|
||||
Result<TypeInfererInterface, ParseError> typer = model.getTypeInferer(term, new HashMap<>());
|
||||
InferenceStep first = typer.unwrap().getFirstInferenceStep();
|
||||
}
|
||||
|
||||
// this is how to rerun a specific fuzz result
|
||||
/*
|
||||
@Fuzz(repro="target/fuzz-results/edu.kit.typicalc.model.parser.LambdaParserFuzzTest/testInference/corpus/id_000066")
|
||||
public void testWithGenerator(@From(LambdaTermGenerator.class) String code) {
|
||||
System.out.println(code);
|
||||
}
|
||||
*/
|
||||
|
||||
@Fuzz
|
||||
@Ignore // remove if you intend to use AFL
|
||||
public void testLambdaParserAFL(InputStream input) {
|
||||
String term;
|
||||
try {
|
||||
term = new String(input.readAllBytes());
|
||||
} catch (Throwable t) {
|
||||
return;
|
||||
}
|
||||
LambdaParser parser = new LambdaParser(term);
|
||||
Result<LambdaTerm, ParseError> result = parser.parse();
|
||||
if (result.isOk()) {
|
||||
LambdaTerm term1 = result.unwrap();
|
||||
String sameTerm = term1.toString();
|
||||
LambdaParser parser2 = new LambdaParser(sameTerm);
|
||||
Result<LambdaTerm, ParseError> result2 = parser2.parse();
|
||||
LambdaTerm term2 = result2.unwrap();
|
||||
if (!term2.equals(term1)) {
|
||||
throw new IllegalStateException("results differ, when parsing: " + term);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package edu.kit.typicalc.model.parser;
|
||||
|
||||
import com.pholser.junit.quickcheck.generator.GenerationStatus;
|
||||
import com.pholser.junit.quickcheck.generator.Generator;
|
||||
import com.pholser.junit.quickcheck.random.SourceOfRandomness;
|
||||
import edu.kit.typicalc.model.term.AbsTerm;
|
||||
import edu.kit.typicalc.model.term.AppTerm;
|
||||
import edu.kit.typicalc.model.term.IntegerTerm;
|
||||
import edu.kit.typicalc.model.term.LambdaTerm;
|
||||
import edu.kit.typicalc.model.term.LetTerm;
|
||||
import edu.kit.typicalc.model.term.VarTerm;
|
||||
|
||||
public class LambdaTermGenerator extends Generator<String> {
|
||||
|
||||
public LambdaTermGenerator() {
|
||||
super(String.class); // Register the type of objects that we can create
|
||||
}
|
||||
|
||||
public static final String[] VARIABLES = new String[]{"x", "y", "z"};
|
||||
|
||||
/**
|
||||
* Generate a random lambda term.
|
||||
*
|
||||
* @param random source of randomness
|
||||
* @param status not used
|
||||
* @return a random lambda term
|
||||
*/
|
||||
@Override
|
||||
public String generate(SourceOfRandomness random, GenerationStatus status) {
|
||||
return generateReal(random).toString();
|
||||
}
|
||||
|
||||
private LambdaTerm generateReal(SourceOfRandomness random) {
|
||||
if (random.nextInt(1, 7) < 3) {
|
||||
LambdaTerm one = generateReal(random);
|
||||
LambdaTerm two = generateReal(random);
|
||||
if (random.nextInt(1, 10) < 8) {
|
||||
return new AppTerm(one, two);
|
||||
} else {
|
||||
return new LetTerm(new VarTerm(random.choose(VARIABLES)), one, two);
|
||||
}
|
||||
} else {
|
||||
if (random.nextBoolean()) {
|
||||
LambdaTerm one = generateReal(random);
|
||||
return new AbsTerm(new VarTerm(random.choose(VARIABLES)), one);
|
||||
} else if (random.nextBoolean()) {
|
||||
return new VarTerm(random.choose(VARIABLES));
|
||||
} else {
|
||||
return new IntegerTerm(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
src/test/resources/terms/abs
Normal file
1
src/test/resources/terms/abs
Normal file
@ -0,0 +1 @@
|
||||
λx. x
|
1
src/test/resources/terms/app
Normal file
1
src/test/resources/terms/app
Normal file
@ -0,0 +1 @@
|
||||
x y
|
1
src/test/resources/terms/complex
Normal file
1
src/test/resources/terms/complex
Normal file
@ -0,0 +1 @@
|
||||
(λy. y 5)(λx.x)
|
1
src/test/resources/terms/const
Normal file
1
src/test/resources/terms/const
Normal file
@ -0,0 +1 @@
|
||||
true
|
1
src/test/resources/terms/let
Normal file
1
src/test/resources/terms/let
Normal file
@ -0,0 +1 @@
|
||||
let f = λx.x in f 5
|
Loading…
Reference in New Issue
Block a user