An open API service indexing awesome lists of open source software.

https://github.com/sri-csl/daikon-gradle-plugin

(experimental) daikon gradle plugin
https://github.com/sri-csl/daikon-gradle-plugin

Last synced: about 1 month ago
JSON representation

(experimental) daikon gradle plugin

Awesome Lists containing this project

README

        

# Daikon Gradle Plugin

[![License](https://img.shields.io/badge/license-apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)

This Gradle plug-in creates a task, `runDaikon`, that runs [Daikon](https://plse.cs.washington.edu/daikon/) on Java projects' unit tests.

## Configuration

To use this plug-in you must apply the Randoop plug-in to the root project’s `build.gradle`:

```groovy
plugins {
id 'java'
id 'maven-publish'
id 'com.sri.gradle.daikon' version '0.0.2-SNAPSHOT'
}
```

Then, you must specify you must specify a few configuration parameters in your `runDaikon` configuration.
For example, the location where the plug-in can find the Daikon tool, the Daikon output directory,
the test driver package name, etc.

You can find a complete example of this configuration below:

```groovy
plugins {
id 'java'
id 'maven-publish'
id 'com.sri.gradle.daikon' version '0.0.2-SNAPSHOT'
}

repositories {
mavenLocal()
mavenCentral()
maven {
url 'https://plugins.gradle.org/m2/'
}
}

dependencies {
implementation 'com.google.guava:guava:28.0-jre'
testImplementation 'org.hamcrest:hamcrest:2.2'
testImplementation 'junit:junit:4.13'
}

runDaikon {
outputDir = file("${projectDir}/build/daikon-output")
// the project directory where daikon.jar, ChicoryPremain.jar,
// and dcomp_*.jar files exist
requires = file("libs")
// *TestDriver package name
// The Daikon tool requires a test driver. If you use Randoop,
// then Randoop will generate one for you.
testDriverPackage = "com.foo"
// Otherwise, you need to tell this plugin to create one for you.
// The instructions for how to do this are described later in this
// README file.
}
```

## Using a locally-built plugin

You can build the plug-in locally rather than downloading it from Maven Central.

To build the plug-in from source, run the `./gradlew build` command.

If you want to use a locally-built version of the plug-in, you must add the following configuration to
the `settings.gradle` file of your Gradle project:

```
pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
}
}
```

Then, you can publish the plug-in to your local Maven repository simply by running the `./gradlew publishToMavenLocal` command.
Make sure you run both the `clean` and the `build` tasks before running this command:

```sh
› ./gradlew clean
› ./gradlew build
› ./gradlew publishToMavenLocal
```

After that, you can use any of the Gradle tasks offered by the Daikon plug-in.

## Daikon Tasks

The plugin support the following tasks. The main task of this plugin is the `runDaikon` task, which
runs other supporting tasks, such as `generateTestDriverCode`. The entire list of tasks is presented here:

- `daikonCheck` - Checks if Daikon is in your project's classpath.
- `daikonEvidence` - Produces an evidence artifact containing the specific details of the Daikon execution.
- `generateTestDriverCode` - Generates test driver code that Daikon can execute.
- `runDaikon` - Detection of likely program invariants using Daikon.

**Additional build properties:**

- `-Pdriver` - Tells the plugin to generate its own test driver at `build/driver` directory.

If the above property is not provided, then the plugin assumes there is already test driver it can use with Daikon.

## An example: Applying the Daikon plug-in to a simple Java project

A simple example of how to use this plugin on a basic Java project can be found at this project's
`consumer` sub-directory. Here are the steps for using the plugin:

1. Make sure you publish the plugin to Maven local first (See steps above)

If `build` tasks throws an error, try running the used commands with the `--stacktrace` or `--debug` options. E.g.,

```sh
› ./gradlew clean
› ./gradlew build --stacktrace
› ./gradlew publishToMavenLocal
```

2. Run either `daikonEvidence` or `runDaikon` tasks

If you want to see the plugin in action, you can just run the `runDaikon` task. That should be enough.
This task will execute Daikon based on the configuration on `build.gradle` file. However, if you want to generate
an evidence artifact that provides a summary of a Daikon execution (based on the files generated by `runDaikon`),
then you can run the `daikonEvidence` task.

```sh
› cd consumer
› ./gradlew daikonEvidence
```

## Results

The tasks `runDaikon` and `daikonEvidence` generates a few files. The main ones are
`*TestDriver.inv.txt`, `daikon-evidence.json`. It also produces three CSV files:
`DaikonInvsAndMetrics.csv`, `DaikonPluginConfig`, and `DaikonPluginQualification.csv`.
The `daikon-evidence.json` file aggregates all the information in the other `CSV` files.

Here is a snippet of the first one:

```text
===========================================================================
com.foo.Foo:::OBJECT
===========================================================================
com.foo.Foo.Foo():::EXIT
===========================================================================
com.foo.Foo.mutate():::ENTER
===========================================================================
com.foo.Foo.mutate():::EXIT
===========================================================================
com.foo.FooManager:::OBJECT
===========================================================================
com.foo.FooManager.FooManager(com.foo.Foo):::ENTER
===========================================================================
com.foo.FooManager.FooManager(com.foo.Foo):::EXIT
===========================================================================
com.foo.FooManager.initialize():::ENTER
this.foo != null
===========================================================================
com.foo.FooManager.initialize():::EXIT
this.foo == orig(this.foo)
this.foo != null
===========================================================================
```

And here is the second file:

```json
{
"Evidence": {
"DaikonPluginConfig": {
"OUTPUT_DIR": "build/daikon-output",
"TEST_DRIVER_PACKAGE": "com.foo"
},
"DaikonPluginQualification": {
"DATE": "2021-3-30",
"SUMMARY": "Runs the Daikon Tool",
"QUALIFIEDBY": "SRI International",
"INSTALLATION": "https://github.com/SRI-CSL/daikon-gradle-plugin/blob/master/README.md",
"USERGUIDE": "https://github.com/SRI-CSL/daikon-gradle-plugin/blob/master/README.md",
"TITLE": "DaikonGradlePlugin",
"ACTIVITY": "Dynamic Analysis"
},
"DaikonInvsAndMetrics": {
"CORES": "16",
"JVM_MEMORY_LIMIT_IN_BYTES": "477626368",
"SUPPORT_FILES": [
"build/daikon-output/RegressionTestDriver.dtrace.gz",
"build/daikon-output/RegressionTestDriver.decls-DynComp",
"build/daikon-output/RegressionTestDriver.inv.gz"
],
"PP_COUNT": "5",
"INVARIANTS_FILE": "build/daikon-output/RegressionTestDriver.inv.txt",
"MEMORY_AVAILABLE_TO_JVM_IN_BYTES": "432013312",
"CLASSES_COUNT": "1",
"TEST_DRIVER": "src/test/java/com/foo/RegressionTestDriver.java",
"TESTS_COUNT": "4",
"INVARIANT_COUNT": "0"
}
}
}
```

## License

Copyright (C) 2020 SRI International

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.