package com.sap.furcas.runtime.parser.textblocks.observer; import static org.junit.Assert.assertEquals; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; import org.junit.Before; import org.junit.Test; import com.sap.furcas.metamodel.FURCAS.TCS.ConcreteSyntax; import com.sap.furcas.metamodel.FURCAS.textblocks.LexedToken; import com.sap.furcas.metamodel.FURCAS.textblocks.TextBlock; import com.sap.furcas.parser.tcs.TCSParserFactory; import com.sap.furcas.runtime.parser.PartitionAssignmentHandler; import com.sap.furcas.runtime.parser.antlr3.ANTLR3LocationTokenImpl; import com.sap.furcas.runtime.parser.impl.ParserScope; import com.sap.furcas.runtime.parser.testbase.MockPartitionAssignmentHandler; import com.sap.furcas.runtime.tcs.TcsUtil; import com.sap.furcas.runtime.textblocks.testbase.TextBlockTest; import com.sap.furcas.runtime.textblocks.testbase.TextblocksTestHelper; import com.sap.furcas.runtime.textblocks.testutils.TestSourceTextBlockCreator; public class TestTextBlocksObserver extends TextBlockTest { private URI templateURI; private Resource resource; private TokenStreamMock tokenStreamMock; private ParserTextBlocksHandler observer; @Before public void init() { resource = TextblocksTestHelper.createTransientResource(); ResourceSet resourceSet = resource.getResourceSet(); tokenStreamMock = new TokenStreamMock(); TCSParserFactory factory = new TCSParserFactory(); ParserScope parserScope = new ParserScope(resourceSet, factory); PartitionAssignmentHandler partitioningHandler = new MockPartitionAssignmentHandler(resource); observer = new ParserTextBlocksHandler(tokenStreamMock, parserScope, partitioningHandler); ConcreteSyntax tcsSyntax = (ConcreteSyntax) resourceSet.getEObject(URI.createURI(factory.getSyntaxUUID()), /*load*/true); templateURI = EcoreUtil.getURI(TcsUtil.getMainClassTemplate(tcsSyntax)); } @Test public void testEnterExitRuleNullTokens() { // should leave the textblock as it is. TextBlock root = modelFactory.createTextBlock(); observer.setRootBlock(root); observer.notifyEnterRule(templateURI.toString()); observer.notifyExitRule(); // assert no exception occured } @Test public void testEnterExitRuleNoTokenMove() { // should leave the textblock as it is. LexedToken contentToken = createToken("test"); tokenStreamMock.nextToken = contentToken; // token is already in root block, so it should not get moved TextBlock root = TestSourceTextBlockCreator.initialiseTextBlocksWithContentToken(modelFactory, contentToken); observer.setRootBlock(root); observer.notifyEnterRule(templateURI.toString()); observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root blcok observer.notifyExitRule(); assertEquals(1,observer.getCurrentTbProxy().getSubNodes().size()); assertEquals(contentToken, observer.getCurrentTbProxy().getSubNodes().get(0)); } @Test public void testEnterExitRuleTokenMove() { LexedToken contentToken = createToken("test"); tokenStreamMock.nextToken = contentToken; TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS observer.setRootBlock(root); observer.notifyEnterRule(templateURI.toString()); observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root blcok observer.notifyExitRule(); // assert token was added to root assertEquals(1, observer.getCurrentTbProxy().getSubNodes().size()); assertEquals(contentToken, observer.getCurrentTbProxy().getSubNodes().get(0)); } @Test public void testNewSubBlocks() throws Exception { TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS observer.setRootBlock(root); LexedToken token1 = createToken("test"); tokenStreamMock.nextToken = token1; observer.notifyEnterRule(templateURI.toString()); observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root block LexedToken token2 = createToken("test2"); token2.setOffset(4); tokenStreamMock.nextToken = token2; observer.notifyEnterRule(templateURI.toString()); observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token2 to sub block observer.notifyExitRule(); LexedToken token3 = createToken("test3"); token3.setOffset(9); tokenStreamMock.nextToken = token3; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token3 to root block observer.notifyExitRule(); // assert token was added to root assertEquals(3, observer.getCurrentTbProxy().getSubNodes().size()); assertEquals(token1, observer.getCurrentTbProxy().getSubNodes().get(0)); assertEquals(token3, observer.getCurrentTbProxy().getSubNodes().get(2)); TextBlockProxy newBlock = (TextBlockProxy) observer.getCurrentTbProxy().getSubNodes().get(1); assertEquals(1, newBlock.getSubNodes().size()); assertEquals(token2, newBlock.getSubNodes().get(0)); } @Test public void testExistingSubBlocks() throws Exception { TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS TextBlock subBlock = modelFactory.createTextBlock(); subBlock.setParent(root); // first subnode observer.setRootBlock(root); LexedToken token1 = createToken("test"); tokenStreamMock.nextToken = token1; observer.notifyEnterRule(templateURI.toString()); observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root block LexedToken token2 = createToken("test2"); token2.setOffset(4); tokenStreamMock.nextToken = token2; observer.notifyEnterRule(templateURI.toString()); observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test2")); // should add token2 to sub block observer.notifyExitRule(); LexedToken token3 = createToken("test3"); token3.setOffset(9); tokenStreamMock.nextToken = token3; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test3")); // should add token3 to root block observer.notifyExitRule(); // assert token was added to root assertEquals(3, observer.getCurrentTbProxy().getSubNodes().size()); assertEquals(token1, observer.getCurrentTbProxy().getSubNodes().get(0)); assertEquals(token3, observer.getCurrentTbProxy().getSubNodes().get(2)); TextBlockProxy subBlockProxy = (TextBlockProxy) observer.getCurrentTbProxy().getSubNodes().get(1); // assertEquals(subBlock, observer.getCurrentTbProxy().getSubNodes().get(0)); assertEquals(1, subBlockProxy.getSubNodes().size()); assertEquals(token2, subBlockProxy.getSubNodes().get(0)); } @Test public void testEnterExitRuleTokenMoveWithOffChannelsTokens() throws Exception { LexedToken ocToken1 = createToken("tab"); LexedToken ocToken2 = createToken("blank"); ocToken2.setOffset(3); tokenStreamMock.offChannelTokens.add(ocToken1); tokenStreamMock.offChannelTokens.add(ocToken2); LexedToken contentToken = createToken("test"); contentToken.setOffset(8); tokenStreamMock.nextToken = contentToken; TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS observer.setRootBlock(root); observer.notifyEnterRule(templateURI.toString()); observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root blcok observer.notifyExitRule(); // assert token was added to root assertEquals(3, observer.getCurrentTbProxy().getSubNodes().size()); // (oc1, oc2, contentToken) expected assertEquals(ocToken1, observer.getCurrentTbProxy().getSubNodes().get(0)); assertEquals(ocToken2, observer.getCurrentTbProxy().getSubNodes().get(1)); assertEquals(contentToken, observer.getCurrentTbProxy().getSubNodes().get(2)); } @Test public void testMoveTokensToSubBlock() throws Exception { TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS root.setLength(14); TextBlock subBlock = modelFactory.createTextBlock(); subBlock.setParent(root); // first subnode observer.setRootBlock(root); LexedToken token1 = createToken("test"); token1.setParent(root); LexedToken token2 = createToken("test2"); token2.setOffset(4); token2.setParent(root); LexedToken token3 = createToken("test3"); token3.setOffset(9); token3.setParent(root); observer.notifyEnterRule(templateURI.toString()); // enter root observer.notifyEnterRule(templateURI.toString()); // enter sub tokenStreamMock.nextToken = token1; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to sub block tokenStreamMock.nextToken = token2; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token2 to sub block tokenStreamMock.nextToken = token3; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token3 to sub block observer.notifyExitRule(); observer.notifyExitRule(); // assert tokens were moved from root to sub assertEquals(1, observer.getCurrentTbProxy().getSubNodes().size()); TextBlockProxy subBlockProxy = (TextBlockProxy) observer.getCurrentTbProxy().getSubNodes().get(0); assertEquals(3, subBlockProxy.getSubNodes().size()); assertEquals(token1, subBlockProxy.getSubNodes().get(0)); assertEquals(token2, subBlockProxy.getSubNodes().get(1)); assertEquals(token3, subBlockProxy.getSubNodes().get(2)); } @Test public void testMoveTokensToRoot() throws Exception { TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS TextBlock subBlock = modelFactory.createTextBlock(); subBlock.setParent(root); // first subnode observer.setRootBlock(root); LexedToken token1 = createToken("test"); token1.setParent(subBlock); LexedToken token2 = createToken("test2"); token2.setOffset(4); token2.setParent(subBlock); LexedToken token3 = createToken("test3"); token3.setOffset(9); token3.setParent(subBlock); observer.notifyEnterRule(templateURI.toString()); // enter root tokenStreamMock.nextToken = token1; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root block tokenStreamMock.nextToken = token2; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token2 to root block tokenStreamMock.nextToken = token3; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token3 to root block observer.notifyExitRule(); // assert tokens were moved from root to sub assertEquals(3, observer.getCurrentTbProxy().getSubNodes().size()); assertEquals(token1, observer.getCurrentTbProxy().getSubNodes().get(0)); assertEquals(token2, observer.getCurrentTbProxy().getSubNodes().get(1)); assertEquals(token3, observer.getCurrentTbProxy().getSubNodes().get(2)); } @Test public void testMoveTokensToRootWithExisting() throws Exception { TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS TextBlock subBlock = modelFactory.createTextBlock(); subBlock.setLength(9); subBlock.setParent(root); // first subnode observer.setRootBlock(root); LexedToken token1 = createToken("test"); token1.setOffsetRelative(true); token1.setParent(subBlock); LexedToken token2 = createToken("test2"); token2.setOffsetRelative(true); token2.setOffset(4); token2.setParent(subBlock); LexedToken token3 = createToken("test3"); token3.setOffsetRelative(true); token3.setOffset(9); token3.setParent(root); // token already in root!! observer.notifyEnterRule(templateURI.toString()); // enter root tokenStreamMock.nextToken = token1; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root block tokenStreamMock.nextToken = token2; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token2 to root block tokenStreamMock.nextToken = token3; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token3 to root block observer.notifyExitRule(); // assert tokens were moved from root to sub assertEquals(3,observer.getCurrentTbProxy().getSubNodes().size()); assertEquals(token1, observer.getCurrentTbProxy().getSubNodes().get(0)); assertEquals(token2, observer.getCurrentTbProxy().getSubNodes().get(1)); assertEquals(token3, observer.getCurrentTbProxy().getSubNodes().get(2)); } @Test public void testMoveBetweenSubBlocks() throws Exception { TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS root.setLength(14); TextBlock subBlock1 = modelFactory.createTextBlock(); subBlock1.setParent(root); // first subnode subBlock1.setLength(14); TextBlock subBlock2 = modelFactory.createTextBlock(); subBlock2.setParent(root); // first subnode observer.setRootBlock(root); LexedToken token1 = createToken("test"); token1.setParent(subBlock1); LexedToken token2 = createToken("test2"); token2.setOffset(4); token2.setParent(subBlock1); LexedToken token3 = createToken("test3"); token3.setOffset(9); token3.setParent(subBlock1); observer.notifyEnterRule(templateURI.toString()); // enter root observer.notifyEnterRule(templateURI.toString()); // enter subBlock1 observer.notifyExitRule(); observer.notifyEnterRule(templateURI.toString()); // enter subBlock2 tokenStreamMock.nextToken = token1; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root block tokenStreamMock.nextToken = token2; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token2 to root block tokenStreamMock.nextToken = token3; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token3 to root block observer.notifyExitRule(); // exit subBlock2 observer.notifyExitRule(); // exit root // assert tokens were moved from root to sub and no empty textblock was created assertEquals(1,observer.getCurrentTbProxy().getSubNodes().size()); TextBlockProxy subBlock2Proxy = (TextBlockProxy) observer.getCurrentTbProxy().getSubNodes().get(0); assertEquals(token1, subBlock2Proxy.getSubNodes().get(0)); assertEquals(token2, subBlock2Proxy.getSubNodes().get(1)); assertEquals(token3, subBlock2Proxy.getSubNodes().get(2)); } @Test public void testMoveBetweenSubBlocksDeep() throws Exception { // special case to check parents get updated /* * start: * - root * -- subBlock1 * --- subSubBlock1 * ---- subSubSubBlock1 * ----- token1 * ----- token2 * ----- token3 * -- subBlock2 * --- subSubBlock2 * * End: * - root * -- subBlock1 * --- subSubBlock1 * ---- subSubSubBlock1 * ----- token1 * -- subBlock2 * --- subSubBlock2 * ---- token2 * ---- token3 */ TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS root.setLength(14); TextBlock subBlock1 = modelFactory.createTextBlock(); subBlock1.setParent(root); // first subnode subBlock1.setLength(14); TextBlock subSubBlock1 = modelFactory.createTextBlock(); subSubBlock1.setParent(subBlock1); subSubBlock1.setLength(14); TextBlock subSubSubBlock1 = modelFactory.createTextBlock(); subSubSubBlock1.setParent(subSubBlock1); subSubSubBlock1.setLength(14); TextBlock subBlock2 = modelFactory.createTextBlock(); subBlock2.setParent(root); // first subnode subBlock2.setOffset(14); TextBlock subSubBlock2 = modelFactory.createTextBlock(); subSubBlock2.setParent(subBlock2); // first subnode subSubBlock2.setOffset(14); observer.setRootBlock(root); LexedToken token1 = createToken("test"); token1.setParent(subSubSubBlock1); LexedToken token2 = createToken("test2"); token2.setOffset(4); token2.setParent(subSubSubBlock1); LexedToken token3 = createToken("test3"); token3.setOffset(9); token3.setParent(subSubSubBlock1); observer.notifyEnterRule(templateURI.toString()); // enter root observer.notifyEnterRule(templateURI.toString()); // enter subBlock1 observer.notifyEnterRule(templateURI.toString()); // enter subSubBlock1 observer.notifyEnterRule(templateURI.toString()); // enter subSubSubBlock1 tokenStreamMock.nextToken = token1; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root block observer.notifyExitRule(); // leave subSubSubBlock1 observer.notifyExitRule(); // leave subSubBlock1 observer.notifyExitRule(); // leave subBlock1 observer.notifyEnterRule(templateURI.toString()); // enter subBlock2 observer.notifyEnterRule(templateURI.toString()); // enter subSubBlock2 tokenStreamMock.nextToken = token2; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token2 to root block tokenStreamMock.nextToken = token3; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token2 to root block observer.notifyExitRule(); // exit subSubBlock2 observer.notifyExitRule(); // exit subBlock2 observer.notifyExitRule(); // exit root /* End: * - root * -- subBlock1 * --- subSubBlock1 * ---- subSubSubBlock1 * ----- token1 * -- subBlock2 * --- subSubBlock2 * ---- token2 * ---- token3 */ // assert tokens were moved from root to sub assertEquals(2, observer.getCurrentTbProxy().getSubNodes().size()); TextBlockProxy subBlockProxy1 = (TextBlockProxy) observer.getCurrentTbProxy().getSubNodes().get(0); TextBlockProxy subsubBloclProxy1 = (TextBlockProxy) subBlockProxy1.getSubNodes().get(0); TextBlockProxy subsubsubBlockProxy = (TextBlockProxy) subsubBloclProxy1.getSubNodes().get(0); TextBlockProxy subBlockProxy2 = (TextBlockProxy) observer.getCurrentTbProxy().getSubNodes().get(1); TextBlockProxy subsubBloclProxy2 = (TextBlockProxy) subBlockProxy2.getSubNodes().get(0); assertEquals(1, subsubsubBlockProxy.getSubNodes().size()); assertEquals(token1, subsubsubBlockProxy.getSubNodes().get(0)); assertEquals(2, subsubBloclProxy2.getSubNodes().size()); assertEquals(token2, subsubBloclProxy2.getSubNodes().get(0)); assertEquals(token3, subsubBloclProxy2.getSubNodes().get(1)); } @Test public void testOffChannelTokenAtBeginningOfSubblock() throws Exception { TextBlock root = modelFactory.createTextBlock(); // using emtpy block here, not block with BOS, EOS root.setLength(9); TextBlock subBlock1 = modelFactory.createTextBlock(); subBlock1.setParent(root); // first subnode subBlock1.setLength(5); observer.setRootBlock(root); LexedToken token1 = createToken("test"); token1.setParent(root); LexedToken space = createToken(" "); space.setOffset(4); space.setParent(root); LexedToken token2 = createToken("test2"); token2.setOffset(5); token2.setParent(subBlock1); observer.notifyEnterRule(templateURI.toString()); // enter root tokenStreamMock.nextToken = token1; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test")); // should add token1 to root block observer.notifyEnterRule(templateURI.toString()); // enter subBlock1 tokenStreamMock.offChannelTokens.add(space); tokenStreamMock.nextToken = token2; observer.notifyTokenConsume(new ANTLR3LocationTokenImpl(0, "test2")); // should add space and token2 to subblock observer.notifyExitRule(); observer.notifyExitRule(); // exit root assertEquals(2, observer.getCurrentTbProxy().getSubNodes().size()); TextBlockProxy subBlockProxy1 = (TextBlockProxy) observer.getCurrentTbProxy().getSubNodes().get(1); assertEquals(2, subBlockProxy1.getSubNodes().size()); //space should be moved to subblock } private LexedToken createToken(String string) { return modelFactory.createToken(string); } }