Skip to content

Commit 5fb835b

Browse files
committed
readme, example, anonymisation, cleanup
1 parent 3b95a93 commit 5fb835b

107 files changed

Lines changed: 935 additions & 644 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 160 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,166 @@
1-
# SPLVariantEvolution
2-
Generate Clone-and-Own Histories with Ground-Truth in Space and Time from Software Product Lines
1+
# VEVOS - Variant Generation
2+
3+
## begin todos
4+
TODO: Find names for
5+
- **ground truth extraction**: VEVOS_Extraction, VEVOSX, VEvoSX
6+
- **variant generation**: VEVOS_Generation, VEVOSG, VEvoSG
7+
## end todos
8+
9+
VEVOS is a tool suite for the simulation of the evolution of clone-and-own projects.
10+
VEVOS has two main components: The ground truth extraction, called VEVOS_Extraction and the variant generation called VEVOS_Generation.
11+
12+
This repository contains VEVOS_Generation and thus the second part of the replication package for the paper _Simulating the Evolution of Clone-and-Own Projects with VEVOS_ submitted to the International Conference on Evaluation and Assessment in Software Engineering (EASE) 2022.
13+
VEVOS_Generation is a java library for generating variants with ground truth from an input software product line and dataset extracted with VEVOS_Extraction.
14+
15+
## Example Usage and Main Features
16+
17+
VEVOS_Generation is supposed to be used by your research prototype on clone-and-own or variability in software systems.
18+
In the following we give a step by step example in how the library can be used to
19+
- parse the ground truth dataset extracted by VEVOS_Extraction,
20+
- traverse the datasets' evolution history,
21+
- sample variants randomly, or use a predefined set of variants for generation,
22+
- generate variants for each step in the evolution history,
23+
- obtain the ground truth of generated variants.
24+
The examples source code can also be found in [GenerationExample.java](src/main/java/vevos/examples/GenerationExample.java).
25+
We also give a brief introduction of the key features of the library we use in the following example.
26+
27+
We start by specifying the necessary paths to (1) the git repository of the input software product line, (2) the directory of the extracted ground truth dataset, (3) and a directory to which we want to generate variants. (We use case sensitive paths to also allow the generation of Linux variants under Windows).
28+
```java
29+
final CaseSensitivePath splRepositoryPath = CaseSensitivePath.of("path", "to", "SPL", "git", "repository");
30+
final CaseSensitivePath groundTruthDatasetPath = CaseSensitivePath.of("path", "to", "datasets");
31+
final CaseSensitivePath variantsGenerationDir = CaseSensitivePath.of("directory", "to", "put", "generated", "variants");
32+
```
33+
We can now load the extraced ground truth dataset:
34+
```java
35+
final VariabilityDataset dataset = Resources.Instance()
36+
.load(VariabilityDataset.class, groundTruthDatasetPath.path());
37+
```
38+
For loading data, VEVOS_Generation uses a central service for resource loading and writing called `Resources`.
39+
`Resources` provides a unified interface for reading and writing data of any type.
40+
Above, we use the resources to load a `VariabilityDataset` from the given path.
41+
Internally, `Resources` stores `ResourceLoader` and `ResourceWriter` objects that perform the file system interaction.
42+
This central interface allows users to add loaders and writers for further or custom data types as well as to replace existing loaders.
43+
Currently, `Resources` support IO of CSV files, feature models (KernelHaven `json`, and FeatureIDE `dimacs`, `xml`), variant configurations (FeatureIDE `xml`), and presence conditions of product lines and variants.
44+
45+
From the loaded `dataset`, we can obtain the available evolution step.
46+
An evolution step describes a commit-sized change to the input software product line, and is defined by the (child) commit performing a change to a previous (parent) commit.
47+
Note that the evolution steps are not ordered because commits in the input product-line repository might not have been ordered as the commits might have been extracted from different branches.
48+
Alternatively, we can also request a continuous history of evolution steps instead of an unordered set.
49+
Therefore, a `SequenceExtractor` is used to determine how the successfully extracted commits should ordered.
50+
In this example, we use the `LongestNonOverlappingSequences` extractor to sort the commits into one single continuous history.
51+
Nevertheless, merge commits and error commits (where VEVOS_Extraction failed) are excluded from the history and thus, the returned list of commits has gaps.
52+
Because of these gaps, we obtain a list of sub-histories, where each sub-history is continuous but sub-histories are divided by merge and error commits.
53+
```java
54+
final Set<EvolutionStep<SPLCommit>> evolutionSteps = dataset.getEvolutionSteps();
55+
56+
/// Organize all evolution steps into a history for the clone-and-own project.
57+
final VariabilityHistory history = dataset.getVariabilityHistory(new LongestNonOverlappingSequences());
58+
/// This yields a list of continuous sub-histories.
59+
/// The history is divided into sub-histories because for some commits in the SPL, the commit extraction might have failed.
60+
/// If the extraction fails for a commit c, then we have to exclude c from the variant generation.
61+
/// This cuts the evolution history into two pieces.
62+
/// Thus, we divide the history into sub-histories at each failed commit.
63+
final NonEmptyList<NonEmptyList<SPLCommit>> sequencesInHistory = history.commitSequences();
64+
```
65+
To generate variants, we have to specify which variants should be generated.
66+
Therefore, a `Sampler` is used that returns the set of variants to use for a certain feature model.
67+
Apart from the possibility of introducing custom samplers, VEVOS_Generation comes with two built-in ways for sampling:
68+
Random configuration sampling using the FeatureIDE library, and constant sampling.
69+
Random sampling returns a random set of valid configuration from a given feature model.
70+
Constant sampling uses a pre-defined set of variants to generate ignoring the feature model.
71+
The set of desired variants is encapsulated in samplers because the set of valid variants of the input product line may change when the feature model changes.
72+
Thus, the sampler can be invoked during each step of the variant generation.
73+
```java
74+
/// Either use random sampling, ...
75+
final int numberOfVariantsToGenerate = 42;
76+
Sampler variantsSampler = FeatureIDESampler.CreateRandomSampler(numberOfVariantsToGenerate);
77+
```
78+
```java
79+
/// ... or use a predefined set of variants.
80+
final Sample variantsToGenerate = new Sample(List.of(
81+
new Variant("Bernard", new SimpleConfiguration(List.of(
82+
/// Features selected in variant Bernhard.
83+
"A", "B", "D", "E", "N", "R"
84+
))),
85+
new Variant("Bianca", new SimpleConfiguration(List.of(
86+
"A", "B", "C", "I", "N"
87+
)))
88+
));
89+
Sampler variantsSampler = new ConstSampler(variantsToGenerate);
90+
}
91+
```
92+
We are now ready to traverse the evolution history to generate variants:
93+
```java
94+
for (final NonEmptyList<SPLCommit> subhistory : history.commitSequences()) {
95+
for (final SPLCommit splCommit : subhistory) {
96+
final Lazy<Optional<IFeatureModel>> loadFeatureModel = splCommit.featureModel();
97+
final Lazy<Optional<Artefact>> loadPresenceConditions = splCommit.presenceConditions();
98+
```
99+
The history we retrieved earlier is structured into sub-histories. For each sub-history we can get the commits (as objects of type `SPLCommit`) from the input software product line that was analysed by VEVOS_Extraction.
100+
Through an `SPLCommit`, we can access the feature model and the presence condition of the software product line at the respective commit.
101+
However, both types of data are not directly accessible but have to be loaded first.
102+
This is what the `Lazy` type is used for: It defers the loading of data until it is actually required.
103+
This makes accessing the possibly huge (93GB for 13k commits of Linux, yikes!) ground truth dataset faster and memory-friendly as only required data is loaded into memory.
104+
We can start the loading process by invoking `Lazy::run` that returns a value of the loaded type (i.e., `Optional<IFeatureModel>` or `Optional<Artefact>`).
105+
A `Lazy` caches its loaded value so loading is only performed once.
106+
(Loaded data that is not required anymore can and should be freed by invoking `Lazy::forget`.)
107+
As the extraction of feature model or presence condition might have failed, both types are again wrapped in an `Optional` that contains a value if extraction was successful.
108+
Let's assume the extraction succeeded by just invoking `orElseThrow` here.
109+
```java
110+
final Artefact pcs = loadPresenceConditions.run().orElseThrow();
111+
final IFeatureModel featureModel = loadFeatureModel.run().orElseThrow();
112+
```
113+
Having the feature model at hand, we can now sample the variants we want to generate for the current `splCommit`.
114+
In case the `variantsSampler` is actually a `ConstSampler` (see above), it will ignore the feature model and will just always return the same set of variants you specified earlier in the `ConstSampler`.
115+
```java
116+
final Sample variants = variantsSampler.sample(featureModel);
117+
```
118+
Optionally, we might want to filter which files of a variant to generate.
119+
For example, a study on evolution of code in variable software systems could be interested only in generating the changed files of a commit.
120+
In our case, let's just generate all variants.
121+
Moreover, `VariantGenerationOptions` allow to configure some parameters for the variant generation.
122+
Here, we just instruct the generation to exit in case an error happens but we could for example also instruct it to ignore errors and proceed.
123+
```java
124+
final ArtefactFilter<SourceCodeFile> artefactFilter = ArtefactFilter.KeepAll();
125+
final VariantGenerationOptions generationOptions = VariantGenerationOptions.ExitOnError(artefactFilter);
126+
```
127+
Finally, we may indeed generate our variants:
128+
```java
129+
for (final Variant variant : variants) {
130+
/// Let's put the variant into our target directory but indexed by commit hash and its name.
131+
final CaseSensitivePath variantDir = variantsGenerationDir.resolve(splCommit.id(), variant.getName());
132+
final Result<GroundTruth, Exception> result =
133+
pcs.generateVariant(variant, splRepositoryPath, variantDir, generationOptions);
134+
```
135+
The generation returns a `Result` that either represents the ground truth for the generated variant, or contains an exception if something went wrong.
136+
In case the generation was successful, we can inspect the `groundTruth` of the variant.
137+
The `groundTruth` consists of
138+
- the presence conditions and feature mappings of the variant (which are different from the software product lines presence conditions, for example because line numbers shifted),
139+
- and a block matching that for each source code file (key of the map) tells us which blocks of source code in the variant steam from which blocks of source code in the software product line.
140+
We may also export ground truth data to disk for later usage.
141+
142+
(Here it is important to export the ground truth as `.variant.csv` as this suffix is used by our `Resources` to correctly load the ground truth.
143+
In contrast, the suffix is `.spl.csv` for ground truth presence conditions of the input software product line. The major difference here is that some line numbers have to be interpreted differently upon read and write because variants are stripped off their annotations while product lines still have them.)
144+
```java
145+
if (result.isSuccess()) {
146+
final GroundTruth groundTruth = result.getSuccess();/// 1. the presence conditions.
147+
final Artefact presenceConditionsOfVariant = groundTruth.variant();
148+
/// 2. a map that stores matchings of blocks for each source code file
149+
final Map<CaseSensitivePath, AnnotationGroundTruth> fileMatches = groundTruth.fileMatches();
150+
151+
/// We can also export the ground truth PCs of the variant.
152+
Resources.Instance().write(Artefact.class, presenceConditionsOfVariant, variantDir.resolve("pcs.variant.csv").path());
153+
}
154+
```
155+
This was round-trip about the major features of VEVOS_Generation. Further features and convencience methods can be found in our documentation.
3156

