Merge branch '552698-git' (fixes #552698)
diff --git a/features/org.hawk.git.feature/feature.xml b/features/org.hawk.git.feature/feature.xml
index 2acd80f..4f4c31d 100644
--- a/features/org.hawk.git.feature/feature.xml
+++ b/features/org.hawk.git.feature/feature.xml
@@ -3,20 +3,28 @@
id="org.hawk.git.feature"
label="Hawk Git Feature"
version="1.2.0.qualifier"
- provider-name="University of York">
+ provider-name="Eclipse.org">
<description>
- Provides the ability for Hawk to index local Git working copies.
+ Provides the ability for Hawk to index local Git working copies.
</description>
<copyright>
- Copyright (C) 2015-2018 Universit of York, Aston University.
+ Copyright (C) 2015-2019 University of York, Aston University.
</copyright>
<license url="https://www.eclipse.org/legal/epl-2.0/">
Eclipse Public License v2.0 with GPLv3.0 Secondary License
</license>
+ <requires>
+ <import plugin="org.hawk.core"/>
+ <import plugin="org.slf4j.api" version="1.7.2" match="greaterOrEqual"/>
+ <import plugin="org.eclipse.jgit" version="5.0.0" match="greaterOrEqual"/>
+ <import plugin="org.apache.httpcomponents.httpclient" version="4.3.6" match="greaterOrEqual"/>
+ <import plugin="org.apache.httpcomponents.httpcore" version="4.3.3" match="greaterOrEqual"/>
+ </requires>
+
<plugin
id="org.hawk.git"
download-size="0"
@@ -24,4 +32,11 @@
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.hawk.jgit"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
</feature>
diff --git a/plugins-server/org.hawk.service.server.logback/src/logback.xml b/plugins-server/org.hawk.service.server.logback/src/logback.xml
index e848a29..fd53756 100644
--- a/plugins-server/org.hawk.service.server.logback/src/logback.xml
+++ b/plugins-server/org.hawk.service.server.logback/src/logback.xml
@@ -43,7 +43,7 @@
<appender-ref ref="FILE" />
</logger>
- <root level="debug">
+ <root level="info">
<appender-ref ref="STDOUT" />
</root>
diff --git a/plugins-server/org.hawk.service.servlet/src/org/hawk/service/servlet/config/ConfigFileParser.java b/plugins-server/org.hawk.service.servlet/src/org/hawk/service/servlet/config/ConfigFileParser.java
index 039a17c..2d66608 100644
--- a/plugins-server/org.hawk.service.servlet/src/org/hawk/service/servlet/config/ConfigFileParser.java
+++ b/plugins-server/org.hawk.service.servlet/src/org/hawk/service/servlet/config/ConfigFileParser.java
@@ -209,15 +209,10 @@
config.setFactory(hawkElement.hasAttribute(FACTORY) ? hawkElement.getAttribute(FACTORY) : null);
readDelay(hawkElement.getElementsByTagName(DELAY), config);
-
readPlugins(hawkElement.getElementsByTagName(PLUGINS), config);
-
readMetamodels(hawkElement.getElementsByTagName(METAMODELS), config);
-
readRepositories(hawkElement.getElementsByTagName(REPOSITORIES), config);
-
readIndexedAttributes(hawkElement.getElementsByTagName(INDEXED_ATTRIBUTES), config);
-
readDerivedAttributes(hawkElement.getElementsByTagName(DERIVED_ATTRIBUTES), config);
}
}
@@ -415,8 +410,8 @@
RepositoryParameters params = new RepositoryParameters(
repoElement.getAttribute(TYPE),
repoElement.getAttribute(LOCATION),
- repoElement.getAttribute(USER),
- repoElement.getAttribute(PASS),
+ repoElement.hasAttribute(USER) ? repoElement.getAttribute(USER) : null,
+ repoElement.hasAttribute(PASS) ? repoElement.getAttribute(PASS) : null,
Boolean.valueOf(repoElement.getAttribute(FROZEN)));
config.getRepositories().add(params);
@@ -483,7 +478,7 @@
}
private void createAndAddAttribute(Document document, Element element, String tagName, String value) {
- if(value != null) {
+ if (value != null) {
Attr attr = document.createAttribute(tagName);
attr.setValue(value);
element.setAttributeNode(attr);
diff --git a/plugins/org.hawk.core/src/org/hawk/core/IVcsManager.java b/plugins/org.hawk.core/src/org/hawk/core/IVcsManager.java
index c337c8a..cd7ce7b 100644
--- a/plugins/org.hawk.core/src/org/hawk/core/IVcsManager.java
+++ b/plugins/org.hawk.core/src/org/hawk/core/IVcsManager.java
@@ -21,7 +21,6 @@
import java.io.File;
import java.util.Collection;
-import org.hawk.core.IHawkPlugin.Category;
import org.hawk.core.model.IHawkObject;
public interface IVcsManager extends IHawkPlugin {
@@ -37,12 +36,20 @@
String getFirstRevision() throws Exception;
/**
- * Returns the set of changed items from this revision.
+ * Returns the set of changed items after this revision.
*/
Collection<VcsCommitItem> getDelta(String startRevision) throws Exception;
/**
- * Returns the set of changed items between these revisions.
+ * Returns the set of changed items strictly after <code>startRevision</code>
+ * until <code>endRevision</code> (included).
+ *
+ * @param startRevision Oldest revision in the range (excluded). Some special
+ * values are allowed: both <code>null</code> and strings
+ * with negative integers (e.g. "-3") mean "before the
+ * first revision". This allows Hawk to fetch the changes
+ * introduced by the very first revision.
+ * @param endRevision Newest revision in the range (included).
*/
VcsRepositoryDelta getDelta(String startRevision, String endRevision) throws Exception;
@@ -57,16 +64,16 @@
*
* Returns <code>null</code> if the file could not be found.
*
- * @param revision
- * Identifier of the desired revision of the specified file.
- * Implementations that do not support retrieving past versions of
- * the file may ignore this argument.
- * @param path
- * Path within the repository where the file is stored.
- * @param optionalTemp
- * If the file is not available as-is in the local filesystem (e.g.
- * needs to be retrieved over the network), this argument provides a
- * location where the implementation can temporarily save it.
+ * @param revision Identifier of the desired revision of the specified file.
+ * Implementations that do not support retrieving past
+ * versions of the file may ignore this argument.
+ * @param path Path within the repository where the file is stored.
+ * @param optionalTemp If the file is not available as-is in the local
+ * filesystem (e.g. needs to be retrieved over the network),
+ * this argument provides a location where the
+ * implementation can temporarily save it.
+ * @return {@link File} object with the contents of the path, or
+ * <code>null</code> if the file could not be found.
*/
File importFile(String revision, String path, File optionalTemp);
diff --git a/plugins/org.hawk.core/src/org/hawk/core/runtime/BaseModelIndexer.java b/plugins/org.hawk.core/src/org/hawk/core/runtime/BaseModelIndexer.java
index 2b3b922..4bbb6f4 100644
--- a/plugins/org.hawk.core/src/org/hawk/core/runtime/BaseModelIndexer.java
+++ b/plugins/org.hawk.core/src/org/hawk/core/runtime/BaseModelIndexer.java
@@ -936,12 +936,16 @@
@Override
public boolean addGraphChangeListener(IGraphChangeListener changeListener) {
- return listener.add(changeListener);
+ final boolean add = listener.add(changeListener);
+ changeListener.setModelIndexer(this);
+ return add;
}
@Override
public boolean removeGraphChangeListener(IGraphChangeListener changeListener) {
- return listener.remove(changeListener);
+ final boolean remove = listener.remove(changeListener);
+ changeListener.setModelIndexer(null);
+ return remove;
}
@Override
diff --git a/plugins/org.hawk.graph.syncValidationListener/src/org/hawk/graph/syncValidationListener/SyncValidationListener.java b/plugins/org.hawk.graph.syncValidationListener/src/org/hawk/graph/syncValidationListener/SyncValidationListener.java
index 3010d2c..254421b 100644
--- a/plugins/org.hawk.graph.syncValidationListener/src/org/hawk/graph/syncValidationListener/SyncValidationListener.java
+++ b/plugins/org.hawk.graph.syncValidationListener/src/org/hawk/graph/syncValidationListener/SyncValidationListener.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011-2016 The University of York.
+ * Copyright (c) 2011-2019 The University of York, Aston University.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
@@ -13,6 +13,7 @@
*
* Contributors:
* Konstantinos Barmpis - initial API and implementation
+ * Antonio Garcia-Dominguez - collect errors in list instead of printing them
******************************************************************************/
package org.hawk.graph.syncValidationListener;
@@ -20,10 +21,12 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -50,8 +53,24 @@
public class SyncValidationListener implements IGraphChangeListener {
+ public class ValidationError {
+ private final String message;
+
+ public ValidationError(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+ }
+
private ModelIndexerImpl hawk;
- private int removedProxies, totalErrors, deleted, malformed, singletonCount, totalGraphSize, totalResourceSizes;
+
+ // stats
+ private List<ValidationError> errors = new ArrayList<>();
+ private int removedProxies, deleted, malformed, singletonCount, totalGraphSize, totalResourceSizes;
+
private Set<String> changed = new HashSet<>();
private IGraphNodeIndex singletonIndex;
@@ -65,8 +84,10 @@
public void setModelIndexer(IModelIndexer hawk) {
this.hawk = (ModelIndexerImpl) hawk;
- System.err.println("SyncValidationListener: hawk.setSyncMetricsEnabled(true) called, performance will suffer!");
- hawk.setSyncMetricsEnabled(true);
+ if (this.hawk != null) {
+ System.err.println("SyncValidationListener: hawk.setSyncMetricsEnabled(true) called, performance will suffer!");
+ hawk.setSyncMetricsEnabled(true);
+ }
}
@Override
@@ -82,7 +103,9 @@
@Override
public void synchroniseEnd() {
try {
- validateChanges();
+ if (hawk != null) {
+ validateChanges();
+ }
} catch (URISyntaxException e) {
e.printStackTrace();
}
@@ -91,11 +114,17 @@
changed.clear();
}
+ public List<ValidationError> getErrors() {
+ return errors;
+ }
+
public int getTotalErrors() {
- return totalErrors;
+ return errors.size();
}
private void validateChanges() throws URISyntaxException {
+ assert this.hawk != null : "validateChanges() should only be called if the indexer has been set";
+
System.err.println("sync metrics:");
System.err.println("interesting\t" + hawk.getInterestingFiles());
System.err.println("deleted\t\t" + hawk.getDeletedFiles());
@@ -107,8 +136,8 @@
System.err.println("validating changes...");
+ errors.clear();
removedProxies = 0;
- totalErrors = 0;
malformed = 0;
singletonCount = 0;
totalResourceSizes = 0;
@@ -124,19 +153,20 @@
}
System.err.println("changed resource size: " + totalResourceSizes);
-
System.err.println("relevant graph size: "
+ totalGraphSize
+ (singletonCount > 0 ? (" + singleton count: " + singletonCount) : ""));
if (totalGraphSize + singletonCount != totalResourceSizes) {
- totalErrors++;
+ errors.add(new ValidationError(
+ String.format("Mismatched resource size: %d + %d != %d", totalGraphSize, singletonCount, totalResourceSizes)
+ ));
}
System.err.println("validated changes... "
- + (totalErrors == 0 ? "true"
- : ((totalErrors == malformed) + " (with "
- + totalErrors + " total and "
+ + (errors.isEmpty() ? "true"
+ : ((errors.size() == malformed) + " (with "
+ + errors.size() + " total and "
+ malformed + " malformed errors)"))
+ (removedProxies == 0 ? "" : " [" + removedProxies
+ "] unresolved hawk proxies matched"));
@@ -168,33 +198,36 @@
file = repository + GraphModelUpdater.FILEINDEX_REPO_SEPARATOR + c.getPath();
filenode = graph.getFileIndex().get("id", file).getSingle();
} catch (Exception ee) {
- System.err.println("expected file " + file
- + " but it did not exist (maybe metamodel not registered, if so expect +1 errors)");
- totalErrors++;
+ errors.add(new ValidationError(
+ String.format(
+ "Expected file %s but it did not exist "
+ + "(maybe metamodel not registered, if so expect +1 errors)",
+ file)
+ ));
return;
}
// cache model elements in current resource
- Map<String, IHawkObject> eobjectCache = new HashMap<>();
+ Map<String, IHawkObject> eObjectCache = new HashMap<>();
// cache of malformed object identifiers (to ignore references)
Set<String> malformedObjectCache = new HashSet<>();
- cacheModelElements(c, r, eobjectCache, malformedObjectCache);
+ cacheModelElements(c, r, eObjectCache, malformedObjectCache);
// go through all nodes in graph from the file the resource is in
for (IGraphEdge instanceEdge : filenode.getIncomingWithType(ModelElementNode.EDGE_LABEL_FILE)) {
final IGraphNode instance = instanceEdge.getStartNode();
totalGraphSize++;
- final IHawkObject eobject = eobjectCache.get(instance.getProperty(IModelIndexer.IDENTIFIER_PROPERTY));
+ final IHawkObject eobject = eObjectCache.get(instance.getProperty(IModelIndexer.IDENTIFIER_PROPERTY));
// if a node cannot be found in the model cache
if (eobject == null) {
- System.err.println("error in validating: graph contains node with identifier:"
- + instance.getProperty(IModelIndexer.IDENTIFIER_PROPERTY) + " but resource does not!");
// this triggers when a malformed model has 2 identical identifiers
- totalErrors++;
+ errors.add(new ValidationError(
+ String.format("Graph contains node with identifier: %s but resource does not!", instance.getProperty(IModelIndexer.IDENTIFIER_PROPERTY))
+ ));
} else {
- eobjectCache.remove(instance.getProperty(IModelIndexer.IDENTIFIER_PROPERTY));
+ eObjectCache.remove(instance.getProperty(IModelIndexer.IDENTIFIER_PROPERTY));
if (!malformedObjectCache.contains(eobject.getUri())) {
compareAttributes(instance, eobject);
@@ -204,10 +237,10 @@
}
// if there are model elements not found in nodes
- if (eobjectCache.size() > 0) {
- System.err.println("error in validating: the following objects were not found in the graph:");
- System.err.println(eobjectCache.keySet());
- totalErrors++;
+ if (eObjectCache.size() > 0) {
+ errors.add(new ValidationError(
+ String.format("The following objects were not found in the graph:\n%s", eObjectCache.keySet())
+ ));
}
t.success();
@@ -273,21 +306,25 @@
filterFragmentBasedReferences(noderefvaluesclone, modelrefvaluesclone);
if (noderefvaluesclone.size() > 0) {
- System.err.println("error in validating: reference " + modelRefName + " of node: "
- + instance.getProperty(IModelIndexer.IDENTIFIER_PROPERTY) + "\nlocated: "
- + instance.getOutgoingWithType(ModelElementNode.EDGE_LABEL_FILE).iterator().next().getEndNode()
- .getProperty(IModelIndexer.IDENTIFIER_PROPERTY));
- System.err.println(noderefvaluesclone);
- System.err.println("the above ids were found in the graph but not the model");
- totalErrors++;
+ final IGraphNode fileNode = instance.getOutgoingWithType(ModelElementNode.EDGE_LABEL_FILE).iterator().next().getEndNode();
+ errors.add(new ValidationError(
+ String.format(
+ "Reference %s of node: %s\n"
+ + "Located: %s\n%s\n"
+ + "The above IDs were found in the graph but not the model",
+ modelRefName, instance.getProperty(IModelIndexer.IDENTIFIER_PROPERTY),
+ fileNode, noderefvaluesclone)
+ ));
}
if (modelrefvaluesclone.size() > 0) {
- System.err.println("error in validating: reference " + modelRefName + " of model element: "
- + eobject.getUriFragment() + "\nlocated: " + eobject.getUri());
- System.err.println(modelrefvaluesclone);
- System.err.println("the above ids were found in the model but not the graph");
- totalErrors++;
+ errors.add(new ValidationError(
+ String.format("Reference %s of model element: %s\n"
+ + "Located: %s\n%s\n"
+ + "The above IDs were found in the model but not the graph",
+ modelRefName, eobject.getUriFragment(),
+ eobject.getUri(), modelrefvaluesclone)
+ ));
}
nodereferences.remove(modelRefName);
@@ -295,10 +332,10 @@
}
if (nodereferences.size() > 0) {
- System.err.println("error in validating: references " + nodereferences.keySet()
- + " had targets in the graph but not in the model: ");
- System.err.println(nodereferences);
- totalErrors++;
+ errors.add(new ValidationError(String.format(
+ "References %s had targets in the graph but not in the model:\n%s",
+ nodereferences.keySet(), nodereferences)
+ ));
}
}
@@ -396,35 +433,35 @@
for (String propertykey : node.getPropertyKeys()) {
if (!propertykey.equals(IModelIndexer.SIGNATURE_PROPERTY)
&& !propertykey.equals(IModelIndexer.IDENTIFIER_PROPERTY)
- && !propertykey.startsWith(GraphModelUpdater.PROXY_REFERENCE_PREFIX)) {
+ && !propertykey.startsWith(GraphModelUpdater.PROXY_REFERENCE_PREFIX)
+ && !propertykey.equals(GraphModelInserter.LAST_DERIVED_TSTAMP_NODEPROP)) {
Object dbattr = node.getProperty(propertykey);
Object attr = modelAttributes.get(propertykey);
if (!flattenedStringEquals(dbattr, attr)) {
- totalErrors++;
- System.err.println("error in validating, attribute: " + propertykey + " has values:");
- final String cla1 = dbattr != null ? dbattr.getClass().toString() : "null attr";
- System.err.println(String.format("database:\t%s JAVATYPE: %s IN NODE: %s WITH ID: %s",
- (dbattr instanceof Object[] ? (Arrays.asList((Object[]) dbattr)) : dbattr),
- cla1, node.getId(), node.getProperty(IModelIndexer.IDENTIFIER_PROPERTY)));
+ final String dbJavaType = dbattr != null ? dbattr.getClass().toString() : "null attr";
+ final Object dbValue = dbattr instanceof Object[] ? (Arrays.asList((Object[]) dbattr)) : dbattr;
+ final String modelJavaType = attr != null ? attr.getClass().toString() : "null attr";
+ final Object modelValue = attr instanceof Object[] ? (Arrays.asList((Object[]) attr)) : attr;
- String cla2 = attr != null ? attr.getClass().toString() : "null attr";
- System.err.println(String.format("model:\t\t%s JAVATYPE: %s IN ELEMENT WITH ID %s",
- (attr instanceof Object[] ? (Arrays.asList((Object[]) attr)) : attr),
- cla2, modelElement.getUriFragment()));
+ errors.add(new ValidationError(String.format(
+ "Attribute %s has mismatched values:\n"
+ + " * database:\t%s JAVATYPE: %s IN NODE: %s WITH ID: %s\n"
+ + " * model:\t\t%s JAVATYPE: %s IN ELEMENT WITH ID %s",
+ propertykey,
+ dbValue, dbJavaType, node.getId(), node.getProperty(IModelIndexer.IDENTIFIER_PROPERTY),
+ modelValue, modelJavaType, modelElement.getUriFragment()
+ )));
}
modelAttributes.remove(propertykey);
}
}
if (modelAttributes.size() > 0) {
- System.err.println(String.format(
- "error in validating, the following attributes were "
- + "not found in the graph node %s: %s",
- node.getId(), modelAttributes.keySet()));
-
- totalErrors++;
+ errors.add(new ValidationError(String.format(
+ "The following attributes were not found in the graph node %s: %s", node.getId(), modelAttributes.keySet()
+ )));
}
}
diff --git a/plugins/org.hawk.greycat/src/org/hawk/greycat/GreycatNode.java b/plugins/org.hawk.greycat/src/org/hawk/greycat/GreycatNode.java
index aaf411f..19f85bb 100644
--- a/plugins/org.hawk.greycat/src/org/hawk/greycat/GreycatNode.java
+++ b/plugins/org.hawk.greycat/src/org/hawk/greycat/GreycatNode.java
@@ -939,10 +939,14 @@
final Node n = rn.get();
CompletableFuture<long[]> result = new CompletableFuture<>();
- n.timepoints(Constants.BEGINNING_OF_TIME,
- getTime() > Constants.BEGINNING_OF_TIME ? getTime() - 1 : getTime(),
- (value) -> result.complete(value)
- );
+
+ /*
+ * While the GreyCat javadocs say that both ends of the timepoints range are
+ * inclusive, the TimeAwareBackendTest#nextPrev method showed that the end of
+ * the range is exclusive.
+ */
+ n.timepoints(Constants.BEGINNING_OF_TIME, getTime(),
+ (value) -> result.complete(value));
/*
* We assume timepoints(...) produces elements from newest to oldest. The
diff --git a/plugins/org.hawk.http/pom-plain.xml b/plugins/org.hawk.http/pom-plain.xml
index 71429a1..04a3d17 100644
--- a/plugins/org.hawk.http/pom-plain.xml
+++ b/plugins/org.hawk.http/pom-plain.xml
@@ -23,7 +23,6 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
- <version>4.3.6</version>
</dependency>
</dependencies>
</project>
diff --git a/plugins/org.hawk.jgit/.classpath b/plugins/org.hawk.jgit/.classpath
new file mode 100644
index 0000000..6e16b23
--- /dev/null
+++ b/plugins/org.hawk.jgit/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.hawk.jgit/.project b/plugins/org.hawk.jgit/.project
new file mode 100644
index 0000000..629d3d5
--- /dev/null
+++ b/plugins/org.hawk.jgit/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.hawk.jgit</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.hawk.jgit/META-INF/MANIFEST.MF b/plugins/org.hawk.jgit/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c6be03a
--- /dev/null
+++ b/plugins/org.hawk.jgit/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Hawk JGit Plugin
+Bundle-SymbolicName: org.hawk.jgit;singleton:=true
+Bundle-Version: 1.2.0.qualifier
+Bundle-Vendor: Eclipse.org
+Require-Bundle: org.hawk.core,
+ org.slf4j.api;bundle-version="1.7.2",
+ org.eclipse.jgit;bundle-version="5.0.0",
+ org.apache.httpcomponents.httpclient;bundle-version="4.3.6",
+ org.apache.httpcomponents.httpcore;bundle-version="4.3.3"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Export-Package: org.hawk.git
diff --git a/plugins/org.hawk.jgit/build.properties b/plugins/org.hawk.jgit/build.properties
new file mode 100644
index 0000000..6f20375
--- /dev/null
+++ b/plugins/org.hawk.jgit/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml
diff --git a/plugins/org.hawk.jgit/plugin.xml b/plugins/org.hawk.jgit/plugin.xml
new file mode 100644
index 0000000..73387e4
--- /dev/null
+++ b/plugins/org.hawk.jgit/plugin.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+ <extension
+ point="org.hawk.core.VCSExtensionPoint">
+
+ <VCS
+ VCSManager="org.hawk.git.JGitRepository">
+ </VCS>
+ </extension>
+
+</plugin>
diff --git a/plugins/org.hawk.jgit/pom-plain.xml b/plugins/org.hawk.jgit/pom-plain.xml
new file mode 100644
index 0000000..a648701
--- /dev/null
+++ b/plugins/org.hawk.jgit/pom-plain.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.eclipse.hawk</groupId>
+ <artifactId>mondo-hawk-plain</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <relativePath>../../pom-plain.xml</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.hawk</groupId>
+ <artifactId>org.eclipse.hawk.jgit</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>org.eclipse.hawk.core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/plugins/org.hawk.jgit/src/org/hawk/git/JGitRepository.java b/plugins/org.hawk.jgit/src/org/hawk/git/JGitRepository.java
new file mode 100644
index 0000000..f683696
--- /dev/null
+++ b/plugins/org.hawk.jgit/src/org/hawk/git/JGitRepository.java
@@ -0,0 +1,511 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2019 The University of York, Aston University, and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the Eclipse
+ * Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
+ *
+ * Contributors:
+ * Konstantinos Barmpis - initial API and implementation
+ * Antonio Garcia-Dominguez - use Java 7 Path instead of File+string processing
+ * Horacio Hoyos Rodriguez - Add proper Git support (with code review from Antonio)
+ ******************************************************************************/
+package org.hawk.git;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.diff.DiffEntry;
+import org.eclipse.jgit.diff.DiffFormatter;
+import org.eclipse.jgit.errors.AmbiguousObjectException;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.RevisionSyntaxException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevSort;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.util.io.NullOutputStream;
+import org.hawk.core.ICredentialsStore;
+import org.hawk.core.IModelIndexer;
+import org.hawk.core.IVcsManager;
+import org.hawk.core.VcsChangeType;
+import org.hawk.core.VcsCommit;
+import org.hawk.core.VcsCommitItem;
+import org.hawk.core.VcsRepositoryDelta;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <p>
+ * An implementation of {@link IVcsManager} that supports Git repositories.
+ * </p>
+ * <p>
+ * This implementation relies on JGit to provide its functionality. The Git tree
+ * and history is used to provide version information and to generate file
+ * contents.
+ * </p>
+ */
+public class JGitRepository implements IVcsManager {
+
+ /**
+ * Thrown if a revision cannot be found in the repository.
+ */
+ public class UnableToFindRevisionException extends Exception {
+ private static final long serialVersionUID = -7277359120689923918L;
+
+ public UnableToFindRevisionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ }
+
+ /**
+ * Thrown if a delta is requested for revisions that do not belong to the same ancestry.
+ */
+ public class UnmergedAncestryException extends Exception {
+ private static final long serialVersionUID = -1805916162822065083L;
+
+ public UnmergedAncestryException(String message) {
+ super(message);
+ }
+ }
+
+ /**
+ * Name of the query parameter that can be used to specify an alternate branch.
+ */
+ static final String BRANCH_QPARAM = "branch";
+
+ private static final Logger LOG = LoggerFactory.getLogger(JGitRepository.class);
+
+ private String branch;
+
+ private Repository repository;
+ private String firstRevision;
+ private Path rootLocation;
+ private boolean active;
+ private boolean isFrozen;
+
+ @Override
+ public String getCurrentRevision() throws Exception {
+ try {
+ final ObjectId oid = repository.resolve(branch);
+ return ObjectId.toString(oid);
+ } catch (RevisionSyntaxException | AmbiguousObjectException | IncorrectObjectTypeException e) {
+ throw new IllegalStateException("Unexpected exception", e);
+ } catch (IOException e) {
+ throw new UnableToFindRevisionException("Unable to resolve the tip of branch " + branch, e);
+ }
+ }
+
+ @Override
+ public synchronized String getFirstRevision() throws Exception {
+ if (firstRevision == null) {
+ repository.scanForRepoChanges();
+ try (RevWalk walk = new RevWalk(repository)) {
+ walk.markStart(walk.parseCommit(repository.resolve(branch)));
+ walk.sort(RevSort.COMMIT_TIME_DESC, true);
+ walk.sort(RevSort.REVERSE, true);
+ RevCommit commit = walk.next();
+ firstRevision = ObjectId.toString(commit.getId());
+ } catch (IOException e) {
+ throw new UnableToFindRevisionException("Unable to resolve the first revision", e);
+ }
+ }
+ return firstRevision;
+ }
+
+ @Override
+ public List<VcsCommitItem> getDelta(String startRevision) throws Exception {
+ if (startRevision != null && startRevision.startsWith("-")) {
+ startRevision = null;
+ }
+ return getDelta(startRevision, getCurrentRevision()).getCompactedCommitItems();
+ }
+
+ @Override
+ public VcsRepositoryDelta getDelta(String startRevision, String endRevision) throws Exception {
+ if (startRevision == null) {
+ // nothing to do here!
+ } else if (startRevision.startsWith("-")) {
+ startRevision = null;
+ } else {
+ checkRangeAncestry(startRevision, endRevision);
+ }
+
+ VcsRepositoryDelta delta = new VcsRepositoryDelta();
+ delta.setManager(this);
+ try (Git git = Git.open(rootLocation.toFile())) {
+ Iterable<RevCommit> revs;
+ if (startRevision == null) {
+ revs = git.log().add(ObjectId.fromString(endRevision)).call();
+ } else {
+ revs = git.log().addRange(
+ ObjectId.fromString(startRevision),
+ ObjectId.fromString(endRevision)
+ ).call();
+ }
+
+ // Generate deltas between revisions
+ List<VcsCommit> commits = new ArrayList<>();
+ RevCommit previous = null;
+ for (RevCommit rev : revs) {
+ if (previous == null && rev.getParentCount() > 0) {
+ previous = rev.getParent(0);
+ }
+
+ diff(rev, previous).stream()
+ .findFirst().ifPresent(c -> commits.add(c.getCommit()));
+
+ previous = rev;
+ }
+
+ /*
+ * 'git log' returns revisions from newest to oldest, but the Hawk core expects
+ * them from oldest to newest.
+ */
+ for (ListIterator<VcsCommit> itCommit = commits.listIterator(commits.size()); itCommit.hasPrevious(); ) {
+ final VcsCommit commit = itCommit.previous();
+ commit.setDelta(delta);
+ delta.getCommits().add(commit);
+ }
+ }
+
+ return delta;
+ }
+
+ private void checkRangeAncestry(String startRevision, String endRevision)
+ throws UnmergedAncestryException, UnableToFindRevisionException {
+ try (RevWalk walk = new RevWalk(repository)) {
+ RevCommit startCommit = walk.parseCommit(repository.resolve(startRevision));
+ RevCommit endCommit = walk.parseCommit(repository.resolve(endRevision));
+ if (!walk.isMergedInto(startCommit, endCommit)) {
+ throw new UnmergedAncestryException(
+ String.format("Revision %s (end) is in a branch not merged "
+ + "into the branch that contains revision %s (start).", endRevision, startRevision));
+ }
+ } catch (IOException e) {
+ throw new UnableToFindRevisionException("Unable to resolve the delta of revision", e);
+ }
+ }
+
+
+ @Override
+ public File importFile(String revision, String path, File optionalTemp) {
+ if (path.startsWith("/")) {
+ // Strip out starting / from the paths produced by diff(), if present
+ path = path.substring(1);
+ }
+
+ // Do a TreeWalk over the tree of the commit pointed by the provided revision
+ try (RevWalk revWalk = new RevWalk(repository)) {
+ try (TreeWalk treeWalk = TreeWalk.forPath(
+ repository,
+ path,
+ revWalk.parseCommit(ObjectId.fromString(revision)).getTree())) {
+ if (treeWalk == null) {
+ LOG.warn("Could not find path '{}' on revision {} of the Git repository at '{}'", path, revision, rootLocation);
+ return null;
+ }
+
+ ObjectId blobId = treeWalk.getObjectId(0);
+ try (ObjectReader objectReader = repository.newObjectReader()) {
+ ObjectLoader objectLoader = objectReader.open(blobId);
+ byte[] bytes = objectLoader.getBytes();
+ try (FileOutputStream fOS = new FileOutputStream(optionalTemp)) {
+ fOS.write(bytes);
+ }
+ catch (Exception e) {
+ LOG.error("There was an error writing the contents of the file in the repository into the provided file.", e);
+ }
+ }
+ }
+ catch (Exception e) {
+ LOG.error("There was an error traversing the Git tree to retrieve the file contents.", e);
+ }
+ } catch (Exception e) {
+ LOG.error("There was an error accessing the Git repository to retrieve the file contents.", e);
+ }
+ return optionalTemp;
+ }
+
+ @Override
+ public boolean isActive() {
+ return active;
+ }
+
+ /**
+ * Prepares this manager to be run. Always invoked before {@link #run()}.
+ *
+ * @param vcsloc Path or <code>file://</code> URL to the root folder of the
+ * repository. If using a <code>file://</code> URL, the branch to
+ * be indexed can be specified via <code>?branch=BRANCH</code>.
+ * @param indexer Hawk indexer that will manage this VCS.
+ */
+ @Override
+ public void init(String vcsloc, IModelIndexer indexer) throws Exception {
+ // Accept both regular paths and file:// URIs
+ Path path;
+ try {
+ final URI uri = new URI(vcsloc);
+
+ /*
+ * This is needed to remove the query part cleanly (Paths.get will complain otherwise).
+ */
+ path = Paths.get(uri.resolve("."));
+
+ List<NameValuePair> pairs = URLEncodedUtils.parse(uri, "UTF-8");
+ for (NameValuePair pair : pairs) {
+ if (BRANCH_QPARAM.equals(pair.getName())) {
+ branch = pair.getValue();
+ }
+ }
+ } catch (URISyntaxException | IllegalArgumentException ex) {
+ path = Paths.get(vcsloc);
+ }
+
+ File canonicalFile;
+ try {
+ canonicalFile = path.toFile().getCanonicalFile();
+ } catch (IOException e) {
+ throw new IllegalArgumentException(String.format("Unable to access '%s' as a local folder", vcsloc));
+ }
+ if (!canonicalFile.isDirectory()) {
+ throw new IllegalArgumentException(String.format(
+ "The location pointed to by %s is not a folder", vcsloc));
+ }
+
+ rootLocation = canonicalFile.toPath();
+
+ // Assess if the vcsloc is actually a git repo
+ FileRepositoryBuilder builder = new FileRepositoryBuilder().addCeilingDirectory(canonicalFile.getParentFile())
+ .findGitDir(canonicalFile);
+ if (builder.getGitDir() == null) {
+ throw new IllegalArgumentException(
+ String.format("The location pointed to by %s doesn't appear to be a valid Git "
+ + "repository (.git folder not found or invalid).", vcsloc));
+ }
+
+ repository = builder.setMustExist(true).build();
+ if (branch == null) {
+ /*
+ * If the user has not specified a branch by using
+ * <code>file:///path/to/root?branch=BRANCH</code>, then we will use the
+ * currently checked out branch.
+ */
+ branch = repository.getFullBranch();
+ }
+ }
+
+ @Override
+ public void run() {
+ active = true;
+ }
+
+ @Override
+ public void shutdown() {
+ rootLocation = null;
+ repository.close();
+ active = false;
+ }
+
+ @Override
+ public String getLocation() {
+ return rootLocation.toString();
+ }
+
+ /**
+ * Git repositories do <b>NOT</b> support authentication. Calling any of the authentication related
+ * methods will throw an {@link UnsupportedOperationException}
+ *
+ * @see #getUsername()
+ * @see #getPassword()
+ * @see #setCredentials(String, String, ICredentialsStore)
+ */
+ @Override
+ public boolean isAuthSupported() {
+ return false;
+ }
+
+ /**
+ * Git repositories do <b>NOT</b> support authentication. This method always throws {@link UnsupportedOperationException}
+ * @see #isAuthSupported()
+ */
+ @Override
+ public String getUsername() {
+ throw new UnsupportedOperationException("Git repository does not support authentication.");
+ }
+
+ /**
+ * Git repositories do <b>NOT</b> support authentication. This method always throws {@link UnsupportedOperationException}
+ * @see #isAuthSupported()
+ */
+ @Override
+ public String getPassword() {
+ throw new UnsupportedOperationException("Git repository does not support authentication.");
+ }
+
+ /**
+ * Git repositories do <b>NOT</b> support authentication. This method always throws {@link UnsupportedOperationException}
+ * @see #isAuthSupported()
+ */
+ @Override
+ public void setCredentials(String username, String password, ICredentialsStore credStore) {
+ throw new UnsupportedOperationException("Git repository does not support authentication.");
+ }
+
+
+ @Override
+ public String getHumanReadableName() {
+ return "Git Repository (JGit-based)";
+ }
+
+ @Override
+ public boolean isPathLocationAccepted() {
+ return true;
+ }
+
+ @Override
+ public boolean isURLLocationAccepted() {
+ return false;
+ }
+
+ @Override
+ public String getRepositoryPath(String rawPath) {
+ return rootLocation.relativize(Paths.get(rawPath)).toString();
+ }
+
+ @Override
+ public boolean isFrozen() {
+ return isFrozen;
+ }
+
+ @Override
+ public void setFrozen(boolean f) {
+ isFrozen = f;
+ }
+
+ /**
+ * Create the set of VcsCommitItems between the two commits.
+ * <p>
+ * The previous commit can be <b>null</b> in which case the changes will be reported against an
+ * empty tree. This is useful when getting the differences of the first commit.
+ *
+ * @param current the current commit
+ * @param previous the previous commit (can be null)
+ * @return a list of VcsCommitItems
+ * @throws IOException if there is an error accessing the git information
+ */
+ private Collection<VcsCommitItem> diff(RevCommit current, RevCommit previous) throws IOException {
+ Collection<VcsCommitItem> result = new ArrayList<VcsCommitItem>();
+ try (DiffFormatter diffFmt = new DiffFormatter(NullOutputStream.INSTANCE)) {
+ diffFmt.setRepository(repository);
+ VcsCommit commit = asVcsCommit(current);
+ for (DiffEntry diff : diffFmt.scan(
+ previous == null ? null : previous.getTree(),
+ current.getTree())) {
+ VcsCommitItem item = new VcsCommitItem();
+ switch (diff.getChangeType()) {
+ case ADD:
+ item.setChangeType(VcsChangeType.ADDED);
+ item.setPath("/" + diff.getNewPath());
+ break;
+ case DELETE:
+ item.setChangeType(VcsChangeType.DELETED);
+ item.setPath("/" + diff.getOldPath());
+ break;
+ case MODIFY:
+ item.setChangeType(VcsChangeType.UPDATED);
+ item.setPath("/" + diff.getNewPath());
+ break;
+ case RENAME:
+ item.setChangeType(VcsChangeType.REPLACED);
+ item.setPath("/" + diff.getNewPath());
+ break;
+ case COPY:
+ item.setChangeType(VcsChangeType.UNKNOWN);
+ default:
+ break;
+ }
+ item.setCommit(commit);
+ commit.getItems().add(item);
+ result.add(item);
+ }
+ return result;
+ }
+ }
+
+ private VcsCommit asVcsCommit(RevCommit current) throws MissingObjectException, IncorrectObjectTypeException, IOException {
+ final PersonIdent authorIdent = current.getAuthorIdent();
+
+ /*
+ * Git's commit timestamps have a 1 second resolution, meaning that if we commit
+ * very quickly in sequence (within the same second), the temporal graph may
+ * actually lose versions.
+ *
+ * As a workaround, we can count how many commits before the current one have
+ * the same timestamp, and add that number of milliseconds to the VcsCommit
+ * timestamp. This means we'd only run afoul of this limitation if we managed to
+ * commit more than 1000 times in a second (which is normally very unlikely).
+ */
+ Date commitDate = authorIdent.getWhen();
+ if (current.getParentCount() > 0) {
+ try (RevWalk walk = new RevWalk(repository)) {
+ walk.markStart(walk.parseCommit(current.getId()));
+
+ int nCommitsSameTimestamp = 0;
+ final Iterator<RevCommit> itCommit = walk.iterator();
+ while (itCommit.hasNext()) {
+ RevCommit ancestor = itCommit.next();
+ if (ancestor.getAuthorIdent().getWhen().equals(commitDate)) {
+ ++nCommitsSameTimestamp;
+ } else {
+ break;
+ }
+ }
+
+ if (nCommitsSameTimestamp > 0) {
+ Instant newInstant = commitDate.toInstant().plus(Duration.ofMillis(nCommitsSameTimestamp));
+ commitDate = Date.from(newInstant);
+ }
+ }
+ }
+
+ VcsCommit commit = new VcsCommit();
+ commit.setAuthor(authorIdent.getName());
+ commit.setJavaDate(commitDate);
+ commit.setMessage(current.getFullMessage());
+ commit.setRevision(current.getName());
+
+ return commit;
+ }
+
+}
diff --git a/plugins/org.hawk.svn/src/org/hawk/svn/SvnManager.java b/plugins/org.hawk.svn/src/org/hawk/svn/SvnManager.java
index 0a3e68b..a7cbc99 100644
--- a/plugins/org.hawk.svn/src/org/hawk/svn/SvnManager.java
+++ b/plugins/org.hawk.svn/src/org/hawk/svn/SvnManager.java
@@ -280,7 +280,7 @@
@Override
public Collection<VcsCommitItem> getDelta(String startRevision) throws Exception {
if (Long.valueOf(startRevision) < 0)
- return getDelta(getFirstRevision(), getCurrentRevision()).getCompactedCommitItems();
+ return getDelta(null, getCurrentRevision()).getCompactedCommitItems();
else
return getDelta(startRevision, getCurrentRevision()).getCompactedCommitItems();
}
diff --git a/pom-plain.xml b/pom-plain.xml
index 1bfa932..833a320 100644
--- a/pom-plain.xml
+++ b/pom-plain.xml
@@ -20,6 +20,7 @@
<module>plugins/org.hawk.git/pom-plain.xml</module>
<module>plugins/org.hawk.graph/pom-plain.xml</module>
<module>plugins/org.hawk.http/pom-plain.xml</module>
+ <module>plugins/org.hawk.jgit/pom-plain.xml</module>
<module>plugins/org.hawk.localfolder/pom-plain.xml</module>
<module>plugins/org.hawk.modelio.exml/pom-plain.xml</module>
<module>plugins/org.hawk.orientdb/pom-plain.xml</module>
@@ -53,6 +54,16 @@
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit</artifactId>
+ <version>5.5.0.201909110433-r</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.3.6</version>
+ </dependency>
</dependencies>
</dependencyManagement>
diff --git a/pom.xml b/pom.xml
index e4cb921..91da5dd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,7 @@
<module>plugins/org.hawk.graph</module>
<module>plugins/org.hawk.greycat</module>
<module>plugins/org.hawk.http</module>
+ <module>plugins/org.hawk.jgit</module>
<module>plugins/org.hawk.localfolder</module>
<module>plugins/org.hawk.manifest</module>
<module>plugins/org.hawk.modelio.exml.ecoregen</module>
@@ -102,6 +103,7 @@
<module>tests/org.hawk.backend.tests</module>
<module>tests/org.hawk.emf.tests</module>
<module>tests/org.hawk.integration.tests</module>
+ <module>tests/org.hawk.jgit.tests</module>
<module>tests/org.hawk.localfolder.tests</module>
<module>tests/org.hawk.manifest.tests</module>
<module>tests/org.hawk.modelio.exml.tests</module>
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/ModelIndexingTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/ModelIndexingTest.java
index 6620e24..6592c96 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/ModelIndexingTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/ModelIndexingTest.java
@@ -172,26 +172,26 @@
db.delete();
}
- protected void waitForSync() throws Throwable {
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- // nothing to do
- return null;
- }
- });
+ /**
+ * Simple version which just waits for the indexing to happen.
+ */
+ protected void scheduleAndWait() throws Throwable {
+ scheduleAndWait(() -> null);
}
- protected void waitForSync(final Callable<?> r) throws Throwable {
+ /**
+ * Schedules a piece of code on the same thread as Hawk's indexing, and waits
+ * for it to be run. Times out with a test failure after 10 minutes.
+ */
+ protected void scheduleAndWait(final Callable<?> r) throws Throwable {
final Semaphore sem = new Semaphore(0);
- final SyncEndListener changeListener = new SyncEndListener(r, sem);
- indexer.addGraphChangeListener(changeListener);
+ final ScheduledTask<?> task = new ScheduledTask<>(r, sem);
+ indexer.scheduleTask(task, 0);
if (!sem.tryAcquire(600, TimeUnit.SECONDS)) {
fail("Synchronization timed out");
} else {
- indexer.removeGraphChangeListener(changeListener);
- if (changeListener.getThrowable() != null) {
- throw changeListener.getThrowable();
+ if (task.getThrowable() != null) {
+ throw task.getThrowable();
}
}
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/SyncEndListener.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/ScheduledTask.java
similarity index 71%
rename from tests/org.hawk.integration.tests/src/org/hawk/integration/tests/SyncEndListener.java
rename to tests/org.hawk.integration.tests/src/org/hawk/integration/tests/ScheduledTask.java
index 2dd1fa4..831007d 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/SyncEndListener.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/ScheduledTask.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015-2017 The University of York, Aston University.
+ * Copyright (c) 2019 The University of York, Aston University.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
@@ -19,32 +19,28 @@
import java.util.concurrent.Callable;
import java.util.concurrent.Semaphore;
-import org.hawk.core.util.GraphChangeAdapter;
-
-/**
- * Simple listener that allows for blocking another thread until a
- * synchronisation has been completed.
- */
-public class SyncEndListener extends GraphChangeAdapter {
- private final Callable<?> r;
+public class ScheduledTask<T> implements Callable<T> {
+ private final Callable<T> r;
private final Semaphore sem;
private Throwable ex = null;
- public SyncEndListener(Callable<?> r, Semaphore sem) {
- this.r = r;
+ public ScheduledTask(Callable<T> wrapped, Semaphore sem) {
+ this.r = wrapped;
this.sem = sem;
}
@Override
- public void synchroniseEnd() {
+ public T call() throws Exception {
+ T result = null;
try {
if (r != null) {
- r.call();
+ result = r.call();
}
} catch (Throwable e) {
ex = e;
}
sem.release();
+ return result;
}
public Throwable getThrowable() {
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/bpmn/ModelVersioningTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/bpmn/ModelVersioningTest.java
index 7e9198d..d6b5b93 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/bpmn/ModelVersioningTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/bpmn/ModelVersioningTest.java
@@ -62,12 +62,9 @@
Files.copy(new File("resources/models/" + baseModel).toPath(), modelPath);
requestFolderIndex(modelFolder.getRoot());
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ return null;
});
}
@@ -85,7 +82,7 @@
for (int i = 1; i <= 8; i++) {
replaceWith("bpmn/v" + i + "-B.2.0.bpmn");
indexer.requestImmediateSync();
- waitForSync(noErrors);
+ scheduleAndWait(noErrors);
}
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/CountInstancesTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/CountInstancesTest.java
index 4781a53..35587b1 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/CountInstancesTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/CountInstancesTest.java
@@ -22,7 +22,6 @@
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
-import java.util.concurrent.Callable;
import org.hawk.backend.tests.BackendTestSuite;
import org.hawk.backend.tests.factories.IGraphDatabaseFactory;
@@ -58,16 +57,13 @@
new File("resources/metamodels/Tree.ecore"));
requestFolderIndex(new File("resources/models/tree"));
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- assertEquals(2, eol("return Tree.all.size;"));
- assertEquals("t3", eol("return Tree.all.selectOne(t|t.label='t9000').eContainer.label;"));
- assertEquals(0, eol("return Tree.all.selectOne(t|t.label='t3').eContainers.size;"));
- assertEquals(1, eol("return Tree.all.selectOne(t|t.label='t9000').eContainers.size;"));
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ assertEquals(2, eol("return Tree.all.size;"));
+ assertEquals("t3", eol("return Tree.all.selectOne(t|t.label='t9000').eContainer.label;"));
+ assertEquals(0, eol("return Tree.all.selectOne(t|t.label='t3').eContainers.size;"));
+ assertEquals(1, eol("return Tree.all.selectOne(t|t.label='t9000').eContainers.size;"));
+ return null;
});
}
@@ -78,27 +74,23 @@
new File("resources/metamodels/Tree.ecore"));
requestFolderIndex(new File("resources/models/tree-xres"));
- waitForSync(new Callable<Object>() {
- @SuppressWarnings("unchecked")
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
-
- // Test for bug #56: select(t:Type|xyz) does not work
- assertEquals(3, eol("return Model.allContents.select(t:Tree|true).size;"));
-
- final Collection<String> labels = (Collection<String>) eol("return Model.allContents.collect(t:Tree|t.label);");
- assertEquals(3, labels.size());
- for (String e : Arrays.asList("xyz", "root", "abc")) {
- assertTrue(labels.contains(e));
- }
-
- assertEquals(3, eol("return Tree.all.size;"));
- assertEquals(2, eol("return Tree.all.selectOne(t|t.label='root').children.size;"));
- assertEquals("root", eol("return Tree.all.selectOne(t|t.label='xyz').eContainer.label;"));
- assertEquals("root", eol("return Tree.all.selectOne(t|t.label='abc').eContainer.label;"));
- return null;
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+
+ // Test for bug #56: select(t:Type|xyz) does not work
+ assertEquals(3, eol("return Model.allContents.select(t:Tree|true).size;"));
+
+ final Collection<String> labels = (Collection<String>) eol("return Model.allContents.collect(t:Tree|t.label);");
+ assertEquals(3, labels.size());
+ for (String e : Arrays.asList("xyz", "root", "abc")) {
+ assertTrue(labels.contains(e));
}
+
+ assertEquals(3, eol("return Tree.all.size;"));
+ assertEquals(2, eol("return Tree.all.selectOne(t|t.label='root').children.size;"));
+ assertEquals("root", eol("return Tree.all.selectOne(t|t.label='xyz').eContainer.label;"));
+ assertEquals("root", eol("return Tree.all.selectOne(t|t.label='abc').eContainer.label;"));
+ return null;
});
}
@@ -109,18 +101,15 @@
new File("resources/metamodels/JDTAST.ecore"));
requestFolderIndex(new File("resources/models/set0"));
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- assertEquals(1, eol("return IJavaProject.all.size;"));
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ assertEquals(1, eol("return IJavaProject.all.size;"));
+
+ final int reportedSize = (Integer) eol("return TypeDeclaration.all.size;");
+ final Collection<?> actualList = (Collection<?>) eol("return TypeDeclaration.all;");
+ assertEquals(reportedSize, actualList.size());
- final int reportedSize = (Integer) eol("return TypeDeclaration.all.size;");
- final Collection<?> actualList = (Collection<?>) eol("return TypeDeclaration.all;");
- assertEquals(reportedSize, actualList.size());
-
- return null;
- }
+ return null;
});
}
@@ -138,16 +127,13 @@
});
vcs.run();
indexer.addVCSManager(vcs, true);
-
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- assertEquals(1, eol("return Tree.all.size;"));
- assertEquals(1, eol("return Model.getAllOf('Tree', 'Tree', '/tree with spaces/space tree.model').size;"));
- assertEquals(1, eol("return Model.getAllOf('Tree', 'Tree', '/tree%20with%20spaces/space%20tree.model').size;"));
- return null;
- }
+
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ assertEquals(1, eol("return Tree.all.size;"));
+ assertEquals(1, eol("return Model.getAllOf('Tree', 'Tree', '/tree with spaces/space tree.model').size;"));
+ assertEquals(1, eol("return Model.getAllOf('Tree', 'Tree', '/tree%20with%20spaces/space%20tree.model').size;"));
+ return null;
});
}
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/DerivedFeatureTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/DerivedFeatureTest.java
index cab640b..8e68f77 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/DerivedFeatureTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/DerivedFeatureTest.java
@@ -27,7 +27,6 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.concurrent.Callable;
import org.hawk.backend.tests.BackendTestSuite;
import org.hawk.backend.tests.factories.IGraphDatabaseFactory;
@@ -53,61 +52,60 @@
new File("resources/metamodels/Tree.ecore"));
requestFolderIndex(new File("resources/models/tree-dedges"));
- waitForSync(new Callable<Object>() {
- @SuppressWarnings("unchecked")
- @Override
- public Object call() throws Exception {
- indexer.addDerivedAttribute("Tree", "Tree", "descendants", "dummy", true, true, false,
- EOLQueryEngine.TYPE, "return self.closure(c|c.children).flatten;");
+ scheduleAndWait(() -> {
+ indexer.addDerivedAttribute("Tree", "Tree", "descendants", "dummy", true, true, false, EOLQueryEngine.TYPE,
+ "return self.closure(c|c.children).flatten;");
- // Forward derived edges
- {
- final Map<String, Integer> expected = new HashMap<>();
- expected.put("t3", 3);
- expected.put("t4", 1);
- expected.put("t5", 0);
- expected.put("t6", 0);
+ // Forward derived edges
+ {
+ final Map<String, Integer> expected = new HashMap<>();
+ expected.put("t3", 3);
+ expected.put("t4", 1);
+ expected.put("t5", 0);
+ expected.put("t6", 0);
- for (Entry<String, Integer> entry : expected.entrySet()) {
- final Map<String, Object> context = Collections.singletonMap(EOLQueryEngine.PROPERTY_ARGUMENTS,
- (Object) Collections.singletonMap("nodeLabel", entry.getKey()));
+ for (Entry<String, Integer> entry : expected.entrySet()) {
+ final Map<String, Object> context = Collections.singletonMap(EOLQueryEngine.PROPERTY_ARGUMENTS,
+ (Object) Collections.singletonMap("nodeLabel", entry.getKey()));
- Object result = eol("return Tree.all.selectOne(t|t.label=nodeLabel).descendants.size;", context);
- assertEquals(
- String.format("%s should have %d descendants", entry.getKey(), entry.getValue()),
+ Object result = eol("return Tree.all.selectOne(t|t.label=nodeLabel).descendants.size;", context);
+ assertEquals(String.format("%s should have %d descendants", entry.getKey(), entry.getValue()),
entry.getValue(), result);
- }
}
-
- // Reverse derived edges
- {
- final Map<String, Integer> reverseExpected = new HashMap<>();
- reverseExpected.put("t3", 0);
- reverseExpected.put("t4", 1);
- reverseExpected.put("t5", 1);
- reverseExpected.put("t6", 2);
-
- for (Entry<String, Integer> entry : reverseExpected.entrySet()) {
- final Map<String, Object> context = Collections.singletonMap(EOLQueryEngine.PROPERTY_ARGUMENTS,
- (Object) Collections.singletonMap("nodeLabel", entry.getKey()));
-
- Object result = eol("return Tree.all.selectOne(t|t.label=nodeLabel).revRefNav_descendants.size;", context);
- assertEquals(
- String.format("%s should have %d ancestors", entry.getKey(), entry.getValue()),
- entry.getValue(), result);
- }
- }
-
- // Reverse reference navigation for the edges returns the element nodes and not just the derived value nodes
- List<String> expected = Arrays.asList("t3", "t4");
- Collection<String> result = (Collection<String>) eol("return Tree.all.selectOne(t|t.label='t6').revRefNav_descendants.label.flatten;");
- assertEquals(expected.size(), result.size());
- for (String e: expected) {
- assertTrue(result.contains(e));
- }
-
- return null;
}
+
+ // Reverse derived edges
+ {
+ final Map<String, Integer> reverseExpected = new HashMap<>();
+ reverseExpected.put("t3", 0);
+ reverseExpected.put("t4", 1);
+ reverseExpected.put("t5", 1);
+ reverseExpected.put("t6", 2);
+
+ for (Entry<String, Integer> entry : reverseExpected.entrySet()) {
+ final Map<String, Object> context = Collections.singletonMap(EOLQueryEngine.PROPERTY_ARGUMENTS,
+ (Object) Collections.singletonMap("nodeLabel", entry.getKey()));
+
+ Object result = eol("return Tree.all.selectOne(t|t.label=nodeLabel).revRefNav_descendants.size;",
+ context);
+ assertEquals(String.format("%s should have %d ancestors", entry.getKey(), entry.getValue()),
+ entry.getValue(), result);
+ }
+ }
+
+ // Reverse reference navigation for the edges returns the element nodes and not
+ // just the derived value nodes
+ List<String> expected = Arrays.asList("t3", "t4");
+ @SuppressWarnings("unchecked")
+ Collection<String> result = (Collection<String>) eol(
+ "return Tree.all.selectOne(t|t.label='t6').revRefNav_descendants.label.flatten;");
+
+ assertEquals(expected.size(), result.size());
+ for (String e : expected) {
+ assertTrue(result.contains(e));
+ }
+
+ return null;
});
}
@@ -117,40 +115,38 @@
new File("resources/metamodels/Tree.ecore"));
requestFolderIndex(new File("resources/models/tree-dedges"));
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- indexer.addDerivedAttribute("Tree", "Tree", "maxDescendant", "dummy", false, true, false,
- EOLQueryEngine.TYPE, "return self.closure(c|c.children).flatten.sortBy(t|t.label).last;");
+ scheduleAndWait(() -> {
+ indexer.addDerivedAttribute("Tree", "Tree", "maxDescendant", "dummy", false, true, false,
+ EOLQueryEngine.TYPE, "return self.closure(c|c.children).flatten.sortBy(t|t.label).last;");
- // Forward derived edge
- {
- // TODO: isMany is not honored on queries - need to add first
- Object result = eol("return Tree.all.selectOne(t|t.label='t3').maxDescendant.first.label;");
- assertEquals("t6", result);
- }
-
- // Reverse derived edges
- {
- final Map<String, Integer> reverseExpected = new HashMap<>();
- reverseExpected.put("t3", 0);
- reverseExpected.put("t4", 0);
- reverseExpected.put("t5", 0);
- reverseExpected.put("t6", 2); // t6 is the descendant of t3 and t4 with the last label in dictionary order
-
- for (Entry<String, Integer> entry : reverseExpected.entrySet()) {
- final Map<String, Object> context = Collections.singletonMap(EOLQueryEngine.PROPERTY_ARGUMENTS,
- (Object) Collections.singletonMap("nodeLabel", entry.getKey()));
-
- Object result = eol("return Tree.all.selectOne(t|t.label=nodeLabel).revRefNav_maxDescendant.size;", context);
- assertEquals(
- String.format("%s should have %d maxDescendant reverse refs", entry.getKey(), entry.getValue()),
- entry.getValue(), result);
- }
- }
-
- return null;
+ // Forward derived edge
+ {
+ // TODO: isMany is not honored on queries - need to add first
+ Object result = eol("return Tree.all.selectOne(t|t.label='t3').maxDescendant.first.label;");
+ assertEquals("t6", result);
}
+
+ // Reverse derived edges
+ {
+ final Map<String, Integer> reverseExpected = new HashMap<>();
+ reverseExpected.put("t3", 0);
+ reverseExpected.put("t4", 0);
+ reverseExpected.put("t5", 0);
+ reverseExpected.put("t6", 2); // t6 is the descendant of t3 and t4 with the last label in dictionary
+ // order
+
+ for (Entry<String, Integer> entry : reverseExpected.entrySet()) {
+ final Map<String, Object> context = Collections.singletonMap(EOLQueryEngine.PROPERTY_ARGUMENTS,
+ (Object) Collections.singletonMap("nodeLabel", entry.getKey()));
+
+ Object result = eol("return Tree.all.selectOne(t|t.label=nodeLabel).revRefNav_maxDescendant.size;",
+ context);
+ assertEquals(String.format("%s should have %d maxDescendant reverse refs", entry.getKey(),
+ entry.getValue()), entry.getValue(), result);
+ }
+ }
+
+ return null;
});
}
@@ -162,14 +158,11 @@
EOLQueryEngine.TYPE, "return self.xrefs.size;");
requestFolderIndex(new File("resources/models/scopedQuery"));
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(1, eol("return Element.all.selectOne(e|e.id=0).nRefs;"));
- assertEquals(3, eol("return Element.all.selectOne(e|e.id=1).nRefs;"));
- assertEquals(3, eol("return Element.all.selectOne(e|e.id=23).nRefs;"));
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(1, eol("return Element.all.selectOne(e|e.id=0).nRefs;"));
+ assertEquals(3, eol("return Element.all.selectOne(e|e.id=1).nRefs;"));
+ assertEquals(3, eol("return Element.all.selectOne(e|e.id=23).nRefs;"));
+ return null;
});
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/DerivedFromMetaPropertiesTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/DerivedFromMetaPropertiesTest.java
index 113a991..1b869c8 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/DerivedFromMetaPropertiesTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/DerivedFromMetaPropertiesTest.java
@@ -21,7 +21,6 @@
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
-import java.util.concurrent.Callable;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
@@ -94,12 +93,9 @@
requestFolderIndex(modelFolder.getRoot());
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ return null;
});
}
@@ -122,7 +118,7 @@
tRoot.eResource().save(null);
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(new HashSet<>(Arrays.asList("changed", "childA")),
eol("return Tree.all.selectOne(t|t.label='childAA').allContainers.collect(c|c.label).asSet;"));
assertEquals(new HashSet<>(Arrays.asList("childA", "childAA", "childB")),
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/EnumSupportTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/EnumSupportTest.java
index 0422768..42251fa 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/EnumSupportTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/EnumSupportTest.java
@@ -46,7 +46,7 @@
new File("resources/metamodels/ColoredTree.ecore"));
requestFolderIndex(new File("resources/models/enum-support"));
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(1, eol("return Tree.all.select(t|t.color = Color#red).size;"));
return null;
});
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/ScopedQueryTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/ScopedQueryTest.java
index b20545b..4101c81 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/ScopedQueryTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/ScopedQueryTest.java
@@ -68,17 +68,17 @@
@Test
public void listFiles() throws Throwable {
- waitForSync(() -> {
+ scheduleAndWait(() -> {
try (IGraphTransaction tx = db.beginTransaction()) {
GraphWrapper gw = new GraphWrapper(db);
-
+
Function<String, Supplier<Integer>> query = (String path) -> () -> (Integer) gw
.getFileNodes(Collections.singleton("*"), Collections.singleton(path)).size();
-
+
assertEquals(3, (int) query.apply("*").get());
assertEquals(2, (int) query.apply("/subfolder/*").get());
assertEquals(1, (int) query.apply("/subfolder/subfolder/*").get());
-
+
return null;
}
});
@@ -86,33 +86,33 @@
@Test
public void instanceCounts() throws Throwable {
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(0, syncValidation.getListener().getTotalErrors());
assertEquals("With no context, it should return all six elements", 6, eol("return Element.all.size;"));
assertEquals("With file context '*', it should return all six elements", 6, eol("return Element.all.size;", fc("*")));
assertEquals("With file context '/root.model', it should return only the two root elements",
new HashSet<>(Arrays.asList(0, 1)), eol("return Element.all.id.asSet;", fc("/root.model")));
-
+
assertEquals("With file context '/subfolder/*', it should return four elements", 4,
eol("return Element.all.size;", fc("/subfolder/*")));
assertEquals("With file context '/subfolder/subfolder/*', it should return only two elements", 2,
eol("return Element.all.size;", fc("/subfolder/subfolder/*")));
-
+
return null;
});
}
@Test
public void instanceCountsAllOf() throws Throwable {
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(0, syncValidation.getListener().getTotalErrors());
-
+
try (IGraphTransaction tx = db.beginTransaction()) {
assertEquals("With no context, it should return all six elements of the exact type", 6,
queryEngine.getAllOf("Element", ModelElementNode.EDGE_LABEL_OFTYPE).size());
assertEquals("With no context, it should return all six elements of the exact type or subtypes", 6,
queryEngine.getAllOf("Element", ModelElementNode.EDGE_LABEL_OFKIND).size());
-
+
assertEquals("With file context '*', it should return all six elements", 6,
queryEngine.getAllOf(MM_URI, "Element", "*").size());
assertEquals("With file context '/root.model', it should return only the two root elements", 2,
@@ -123,54 +123,54 @@
queryEngine.getAllOf(MM_URI, "Element", "/subfolder/subfolder/*").size());
tx.success();
}
-
+
return null;
});
}
@Test
public void forwardRefs() throws Throwable {
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(0, syncValidation.getListener().getTotalErrors());
-
+
assertForwardRefs(null, 0, 1);
assertForwardRefs(null, 1, 3);
-
+
assertForwardRefs(null, 12, 1);
assertForwardRefs("/subfolder/*", 12, 0);
assertForwardRefs(null, 15, 2);
assertForwardRefs("/subfolder/*", 15, 1);
-
+
assertForwardRefs(null, 23, 3);
assertForwardRefs("/subfolder/*", 23, 2);
assertForwardRefs("/subfolder/subfolder/*", 23, 1);
assertForwardRefs(null, 27, 1);
-
+
return null;
});
}
@Test
public void reverseRefs() throws Throwable {
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(0, syncValidation.getListener().getTotalErrors());
-
+
assertReverseRefs(null, 0, 3);
assertReverseRefs(null, 1, 1);
-
+
assertReverseRefs(null, 12, 1);
assertReverseRefs("/subfolder/*", 12, 0);
assertReverseRefs(null, 15, 3);
assertReverseRefs("/subfolder/*", 15, 2);
-
+
assertReverseRefs(null, 23, 2);
assertReverseRefs("/subfolder/*", 23, 1);
assertReverseRefs("/subfolder/subfolder/*", 23, 1);
-
+
assertReverseRefs(null, 27, 1);
assertReverseRefs("/subfolder/*", 27, 1);
assertReverseRefs("/subfolder/subfolder/*", 27, 1);
-
+
return null;
});
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/SubtreeContextTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/SubtreeContextTest.java
index 44c9136..8314342 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/SubtreeContextTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/SubtreeContextTest.java
@@ -18,14 +18,17 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Random;
-import java.util.concurrent.Callable;
+import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;
@@ -42,6 +45,7 @@
import org.hawk.core.query.IQueryEngine;
import org.hawk.epsilon.emc.EOLQueryEngine;
import org.hawk.graph.syncValidationListener.SyncValidationListener;
+import org.hawk.graph.syncValidationListener.SyncValidationListener.ValidationError;
import org.hawk.integration.tests.ModelIndexingTest;
import org.junit.Before;
import org.junit.Rule;
@@ -174,24 +178,27 @@
protected void prepareFragmented() throws Exception, Throwable {
requestFolderIndex(folderFragmented);
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- return null;
- }
+ scheduleAndWait(() -> {
+ assertNoValidationErrors("There should be no validation errors on the fragmented model");
+ return null;
});
}
+ private void assertNoValidationErrors(String message) {
+ List<ValidationError> errors = syncValidation.getListener().getErrors();
+ if (!errors.isEmpty()) {
+ List<String> messages = errors.stream()
+ .map(e -> e.getMessage())
+ .collect(Collectors.toList());
+ fail(message + ":\n" + String.join("\n\n", messages));
+ }
+ }
+
protected void prepareOriginal() throws Exception, Throwable {
requestFolderIndex(folderOriginal);
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
-
- return null;
- }
+ scheduleAndWait(() -> {
+ assertNoValidationErrors("There should be no validation errors on the original model");
+ return null;
});
}
@@ -298,21 +305,25 @@
"IPackageFragmentRoot.all.size should be > than BinaryPackageFragmentRoot.all.size: checking %d > %d", ipkgCount, binpkgCount),
ipkgCount > binpkgCount);
- Random rnd = new Random(42);
+ List<String> pathsTouched = new ArrayList<>();
+ final Random rnd = new Random(42);
for (File f : FileUtils.listFiles(folderFragmented, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE)) {
if (rnd.nextDouble() < 0.2) {
FileUtils.touch(f);
+ pathsTouched.add(f.getName());
}
}
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
final int ipkgCount2 = (int) eol("return IPackageFragmentRoot.all.size;", ctx(
IQueryEngine.PROPERTY_REPOSITORYCONTEXT, fragmentedRepoURI,
IQueryEngine.PROPERTY_SUBTREECONTEXT, "/set0.xmi",
IQueryEngine.PROPERTY_SUBTREE_DERIVEDALLOF, "true"
));
- assertEquals(ipkgCount, ipkgCount2);
-
+ assertEquals(
+ "IPackageFragmentRoot.all.size should stay the same after touching " + pathsTouched,
+ ipkgCount, ipkgCount2);
+
return null;
});
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/TreeUpdateTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/TreeUpdateTest.java
index 6ed5ff4..4d8ef49 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/TreeUpdateTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/emf/TreeUpdateTest.java
@@ -23,7 +23,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
-import java.util.concurrent.Callable;
import org.hawk.backend.tests.BackendTestSuite;
import org.hawk.backend.tests.factories.IGraphDatabaseFactory;
@@ -69,12 +68,9 @@
requestFolderIndex(modelFolder.getRoot());
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ return null;
});
}
@@ -91,16 +87,13 @@
prepare("tree/tree.model");
replaceWith("changed-trees/add-child.model");
indexer.requestImmediateSync();
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- try (IGraphTransaction tx = db.beginTransaction()) {
- assertEquals(3, queryEngine.getAllOf("Tree", ModelElementNode.EDGE_LABEL_OFTYPE).size());
- tx.success();
- }
- return null;
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ try (IGraphTransaction tx = db.beginTransaction()) {
+ assertEquals(3, queryEngine.getAllOf("Tree", ModelElementNode.EDGE_LABEL_OFTYPE).size());
+ tx.success();
}
+ return null;
});
}
@@ -109,16 +102,13 @@
prepare("tree/tree.model");
replaceWith("changed-trees/remove-child.model");
indexer.requestImmediateSync();
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- try (IGraphTransaction tx = db.beginTransaction()) {
- assertEquals(1, queryEngine.getAllOf("Tree", ModelElementNode.EDGE_LABEL_OFTYPE).size());
- tx.success();
- }
- return null;
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ try (IGraphTransaction tx = db.beginTransaction()) {
+ assertEquals(1, queryEngine.getAllOf("Tree", ModelElementNode.EDGE_LABEL_OFTYPE).size());
+ tx.success();
}
+ return null;
});
}
@@ -127,14 +117,11 @@
prepare("tree/tree.model");
replaceWith("changed-trees/rename-child.model");
indexer.requestImmediateSync();
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- assertEquals(2, eol("return Tree.all.size;"));
- assertEquals(1, eol("return Tree.all.select(t|t.label='t90001').size;"));
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ assertEquals(2, eol("return Tree.all.size;"));
+ assertEquals(1, eol("return Tree.all.select(t|t.label='t90001').size;"));
+ return null;
});
}
@@ -143,18 +130,14 @@
prepare("tree/tree.model");
replaceWith("changed-trees/rename-root.model");
indexer.requestImmediateSync();
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, syncValidation.getListener().getTotalErrors());
- try (IGraphTransaction tx = db.beginTransaction()) {
- assertEquals(2, queryEngine.getAllOf("Tree", ModelElementNode.EDGE_LABEL_OFTYPE).size());
- assertEquals(1, queryEngine.query(indexer,
- "return Tree.all.select(t|t.label='t40').size;", null));
- tx.success();
- }
- return null;
+ scheduleAndWait(() -> {
+ assertEquals(0, syncValidation.getListener().getTotalErrors());
+ try (IGraphTransaction tx = db.beginTransaction()) {
+ assertEquals(2, queryEngine.getAllOf("Tree", ModelElementNode.EDGE_LABEL_OFTYPE).size());
+ assertEquals(1, queryEngine.query(indexer, "return Tree.all.select(t|t.label='t40').size;", null));
+ tx.success();
}
+ return null;
});
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/manifests/ManifestIndexQueryTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/manifests/ManifestIndexQueryTest.java
index 85c00d8..01e0f7c 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/manifests/ManifestIndexQueryTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/manifests/ManifestIndexQueryTest.java
@@ -19,7 +19,6 @@
import static org.junit.Assert.assertEquals;
import java.io.File;
-import java.util.concurrent.Callable;
import org.hawk.backend.tests.BackendTestSuite;
import org.hawk.backend.tests.factories.IGraphDatabaseFactory;
@@ -44,13 +43,10 @@
@Test
public void indexDuplicateDependencies() throws Throwable {
requestFolderIndex(new File("resources/models/dupdep"));
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- Object result = eol("return ManifestRequires.all.bundle.size;");
- assertEquals(2, (int) result);
- return null;
- }
+ scheduleAndWait(() -> {
+ Object result = eol("return ManifestRequires.all.bundle.size;");
+ assertEquals(2, (int) result);
+ return null;
});
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/modelio/ModelioMetamodelPopulationTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/modelio/ModelioMetamodelPopulationTest.java
index 634c24a..729eeae 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/modelio/ModelioMetamodelPopulationTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/modelio/ModelioMetamodelPopulationTest.java
@@ -23,7 +23,6 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
-import java.util.concurrent.Callable;
import org.hawk.backend.tests.BackendTestSuite;
import org.hawk.backend.tests.factories.IGraphDatabaseFactory;
@@ -102,13 +101,10 @@
public void zoo() throws Throwable {
requestFolderIndex(new File("resources/models/zoo"));
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- assertEquals(0, validationListener.getListener().getTotalErrors());
- assertEquals(6, eol("return Class.all.size;"));
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(0, validationListener.getListener().getTotalErrors());
+ assertEquals(6, eol("return Class.all.size;"));
+ return null;
});
}
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/modelio/ModelioProxyResolutionTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/modelio/ModelioProxyResolutionTest.java
index 7dbdd32..4011a8b 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/modelio/ModelioProxyResolutionTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/modelio/ModelioProxyResolutionTest.java
@@ -31,7 +31,6 @@
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
-import java.util.concurrent.Callable;
import org.apache.commons.io.FileUtils;
import org.hawk.backend.tests.BackendTestSuite;
@@ -93,13 +92,13 @@
public void elephantResolve() throws Throwable {
copyClasses("Elephant");
requestFolderIndex(tempFolder.getRoot());
- waitForSync(() -> {
+ scheduleAndWait(() -> {
// The file should have exactly three unique IDs that others can refer to
try (IGraphTransaction tx = db.beginTransaction()) {
final IGraphNodeIndex fragmentIndex = db
.getOrCreateNodeIndex(GraphModelBatchInjector.FRAGMENT_DICT_NAME);
assertEquals(3, fragmentIndex.query("id", "*").size());
-
+
/*
* We should have two lists with unresolved refs: one to the supertype, and one
* to the package.
@@ -107,30 +106,30 @@
final GraphModelInserter inserter = updater.createInserter();
List<ProxyReferenceList> lists = inserter.getProxyReferenceLists(indexer.getGraph());
assertEquals(2, lists.size());
-
+
final Set<String> unresolved = collectUnresolvedFragments(lists);
assertEquals(new HashSet<>(Arrays.asList(PACKAGE_FRAGMENT, ANIMAL_FRAGMENT)), unresolved);
tx.success();
}
-
+
return null;
});
copyClasses("Animal", "Area");
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
// We should only be missing the package and the string datatype
List<ProxyReferenceList> lists = updater.createInserter().getProxyReferenceLists(indexer.getGraph());
-
+
// Three lists come from Animal, Area, Elephant, which are missing the package.
// Two lists come from Animal.name and Elephant.name, which are missing datatype.
assertEquals(5, lists.size());
-
+
final Set<String> unresolved = collectUnresolvedFragments(lists);
assertEquals(new HashSet<>(Arrays.asList(
STRING_FRAGMENT, PACKAGE_FRAGMENT
)), unresolved);
-
+
return null;
});
}
@@ -139,15 +138,12 @@
public void zoo() throws Throwable {
requestFolderIndex(new File("resources/models/zoo"));
- waitForSync(new Callable<Object>() {
- @Override
- public Object call() throws Exception {
- // We should only be missing the string datatype
- List<ProxyReferenceList> lists = updater.createInserter().getProxyReferenceLists(indexer.getGraph());
- final Set<String> unresolved = collectUnresolvedFragments(lists);
- assertEquals(Collections.emptySet(), unresolved);
- return null;
- }
+ scheduleAndWait(() -> {
+ // We should only be missing the string datatype
+ List<ProxyReferenceList> lists = updater.createInserter().getProxyReferenceLists(indexer.getGraph());
+ final Set<String> unresolved = collectUnresolvedFragments(lists);
+ assertEquals(Collections.emptySet(), unresolved);
+ return null;
});
}
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/AbstractUMLIndexingTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/AbstractUMLIndexingTest.java
index 6eb604d..9ac9ea7 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/AbstractUMLIndexingTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/AbstractUMLIndexingTest.java
@@ -67,7 +67,7 @@
vcs.init(null, indexer);
vcs.run();
indexer.addVCSManager(vcs, true);
- waitForSync();
+ scheduleAndWait();
}
}
\ No newline at end of file
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/UMLIndexingTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/UMLIndexingTest.java
index 6f2877d..67f21a4 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/UMLIndexingTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/UMLIndexingTest.java
@@ -23,7 +23,6 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
-import java.util.concurrent.Callable;
import org.apache.commons.io.FileUtils;
import org.eclipse.emf.common.util.URI;
@@ -57,43 +56,38 @@
@Test
public void zoo() throws Throwable {
requestFolderIndex(new File(BASE_DIRECTORY, "zoo"));
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- assertEquals(1, eol("return Model.types.select(t|t.name='Profile').size;"));
- assertEquals(4, eol("return Class.all.size;",
+ scheduleAndWait(() -> {
+ assertEquals(1, eol("return Model.types.select(t|t.name='Profile').size;"));
+ assertEquals(4, eol("return Class.all.size;",
Collections.singletonMap(CEOLQueryEngine.PROPERTY_FILECONTEXT, "*model.uml")));
- try (IGraphTransaction tx = db.beginTransaction()) {
- GraphNodeWrapper attr = (GraphNodeWrapper) eol(
- "return Class.all.selectOne(c|c.name='Animal').ownedAttribute.selectOne(a|a.name='age');");
+ try (IGraphTransaction tx = db.beginTransaction()) {
+ GraphNodeWrapper attr = (GraphNodeWrapper) eol(
+ "return Class.all.selectOne(c|c.name='Animal').ownedAttribute.selectOne(a|a.name='age');");
- // Check cross-reference to UML predefined library
- final IGraphNode node = attr.getNode();
- final Iterable<IGraphEdge> itOutgoing = node.getOutgoingWithType("type");
- int size = 0;
- for (@SuppressWarnings("unused") IGraphEdge e : itOutgoing) {
- size++;
- }
- assertEquals(1, size);
-
- tx.success();
+ // Check cross-reference to UML predefined library
+ final IGraphNode node = attr.getNode();
+ final Iterable<IGraphEdge> itOutgoing = node.getOutgoingWithType("type");
+ int size = 0;
+ for (@SuppressWarnings("unused")
+ IGraphEdge e : itOutgoing) {
+ size++;
}
+ assertEquals(1, size);
- return null;
+ tx.success();
}
+
+ return null;
});
}
@Test
public void stereotypeAsModel() throws Throwable {
requestFolderIndex(new File(BASE_DIRECTORY, "simpleProfile"));
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- assertEquals(1, eol("return Stereotype.all.select(s|s.name='special').size;"));
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(1, eol("return Stereotype.all.select(s|s.name='special').size;"));
+ return null;
});
}
@@ -127,25 +121,20 @@
public void customProfileV4() throws Throwable {
indexer.registerMetamodels(new File(BASE_DIRECTORY, "simpleProfile/model.profile.uml"));
requestFolderIndex(new File(BASE_DIRECTORY, "simpleProfileApplication"));
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- // Check that we support Papyrus profile versioning
- Map<String, Object> ctx = Collections.singletonMap(
- EOLQueryEngine.PROPERTY_DEFAULTNAMESPACES,
+ scheduleAndWait(() -> {
+ // Check that we support Papyrus profile versioning
+ Map<String, Object> ctx = Collections.singletonMap(EOLQueryEngine.PROPERTY_DEFAULTNAMESPACES,
SIMPLE_PROFILE_NSURI_PREFIX + "/0.0.4");
- assertEquals(1, eol("return special.all.size;", ctx));
- assertEquals(9001, eol("return special.all.first.amount;", ctx));
- assertEquals("Example", eol("return special.all.first.base_Class.name;", ctx));
+ assertEquals(1, eol("return special.all.size;", ctx));
+ assertEquals(9001, eol("return special.all.first.amount;", ctx));
+ assertEquals("Example", eol("return special.all.first.base_Class.name;", ctx));
- // profileApplication is mapped as an ofType edge
- assertEquals(1, eol("return RootElementApplication.all.size;", ctx));
- assertEquals("Example", eol(
- "return RootElementApplication.all.packagedElement.flatten.first.name;", ctx));
+ // profileApplication is mapped as an ofType edge
+ assertEquals(1, eol("return RootElementApplication.all.size;", ctx));
+ assertEquals("Example", eol("return RootElementApplication.all.packagedElement.flatten.first.name;", ctx));
- return null;
- }
+ return null;
});
}
@@ -153,20 +142,17 @@
public void customProfileV5() throws Throwable {
indexer.registerMetamodels(new File(BASE_DIRECTORY, "simpleProfile/model.profile.uml"));
requestFolderIndex(new File(BASE_DIRECTORY, "simpleProfileApplicationNewVersion"));
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- // Check that we support Papyrus profile versioning
- Map<String, Object> ctx = Collections.singletonMap(
- EOLQueryEngine.PROPERTY_DEFAULTNAMESPACES,
- SIMPLE_PROFILE_NSURI_PREFIX + "/0.0.5");
-
- assertEquals(1, eol("return special.all.size;", ctx));
- assertEquals(9002, eol("return special.all.first.amount;", ctx));
- assertEquals("example", eol("return special.all.first.name;", ctx));
- assertEquals("Example", eol("return special.all.first.base_Class.name;", ctx));
- return null;
- }
+ scheduleAndWait(() -> {
+ // Check that we support Papyrus profile versioning
+ Map<String, Object> ctx = Collections.singletonMap(
+ EOLQueryEngine.PROPERTY_DEFAULTNAMESPACES,
+ SIMPLE_PROFILE_NSURI_PREFIX + "/0.0.5");
+
+ assertEquals(1, eol("return special.all.size;", ctx));
+ assertEquals(9002, eol("return special.all.first.amount;", ctx));
+ assertEquals("example", eol("return special.all.first.name;", ctx));
+ assertEquals("Example", eol("return special.all.first.base_Class.name;", ctx));
+ return null;
});
}
@@ -185,7 +171,7 @@
final Map<String, Object> ctxNewVersion = Collections.singletonMap(
EOLQueryEngine.PROPERTY_DEFAULTNAMESPACES,
SIMPLE_PROFILE_NSURI_PREFIX + "/0.0.5");
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(1, eol("return special.all.size;", ctxOldVersion));
assertEquals(0, eol("return special.all.size;", ctxNewVersion));
return null;
@@ -194,7 +180,7 @@
final File newFile = new File(BASE_DIRECTORY, "simpleProfileApplicationNewVersion/model.uml").getCanonicalFile();
copyResource(destURI, newFile);
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(0, eol("return special.all.size;", ctxOldVersion));
assertEquals(1, eol("return special.all.size;", ctxNewVersion));
return null;
@@ -215,7 +201,7 @@
final Map<String, Object> ctxNewVersion = Collections.singletonMap(
EOLQueryEngine.PROPERTY_DEFAULTNAMESPACES,
SIMPLE_PROFILE_NSURI_PREFIX + "/0.0.5");
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(1, eol("return special.all.size;", ctxOldVersion));
assertEquals(0, eol("return special.all.size;", ctxNewVersion));
return null;
@@ -223,7 +209,7 @@
FileUtils.copyFile(new File(BASE_DIRECTORY, "simpleProfileApplicationNewVersion/model.uml"), new File(modelFolder.getRoot(), "simpleProfileApplication/model.uml"));
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(0, eol("return special.all.size;", ctxOldVersion));
assertEquals(1, eol("return special.all.size;", ctxNewVersion));
return null;
@@ -233,7 +219,7 @@
@Test
public void localfolderCrosslinks() throws Throwable {
requestFolderIndex(new File(BASE_DIRECTORY, "crossfile-refs"));
- waitForSync(() -> {
+ scheduleAndWait(() -> {
Map<String, Object> ctx = Collections.singletonMap(CEOLQueryEngine.PROPERTY_FILECONTEXT, "*model.uml");
assertEquals(3, eol("return Class.all.size;", ctx));
assertEquals(new HashSet<>(Arrays.asList("Class1", "Class3")),
diff --git a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/UMLWorkspaceIndexingTest.java b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/UMLWorkspaceIndexingTest.java
index 9bb7e79..24e6be9 100644
--- a/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/UMLWorkspaceIndexingTest.java
+++ b/tests/org.hawk.integration.tests/src/org/hawk/integration/tests/uml/UMLWorkspaceIndexingTest.java
@@ -44,7 +44,7 @@
try {
requestWorkspaceIndex();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(3, eolWorkspace("return Class.all.size;"));
assertEquals(new HashSet<>(Arrays.asList("Class1", "Class3")), eolWorkspace(
"return Class.all.selectOne(c|c.name='Class2').generalization.general.name.flatten.asSet;"));
diff --git a/tests/org.hawk.jgit.tests/.classpath b/tests/org.hawk.jgit.tests/.classpath
new file mode 100644
index 0000000..1747f41
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="resources"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tests/org.hawk.jgit.tests/.project b/tests/org.hawk.jgit.tests/.project
new file mode 100644
index 0000000..c7feccf
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.hawk.jgit.tests</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/tests/org.hawk.jgit.tests/.settings/org.eclipse.jdt.core.prefs b/tests/org.hawk.jgit.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/tests/org.hawk.jgit.tests/META-INF/MANIFEST.MF b/tests/org.hawk.jgit.tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..9d4a0bc
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Tests for Hawk Local Folder VCS
+Bundle-SymbolicName: org.hawk.jgit.tests
+Bundle-Version: 1.0.0.qualifier
+Fragment-Host: org.hawk.jgit;bundle-version="1.2.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.junit;bundle-version="4.12.0",
+ org.mockito;bundle-version="2.13.0",
+ net.bytebuddy.byte-buddy;bundle-version="1.7.9",
+ org.objenesis;bundle-version="2.6.0"
+Automatic-Module-Name: org.hawk.git.tests
diff --git a/tests/org.hawk.jgit.tests/Run Git Tests.launch b/tests/org.hawk.jgit.tests/Run Git Tests.launch
new file mode 100644
index 0000000..5d06aad
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/Run Git Tests.launch
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
+<booleanAttribute key="append.args" value="true"/>
+<stringAttribute key="application" value="org.eclipse.pde.junit.runtime.coretestapplication"/>
+<booleanAttribute key="askclear" value="false"/>
+<booleanAttribute key="automaticAdd" value="true"/>
+<booleanAttribute key="automaticValidate" value="true"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="true"/>
+<booleanAttribute key="clearws" value="true"/>
+<booleanAttribute key="clearwslog" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
+<booleanAttribute key="default" value="false"/>
+<stringAttribute key="deselected_workspace_plugins" value="com.fasterxml.jackson_2.9.6,com.github.peterwippermann.junit4.parameterizedsuite_1.1.0,org.apache.commons.io_1.3.2,org.hawk.backend.tests,org.hawk.bpmn,org.hawk.emf,org.hawk.emf.tests,org.hawk.emfresource,org.hawk.epsilon,org.hawk.examples.docgen,org.hawk.git,org.hawk.graph,org.hawk.graph.sampleListener,org.hawk.graph.syncValidationListener,org.hawk.greycat,org.hawk.http,org.hawk.integration.tests,org.hawk.localfolder,org.hawk.localfolder.tests,org.hawk.manifest,org.hawk.manifest.tests,org.hawk.modelio.exml,org.hawk.modelio.exml.ecoregen,org.hawk.modelio.exml.tests,org.hawk.neo4j-v2,org.hawk.neo4j-v2.dependencies,org.hawk.orientdb,org.hawk.osgiserver,org.hawk.service.api,org.hawk.service.api.dt,org.hawk.service.artemis,org.hawk.service.artemis.server,org.hawk.service.cli,org.hawk.service.cli.product,org.hawk.service.clients.cli.application,org.hawk.service.emc,org.hawk.service.emc.dt,org.hawk.service.emf,org.hawk.service.emf.dt,org.hawk.service.emf.tests,org.hawk.service.remote.thrift,org.hawk.service.remote.thrift.timeaware,org.hawk.service.server.application,org.hawk.service.server.cli,org.hawk.service.server.gzip,org.hawk.service.server.product,org.hawk.service.server.productdefs,org.hawk.service.server.users.cli,org.hawk.service.server.users.servlet,org.hawk.service.servlet,org.hawk.service.servlet.tests,org.hawk.svn,org.hawk.svn.tests,org.hawk.timeaware,org.hawk.timeaware.tests,org.hawk.ui.emc.dt2,org.hawk.ui.emfresource,org.hawk.ui2,org.hawk.uml,org.hawk.uml.tests,org.hawk.workspace,org.hawk.workspace.tests,uk.ac.aston.hawk.mongodb,uk.ac.aston.hawk.mongodb.drones,uk.ac.aston.hawk.mongodb.drones.integrationtest,uk.ac.aston.hawk.mongodb.drones.parser,uk.ac.aston.hawk.mongodb.drones.parser.tests,uk.ac.aston.hawk.mongodb.drones.tests,uk.ac.aston.hawk.mongodb.tests,uk.ac.aston.log2repo.drone,uk.ac.aston.log2repo.drone.hawk,uk.ac.aston.log2repo.rdm,uk.ac.aston.log2repo.rdm.hawk,uk.ac.aston.logmodel"/>
+<booleanAttribute key="includeOptional" value="true"/>
+<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.hawk.jgit.tests/src/org/hawk/git/JGitRepositoryTest.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.hawk.git.JGitRepositoryTest"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.hawk.jgit.tests"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<stringAttribute key="product" value="org.eclipse.platform.ide"/>
+<booleanAttribute key="run_in_ui_thread" value="true"/>
+<stringAttribute key="selected_target_plugins" value="ch.qos.logback.classic@default:default,ch.qos.logback.core@default:default,ch.qos.logback.slf4j@default:false,com.ibm.icu@default:default,com.jcraft.jsch*0.1.55.v20190404-1902@default:default,com.jcraft.jzlib@default:default,javaewah@default:default,javax.annotation@default:default,javax.inject@default:default,javax.xml@default:default,net.bytebuddy.byte-buddy-agent@default:default,net.bytebuddy.byte-buddy@default:default,org.apache.batik.constants@default:default,org.apache.batik.css*1.9.1.v20180313-1559@default:default,org.apache.batik.i18n@default:default,org.apache.batik.util*1.9.1.v20180227-1645@default:default,org.apache.commons.codec*1.9.0.v20170208-1614@default:default,org.apache.commons.io@default:default,org.apache.commons.jxpath@default:default,org.apache.commons.logging@default:default,org.apache.felix.gogo.runtime@default:default,org.apache.felix.scr@1:true,org.apache.httpcomponents.httpclient*4.5.2.v20170210-0925@default:default,org.apache.httpcomponents.httpcore*4.4.6.v20170210-0925@default:default,org.apache.log4j@default:default,org.apache.xmlgraphics@default:default,org.bouncycastle.bcpg@default:default,org.bouncycastle.bcprov@default:default,org.eclipse.ant.core@default:default,org.eclipse.compare.core@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.core.databinding.property@default:default,org.eclipse.core.databinding@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filesystem.linux.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.resources@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.e4.core.commands@default:default,org.eclipse.e4.core.contexts@default:default,org.eclipse.e4.core.di.annotations@default:default,org.eclipse.e4.core.di.extensions.supplier@default:default,org.eclipse.e4.core.di.extensions@default:default,org.eclipse.e4.core.di@default:default,org.eclipse.e4.core.services@default:default,org.eclipse.e4.emf.xpath@default:default,org.eclipse.e4.ui.bindings@default:default,org.eclipse.e4.ui.css.core@default:default,org.eclipse.e4.ui.css.swt.theme@default:default,org.eclipse.e4.ui.css.swt@default:default,org.eclipse.e4.ui.di@default:default,org.eclipse.e4.ui.model.workbench@default:default,org.eclipse.e4.ui.services@default:default,org.eclipse.e4.ui.swt.gtk@default:false,org.eclipse.e4.ui.widgets@default:default,org.eclipse.e4.ui.workbench.addons.swt@default:default,org.eclipse.e4.ui.workbench.renderers.swt@default:default,org.eclipse.e4.ui.workbench.swt@default:default,org.eclipse.e4.ui.workbench3@default:default,org.eclipse.e4.ui.workbench@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.bidi@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.event@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.region@default:false,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.supplement@default:default,org.eclipse.equinox.transforms.hook@default:false,org.eclipse.equinox.weaving.hook@default:false,org.eclipse.help@default:default,org.eclipse.jetty.osgi-servlet-api@default:default,org.eclipse.jetty.osgi.alpn.fragment@default:false,org.eclipse.jface.databinding@default:default,org.eclipse.jface@default:default,org.eclipse.jgit@default:default,org.eclipse.osgi.compatibility.state@default:false,org.eclipse.osgi.services@default:default,org.eclipse.osgi.util@default:default,org.eclipse.osgi@-1:true,org.eclipse.swt.gtk.linux.x86_64@default:false,org.eclipse.swt@default:default,org.eclipse.team.core@default:default,org.eclipse.ui.trace@default:default,org.eclipse.ui.workbench@default:default,org.eclipse.ui@default:default,org.eclipse.xtext.logging@default:false,org.hamcrest.core@default:default,org.junit@default:default,org.mockito@default:default,org.objenesis@default:default,org.slf4j.api@default:default,org.slf4j.impl.log4j12@default:false,org.w3c.css.sac@default:default,org.w3c.dom.events@default:default,org.w3c.dom.smil@default:default,org.w3c.dom.svg@default:default"/>
+<stringAttribute key="selected_workspace_plugins" value="org.hawk.core.dependencies@default:default,org.hawk.core@default:default,org.hawk.jgit.tests@default:false,org.hawk.jgit@default:default,org.hawk.service.server.logback@default:false"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfig" value="true"/>
+<booleanAttribute key="useDefaultConfigArea" value="false"/>
+<booleanAttribute key="useProduct" value="false"/>
+</launchConfiguration>
diff --git a/tests/org.hawk.jgit.tests/build.properties b/tests/org.hawk.jgit.tests/build.properties
new file mode 100644
index 0000000..f11210d
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/build.properties
@@ -0,0 +1,5 @@
+source.. = src/,\
+ resources/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/tests/org.hawk.jgit.tests/resources/v0/one.txt b/tests/org.hawk.jgit.tests/resources/v0/one.txt
new file mode 100644
index 0000000..43dd47e
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/resources/v0/one.txt
@@ -0,0 +1 @@
+one
\ No newline at end of file
diff --git a/tests/org.hawk.jgit.tests/resources/v1/one.txt b/tests/org.hawk.jgit.tests/resources/v1/one.txt
new file mode 100644
index 0000000..43dd47e
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/resources/v1/one.txt
@@ -0,0 +1 @@
+one
\ No newline at end of file
diff --git a/tests/org.hawk.jgit.tests/resources/v1/two.txt b/tests/org.hawk.jgit.tests/resources/v1/two.txt
new file mode 100644
index 0000000..eeacbdb
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/resources/v1/two.txt
@@ -0,0 +1 @@
+two
diff --git a/tests/org.hawk.jgit.tests/resources/v2/one.txt b/tests/org.hawk.jgit.tests/resources/v2/one.txt
new file mode 100644
index 0000000..7c0d23c
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/resources/v2/one.txt
@@ -0,0 +1,2 @@
+one
+one
\ No newline at end of file
diff --git a/tests/org.hawk.jgit.tests/resources/v2/two.txt b/tests/org.hawk.jgit.tests/resources/v2/two.txt
new file mode 100644
index 0000000..eeacbdb
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/resources/v2/two.txt
@@ -0,0 +1 @@
+two
diff --git a/tests/org.hawk.jgit.tests/resources/v3/two.txt b/tests/org.hawk.jgit.tests/resources/v3/two.txt
new file mode 100644
index 0000000..9ce97cd
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/resources/v3/two.txt
@@ -0,0 +1,2 @@
+two
+two
diff --git a/tests/org.hawk.jgit.tests/src/org/hawk/git/JGitRepositoryTest.java b/tests/org.hawk.jgit.tests/src/org/hawk/git/JGitRepositoryTest.java
new file mode 100644
index 0000000..2dd7b9b
--- /dev/null
+++ b/tests/org.hawk.jgit.tests/src/org/hawk/git/JGitRepositoryTest.java
@@ -0,0 +1,390 @@
+/*******************************************************************************
+ * Copyright (c) 2018-2019 Aston University, and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the Eclipse
+ * Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
+ *
+ * Contributors:
+ * Antonio Garcia-Dominguez - initial API and implementation
+ * Horacio Hoyos Rodriguez - Add proper Git support
+ ******************************************************************************/
+package org.hawk.git;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.jgit.api.AddCommand;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.RmCommand;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.NoFilepatternException;
+import org.hawk.core.IModelIndexer;
+import org.hawk.core.VcsChangeType;
+import org.hawk.core.VcsCommitItem;
+import org.hawk.core.VcsRepositoryDelta;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+public class JGitRepositoryTest {
+
+ private static final String NULL_REV = "0000000000000000000000000000000000000000";
+
+ private enum Version {
+ v0("Initial Commit", "one.txt"), v1("Adds file two", "one.txt", "two.txt"),
+ v2("Fixes file one", "one.txt", "two.txt"), v3("Fixes file two, deletes file one", "two.txt");
+
+ private final String[] allFiles = new String[] { "one.txt", "two.txt" };
+ private final String msg;
+ private final Set<String> names;
+
+ Version(String msg, String... files) {
+ this.msg = msg;
+ this.names = new HashSet<>(Arrays.asList(files));
+ }
+
+ public void commit(TemporaryFolder folder, Map<String, File> files) throws IOException {
+ updateFiles(folder, files);
+ commitChanges(folder, files);
+ }
+
+ private void commitChanges(TemporaryFolder folder, Map<String, File> files) {
+ try (org.eclipse.jgit.api.Git repo = org.eclipse.jgit.api.Git.open(folder.getRoot())) {
+ try {
+ AddCommand add = repo.add();
+ RmCommand rm = repo.rm();
+ for (String name : allFiles) {
+ if (names.contains(name)) {
+ add.addFilepattern(name);
+ } else {
+ rm.addFilepattern(name);
+ }
+ }
+ // Some commands can be empty
+ try {
+ add.call();
+ } catch (NoFilepatternException e) {
+ /* Ignore */ }
+ try {
+ rm.call();
+ } catch (NoFilepatternException e) {
+ /* Ignore */ }
+ repo.commit().setMessage(msg).call();
+ } catch (GitAPIException e) {
+ throw new IllegalStateException("Failed to commit");
+ }
+ } catch (IOException e2) {
+ throw new IllegalStateException("Failed to commit");
+ }
+ }
+
+ private void updateFiles(TemporaryFolder folder, Map<String, File> files)
+ throws IOException, FileNotFoundException {
+ File tempFile;
+ for (String name : allFiles) {
+ tempFile = files.get(name);
+ if (names.contains(name)) {
+ if (tempFile != null) {
+ // Replace it
+ tempFile.delete();
+ }
+ tempFile = folder.newFile(name);
+ copy(name, tempFile);
+ files.put(name, tempFile);
+ } else {
+ if (tempFile != null) {
+ tempFile.delete();
+ files.remove(name);
+ }
+ }
+ }
+ }
+
+ private void copy(String name, File tempFile) throws FileNotFoundException, IOException {
+ InputStream in = JGitRepositoryTest.class.getResourceAsStream(String.format("/%s/%s", this.name(), name));
+ try (OutputStream out = new FileOutputStream(tempFile)) {
+ byte[] buf = new byte[1024];
+ int length;
+ while ((length = in.read(buf)) > 0) {
+ out.write(buf, 0, length);
+ }
+ }
+ }
+
+ }
+
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ private final Map<String, File> files = new HashMap<>();
+
+ private JGitRepository vcs;
+ private IModelIndexer indexer;
+
+ @Before
+ public void setup() throws Exception {
+ org.eclipse.jgit.api.Git.init().setDirectory(folder.getRoot()).call();
+
+ indexer = mock(IModelIndexer.class);
+ vcs = new JGitRepository();
+ vcs.init(folder.getRoot().getCanonicalPath(), indexer);
+ vcs.run();
+ }
+
+ @After
+ public void clean() throws Exception {
+ vcs.shutdown();
+ files.clear();
+ }
+
+ @Test
+ public void currentRevisionWithoutCommits() throws Exception {
+ String currRev = vcs.getCurrentRevision();
+ // Git repo with no commits has revision 0
+ assertEquals(NULL_REV, currRev);
+ }
+
+ @Test
+ public void currentRevisionOneCommit() throws Exception {
+ Version.v0.commit(folder, files);
+ String currRev = vcs.getCurrentRevision();
+ // If there are commits there should be a hash
+ assertNotEquals(NULL_REV, currRev);
+ }
+
+ @Test
+ public void currentRevisionTwoCommits() throws Exception {
+ Version.v0.commit(folder, files);
+ String v0Rev = vcs.getCurrentRevision();
+ System.out.println(v0Rev);
+ assertNotEquals(NULL_REV, v0Rev);
+ Version.v1.commit(folder, files);
+ String v1Rev = vcs.getCurrentRevision();
+ System.out.println(v1Rev);
+ assertNotEquals(NULL_REV, v1Rev);
+ assertNotEquals(v0Rev, v1Rev);
+ }
+
+ @Test
+ public void firstRevisionIsConstant() throws Exception {
+ Version.v0.commit(folder, files);
+ String rev0 = vcs.getCurrentRevision();
+ assertEquals(rev0, vcs.getFirstRevision());
+ Version.v1.commit(folder, files);
+ assertEquals(rev0, vcs.getFirstRevision());
+ Version.v2.commit(folder, files);
+ assertEquals(rev0, vcs.getFirstRevision());
+ Version.v3.commit(folder, files);
+ assertEquals(rev0, vcs.getFirstRevision());
+ }
+
+ @Test
+ public void delta1ArgWithNullRevision() throws Exception {
+ Version.v0.commit(folder, files);
+ List<VcsCommitItem> delta = vcs.getDelta(null);
+
+ assertEquals("1-arg delta with null starts from first revision", 1, delta.size());
+ assertEquals(VcsChangeType.ADDED, delta.get(0).getChangeType());
+ }
+
+ @Test
+ public void delta1ArgWithCurrent() throws Exception {
+ Version.v0.commit(folder, files);
+ Collection<VcsCommitItem> delta = vcs.getDelta(vcs.getCurrentRevision());
+ assertEquals(0, delta.size());
+ }
+
+ @Test
+ public void delta1ArgWithTwoCommits() throws Exception {
+ Version.v0.commit(folder, files);
+ String rev0 = vcs.getCurrentRevision();
+ Version.v1.commit(folder, files);
+ List<VcsCommitItem> delta = vcs.getDelta(rev0);
+ assertEquals(1, delta.size());
+ assertSame(vcs, delta.get(0).getCommit().getDelta().getManager());
+ assertEquals(1L, delta.stream()
+ .filter(i -> i.getChangeType().equals(VcsChangeType.ADDED) && i.getPath().equals("/two.txt")).count());
+ }
+
+ @Test
+ public void delta1ArgWithUpdatedFile() throws Exception {
+ Version.v0.commit(folder, files);
+ Version.v1.commit(folder, files);
+ String rev1 = vcs.getCurrentRevision();
+ Version.v2.commit(folder, files);
+ Collection<VcsCommitItem> delta = vcs.getDelta(rev1);
+ assertEquals(1, delta.size());
+ assertEquals(1L,
+ delta.stream()
+ .filter(i -> i.getChangeType().equals(VcsChangeType.UPDATED) && i.getPath().equals("/one.txt"))
+ .count());
+ }
+
+ @Test
+ public void delta1ArgTwoChanges() throws Exception {
+ Version.v0.commit(folder, files);
+ Version.v1.commit(folder, files);
+ Version.v2.commit(folder, files);
+ final String rev2 = vcs.getCurrentRevision();
+ Version.v3.commit(folder, files);
+
+ Collection<VcsCommitItem> delta = vcs.getDelta(rev2);
+ assertEquals(2, delta.size());
+ assertEquals(1L,
+ delta.stream()
+ .filter(i -> i.getChangeType().equals(VcsChangeType.DELETED) && i.getPath().equals("/one.txt"))
+ .count());
+ assertEquals(1L,
+ delta.stream()
+ .filter(i -> i.getChangeType().equals(VcsChangeType.UPDATED) && i.getPath().equals("/two.txt"))
+ .count());
+ }
+
+ @Test
+ public void delta2ArgAfterFirstOfTwo() throws Exception {
+ Version.v0.commit(folder, files);
+ Version.v1.commit(folder, files);
+ VcsRepositoryDelta delta = vcs.getDelta(vcs.getFirstRevision(), vcs.getCurrentRevision());
+ assertEquals(1, delta.getCommits().size());
+ Collection<VcsCommitItem> commits = delta.getCommits().get(0).getItems();
+ assertEquals(1, commits.size());
+ assertEquals(1L, commits.stream()
+ .filter(i -> i.getChangeType().equals(VcsChangeType.ADDED) && i.getPath().equals("/two.txt")).count());
+ }
+
+ @Test
+ public void delta2ArgAfterFirstOfThree() throws Exception {
+ Version.v0.commit(folder, files);
+ Version.v1.commit(folder, files);
+ Version.v2.commit(folder, files);
+ Version.v3.commit(folder, files);
+
+ VcsRepositoryDelta delta = vcs.getDelta(vcs.getFirstRevision(), vcs.getCurrentRevision());
+ assertEquals(3, delta.getCommits().size());
+ Collection<VcsCommitItem> items = delta.getCompactedCommitItems();
+ assertEquals(2, items.size());
+ assertEquals(1L,
+ items.stream()
+ .filter(i -> i.getChangeType().equals(VcsChangeType.UPDATED) && i.getPath().equals("/two.txt"))
+ .count());
+ assertEquals(1L,
+ items.stream()
+ .filter(i -> i.getChangeType().equals(VcsChangeType.DELETED) && i.getPath().equals("/one.txt"))
+ .count());
+ }
+
+ @Test
+ public void importFile() throws Exception {
+ Version.v0.commit(folder, files);
+ String rev0 = vcs.getCurrentRevision();
+ Version.v1.commit(folder, files);
+ String rev1 = vcs.getCurrentRevision();
+ Version.v2.commit(folder, files);
+ String rev2 = vcs.getCurrentRevision();
+ Version.v3.commit(folder, files);
+ String rev3 = vcs.getCurrentRevision();
+
+ File temp = vcs.importFile(rev0, "one.txt", folder.newFile());
+ List<String> lines = Files.lines(temp.toPath()).collect(Collectors.toList());
+ assertEquals(1, lines.size());
+ assertEquals("one", lines.get(0));
+
+ // Since JGitRepository produces paths starting with "/", importFile should be happy with them too
+ temp = vcs.importFile(rev0, "/one.txt", folder.newFile());
+ lines = Files.lines(temp.toPath()).collect(Collectors.toList());
+ assertEquals("/one.txt should work just as well as one.txt (number of lines)", 1, lines.size());
+ assertEquals("/one.txt should work just as well as one.txt (line content)", "one", lines.get(0));
+
+ assertNull("two.txt does not exist in first revision", vcs.importFile(rev0, "two.txt", folder.newFile()));
+
+ temp = vcs.importFile(rev1, "two.txt", folder.newFile());
+ lines = Files.lines(temp.toPath()).collect(Collectors.toList());
+ assertEquals(1, lines.size());
+ assertEquals("two", lines.get(0));
+
+ temp = vcs.importFile(rev2, "one.txt", folder.newFile());
+ lines = Files.lines(temp.toPath()).collect(Collectors.toList());
+ assertEquals(2, lines.size());
+ assertEquals("one", lines.get(0));
+ assertEquals("one", lines.get(1));
+
+ temp = vcs.importFile(rev3, "two.txt", folder.newFile());
+ lines = Files.lines(temp.toPath()).collect(Collectors.toList());
+ assertEquals(2, lines.size());
+ assertEquals("two", lines.get(0));
+ assertEquals("two", lines.get(1));
+
+ assertNull("one.txt was deleted in fourth revision", vcs.importFile(rev3, "one.txt", folder.newFile()));
+ }
+
+ @Test
+ public void gitHonorsCurrentBranch() throws Exception {
+ Version.v0.commit(folder, files);
+ String rev0 = vcs.getCurrentRevision();
+ Version.v1.commit(folder, files);
+ String rev1 = vcs.getCurrentRevision();
+
+ final String newBranchName = "newbranch";
+ try (Git repo = Git.open(folder.getRoot())) {
+ repo.checkout().setName(newBranchName).setCreateBranch(true).call();
+ Version.v2.commit(folder, files);
+ }
+
+ assertEquals(rev1, vcs.getCurrentRevision());
+ VcsRepositoryDelta delta = vcs.getDelta(null, vcs.getCurrentRevision());
+ assertEquals(2, delta.getCommits().size());
+ assertEquals(rev0, delta.getCommits().get(0).getRevision());
+ assertEquals(rev1, delta.getCommits().get(1).getRevision());
+
+ delta = vcs.getDelta(rev0, vcs.getCurrentRevision());
+ assertEquals(1, delta.getCommits().size());
+ assertEquals(rev1, delta.getCommits().get(0).getRevision());
+
+ // Now try creating a VCS pointing at the new branch
+
+ final JGitRepository repoNewBranch = new JGitRepository();
+ final IModelIndexer indexer = mock(IModelIndexer.class);
+ repoNewBranch.init(String.format(
+ "%s?%s=%s",
+ folder.getRoot().toURI().toString(),
+ JGitRepository.BRANCH_QPARAM,
+ newBranchName), indexer);
+ repoNewBranch.run();
+
+ assertEquals(3, repoNewBranch.getDelta(null,
+ repoNewBranch.getCurrentRevision()).getCommits().size());
+ }
+
+}
diff --git a/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_1.xml b/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_1.xml
index 3ba7c7b..28c5dee 100644
--- a/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_1.xml
+++ b/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_1.xml
@@ -9,6 +9,7 @@
<plugin name="org.hawk.modelio.exml.listeners.ModelioGraphChangeListener"/>
<plugin name="org.hawk.modelio.exml.metamodel.ModelioMetaModelResourceFactory"/>
<plugin name="org.hawk.modelio.exml.model.ModelioModelResourceFactory"/>
+ <plugin name="org.hawk.epsilon.emc.EOLQueryEngine"/>
</plugins>
<metamodels>
<metamodel
@@ -33,6 +34,6 @@
<repositories>
<repository frozen="false"
location="file:///home/antonio/Documents/mondo-hawk/tests/org.hawk.service.servlet.tests/resources/Zoo/"
- pass="" type="org.hawk.localfolder.LocalFolder" user=""/>
+ type="org.hawk.localfolder.LocalFolder" />
</repositories>
</hawk>
diff --git a/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_2.xml b/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_2.xml
index 3178377..20c1ca8 100644
--- a/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_2.xml
+++ b/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_2.xml
@@ -6,6 +6,7 @@
<plugin name="org.hawk.modelio.exml.metamodel.ModelioMetaModelResourceFactory"/>
<plugin name="org.hawk.modelio.exml.model.ModelioModelResourceFactory"/>
<plugin name="org.hawk.graph.updater.GraphModelUpdater"/>
+ <plugin name="org.hawk.epsilon.emc.EOLQueryEngine"/>
</plugins>
<metamodels>
<metamodel
@@ -30,6 +31,6 @@
<repositories>
<repository frozen="false"
location="file:///home/antonio/Documents/mondo-hawk/tests/org.hawk.service.servlet.tests/resources/Zoo/"
- pass="" type="org.hawk.localfolder.LocalFolder" user=""/>
+ type="org.hawk.localfolder.LocalFolder"/>
</repositories>
</hawk>
diff --git a/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_3.xml b/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_3.xml
index b651d64..cf5f0f7 100644
--- a/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_3.xml
+++ b/tests/org.hawk.service.servlet.tests/resources/ServerConfig/instance_3.xml
@@ -9,6 +9,7 @@
<plugin name="org.hawk.modelio.exml.listeners.ModelioGraphChangeListener"/>
<plugin name="org.hawk.modelio.exml.metamodel.ModelioMetaModelResourceFactory"/>
<plugin name="org.hawk.modelio.exml.model.ModelioModelResourceFactory"/>
+ <plugin name="org.hawk.epsilon.emc.EOLQueryEngine"/>
</plugins>
<metamodels>
<metamodel
@@ -32,7 +33,7 @@
</indexedAttributes>
<repositories>
<repository frozen="false"
- location="file:///C:/Desktop/Hawk/Zoo/" pass=""
- type="org.hawk.localfolder.LocalFolder" user=""/>
+ location="file:///C:/Desktop/Hawk/Zoo/"
+ type="org.hawk.localfolder.LocalFolder" />
</repositories>
</hawk>
diff --git a/tests/org.hawk.service.servlet.tests/src/org/hawk/service/servlet/config/ConfigFileParserTest.java b/tests/org.hawk.service.servlet.tests/src/org/hawk/service/servlet/config/ConfigFileParserTest.java
index 0c5a258..384e13e 100644
--- a/tests/org.hawk.service.servlet.tests/src/org/hawk/service/servlet/config/ConfigFileParserTest.java
+++ b/tests/org.hawk.service.servlet.tests/src/org/hawk/service/servlet/config/ConfigFileParserTest.java
@@ -1,12 +1,5 @@
-package org.hawk.service.servlet.config;
-import static org.junit.Assert.*;
-
-import java.io.File;
-
-import org.junit.Test;
-
/*******************************************************************************
- * Copyright (c) 2017 Aston University
+ * Copyright (c) 2017-2019 Aston University
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
@@ -20,26 +13,54 @@
*
* Contributors:
* Orjuwan Al-Wadeai - Test For ConfigFileParser
+ * Antonio Garcia-Dominguez - Use a temporary file
******************************************************************************/
+package org.hawk.service.servlet.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import com.google.common.io.Files;
+
public class ConfigFileParserTest {
private static final String SERVERCONFIG_PATH = "resources/ServerConfig/";
- ConfigFileParser parser;
- HawkInstanceConfig config;
- final String xmlFilePath = SERVERCONFIG_PATH + "instance_3.xml";
- final String xsdFilePath = SERVERCONFIG_PATH + "HawkServerConfigurationSchema.xsd";
+ private static final String XML_PATH = SERVERCONFIG_PATH + "instance_3.xml";
+
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ private ConfigFileParser parser;
+ private HawkInstanceConfig config;
+ private File fConfig;
+
+ @Before
+ public void setup() throws IOException {
+ File fOriginal = new File(XML_PATH);
+ fConfig = folder.newFile(fOriginal.getName());
+ Files.copy(fOriginal, fConfig);
+ }
@Test
public void testParseFile() {
parseXml();
-
- // config config values
+
+ // config values
assertEquals("Instance Name:", "instance_3", config.getName());
assertEquals("Instance Backend:", "org.hawk.orientdb.OrientDatabase", config.getBackend());
assertEquals("Instance Delay Max:", 512000, config.getDelayMax());
assertEquals("Instance Delay Min:", 5000, config.getDelayMin());
-
- assertEquals("Instance Number of Plugins:", 7, config.getPlugins().size());
+
+ assertEquals("Instance Number of Plugins:", 8, config.getPlugins().size());
assertTrue(config.getPlugins().contains("org.hawk.emf.metamodel.EMFMetaModelResourceFactory"));
assertTrue(config.getPlugins().contains("org.hawk.emf.model.EMFModelResourceFactory"));
assertTrue(config.getPlugins().contains("org.hawk.graph.syncValidationListener.SyncValidationListener"));
@@ -47,53 +68,49 @@
assertTrue(config.getPlugins().contains("org.hawk.modelio.exml.listeners.ModelioGraphChangeListener"));
assertTrue(config.getPlugins().contains("org.hawk.modelio.exml.metamodel.ModelioMetaModelResourceFactory"));
assertTrue(config.getPlugins().contains("org.hawk.modelio.exml.model.ModelioModelResourceFactory"));
-
+ assertTrue(config.getPlugins().contains("org.hawk.epsilon.emc.EOLQueryEngine"));
+
assertEquals("Instance Number of Metamodels:", 1, config.getMetamodels().size());
- assertEquals("C:/resources/metamodel/metamodel_descriptor.xml",config.getMetamodels().get(0).getLocation());
- assertEquals("",config.getMetamodels().get(0).getUri());
-
+ assertEquals("C:/resources/metamodel/metamodel_descriptor.xml", config.getMetamodels().get(0).getLocation());
+ assertEquals("", config.getMetamodels().get(0).getUri());
+
assertEquals("Instance Number of Derived Attributes:", 1, config.getDerivedAttributes().size());
assertEquals("modelio://Modeliosoft.Standard/2.0.00", config.getDerivedAttributes().get(0).getMetamodelUri());
assertEquals("Class", config.getDerivedAttributes().get(0).getTypeName());
assertEquals("ownedOperationCount", config.getDerivedAttributes().get(0).getAttributeName());
assertEquals("Integer", config.getDerivedAttributes().get(0).getAttributeType());
-
+
assertEquals(false, config.getDerivedAttributes().get(0).isMany());
assertEquals(false, config.getDerivedAttributes().get(0).isOrdered());
assertEquals(false, config.getDerivedAttributes().get(0).isUnique());
-
- assertEquals("EOLQueryEngine", config.getDerivedAttributes().get(0).getDerivationLanguage());
- assertEquals("\n\t\t\t\t\t\treturn self.OwnedOperation.size;\n\t\t\t\t\t", config.getDerivedAttributes().get(0).getDerivationLogic());
-
-
+ assertEquals("EOLQueryEngine", config.getDerivedAttributes().get(0).getDerivationLanguage());
+ assertEquals("\n\t\t\t\t\t\treturn self.OwnedOperation.size;\n\t\t\t\t\t",
+ config.getDerivedAttributes().get(0).getDerivationLogic());
+
assertEquals("Instance Number of Indexed Attributes:", 1, config.getIndexedAttributes().size());
assertEquals("modelio://Modeliosoft.Standard/2.0.00", config.getIndexedAttributes().get(0).getMetamodelUri());
assertEquals("Class", config.getIndexedAttributes().get(0).getTypeName());
assertEquals("Name", config.getIndexedAttributes().get(0).getAttributeName());
-
+
assertEquals("Instance Number of :Repositories", 1, config.getRepositories().size());
assertEquals("file:///C:/Desktop/Hawk/Zoo/", config.getRepositories().get(0).getLocation());
assertEquals("org.hawk.localfolder.LocalFolder", config.getRepositories().get(0).getType());
- assertEquals("", config.getRepositories().get(0).getUser());
- assertEquals("", config.getRepositories().get(0).getPass());
+ assertNull(config.getRepositories().get(0).getUser());
+ assertNull(config.getRepositories().get(0).getPass());
assertEquals(false, config.getRepositories().get(0).isFrozen());
}
-
private void parseXml() {
parser = new ConfigFileParser();
- config = parser.parse(new File(xmlFilePath));
+ config = parser.parse(fConfig);
}
-
@Test
public void testSaveConfigToFile() {
- parseXml();
+ parseXml();
parser.saveConfigAsXml(config);
testParseFile();
}
-
}
-
diff --git a/tests/org.hawk.service.servlet.tests/src/org/hawk/service/servlet/config/HawkServerConfiguratorTest.java b/tests/org.hawk.service.servlet.tests/src/org/hawk/service/servlet/config/HawkServerConfiguratorTest.java
index 01e4393..c758913 100644
--- a/tests/org.hawk.service.servlet.tests/src/org/hawk/service/servlet/config/HawkServerConfiguratorTest.java
+++ b/tests/org.hawk.service.servlet.tests/src/org/hawk/service/servlet/config/HawkServerConfiguratorTest.java
@@ -45,50 +45,48 @@
public class HawkServerConfiguratorTest {
private static final String SERVERCONFIG_PATH = "resources/ServerConfig/";
- private static final String metamodelDescriptor = "resources/metamodel/metamodel_descriptor.xml";
- private static final String modelsZoo = "resources/Zoo";
+ private static final String MMDESC_PATH = "resources/metamodel/metamodel_descriptor.xml";
+ private static final String ZOO_PATH = "resources/Zoo";
- static final String xmlFileName_1 = "instance_1.xml";
- static final String xmlFileName_2 = "instance_2.xml";
+ private static final String INSTANCE1_PATH = "instance_1.xml";
+ private static final String INSTANCE2_PATH = "instance_2.xml";
- static HManager manager;
- static File configurationFolder;
-
+ private static HManager manager;
+ private static File configurationFolder;
private static HawkThriftIface hawkIface;
-
private static HawkServerConfigurator serverConfigurator;
-
private boolean finishedRetrievingInstanceInfo;
-
- Collection<IVcsManager> repos;
- Collection<IndexedAttributeParameters> derivedAttributes;
- Collection<IndexedAttributeParameters> indexedAttributes;
- List<String> metamodels;
-
+
+ private Collection<IVcsManager> repos;
+ private Collection<IndexedAttributeParameters> derivedAttributes;
+ private Collection<IndexedAttributeParameters> indexedAttributes;
+ private List<String> metamodels;
+
@BeforeClass
- static public void setup() {
+ public static void setup() throws IOException {
initConfigurationFolder();
- setupAndCopyPathsInXmlFile(xmlFileName_1);
- setupAndCopyPathsInXmlFile(xmlFileName_2);
+ setupAndCopyPathsInXmlFile(INSTANCE1_PATH);
+ setupAndCopyPathsInXmlFile(INSTANCE2_PATH);
+
manager = HManager.getInstance();
hawkIface = new HawkThriftIface(ThriftProtocol.TUPLE, null, null);
serverConfigurator = new HawkServerConfigurator(hawkIface);
- serverConfigurator.loadHawkServerConfigurations();
+ serverConfigurator.loadHawkServerConfigurations();
}
@Test
- public void testHawkServerConfigurator_instance1() throws Exception {
- testhawkInstance(xmlFileName_1);
+ public void testHawkServerConfigurator_instance1() throws Exception {
+ testhawkInstance(INSTANCE1_PATH);
}
@Test
public void testHawkServerConfigurator_instance2() throws Exception {
- testhawkInstance(xmlFileName_2);
+ testhawkInstance(INSTANCE2_PATH);
}
private void testhawkInstance(String xmlFileName) throws Exception {
final ConfigFileParser parser = new ConfigFileParser();
- final HawkInstanceConfig config = parser.parse(new File(SERVERCONFIG_PATH, xmlFileName));
+ final HawkInstanceConfig config = parser.parse(new File(configurationFolder, xmlFileName));
final HModel instance = manager.getHawkByName(config.getName());
assertTrue(instance.isRunning());
@@ -100,7 +98,7 @@
finishedRetrievingInstanceInfo = false;
instance.configurePolling(0, 0);
- instance.getHawk().getModelIndexer().scheduleTask(new Callable<Void>(){
+ instance.getHawk().getModelIndexer().scheduleTask(new Callable<Void>() {
@Override
public Void call() {
metamodels = instance.getRegisteredMetamodels();
@@ -110,27 +108,28 @@
finishedRetrievingInstanceInfo = true;
return null;
}
- }, 0);;
-
- while(!finishedRetrievingInstanceInfo) {
+ }, 0);
+ ;
+
+ while (!finishedRetrievingInstanceInfo) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
-
- // repositories
- assertTrue(compareRepositories(config.getRepositories(), repos));
- // metamodels
+ // repositories
+ compareRepositories(config.getRepositories(), repos);
+
+ // metamodels
assertTrue(metamodels.contains("modelio://ModelioMetaPackage"));
assertTrue(metamodels.contains("modelio://Modeliosoft.Archimate/1.0.03"));
assertTrue(metamodels.contains("modelio://Modeliosoft.Analyst/2.0.00"));
assertTrue(metamodels.contains("modelio://Modeliosoft.modelio.kernel/1.0.00"));
assertTrue(metamodels.contains("modelio://Modeliosoft.Standard/2.0.00"));
assertTrue(metamodels.contains("modelio://Modeliosoft.Infrastructure/2.1.00"));
-
+
// derived attributes
assertTrue(derivedAttributes.size() > 0);
assertTrue(derivedAttributes.contains(config.getDerivedAttributes().get(0)));
@@ -139,93 +138,59 @@
assertEquals(indexedAttributes.size(), config.getIndexedAttributes().size());
assertTrue(indexedAttributes.contains(config.getIndexedAttributes().get(0)));
}
-
- private boolean compareRepositories(List<RepositoryParameters> repositories, Collection<IVcsManager> collection) {
- if(repositories.size() != collection.size()) {
- return false;
- }
+ private void compareRepositories(List<RepositoryParameters> repositories, Collection<IVcsManager> collection) {
+ assertEquals(repositories.size(), collection.size());
- boolean allEqual = true;
for (IVcsManager vcsManager : collection) {
- boolean FoundAndEqual = false;
- for(RepositoryParameters repos : repositories) {
- if( repos.getType().equals(vcsManager.getType()) &&
- repos.getLocation().equals(vcsManager.getLocation()) &&
- repos.isFrozen() == vcsManager.isFrozen())
- {
- FoundAndEqual = true;
- if(vcsManager.getUsername() != null) {
- FoundAndEqual = repos.getUser().equals(vcsManager.getUsername());
- } else {
- FoundAndEqual = (repos.getUser().isEmpty() || repos.getUser() == null);
- }
+ boolean foundAndEqual = false;
- if(vcsManager.getPassword() != null) {
- FoundAndEqual = repos.getUser().equals(vcsManager.getPassword());
- } else {
- FoundAndEqual = (repos.getPass().isEmpty() || repos.getPass() == null);
- }
-
- break;
- }
+ for (RepositoryParameters repos : repositories) {
+ foundAndEqual = foundAndEqual ||
+ (vcsManager.getType().equals(repos.getType())
+ && vcsManager.getLocation().equals(repos.getLocation())
+ && vcsManager.isFrozen() == repos.isFrozen()
+ && (vcsManager.getUsername() == null
+ ? repos.getUser() == null
+ : vcsManager.getUsername().equals(repos.getUser()))
+ && (vcsManager.getPassword() == null
+ ? repos.getPass() == null
+ : vcsManager.getPassword().equals(repos.getPass())));
}
- if(!FoundAndEqual) {
- allEqual = false;
- break;
- }
+ assertTrue("Should be able to find repo " + vcsManager.getLocation(), foundAndEqual);
}
-
- return allEqual;
}
- static public void setupAndCopyPathsInXmlFile(String xmlFileName) {
+ private static void setupAndCopyPathsInXmlFile(String xmlFileName) throws IOException {
+ final File fOriginal = new File(SERVERCONFIG_PATH, xmlFileName);
+ final File fCopy = new File(configurationFolder, xmlFileName);
+ Files.copy(fOriginal, fCopy);
+
ConfigFileParser parser = new ConfigFileParser();
- HawkInstanceConfig config = parser.parse(new File(SERVERCONFIG_PATH, xmlFileName));
- File location = new File(metamodelDescriptor);
+ HawkInstanceConfig config = parser.parse(fCopy);
+ File location = new File(MMDESC_PATH);
config.getMetamodels().get(0).setLocation(location.getAbsolutePath());
- config.getRepositories().get(0).setLocation(getLocalFilePath(modelsZoo));
+ config.getRepositories().get(0).setLocation(getLocalFilePath(ZOO_PATH));
parser.saveConfigAsXml(config);
-
- // copy
- try {
- Files.copy(new File(SERVERCONFIG_PATH, xmlFileName), new File(configurationFolder, xmlFileName));
- } catch (IOException e) {
- e.printStackTrace();
- }
}
- static public String getLocalFilePath(String fileLocation) {
+ private static String getLocalFilePath(String fileLocation) throws IOException {
String repositoryURI = fileLocation;
+ Path path = Paths.get(fileLocation);
- try {
- Path path;
- path = Paths.get(fileLocation);
+ File canonicalFile = null;
+ canonicalFile = path.toFile().getCanonicalFile();
- File canonicalFile = null;
- canonicalFile = path.toFile().getCanonicalFile();
-
- Path rootLocation = canonicalFile.toPath();
- repositoryURI = rootLocation.toUri().toString();
-
- } catch (IOException e) {
- e.printStackTrace();
- }
-
+ Path rootLocation = canonicalFile.toPath();
+ repositoryURI = rootLocation.toUri().toString();
return repositoryURI;
}
- static public void initConfigurationFolder() {
- try {
- URL installURL = Platform.getConfigurationLocation().getURL();
- String path = FileLocator.toFileURL(installURL).getPath();
-
- configurationFolder = new File(path);
- } catch (IOException e) {
- e.printStackTrace();
- }
+ private static void initConfigurationFolder() throws IOException {
+ final URL installURL = Platform.getConfigurationLocation().getURL();
+ final String path = FileLocator.toFileURL(installURL).getPath();
+ configurationFolder = new File(path);
}
}
-
diff --git a/tests/org.hawk.timeaware.tests/META-INF/MANIFEST.MF b/tests/org.hawk.timeaware.tests/META-INF/MANIFEST.MF
index 50451b8..9a98213 100644
--- a/tests/org.hawk.timeaware.tests/META-INF/MANIFEST.MF
+++ b/tests/org.hawk.timeaware.tests/META-INF/MANIFEST.MF
@@ -27,5 +27,7 @@
org.hawk.service.api;bundle-version="1.2.0",
javax.servlet;bundle-version="3.1.0",
org.hawk.service.artemis.server;bundle-version="1.2.0",
- org.apache.thrift;bundle-version="0.9.3"
+ org.apache.thrift;bundle-version="0.9.3",
+ org.hawk.jgit;bundle-version="1.2.0",
+ org.eclipse.jgit;bundle-version="5.5.0"
Bundle-ActivationPolicy: lazy
diff --git a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/AbstractTimeAwareModelIndexingTest.java b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/AbstractTimeAwareModelIndexingTest.java
index 6dc585a..eae0a44 100644
--- a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/AbstractTimeAwareModelIndexingTest.java
+++ b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/AbstractTimeAwareModelIndexingTest.java
@@ -16,8 +16,6 @@
******************************************************************************/
package org.hawk.timeaware.tests;
-import static org.junit.Assert.assertEquals;
-
import java.io.File;
import java.util.Collections;
import java.util.Map;
diff --git a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/DerivedAttributeHistoryTest.java b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/DerivedAttributeHistoryTest.java
index 92f5306..193aaa1 100644
--- a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/DerivedAttributeHistoryTest.java
+++ b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/DerivedAttributeHistoryTest.java
@@ -23,7 +23,6 @@
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
-import java.util.concurrent.Callable;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
@@ -76,23 +75,19 @@
public void computedForAllVersions() throws Throwable {
oneDerivedAttribute();
requestSVNIndex(svnRepository);
+ scheduleAndWait(() -> {
+ // .all works on revision 0
+ assertTrue((boolean)
+ timeAwareEOL("return Tree.latest.all.first.always(v|v.Important.isDefined());"));
+ assertTrue((boolean)
+ timeAwareEOL("return Tree.latest.all.first.earliest.Important;"));
+ assertFalse((boolean)
+ timeAwareEOL("return Tree.latest.all.first.latest.Important;"));
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- // .all works on revision 0
- assertTrue((boolean)
- timeAwareEOL("return Tree.latest.all.first.always(v|v.Important.isDefined());"));
- assertTrue((boolean)
- timeAwareEOL("return Tree.latest.all.first.earliest.Important;"));
- assertFalse((boolean)
- timeAwareEOL("return Tree.latest.all.first.latest.Important;"));
-
- assertEquals(1,
- timeAwareEOL("return Tree.latest.all.first.whenAnnotated('Important').versions.size;"));
-
- return null;
- }
+ assertEquals(1,
+ timeAwareEOL("return Tree.latest.all.first.whenAnnotated('Important').versions.size;"));
+
+ return null;
});
}
@@ -100,21 +95,18 @@
public void whenComposability() throws Throwable {
twoDerivedAttributeRepository();
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- // whenAnnotated
- assertEquals(2,
- timeAwareEOL("return Tree.earliest.next.all.first.whenAnnotated('Important').versions.size;"));
- assertEquals(2,
- timeAwareEOL("return Tree.earliest.next.all.first.whenAnnotated('HasChildren').versions.size;"));
- assertEquals(1,
- timeAwareEOL("return Tree.earliest.next.all.first.whenAnnotated('Important').whenAnnotated('HasChildren').versions.size;"));
- assertEquals(1,
- timeAwareEOL("return Tree.earliest.next.all.first.whenAnnotated('HasChildren').whenAnnotated('Important').versions.size;"));
-
- return null;
- }
+ scheduleAndWait(() -> {
+ // whenAnnotated
+ assertEquals(2,
+ timeAwareEOL("return Tree.earliest.next.all.first.whenAnnotated('Important').versions.size;"));
+ assertEquals(2,
+ timeAwareEOL("return Tree.earliest.next.all.first.whenAnnotated('HasChildren').versions.size;"));
+ assertEquals(1,
+ timeAwareEOL("return Tree.earliest.next.all.first.whenAnnotated('Important').whenAnnotated('HasChildren').versions.size;"));
+ assertEquals(1,
+ timeAwareEOL("return Tree.earliest.next.all.first.whenAnnotated('HasChildren').whenAnnotated('Important').versions.size;"));
+
+ return null;
});
}
@@ -122,15 +114,12 @@
public void sinceAnnotated() throws Throwable {
twoDerivedAttributeRepository();
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- assertEquals(4, timeAwareEOL("return Tree.earliest.next.all.first.earliest.sinceAnnotated('Important').versions.size;"));
- assertEquals(1, timeAwareEOL("return Tree.earliest.next.all.first.earliest.next.sinceAnnotated('Important').versions.size;"));
- assertEquals(2, timeAwareEOL("return Tree.earliest.next.all.first.earliest.sinceAnnotated('HasChildren').versions.size;"));
-
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(4, timeAwareEOL("return Tree.earliest.next.all.first.earliest.sinceAnnotated('Important').versions.size;"));
+ assertEquals(1, timeAwareEOL("return Tree.earliest.next.all.first.earliest.next.sinceAnnotated('Important').versions.size;"));
+ assertEquals(2, timeAwareEOL("return Tree.earliest.next.all.first.earliest.sinceAnnotated('HasChildren').versions.size;"));
+
+ return null;
});
}
@@ -138,15 +127,12 @@
public void afterAnnotated() throws Throwable {
twoDerivedAttributeRepository();
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- assertEquals(3, timeAwareEOL("return Tree.earliest.next.all.first.earliest.afterAnnotated('Important').versions.size;"));
- assertFalse((boolean) timeAwareEOL("return Tree.earliest.next.all.first.earliest.next.afterAnnotated('Important').isDefined();"));
- assertEquals(1, timeAwareEOL("return Tree.earliest.next.all.first.earliest.afterAnnotated('HasChildren').versions.size;"));
-
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(3, timeAwareEOL("return Tree.earliest.next.all.first.earliest.afterAnnotated('Important').versions.size;"));
+ assertFalse((boolean) timeAwareEOL("return Tree.earliest.next.all.first.earliest.next.afterAnnotated('Important').isDefined();"));
+ assertEquals(1, timeAwareEOL("return Tree.earliest.next.all.first.earliest.afterAnnotated('HasChildren').versions.size;"));
+
+ return null;
});
}
@@ -154,18 +140,15 @@
public void untilAnnotated() throws Throwable {
twoDerivedAttributeRepository();
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- assertEquals(1, timeAwareEOL("return Tree.earliest.next.all.first.earliest.untilAnnotated('Important').versions.size;"));
- assertEquals(3, timeAwareEOL("return Tree.earliest.next.all.first.earliest.next.sinceThen.untilAnnotated('Important').versions.size;"));
- assertEquals(3, timeAwareEOL("return Tree.earliest.next.all.first.earliest.untilAnnotated('HasChildren').versions.size;"));
-
- assertEquals(1, timeAwareEOL("return Tree.earliest.next.all.first.earliest.untilAnnotated('HasChildren').untilAnnotated('Important').versions.size;"));
- assertFalse((boolean) timeAwareEOL("return Tree.earliest.next.all.first.earliest.untilAnnotated('Important').untilAnnotated('HasChildren').isDefined();"));
-
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(1, timeAwareEOL("return Tree.earliest.next.all.first.earliest.untilAnnotated('Important').versions.size;"));
+ assertEquals(3, timeAwareEOL("return Tree.earliest.next.all.first.earliest.next.sinceThen.untilAnnotated('Important').versions.size;"));
+ assertEquals(3, timeAwareEOL("return Tree.earliest.next.all.first.earliest.untilAnnotated('HasChildren').versions.size;"));
+
+ assertEquals(1, timeAwareEOL("return Tree.earliest.next.all.first.earliest.untilAnnotated('HasChildren').untilAnnotated('Important').versions.size;"));
+ assertFalse((boolean) timeAwareEOL("return Tree.earliest.next.all.first.earliest.untilAnnotated('Important').untilAnnotated('HasChildren').isDefined();"));
+
+ return null;
});
}
@@ -173,14 +156,11 @@
public void beforeAnnotated() throws Throwable {
twoDerivedAttributeRepository();
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- assertFalse((boolean) timeAwareEOL("return Tree.earliest.next.all.first.earliest.beforeAnnotated('Important').isDefined();"));
- assertEquals(2, timeAwareEOL("return Tree.earliest.next.all.first.earliest.next.sinceThen.beforeAnnotated('Important').versions.size;"));
- assertEquals(2, timeAwareEOL("return Tree.earliest.next.all.first.earliest.beforeAnnotated('HasChildren').versions.size;"));
- return null;
- }
+ scheduleAndWait(() -> {
+ assertFalse((boolean) timeAwareEOL("return Tree.earliest.next.all.first.earliest.beforeAnnotated('Important').isDefined();"));
+ assertEquals(2, timeAwareEOL("return Tree.earliest.next.all.first.earliest.next.sinceThen.beforeAnnotated('Important').versions.size;"));
+ assertEquals(2, timeAwareEOL("return Tree.earliest.next.all.first.earliest.beforeAnnotated('HasChildren').versions.size;"));
+ return null;
});
}
@@ -197,7 +177,7 @@
parentLabelRepository();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals("Root2", timeAwareEOL("return Tree.latest.all.selectOne(l|l.latest.label='Child').latest.parentLabel;"));
assertEquals(3, timeAwareEOL("return Tree.latest.all.selectOne(l|l.latest.label='Child').versions.size;"));
return null;
@@ -217,7 +197,7 @@
parentLabelRepository();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals("Root2", timeAwareEOL("return Tree.latest.all.selectOne(l|l.latest.label='Child').latest.parentLabel;"));
assertEquals(3, timeAwareEOL("return Tree.latest.all.selectOne(l|l.latest.label='Child').versions.size;"));
return null;
diff --git a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/FileContextTimeAwareEOLQueryEngineTest.java b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/FileContextTimeAwareEOLQueryEngineTest.java
index ac3a518..71b934a 100644
--- a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/FileContextTimeAwareEOLQueryEngineTest.java
+++ b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/FileContextTimeAwareEOLQueryEngineTest.java
@@ -20,7 +20,6 @@
import java.io.File;
import java.util.Arrays;
-import java.util.concurrent.Callable;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
@@ -34,7 +33,6 @@
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
-import org.tmatesoft.svn.core.SVNCommitInfo;
/**
* Tests for time-aware queries that use additional context parameters, e.g.
@@ -81,7 +79,7 @@
rTreeA.getContents().add(a1);
rTreeA.save(null);
svnRepositoryA.add(fTreeA);
- final SVNCommitInfo cInfoA1 = svnRepositoryA.commit("first in A");
+ svnRepositoryA.commit("first in A");
// Now do the same at least one second later, in the second SVN repository
final long startMillis = System.currentTimeMillis();
@@ -95,7 +93,7 @@
rTreeB.getContents().add(b1);
rTreeB.save(null);
svnRepositoryB.add(fTreeB);
- final SVNCommitInfo cInfoB1 = svnRepositoryB.commit("first in B");
+ svnRepositoryB.commit("first in B");
// Run the SVN indexing now
requestSVNIndex();
@@ -114,9 +112,9 @@
private void requestSVNIndex() throws Throwable {
requestSVNIndex(svnRepositoryA);
- waitForSync();
+ scheduleAndWait();
requestSVNIndex(svnRepositoryB);
- waitForSync();
+ scheduleAndWait();
}
}
diff --git a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/GitNodeHistoryTest.java b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/GitNodeHistoryTest.java
new file mode 100644
index 0000000..7416996
--- /dev/null
+++ b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/GitNodeHistoryTest.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2018-2019 Aston University.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the Eclipse
+ * Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
+ *
+ * Contributors:
+ * Antonio Garcia-Dominguez - initial API and implementation
+ ******************************************************************************/
+package org.hawk.timeaware.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.util.Arrays;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.jgit.api.Git;
+import org.hawk.backend.tests.BackendTestSuite;
+import org.hawk.backend.tests.factories.IGraphDatabaseFactory;
+import org.hawk.git.JGitRepository;
+import org.hawk.integration.tests.emf.EMFModelSupportFactory;
+import org.hawk.integration.tests.mm.Tree.Tree;
+import org.hawk.integration.tests.mm.Tree.TreeFactory;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests for the time-aware indexing of model element nodes, using Subversion.
+ */
+@RunWith(Parameterized.class)
+public class GitNodeHistoryTest extends AbstractTimeAwareModelIndexingTest {
+
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ @Parameters(name = "{0}")
+ public static Iterable<Object[]> params() {
+ Object[][] baseParams = BackendTestSuite.timeAwareBackends();
+
+ Object[][] params = new Object[baseParams.length][];
+ for (int i = 0; i < baseParams.length; i++) {
+ params[i] = new Object[] { baseParams[i][0], new EMFModelSupportFactory() };
+ }
+
+ return Arrays.asList(params);
+ }
+
+ public GitNodeHistoryTest(IGraphDatabaseFactory dbFactory, IModelSupportFactory modelSupportFactory) {
+ super(dbFactory, modelSupportFactory);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ Git.init().setDirectory(folder.getRoot()).call();
+ }
+
+ @Override
+ protected void setUpMetamodels() throws Exception {
+ indexer.registerMetamodels(new File(TREE_MM_PATH));
+ }
+
+ @Test
+ public void defaultBranch() throws Throwable {
+ final File fTree = new File(folder.getRoot(), "root.xmi");
+ final Resource rTree = rsTree.createResource(URI.createFileURI(fTree.getAbsolutePath()));
+
+ final Tree tRoot = TreeFactory.eINSTANCE.createTree();
+ tRoot.setLabel("root");
+ rTree.getContents().add(tRoot);
+ rTree.save(null);
+
+ try (Git git = Git.open(folder.getRoot())) {
+ git.add().addFilepattern(fTree.getName()).call();
+ git.commit().setMessage("first commit").call();
+
+ final Tree tChild = TreeFactory.eINSTANCE.createTree();
+ tChild.setLabel("child");
+ tRoot.getChildren().add(tChild);
+ rTree.save(null);
+ git.commit().setAll(true).setMessage("second commit").call();
+ }
+
+ JGitRepository vcs = new JGitRepository();
+ vcs.init(folder.getRoot().getAbsolutePath(), indexer);
+ vcs.run();
+ indexer.addVCSManager(vcs, true);
+
+ scheduleAndWait(() -> {
+ // 3 versions: beginning of time + 2 commits
+ assertEquals(3, timeAwareEOL("return Tree.versions.size;"));
+ assertEquals(2, timeAwareEOL("return Tree.latest.all.size;"));
+ assertEquals(1, timeAwareEOL("return Tree.latest.prev.all.size;"));
+ assertEquals(0, timeAwareEOL("return Tree.latest.prev.prev.all.size;"));
+ return null;
+ });
+ }
+
+ @Test
+ public void nonDefaultBranch() throws Throwable {
+ final File fTree = new File(folder.getRoot(), "root.xmi");
+ final Resource rTree = rsTree.createResource(URI.createFileURI(fTree.getAbsolutePath()));
+
+ final Tree tRoot = TreeFactory.eINSTANCE.createTree();
+ tRoot.setLabel("root");
+ rTree.getContents().add(tRoot);
+ rTree.save(null);
+
+ try (Git git = Git.open(folder.getRoot())) {
+ git.add().addFilepattern(fTree.getName()).call();
+ git.commit().setMessage("first commit").call();
+
+ final Tree tChild = TreeFactory.eINSTANCE.createTree();
+ tChild.setLabel("child");
+ tRoot.getChildren().add(tChild);
+ rTree.save(null);
+ git.commit().setAll(true).setMessage("second commit").call();
+
+ git.checkout().setName("newbranch").setCreateBranch(true).call();
+ tChild.setLabel("changed");
+ rTree.save(null);
+ git.commit().setAll(true).setMessage("third commit in new branch").call();
+
+ git.checkout().setName("master").call();
+ }
+
+ JGitRepository vcs = new JGitRepository();
+ vcs.init(folder.getRoot().toURI().toString() + "?branch=newbranch", indexer);
+ vcs.run();
+ indexer.addVCSManager(vcs, true);
+
+ scheduleAndWait(() -> {
+ // 3 versions: beginning of time + 2 commits
+ assertEquals(1, timeAwareEOL("return Tree.latest.all.select(t|t.label='child').size;"));
+ assertEquals("changed", timeAwareEOL("return Tree.latest.all.selectOne(t|t.label='child').latest.label;"));
+ assertEquals(2, timeAwareEOL("return Tree.latest.all.selectOne(t|t.label='child').versions.size;"));
+ return null;
+ });
+ }
+
+}
diff --git a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/NodeHistoryTest.java b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/SubversionNodeHistoryTest.java
similarity index 89%
rename from tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/NodeHistoryTest.java
rename to tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/SubversionNodeHistoryTest.java
index a9cb661..0638c68 100644
--- a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/NodeHistoryTest.java
+++ b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/SubversionNodeHistoryTest.java
@@ -24,16 +24,13 @@
import java.io.File;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
-import java.util.concurrent.Callable;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.hawk.backend.tests.BackendTestSuite;
import org.hawk.backend.tests.factories.IGraphDatabaseFactory;
import org.hawk.core.graph.timeaware.ITimeAwareGraphNode;
-import org.hawk.epsilon.emc.EOLQueryEngine;
import org.hawk.epsilon.emc.wrappers.GraphNodeWrapper;
import org.hawk.integration.tests.emf.EMFModelSupportFactory;
import org.hawk.svn.tests.rules.TemporarySVNRepository;
@@ -46,26 +43,26 @@
import org.junit.runners.Parameterized.Parameters;
/**
- * Tests for the time-aware indexing of model element nodes.
+ * Tests for the time-aware indexing of model element nodes, using Subversion.
*/
@RunWith(Parameterized.class)
-public class NodeHistoryTest extends AbstractTimeAwareModelIndexingTest {
+public class SubversionNodeHistoryTest extends AbstractTimeAwareModelIndexingTest {
@Rule
public TemporarySVNRepository svnRepository = new TemporarySVNRepository();
@Parameters(name = "{0}")
- public static Iterable<Object[]> params() {
- Object[][] baseParams = BackendTestSuite.timeAwareBackends();
+ public static Iterable<Object[]> params() {
+ Object[][] baseParams = BackendTestSuite.timeAwareBackends();
- Object[][] params = new Object[baseParams.length][];
- for (int i = 0; i < baseParams.length; i++) {
- params[i] = new Object[] { baseParams[i][0], new EMFModelSupportFactory() };
- }
+ Object[][] params = new Object[baseParams.length][];
+ for (int i = 0; i < baseParams.length; i++) {
+ params[i] = new Object[] { baseParams[i][0], new EMFModelSupportFactory() };
+ }
- return Arrays.asList(params);
- }
+ return Arrays.asList(params);
+ }
- public NodeHistoryTest(IGraphDatabaseFactory dbFactory, IModelSupportFactory modelSupportFactory) {
+ public SubversionNodeHistoryTest(IGraphDatabaseFactory dbFactory, IModelSupportFactory modelSupportFactory) {
super(dbFactory, modelSupportFactory);
}
@@ -77,7 +74,7 @@
@Test
public void travelToMissingTimepointReturnsNull() throws Throwable {
twoCommitTree();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
GraphNodeWrapper gnw = (GraphNodeWrapper) timeAwareEOL("return Tree.latest.prev.all.first;");
assertNotNull(gnw.getNode());
assertNull(((ITimeAwareGraphNode) gnw.getNode()).travelInTime(ITimeAwareGraphNode.NO_SUCH_INSTANT));
@@ -88,22 +85,20 @@
@Test
public void createDeleteNode() throws Throwable {
twoCommitTree();
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- // .all works on revision 0
- assertEquals(0, timeAwareEOL("return Tree.all.size;"));
+ scheduleAndWait(() -> {
+ // .all works on revision 0
+ assertEquals(0, timeAwareEOL("return Tree.all.size;"));
- // We also deleted everything in the latest revision
- assertEquals(0, timeAwareEOL("return Tree.latest.all.size;"));
+ // We also deleted everything in the latest revision
+ assertEquals(0, timeAwareEOL("return Tree.latest.all.size;"));
- // .created can return instances that have been created from a certain moment in time (even if not alive anymore)
- assertEquals(1, timeAwareEOL("return Tree.latest.prev.size;"));
+ // .created can return instances that have been created from a certain moment in
+ // time (even if not alive anymore)
+ assertEquals(1, timeAwareEOL("return Tree.latest.prev.size;"));
- assertEquals("xy", timeAwareEOL("return Tree.latest.prev.all.first.label;"));
+ assertEquals("xy", timeAwareEOL("return Tree.latest.prev.all.first.label;"));
- return null;
- }
+ return null;
});
}
@@ -127,30 +122,24 @@
@Test
public void countInstancesFromModelTypes() throws Throwable {
twoCommitTree();
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').all.size;"));
- assertEquals(1, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').latest.prev.all.size;"));
- assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').latest.prev.prev.all.size;"));
- assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').earliest.all.size;"));
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').all.size;"));
+ assertEquals(1, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').latest.prev.all.size;"));
+ assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').latest.prev.prev.all.size;"));
+ assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').earliest.all.size;"));
+ return null;
});
}
@Test
public void countInstancesFromModel() throws Throwable {
twoCommitTree();
- waitForSync(new Callable<Object>(){
- @Override
- public Object call() throws Exception {
- assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').all.size;"));
- assertEquals(1, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').latest.prev.all.size;"));
- assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').latest.prev.prev.all.size;"));
- assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').earliest.all.size;"));
- return null;
- }
+ scheduleAndWait(() -> {
+ assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').all.size;"));
+ assertEquals(1, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').latest.prev.all.size;"));
+ assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').latest.prev.prev.all.size;"));
+ assertEquals(0, timeAwareEOL("return Model.types.selectOne(t|t.name='Tree').earliest.all.size;"));
+ return null;
});
}
@@ -158,7 +147,7 @@
@Test
public void countInstancesTimeline() throws Throwable {
twoCommitTree();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
List<List<Object>> results = (List<List<Object>>) timelineEOL("return Tree.all.size;");
assertEquals(0, results.get(0).get(1));
assertEquals(0, (int) timeAwareEOL("return Model.allInstancesAt(t).size;", "t", results.get(0).get(0)));
@@ -193,7 +182,7 @@
svnRepository.commit("First commit");
requestSVNIndex();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(0, timeAwareEOL("return Model.allInstances.collect(t|t.label).size;"));
assertEquals(0, timeAwareEOL("return Model.allInstances.size;"));
assertEquals(1, timeAwareEOL("return Model.allInstancesNow.size;"));
@@ -227,7 +216,7 @@
@Test
public void rangesAreBothInclusive() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
GraphNodeWrapper gnw = (GraphNodeWrapper) timeAwareEOL(
"return Tree.latest.all.selectOne(t|t.latest.label = 'Root');"
);
@@ -260,7 +249,7 @@
@Test
public void alwaysTrue() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertTrue((boolean) timeAwareEOL(
"return Tree.latest.all.selectOne(t|t.label='Root').always(v|v.label = 'Root');"
));
@@ -299,7 +288,7 @@
@Test
public void after() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(".after is an open left range, i.e. excludes matching version", 2, (int) timeAwareEOL(
"return Tree.latest.all.selectOne(t|t.label='Root').earliest.after(v|v.children.size > 0).children.size;"
));
@@ -320,7 +309,7 @@
svnRepository.commit("Added fourth child");
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(".until is a closed end range, i.e. includes matching version", 2, (int) timeAwareEOL(
"return Tree.earliest.next.all.selectOne(t|t.label='Root').until(v|v.children.size > 1).latest.children.size;"
));
@@ -344,7 +333,7 @@
svnRepository.commit("Added fourth child");
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(".before is a open end range, i.e. excludes matching version", 1, (int) timeAwareEOL(
"return Tree.earliest.next.all.selectOne(t|t.label='Root').before(v|v.children.size > 1).latest.children.size;"
));
@@ -366,7 +355,7 @@
public void sinceThen() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertFalse("Type node - Without .sinceThen, always uses all versions", (boolean) timeAwareEOL(
"return Tree.earliest.next.always(v|v.all.size > 0);"
));
@@ -389,7 +378,7 @@
public void afterThen() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertFalse("Type node - Without .afterThen, always uses all versions", (boolean) timeAwareEOL(
"return Tree.earliest.next.always(v|v.all.size > 1);"
));
@@ -412,7 +401,7 @@
public void untilThen() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertTrue("Positive combination of .sinceThen + .untilThen", (boolean) timeAwareEOL(
"return Tree.earliest.next.sinceThen.latest.prev.untilThen.always(v|v.all.size > 0 and v.all.size < 4);"
));
@@ -427,7 +416,7 @@
public void beforeThen() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertTrue("Positive combination of .afterThen + .beforeThen", (boolean) timeAwareEOL(
"return Tree.earliest.afterThen.latest.beforeThen.always(v|v.all.size > 0 and v.all.size < 4);"
));
@@ -446,7 +435,7 @@
svnRepository.commit("Removed third child");
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals(".when with all versions", 5, (int) timeAwareEOL(
"return Tree.earliest.next.all.selectOne(t|t.label='Root').when(v|v.children.size >= 0).versions.size;"
));
@@ -528,7 +517,7 @@
// END OF TEST SETUP
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertEquals("There are three versions with an empty root node", 3, (int)timeAwareEOL(
"return Tree.latest.all.selectOne(t|not t.eContainer.isDefined())"
+ ".earliest.when(v|v.children.isEmpty).versions.size;"
@@ -578,7 +567,7 @@
svnRepository.commit("Changed label");
indexer.requestImmediateSync();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
assertFalse((boolean) timeAwareEOL(
"return Tree.latest.all.selectOne(t|t.latest.label='SomethingElse').always(v|v.label = 'Root');"
));
diff --git a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/ThriftEncodingTest.java b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/ThriftEncodingTest.java
index c8b8412..a68e7dd 100644
--- a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/ThriftEncodingTest.java
+++ b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/ThriftEncodingTest.java
@@ -71,19 +71,20 @@
indexer.registerMetamodels(new File(TREE_MM_PATH));
}
+ @SuppressWarnings("unchecked")
@Test
public void encodeLatestVersion() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
Collection<GraphNodeWrapper> ret = (Collection<GraphNodeWrapper>) timeAwareEOL("return Model.allInstancesNow;");
HawkModelElementEncoder enc = new HawkModelElementEncoder(new GraphWrapper(indexer.getGraph()));
enc.setUseContainment(false);
-
+
List<ModelElement> encoded = new ArrayList<>(ret.size());
for (GraphNodeWrapper gnw : ret) {
encoded.add(enc.encode(gnw.getNode()));
}
-
+
assertEquals(4, encoded.size());
return null;
});
@@ -92,11 +93,11 @@
@Test
public void encodeLatestVersionRoot() throws Throwable {
keepAddingChildren();
- waitForSync(() -> {
+ scheduleAndWait(() -> {
GraphNodeWrapper ret = (GraphNodeWrapper) timeAwareEOL("return Model.allInstancesNow.selectOne(t|t.eContainer.isUndefined());");
HawkModelElementEncoder enc = new HawkModelElementEncoder(new GraphWrapper(indexer.getGraph()));
ModelElement encoded = enc.encode(ret.getNode());
-
+
assertNotNull(encoded);
assertEquals("Root", encoded.getAttributes().get(0).value.getVString());
assertEquals(3, encoded.getContainers().get(0).elements.size());
diff --git a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/TimeAwareBackendTest.java b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/TimeAwareBackendTest.java
index 0f9e5a0..cf8db01 100644
--- a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/TimeAwareBackendTest.java
+++ b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/TimeAwareBackendTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -231,6 +232,36 @@
createDeleteHeavyEdge();
}
+ @Test
+ public void nextPrev() throws Exception {
+ ITimeAwareGraphNode n;
+ try (IGraphTransaction tx = db.beginTransaction()) {
+ taDB.setTime(9);
+ n = taDB.createNode(Collections.singletonMap("x", 1), "example");
+ tx.success();
+ }
+ try (IGraphTransaction tx = db.beginTransaction()) {
+ n.travelInTime(10).setProperty("x", 3);
+ tx.success();
+ }
+ try (IGraphTransaction tx = db.beginTransaction()) {
+ n.travelInTime(11).setProperty("x", 5);
+ tx.success();
+ }
+
+ try (IGraphTransaction tx = db.beginTransaction()) {
+ assertEquals(Arrays.asList(11L, 10L, 9L), n.getAllInstants());
+
+ assertEquals(10, n.travelInTime(9).getNextInstant());
+ assertEquals(11, n.travelInTime(10).getNextInstant());
+ assertEquals(ITimeAwareGraphNode.NO_SUCH_INSTANT, n.travelInTime(11).getNextInstant());
+
+ assertEquals(ITimeAwareGraphNode.NO_SUCH_INSTANT, n.travelInTime(9).getPreviousInstant());
+ assertEquals(9, n.travelInTime(10).getPreviousInstant());
+ assertEquals(10, n.travelInTime(11).getPreviousInstant());
+ }
+ }
+
private void createDeleteHeavyEdge() throws Exception {
Object heavyEdgeId;
try (IGraphTransaction tx = db.beginTransaction()) {
diff --git a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/VCSManagerIndexTest.java b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/VCSManagerIndexTest.java
index 8d1a0cb..d16ea47 100644
--- a/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/VCSManagerIndexTest.java
+++ b/tests/org.hawk.timeaware.tests/src/org/hawk/timeaware/tests/VCSManagerIndexTest.java
@@ -52,10 +52,10 @@
private VCSManagerIndex idx;
@Parameters(name = "{0}")
- public static Object[] params() {
- return BackendTestSuite.params();
- }
-
+ public static Object[][] params() {
+ return BackendTestSuite.timeAwareBackends();
+ }
+
public VCSManagerIndexTest(IGraphDatabaseFactory factory) {
this.dbFactory = factory;
}