/* * SonarQube Java * Copyright (C) 2012-2016 SonarSource SA * mailto:contact AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonar.java.xml.maven; import org.junit.Before; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.sonar.java.AnalyzerMessage; import org.sonar.java.AnalyzerMessage.TextSpan; import org.sonar.java.SonarComponents; import org.sonar.java.xml.maven.PomCheckContext.Location; import org.sonar.maven.model.LocatedTree; import org.sonar.maven.model.LocatedTreeImpl; import org.sonar.maven.model.XmlLocation; import org.sonar.maven.model.maven2.MavenProject; import org.w3c.dom.Document; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathFactory; import java.io.File; import java.util.ArrayList; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; public class PomCheckContextImplTest { private static String reportedMessage; private PomCheckContext context; private static final PomCheck CHECK = new PomCheck() { @Override public void scanFile(PomCheckContext context) { } }; private static final int LINE = 42; @Before public void setup() { reportedMessage = null; SonarComponents sonarComponents = createSonarComponentsMock(); XPath xPath = XPathFactory.newInstance().newXPath(); context = new PomCheckContextImpl(mock(MavenProject.class), mock(Document.class), mock(File.class), xPath, sonarComponents); } @Test public void getMavenProject() { assertThat(context.getMavenProject()).isNotNull(); } @Test public void should_report_issue_on_line() { context.reportIssue(CHECK, LINE, "message"); assertThat(reportedMessage).isEqualTo("onLine:message"); } @Test public void should_report_issue_on_tree() { context.reportIssue(CHECK, fakeLocatedTreeWithUnknownColumn(LINE), "message"); assertThat(reportedMessage).isEqualTo("onLine:message"); } @Test public void should_report_issue_on_file() { context.reportIssueOnFile(CHECK, "message"); assertThat(reportedMessage).isEqualTo("onFile:message"); } @Test public void should_report_issue_on_no_locations() { context.reportIssue(CHECK, LINE, "message", new ArrayList<Location>()); assertThat(reportedMessage).isEqualTo("analyzerMessage:message"); } @Test public void should_report_issue_on_lines_of_all_locations() { ArrayList<Location> secondaries = new ArrayList<Location>(); // secondary on located tree int secondary1Line = 42; int secondary1Column = 3; int secondary1Size = 5; String msg1 = "msg1"; secondaries.add(new Location(msg1, fakeLocatedTree(secondary1Line, secondary1Column, secondary1Size))); // secondary on located tree with unknown column int secondary2Line = 43; String msg2 = "msg2"; secondaries.add(new Location(msg2, fakeLocatedTreeWithUnknownColumn(secondary2Line))); String msg = "message"; context.reportIssue(CHECK, LINE, msg, secondaries); String expected = "analyzerMessage:" + msg; expected += ";" + msg1 + "[" + secondary1Line + ";" + (secondary1Column - 1) + "/" + secondary1Line + ";" + (secondary1Column + secondary1Size - 1) + "]"; expected += ";" + msg2 + "[" + secondary2Line + ";0/" + secondary2Line + ";0]"; assertThat(reportedMessage).isEqualTo(expected); } private static SonarComponents createSonarComponentsMock() { SonarComponents sonarComponents = mock(SonarComponents.class); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { reportedMessage = "onLine:" + invocation.getArguments()[3]; return null; } }).when(sonarComponents).addIssue(any(File.class), eq(CHECK), eq(LINE), anyString(), eq(null)); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { reportedMessage = "onFile:" + invocation.getArguments()[3]; return null; } }).when(sonarComponents).addIssue(any(File.class), eq(CHECK), eq(-1), anyString(), eq(null)); doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { AnalyzerMessage analyzerMessage = (AnalyzerMessage) invocation.getArguments()[0]; reportedMessage = "analyzerMessage:" + analyzerMessage.getMessage(); for (AnalyzerMessage secondary : analyzerMessage.flows.stream().map(l -> l.get(0)).collect(Collectors.toList())) { TextSpan location = secondary.primaryLocation(); reportedMessage += ";" + secondary.getMessage() + "[" + location.startLine + ";" + location.startCharacter + "/" + location.endLine + ";" + location.endCharacter + "]"; } return null; } }).when(sonarComponents).reportIssue(any(AnalyzerMessage.class)); return sonarComponents; } private static LocatedTree fakeLocatedTreeWithUnknownColumn(int line) { LocatedTreeImpl tree = new LocatedTreeImpl() { }; tree.setStartLocation(new XmlLocation(line, 0)); tree.setEndLocation(new XmlLocation(line, 0)); return tree; } private static LocatedTree fakeLocatedTree(int line, int column, int size) { LocatedTreeImpl tree = new LocatedTreeImpl() { }; tree.setStartLocation(new XmlLocation(line, column, 0)); tree.setEndLocation(new XmlLocation(line, column + size, size)); return tree; } }