package com.sap.furcas.referenceresolving.tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import com.sap.furcas.test.fixture.ScenarioFixtureData; import com.sap.ide.cts.parser.errorhandling.SemanticParserException; /** * A test case that use a FURCAS mapping specification (".tcs" file) and based on this produce lexer and * parser, then parse a text resource and register all reference resolving callbacks. Then, the test * manipulates the model produced by the parser run and observes how OCL-based property assignments get re-assigned. * * This specific test class deals with "when" clauses of "foreach" property initializations. Model changes * may affect the "foreach" expression itself or any of the "when" clauses. The test also manifests the * behavior of no matching when-clauses with no default clause. * * @author Axel Uhl (D043530) * */ public class TestPropertyInitReEvaluationWithForeachWithWhen extends AbstractReferenceResolvingTest { private static final String LANGUAGE = "BibtexWithForeachWithWhen"; private static final File TCS = new File("fixtures/BibtexWithForeachWithWhen.tcs"); private static final File[] METAMODELS = { ScenarioFixtureData.BIBTEXT_METAMODEL, ScenarioFixtureData.BIBTEXT1_METAMODEL }; private EObject johnDoe; private EObject janeDoll; private List<EObject> articles; private EClass authorClass; private EClass articleClass; @BeforeClass public static void setupParser() throws Exception { setupParser(LANGUAGE, TCS, METAMODELS); } /** * Tests whether an simple addition to a textblock is correctly mapped to an insertion in the model without * re-creating the parent element. * * @throws Exception */ @Before public void setupInitialModel() throws SemanticParserException { String textToParse = "article{ Shrt, \"John Doe\"}" + "article{ Medium, \"John Doe\"}" + "article{ LongLongLong, \"Jane Doll\"}" + "author = \"John Doe\"." + "author = \"Jane Doll\"."; setupModelFromTextToParse(textToParse); johnDoe = null; articles = new ArrayList<EObject>(3); authorClass = null; articleClass = null; assertNotNull(rootElement); EClass bibTexFileClass = rootElement.eClass(); assertEquals("BibTextFile", bibTexFileClass.getName()); @SuppressWarnings("unchecked") Collection<EObject> entries = (Collection<EObject>) rootElement.eGet(bibTexFileClass .getEStructuralFeature("entries")); for (EObject entry : entries) { if (entry.eClass().getName().equals("Author")) { authorClass = entry.eClass(); if (entry.eGet(authorClass.getEStructuralFeature("name")).equals("John Doe")) { johnDoe = entry; } else if (entry.eGet(authorClass.getEStructuralFeature("name")).equals("Jane Doll")) { janeDoll = entry; } } else if (entry.eClass().getName().equals("Article")) { articleClass = entry.eClass(); articles.add(entry); } } } @Test public void testInitialModel() { assertNotNull(rootElement); EList<?> entries = (EList<?>) (rootElement).eGet((rootElement).eClass().getEStructuralFeature("entries")); assertEquals(5, entries.size()); assertEquals(3, articles.size()); assertNotNull(johnDoe); assertFalse(((Collection<?>) johnDoe.eGet(authorClass.getEStructuralFeature("revenues"))).isEmpty()); assertEquals(((Collection<?>) johnDoe.eGet(authorClass.getEStructuralFeature("articles"))).size(), ((Collection<?>) johnDoe.eGet(authorClass.getEStructuralFeature("revenues"))).size()); assertEquals(2, ((Collection<?>) johnDoe.eGet(authorClass.getEStructuralFeature("revenues"))).size()); assertNotNull(janeDoll); // Jane shouldn't have any revenues because her article's key is too long assertTrue(((Collection<?>) janeDoll.eGet(authorClass.getEStructuralFeature("revenues"))).isEmpty()); // now check the reference was set using the right property name for (EObject article : articles) { assertNotNull(article.eGet(articleClass.getEStructuralFeature("author"))); } for (EObject author : new EObject[] { johnDoe, janeDoll }) { @SuppressWarnings("unchecked") Collection<EObject> revenues = (Collection<EObject>) author.eGet(authorClass.getEStructuralFeature("revenues")); for (EObject revenue : revenues) { EObject articleOfRevenue = (EObject) revenue.eGet(revenue.eClass().getEStructuralFeature("article")); String articleName = (String) articleOfRevenue.eGet(articleClass.getEStructuralFeature("key")); assertEquals((articleName.length()<5 ? 1 : articleName.length()<10?2:3)*articleName.length(), revenue.eGet(revenue.eClass().getEStructuralFeature("revenueInEUR"))); } } } /** * By changing an article's "key" the article now matches a when-clause and should produce a revenue * element for Jane. */ @Test public void testChangeArticleNameFromNoClauseToWhenClause() { testInitialModel(); // just to make sure that for this particular test case evaluation the model is correct, too for (EObject article : articles) { if (article.eGet(articleClass.getEStructuralFeature("key")).equals("LongLongLong")) { String newArticleName = "Long"; article.eSet(articleClass.getEStructuralFeature("key"), newArticleName); // testInitialModel(); // test if everything is still alright after the change EObject author = (EObject) article.eGet(articleClass.getEStructuralFeature("author")); assertEquals("Expected Jane to have authored the article with the long key", janeDoll, author); @SuppressWarnings("unchecked") Collection<EObject> revenues = (Collection<EObject>) author.eGet(authorClass.getEStructuralFeature("revenues")); assertEquals(1, revenues.size()); boolean found = false; for (EObject revenue : revenues) { EObject articleOfRevenue = (EObject) revenue.eGet(revenue.eClass().getEStructuralFeature("article")); if (articleOfRevenue == article) { // We clearly had the case that the testInitialModel() call above succeeded but the following // assertion failed. This makes it likely that the article.eSet call above cause a model change // which can only have resulted from an event handler that reacted to the change assertEquals(newArticleName.length(), revenue.eGet(revenue.eClass().getEStructuralFeature("revenueInEUR"))); found = true; } } assertTrue(found); } } } /** * By changing an article's "key" the article now no longer matches a when-clause and should cause * the corresponding RevenueLedger object to be removed from author "John" */ @Test public void testChangeArticleNameFromWhenClauseToNoClause() { testInitialModel(); // just to make sure that for this particular test case evaluation the model is correct, too for (EObject article : articles) { if (article.eGet(articleClass.getEStructuralFeature("key")).equals("Shrt")) { String newArticleName = "NotSoShortAnymore"; article.eSet(articleClass.getEStructuralFeature("key"), newArticleName); // testInitialModel(); // test if everything is still alright after the change EObject author = (EObject) article.eGet(articleClass.getEStructuralFeature("author")); assertEquals("Expected John to have authored the article with the Shrt key", johnDoe, author); @SuppressWarnings("unchecked") Collection<EObject> revenues = (Collection<EObject>) author.eGet(authorClass.getEStructuralFeature("revenues")); assertEquals(1, revenues.size()); boolean found = false; for (EObject revenue : revenues) { EObject articleOfRevenue = (EObject) revenue.eGet(revenue.eClass().getEStructuralFeature("article")); if (articleOfRevenue == article) { found = true; } } assertFalse(found); } } } /** * By changing an article's "key" the article now no longer matches a when-clause and should cause * the corresponding RevenueLedger object to be removed from author "John" */ @Test public void testAddArticleForJane() { testInitialModel(); // just to make sure that for this particular test case evaluation the model is correct, too EObject newArticle = articleClass.getEPackage().getEFactoryInstance().create(articleClass); String newArticleName = "NewMedium"; newArticle.eSet(articleClass.getEStructuralFeature("key"), newArticleName); @SuppressWarnings("unchecked") Collection<EObject> janesArticles = ((Collection<EObject>) janeDoll.eGet(authorClass .getEStructuralFeature("articles"))); janesArticles.add(newArticle); @SuppressWarnings("unchecked") Collection<EObject> revenues = (Collection<EObject>) janeDoll.eGet(authorClass.getEStructuralFeature("revenues")); assertEquals(1, revenues.size()); boolean found = false; for (EObject revenue : revenues) { EObject articleOfRevenue = (EObject) revenue.eGet(revenue.eClass().getEStructuralFeature("article")); if (articleOfRevenue == newArticle) { // We clearly had the case that the testInitialModel() call above succeeded but the following // assertion failed. This makes it likely that the article.eSet call above cause a model change // which can only have resulted from an event handler that reacted to the change assertEquals(2*newArticleName.length(), revenue.eGet(revenue.eClass().getEStructuralFeature("revenueInEUR"))); found = true; } } assertTrue(found); } }