4157
## Setup
5158

159+
You may include VEVOS_Generation as a pre-build `jar` file or build it on your own.
160+
The `jar` file can be found at TODO.
161+
162+
### Build
163+
6164
To initialize to local maven repository for the libraries we use, run the following as maven targets:
7165

8166
- FeatureIDE: `deploy:deploy-file -DgroupId=de.ovgu -DartifactId=featureide.lib.fm -Dversion=3.7.0 -Durl=file:./local-maven-repo/ -DrepositoryId=local-maven-repo -DupdateReleaseInfo=true -Dfile=src/main/resources/lib/de.ovgu.featureide.lib.fm-v3.7.0.jar`

pom.xml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,14 @@
55
<modelVersion>4.0.0</modelVersion>
66

77
<!-- Adjust group id for anonymous projects -->
8-
<groupId>de.variantsync.subjects</groupId>
8+
<groupId>vevos</groupId>
99
<!-- Adjust the generateVariant name -->
10-
<artifactId>SPLVariantEvolution</artifactId>
10+
<artifactId>Generation</artifactId>
1111
<version>0.0.1</version>
1212

1313
<properties>
1414
<!-- Adjust your java version here -->
1515
<java.version>16</java.version>
16-
<!-- Adjust the path to the class that contains the main-method, that is to be executed, here -->
17-
<path.to.main>${groupId}.Main</path.to.main>
18-
<path.to.main>${project.groupId}.Main</path.to.main>
1916
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2017
<maven.compiler.source>${java.version}</maven.compiler.source>
2118
<maven.compiler.target>${java.version}</maven.compiler.target>

src/main/java/de/variantsync/evolution/feature/sampling/Sample.java

Lines changed: 0 additions & 14 deletions
This file was deleted.

src/main/java/de/variantsync/evolution/util/fide/bugfix/FixTrueFalse.java

Lines changed: 0 additions & 91 deletions
This file was deleted.

0 commit comments

Comments
 (0)