Skip to content

Commit

Permalink
Merge pull request #31 from tricktron/f-test-task
Browse files Browse the repository at this point in the history
Adds testFrege Task
  • Loading branch information
tricktron authored Mar 9, 2022
2 parents 0fb7e5b + 6856273 commit 77dd1ed
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 14 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,17 @@ Optional configuration parameters inside `build.gradle`:

- **setupFrege**: Downloads the specified version of the Frege compiler.
- **initFrege**: Creates a default `HelloFrege.fr` example file under
`mainSource/examples/HelloFrege.fr`. Alternatively, you can specify the location
`mainSourceDir/examples/HelloFrege.fr`. Alternatively, you can specify the location
on the command line with `--mainModule=my.mod.HelloFrege`.
- **compileFrege**: Compiles all your `*.fr` files in `mainSourceDir` to `outputDir`.
Alternatively, you can also pass the compile item by command line. Then only the
compile item and its dependencies get compiled.
E.g.: `gradle compileFrege --compileItem=[full module name | absolute path to .fr file]`.
- **runFrege**: Runs the Frege module specified by `mainModule`. Alternatively you can
also pass the main module by command line, e.g: `gradle runFrege --mainModule=my.mod.Name`.
- **testFrege**: Tests all QuickCheck properties defined in the specified `mainModule`.
You can pass test args on the command line, e.g: `gradle testFrege --args="-v -n 1000 -p pred1`.
Run `gradle testFrege --args=-h` to see all options.
- **replFrege**: Takes care of all project dependencies of the specified `replModule`
and prints the command to start the Frege REPL and load the `replModule`.
E.g.: `(echo :l <path to replModule.fr> && cat) | java -cp <your-correct-classpath-with-all-dependencies> frege.repl.FregeRepl`.
Expand Down Expand Up @@ -87,4 +90,4 @@ cache by setting `org.gradle.caching=true` in your `gradle.properites`.


## How to Contribute
Try to add another task, e.g. `fregeDoc` to the [FregePluginFunctionalTest.java](src/functionalTest/java/ch/fhnw/thga/gradleplugins/FregePluginFunctionalTest.java) file and try to make the test pass.
Try to add another task, e.g. `docFrege` to the [FregePluginFunctionalTest.java](src/functionalTest/java/ch/fhnw/thga/gradleplugins/FregePluginFunctionalTest.java) file and try to make the test pass.
2 changes: 1 addition & 1 deletion example-project/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id 'ch.fhnw.thga.frege' version '1.9.0-alpha'
id 'ch.fhnw.thga.frege' version '2.0.0-alpha'
}

