/* * Copyright 2016 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.rf.ide.core.testdata.mapping; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import java.io.File; import java.util.List; import org.junit.Test; import org.mockito.InOrder; import org.rf.ide.core.testdata.RobotParser; import org.rf.ide.core.testdata.RobotParser.RobotParserConfig; import org.rf.ide.core.testdata.mapping.TwoModelReferencesLinker.DifferentOutputFile; import org.rf.ide.core.testdata.mapping.collect.RobotTokensCollector; import org.rf.ide.core.testdata.model.RobotFileOutput; import org.rf.ide.core.testdata.model.RobotProjectHolder; import org.rf.ide.core.testdata.text.read.IRobotLineElement; import org.rf.ide.core.testdata.text.read.RobotLine; import org.rf.ide.core.testdata.text.read.recognizer.RobotToken; import org.rf.ide.core.testdata.text.read.recognizer.RobotTokenType; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; /** * @author wypych */ public class FileOutputsMatchUpdaterTest { @Test public void test_replaceNewReferenceByCorrespondingOld_checkReferenceUpdate() { // prepare final String fContentOld = "*** Settings ***\nLibrary\tnowy\tok\t#bad"; final String fContentNew = "*** Settings ***\nLibrary\tnowy2\tok2\t#bad2"; final RobotProjectHolder holder = new RobotProjectHolder(); final RobotParser parser = RobotParser.create(holder, RobotParserConfig.allImportsLazy()); final RobotFileOutput oldContent = parser.parseEditorContent(fContentOld, new File("fake.txt")); final RobotFileOutput newContent = parser.parseEditorContent(fContentNew, new File("fake.txt")); final RobotTokensCollector robotTokensCollector = new RobotTokensCollector(); final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokens = robotTokensCollector .extractRobotTokens(oldContent); final ListMultimap<RobotTokenType, RobotToken> newViewAboutTokens = robotTokensCollector .extractRobotTokens(newContent); // execute new TwoModelReferencesLinker().replaceNewReferenceByCorrespondingOld(oldContent, oldViewAboutTokens, newContent, newViewAboutTokens); // verify assertOutputsUpdated(oldContent, oldViewAboutTokens, newContent); assertLinesContainsOnlyExpectedTokens(oldContent, oldViewAboutTokens, newContent); } private void assertOutputsUpdated(final RobotFileOutput oldContent, final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokensPrev, final RobotFileOutput newContent) { final RobotTokensCollector robotTokensCollector = new RobotTokensCollector(); final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokens = robotTokensCollector .extractRobotTokens(oldContent); final ListMultimap<RobotTokenType, RobotToken> newViewAboutTokens = robotTokensCollector .extractRobotTokens(newContent); assertThat(oldViewAboutTokens.keySet()).containsOnlyElementsOf(newViewAboutTokens.keySet()); for (final RobotTokenType type : oldViewAboutTokens.keySet()) { final List<RobotToken> oldOutputForType = oldViewAboutTokens.get(type); final List<RobotToken> newOutputForType = newViewAboutTokens.get(type); assertThat(oldOutputForType.size()).isEqualTo(newOutputForType.size()); for (int index = 0; index < oldOutputForType.size(); index++) { assertThat(oldOutputForType.get(index)).isSameAs(oldViewAboutTokensPrev.get(type).get(index)); assertThat(oldOutputForType.get(index).getText()).isEqualTo(newOutputForType.get(index).getText()); assertThat(oldOutputForType.get(index) .getFilePosition() .isSamePlace(newOutputForType.get(index).getFilePosition())).isTrue(); } } } private void assertLinesContainsOnlyExpectedTokens(final RobotFileOutput oldContent, final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokens, final RobotFileOutput newContent) { final List<RobotLine> oldContentRL = oldContent.getFileModel().getFileContent(); final List<RobotLine> newContentRL = newContent.getFileModel().getFileContent(); assertThat(oldContentRL.size()).isEqualTo(newContentRL.size()); for (final RobotLine rl : oldContentRL) { final List<IRobotLineElement> lineElements = rl.getLineElements(); final RobotLine newRobotLine = newContentRL.get(rl.getLineNumber() - 1); final List<IRobotLineElement> newLineElements = newRobotLine.getLineElements(); assertThat(newRobotLine).isSameAs(rl); final int size = lineElements.size(); for (int i = 0; i < size; i++) { final IRobotLineElement elem = lineElements.get(i); if (elem instanceof RobotToken) { assertThat(findIfExistsToken(oldViewAboutTokens, (RobotToken) elem)).isNotNull(); } else { assertThat(newLineElements.get(i)).isSameAs(elem); } } } } private RobotToken findIfExistsToken(final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokens, final RobotToken tok) { RobotToken found = null; final List<RobotToken> list = oldViewAboutTokens.get((RobotTokenType) tok.getTypes().get(0)); for (final RobotToken robotToken : list) { if (robotToken == tok) { found = robotToken; } } return found; } @Test(expected = DifferentOutputFile.class) public void test_validateThatTheSameTokensInView_areNotTheSame_oneType_differentSize_butLastIsNotEmptyInOldAndMissingInNew() { // prepare final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokens = ArrayListMultimap.create(); final RobotTokenType typeOne = RobotTokenType.KEYWORD_ACTION_ARGUMENT; oldViewAboutTokens.put(typeOne, RobotToken.create("ok")); oldViewAboutTokens.put(typeOne, RobotToken.create("ok2")); oldViewAboutTokens.put(typeOne, RobotToken.create("c")); final ListMultimap<RobotTokenType, RobotToken> newViewAboutTokens = ArrayListMultimap.create(); newViewAboutTokens.put(typeOne, RobotToken.create("ok")); newViewAboutTokens.put(typeOne, RobotToken.create("ok2")); // execute & verify new TwoModelReferencesLinker().validateThatTheSameTokensInView(oldViewAboutTokens, newViewAboutTokens); } @Test public void test_validateThatTheSameTokensInView_areTheSame_oneType_differentSize_butWithEmptyTextInTheEndOfOld() { // prepare final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokens = ArrayListMultimap.create(); final RobotTokenType typeOne = RobotTokenType.KEYWORD_ACTION_ARGUMENT; oldViewAboutTokens.put(typeOne, RobotToken.create("ok")); oldViewAboutTokens.put(typeOne, RobotToken.create("ok2")); //// empties oldViewAboutTokens.put(typeOne, RobotToken.create("")); oldViewAboutTokens.put(typeOne, RobotToken.create("")); oldViewAboutTokens.put(typeOne, RobotToken.create("")); final ListMultimap<RobotTokenType, RobotToken> newViewAboutTokens = ArrayListMultimap.create(); newViewAboutTokens.put(typeOne, RobotToken.create("ok")); newViewAboutTokens.put(typeOne, RobotToken.create("ok2")); // execute & verify new TwoModelReferencesLinker().validateThatTheSameTokensInView(oldViewAboutTokens, newViewAboutTokens); } @Test public void test_validateThatTheSameTokensInView_areTheSame_oneType_sameSize_butWithEmptyText() { // prepare final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokens = ArrayListMultimap.create(); final RobotTokenType typeOne = RobotTokenType.KEYWORD_ACTION_ARGUMENT; oldViewAboutTokens.put(typeOne, RobotToken.create("ok")); oldViewAboutTokens.put(typeOne, RobotToken.create("ok2")); oldViewAboutTokens.put(typeOne, RobotToken.create("")); oldViewAboutTokens.put(typeOne, RobotToken.create("d")); final ListMultimap<RobotTokenType, RobotToken> newViewAboutTokens = ArrayListMultimap.create(); newViewAboutTokens.put(typeOne, RobotToken.create("ok")); newViewAboutTokens.put(typeOne, RobotToken.create("ok2")); newViewAboutTokens.put(typeOne, RobotToken.create("\\")); newViewAboutTokens.put(typeOne, RobotToken.create("d")); // execute & verify new TwoModelReferencesLinker().validateThatTheSameTokensInView(oldViewAboutTokens, newViewAboutTokens); } @Test public void test_validateThatTheSameTokensInView_areTheSame_oneType_sameSize_andText() { // prepare final ListMultimap<RobotTokenType, RobotToken> oldViewAboutTokens = ArrayListMultimap.create(); final RobotTokenType typeOne = RobotTokenType.KEYWORD_ACTION_ARGUMENT; oldViewAboutTokens.put(typeOne, RobotToken.create("ok")); oldViewAboutTokens.put(typeOne, RobotToken.create("ok2")); oldViewAboutTokens.put(typeOne, RobotToken.create("ok3")); final ListMultimap<RobotTokenType, RobotToken> newViewAboutTokens = ArrayListMultimap.create(); newViewAboutTokens.put(typeOne, RobotToken.create("ok")); newViewAboutTokens.put(typeOne, RobotToken.create("ok2")); newViewAboutTokens.put(typeOne, RobotToken.create("ok3")); // execute & verify new TwoModelReferencesLinker().validateThatTheSameTokensInView(oldViewAboutTokens, newViewAboutTokens); } @Test public void test_validateBasicThatOutputFromSameFile_areTheSameFiles() { // prepare final RobotFileOutput oldModifiedOutput = mock(RobotFileOutput.class); final File fOldModified = new File("old.txt"); when(oldModifiedOutput.getProcessedFile()).thenReturn(fOldModified); final RobotFileOutput newOutput = mock(RobotFileOutput.class); final File fNew = new File("old.txt"); when(newOutput.getProcessedFile()).thenReturn(fNew); // execute && verify new TwoModelReferencesLinker().validateBasicThatOutputFromSameFile(oldModifiedOutput, newOutput); } @Test(expected = DifferentOutputFile.class) public void test_validateBasicThatOutputFromSameFile_notTheSameFiles() { // prepare final RobotFileOutput oldModifiedOutput = mock(RobotFileOutput.class); final File fOldModified = new File("old.txt"); when(oldModifiedOutput.getProcessedFile()).thenReturn(fOldModified); final RobotFileOutput newOutput = mock(RobotFileOutput.class); final File fNew = new File("old2.txt"); when(newOutput.getProcessedFile()).thenReturn(fNew); // execute & verify new TwoModelReferencesLinker().validateBasicThatOutputFromSameFile(oldModifiedOutput, newOutput); } @Test public void test_update_fallbackAllowedMethod_logicCheck() { assertExecutionLogic(true); } @Test public void test_update_fallbackNotAllowedMethod_logicCheck() { assertExecutionLogic(false); } private void assertExecutionLogic(final boolean fallbackAllowed) { // prepare final RobotFileOutput oldModifiedOutput = mock(RobotFileOutput.class); final RobotFileOutput alreadyDumpedContent = mock(RobotFileOutput.class); final RobotTokensCollector collector = mock(RobotTokensCollector.class); final ListMultimap<RobotTokenType, RobotToken> oldView = ArrayListMultimap.create(); when(collector.extractRobotTokens(oldModifiedOutput)).thenReturn(oldView); final ListMultimap<RobotTokenType, RobotToken> newView = ArrayListMultimap.create(); when(collector.extractRobotTokens(alreadyDumpedContent)).thenReturn(newView); final TwoModelReferencesLinker tested = spy(new TwoModelReferencesLinker(collector)); doNothing().when(tested).validateBasicThatOutputFromSameFile(oldModifiedOutput, alreadyDumpedContent); doNothing().when(tested).replaceNewReferenceByCorrespondingOld(oldModifiedOutput, oldView, alreadyDumpedContent, newView); // execute if (fallbackAllowed) { tested.update(oldModifiedOutput, alreadyDumpedContent); } else { tested.update(oldModifiedOutput, alreadyDumpedContent, false); } // verify final InOrder order = inOrder(tested, collector); if (fallbackAllowed) { order.verify(tested, times(1)).update(oldModifiedOutput, alreadyDumpedContent, true); } order.verify(tested, times(1)).validateBasicThatOutputFromSameFile(oldModifiedOutput, alreadyDumpedContent); order.verify(collector, times(1)).extractRobotTokens(oldModifiedOutput); order.verify(collector, times(1)).extractRobotTokens(alreadyDumpedContent); if (fallbackAllowed) { order.verify(tested, times(1)).validateThatTheSameTokensInView(oldView, newView); } order.verify(tested, times(1)).replaceNewReferenceByCorrespondingOld(oldModifiedOutput, oldView, alreadyDumpedContent, newView); order.verifyNoMoreInteractions(); } }