blob: 92f5306851940d914bd634bf0f5a36605fbf0863 [file] [log] [blame]
/*******************************************************************************
* 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 static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
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;
import org.hawk.backend.tests.BackendTestSuite;
import org.hawk.backend.tests.factories.IGraphDatabaseFactory;
import org.hawk.epsilon.emc.EOLQueryEngine;
import org.hawk.integration.tests.emf.EMFModelSupportFactory;
import org.hawk.svn.tests.rules.TemporarySVNRepository;
import org.hawk.timeaware.tests.tree.Tree.Tree;
import org.hawk.timeaware.tests.tree.Tree.TreeFactory;
import org.hawk.timeaware.tests.tree.Tree.TreePackage;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.tmatesoft.svn.core.SVNException;
/**
* Tests for derived attributes over the history of a node.
*/
@RunWith(Parameterized.class)
public class DerivedAttributeHistoryTest extends AbstractTimeAwareModelIndexingTest {
@Rule
public TemporarySVNRepository svnRepository = new TemporarySVNRepository();
private Resource rTree;
@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 DerivedAttributeHistoryTest(IGraphDatabaseFactory dbFactory, IModelSupportFactory modelSupportFactory) {
super(dbFactory, modelSupportFactory);
}
@Override
protected void setUpMetamodels() throws Exception {
indexer.registerMetamodels(new File(TREE_MM_PATH));
}
@Test
public void computedForAllVersions() throws Throwable {
oneDerivedAttribute();
requestSVNIndex(svnRepository);
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;
}
});
}
@Test
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;
}
});
}
@Test
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;
}
});
}
@Test
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;
}
});
}
@Test
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;
}
});
}
@Test
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;
}
});
}
@Test
public void revRefNavDerived() throws Throwable {
indexer.getMetaModelUpdater().addDerivedAttribute(
TreePackage.eNS_URI, "Tree", "parentLabel", "String",
false, false, false,
EOLQueryEngine.TYPE,
"var parent = self.revRefNav_children.first; "
+ "if (parent.isDefined()) return parent.label; else return '';",
indexer
);
parentLabelRepository();
waitForSync(() -> {
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;
});
}
@Test
public void eContainerDerived() throws Throwable {
indexer.getMetaModelUpdater().addDerivedAttribute(
TreePackage.eNS_URI, "Tree", "parentLabel", "String",
false, false, false,
EOLQueryEngine.TYPE,
"var parent = self.eContainer; "
+ "if (parent.isDefined()) return parent.label; else return '';",
indexer
);
parentLabelRepository();
waitForSync(() -> {
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;
});
}
private void parentLabelRepository() throws Exception {
final File fTree = new File(svnRepository.getCheckoutDirectory(), "root.xmi");
rTree = rsTree.createResource(URI.createFileURI(fTree.getAbsolutePath()));
Tree root = treeFactory.createTree();
root.setLabel("Root");
rTree.getContents().add(root);
rTree.save(null);
svnRepository.add(fTree);
svnRepository.commit("First commit");
Tree child = treeFactory.createTree();
child.setLabel("Child");
root.getChildren().add(child);
rTree.save(null);
svnRepository.commit("Second commit - add child");
root.setLabel("Root1");
rTree.save(null);
svnRepository.commit("Third commit - change label 1");
root.setLabel("Root2");
rTree.save(null);
svnRepository.commit("Third commit - change label 2");
requestSVNIndex(svnRepository);
}
private void twoDerivedAttributeRepository() throws Exception, IOException, SVNException {
indexer.getMetaModelUpdater().addDerivedAttribute(
TreePackage.eNS_URI, "Tree", "HasChildren", "Boolean",
false, false, false,
EOLQueryEngine.TYPE,
"return self.children.size > 0;",
indexer
);
Tree tRoot = oneDerivedAttribute();
Tree tChild = TreeFactory.eINSTANCE.createTree();
tChild.setLabel("Child");
tRoot.getChildren().add(tChild);
rTree.save(null);
svnRepository.commit("Add child node");
tRoot.setLabel("NowYouSeeMe");
rTree.save(null);
svnRepository.commit("Change label back");
requestSVNIndex(svnRepository);
}
private Tree oneDerivedAttribute() throws Exception {
indexer.getMetaModelUpdater().addDerivedAttribute(
TreePackage.eNS_URI, "Tree", "Important", "Boolean",
false, false, false,
EOLQueryEngine.TYPE,
"return self.label = 'NowYouSeeMe';",
indexer
);
final File fTree = new File(svnRepository.getCheckoutDirectory(), "root.xmi");
rTree = rsTree.createResource(URI.createFileURI(fTree.getAbsolutePath()));
Tree t = treeFactory.createTree();
t.setLabel("NowYouSeeMe");
rTree.getContents().add(t);
rTree.save(null);
svnRepository.add(fTree);
svnRepository.commit("First commit");
t.setLabel("NowYouDoNot");
rTree.save(null);
svnRepository.commit("Second commit - change label");
return t;
}
}