frege {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
group = ch.fhnw.thga
version = 1.9.0-alpha
version = 2.0.0-alpha
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package ch.fhnw.thga.gradleplugins;

import static ch.fhnw.thga.gradleplugins.FregeExtension.DEFAULT_RELATIVE_SOURCE_DIR;
import static ch.fhnw.thga.gradleplugins.FregePlugin.TEST_FREGE_TASK_NAME;
import static ch.fhnw.thga.gradleplugins.SharedFunctionalTestLogic.createFregeSection;
import static ch.fhnw.thga.gradleplugins.SharedFunctionalTestLogic.runAndFailGradleTask;
import static ch.fhnw.thga.gradleplugins.SharedFunctionalTestLogic.runGradleTask;
import static ch.fhnw.thga.gradleplugins.SharedTaskLogic.EMPTY_LINE;
import static ch.fhnw.thga.gradleplugins.SharedTaskLogic.NEW_LINE;
import static org.gradle.testkit.runner.TaskOutcome.FAILED;
import static org.gradle.testkit.runner.TaskOutcome.SUCCESS;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.File;
import java.util.stream.Stream;

import org.gradle.api.Project;
import org.gradle.testkit.runner.BuildResult;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.IndicativeSentencesGeneration;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import ch.fhnw.thga.gradleplugins.fregeproject.FregeProjectBuilder;
import ch.fhnw.thga.gradleplugins.fregeproject.FregeSourceFile;

public class TestFregeFunctionalTest
{
private static final FregeSourceFile PROPERTY_TESTS_FR = new FregeSourceFile(
String.format(
"%s/%s",
DEFAULT_RELATIVE_SOURCE_DIR,
"ch/fhnw/thga/PropertyTests.fr"
),
String.join(NEW_LINE,
"module ch.fhnw.thga.PropertyTests where",
EMPTY_LINE,
"import Test.QuickCheck",
EMPTY_LINE,
"p_pass = property $ \\(n::Integer) -> odd n ^^ even n",
"p_fail = property $ \\(n::Integer) -> even n"
)
);

@Nested
@IndicativeSentencesGeneration(
separator = " -> ",
generator = DisplayNameGenerator.ReplaceUnderscores.class
)
class Test_frege_task_works
{
@Test
void given_frege_code_with_true_quick_check_property(
@TempDir File testProjectDir)
throws Exception
{
String mainBuildConfig = createFregeSection(
FregeDTOBuilder
.builder()
.version("'3.25.84'")
.release("'3.25alpha'")
.mainModule("'ch.fhnw.thga.PropertyTests'")
.build()
);

Project project = FregeProjectBuilder
.builder()
.projectRoot(testProjectDir)
.buildFile(mainBuildConfig)
.fregeSourceFiles(() -> Stream.of(PROPERTY_TESTS_FR))
.build();

BuildResult result = runGradleTask(
testProjectDir,
TEST_FREGE_TASK_NAME,
"--args=-v -p p_pass"
);

assertTrue(
project
.getTasks()
.getByName(TEST_FREGE_TASK_NAME)
instanceof TestFregeTask
);
assertEquals(
SUCCESS,
result.task(":" + TEST_FREGE_TASK_NAME).getOutcome()
);
assertTrue(result.getOutput().contains("OK"));
assertTrue(result.getOutput().contains("Properties passed: 1, failed: 0"));
}
}

@Nested
@IndicativeSentencesGeneration(
separator = " -> ",
generator = DisplayNameGenerator.ReplaceUnderscores.class
)
class Test_frege_task_fails
{
@Test
void given_frege_code_with_false_quick_check_property(
@TempDir File testProjectDir)
throws Exception
{
String mainBuildConfig = createFregeSection(
FregeDTOBuilder
.builder()
.version("'3.25.84'")
.release("'3.25alpha'")
.mainModule("'ch.fhnw.thga.PropertyTests'")
.build()
);

Project project = FregeProjectBuilder
.builder()
.projectRoot(testProjectDir)
.buildFile(mainBuildConfig)
.fregeSourceFiles(() -> Stream.of(PROPERTY_TESTS_FR))
.build();

BuildResult result = runAndFailGradleTask(
testProjectDir,
TEST_FREGE_TASK_NAME,
"--args=-v -p p_fail"
);

assertTrue(
project
.getTasks()
.getByName(TEST_FREGE_TASK_NAME)
instanceof TestFregeTask
);
assertEquals(
FAILED,
result.task(":" + TEST_FREGE_TASK_NAME).getOutcome()
);
assertTrue(result.getOutput().contains("Failed"));
assertTrue(result.getOutput().contains("Properties passed: 0, failed: 1"));
}
}
}
43 changes: 34 additions & 9 deletions src/main/java/ch/fhnw/thga/gradleplugins/FregePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@

public class FregePlugin implements Plugin<Project>
{
public static final String SETUP_FREGE_TASK_NAME = "setupFrege";
public static final String COMPILE_FREGE_TASK_NAME = "compileFrege";
public static final String RUN_FREGE_TASK_NAME = "runFrege";
public static final String REPL_FREGE_TASK_NAME = "replFrege";
public static final String INIT_FREGE_TASK_NAME = "initFrege";
public static final String FREGE_PLUGIN_ID = "ch.fhnw.thga.frege";
public static final String FREGE_EXTENSION_NAME = "frege";
public static final String FREGE_IMPLEMENTATION_SCOPE = "implementation";
public static final String SETUP_FREGE_TASK_NAME = "setupFrege";
public static final String COMPILE_FREGE_TASK_NAME = "compileFrege";
public static final String RUN_FREGE_TASK_NAME = "runFrege";
public static final String TEST_FREGE_TASK_NAME = "testFrege";
public static final String REPL_FREGE_TASK_NAME = "replFrege";
public static final String INIT_FREGE_TASK_NAME = "initFrege";
public static final String FREGE_PLUGIN_ID = "ch.fhnw.thga.frege";
public static final String FREGE_EXTENSION_NAME = "frege";
public static final String FREGE_IMPLEMENTATION_SCOPE = "implementation";
public static final String HELLO_FREGE_DEFAULT_MODULE_NAME = "examples.HelloFrege";
public static final String FREGE_TEST_MODULE_NAME = "frege.tools.Quick";
public static final String FREGE_TEST_DEFAULT_ARGS = "-v";

@Override
public void apply(Project project) {
Expand All @@ -38,7 +42,7 @@ public void apply(Project project) {
task ->
{
task.getFregeMainSourceDir().set(extension.getMainSourceDir());
task.getFregeModuleName().set("examples.HelloFrege");
task.getFregeModuleName().set(HELLO_FREGE_DEFAULT_MODULE_NAME);
}
);

Expand Down Expand Up @@ -88,6 +92,27 @@ public void apply(Project project) {
task.getFregeDependencies().set(implementation.getAsPath());
}
);

project.getTasks().register(
TEST_FREGE_TASK_NAME,
TestFregeTask.class,
task ->
{
task.getMainModule().set(extension.getMainModule());
task.dependsOn(compileFregeTask.map(
compileTask ->
{
compileTask.getFregeCompileItem().set(task.getMainModule());
return compileTask;
}
).get());
task.getFregeCompilerJar().set(
setupFregeCompilerTask.get().getFregeCompilerOutputPath());
task.getFregeOutputDir().set(extension.getOutputDir());
task.getFregeDependencies().set(implementation.getAsPath());
task.getFregeArgs().set(FREGE_TEST_DEFAULT_ARGS);
}
);

project.getTasks().register(
REPL_FREGE_TASK_NAME,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ch.fhnw.thga.gradleplugins;

import static ch.fhnw.thga.gradleplugins.SharedTaskLogic.NEW_LINE;
import static ch.fhnw.thga.gradleplugins.SharedTaskLogic.EMPTY_LINE;

import java.io.IOException;
import java.nio.file.Paths;
Expand All @@ -19,7 +20,6 @@

public abstract class InitFregeTask extends DefaultTask
{
private static final String EMPTY_LINE = "";
private static final String HELLO_FREGE_CODE_WITHOUT_MODULE = String.join(NEW_LINE,
"import Test.QuickCheck",
EMPTY_LINE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public final class SharedTaskLogic
private SharedTaskLogic() {};

public static final String NEW_LINE = System.lineSeparator();
public static final String EMPTY_LINE = "";

public static final Provider<FileCollection> setupClasspath(
Project project,
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/ch/fhnw/thga/gradleplugins/TestFregeTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package ch.fhnw.thga.gradleplugins;

import javax.inject.Inject;

import org.gradle.api.DefaultTask;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.JavaExec;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import org.gradle.api.tasks.Internal;
import org.gradle.api.provider.Provider;

public abstract class TestFregeTask extends DefaultTask {
private static final String TEST_MAIN_CLASS = "frege.tools.Quick";
private final JavaExec javaExec;

@InputFile
public abstract RegularFileProperty getFregeCompilerJar();

@InputDirectory
public abstract DirectoryProperty getFregeOutputDir();

@Input
@Option(option = "mainModule",
description = "The full name of the Frege module with a main function, e.g. 'my.mod.Name'")
public abstract Property<String> getMainModule();

@Input
@Option(option = "args",
description = "optional args passed to frege")
public abstract Property<String> getFregeArgs();

@Internal
final Provider<String> getAllArgs()
{
return getFregeArgs()
.map(args -> String.format("%s %s", args, getMainModule().get()));
}

@Input
public abstract Property<String> getFregeDependencies();

@Inject
public TestFregeTask(ObjectFactory objectFactory) {
javaExec = objectFactory.newInstance(JavaExec.class);
}

@TaskAction
public void runFrege() {
javaExec.getMainClass().set(TEST_MAIN_CLASS);
javaExec
.setClasspath(
SharedTaskLogic.setupClasspath(
getProject(),
getFregeDependencies(),
getFregeCompilerJar(),
getFregeOutputDir())
.get()
)
.setArgsString(getAllArgs().get())
.exec();
}
}

0 comments on commit 77dd1ed

Please sign in to comment.