Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
<dependency>
<groupId>io.jenkins.plugins</groupId>
<artifactId>prism-api</artifactId>
<version>1.30.0-701.vf8f8f1f3fd55</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@ private Object createFilteredView(final String link, final Run<?, ?> owner, fina
else {
var marker = asMarker(issue, labelProvider.getSourceCodeDescription(owner, issue), labelProvider.getSmallIconUrl());
try (var affectedFile = buildFolder.readFile(owner, issue.getFileName(), sourceEncoding)) {
return new SourceCodeViewModel(owner, issue.getBaseName(), affectedFile, marker);
return SourceCodeViewModel.create(owner, issue.getBaseName(), affectedFile, marker);
}
catch (IOException e) {
try (var fallback = new StringReader(
"%s%n%s".formatted(ExceptionUtils.getMessage(e), ExceptionUtils.getStackTrace(e)))) {
return new SourceCodeViewModel(owner, issue.getBaseName(), fallback, marker);
return SourceCodeViewModel.create(owner, issue.getBaseName(), fallback, marker);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package io.jenkins.plugins.analysis.core.model;

import org.junit.jupiter.api.Test;

import edu.hm.hafner.analysis.IssueBuilder;
import edu.hm.hafner.analysis.Report;

import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import hudson.model.Run;

import io.jenkins.plugins.analysis.core.testutil.IntegrationTestWithJenkinsPerSuite;
import io.jenkins.plugins.analysis.core.util.BuildFolderFacade;
import io.jenkins.plugins.prism.SourceCodeViewModel;
import io.jenkins.plugins.util.JenkinsFacade;

import static io.jenkins.plugins.analysis.core.testutil.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

/**
* Integration tests for {@link DetailFactory} source file reading functionality.
* These tests require a Jenkins instance because SourceCodeViewModel.create() checks permissions.
*
* @author Akash Manna
*/
class DetailFactorySourceFileITest extends IntegrationTestWithJenkinsPerSuite {
private static final Charset ENCODING = StandardCharsets.UTF_8;
private static final String AFFECTED_FILE_CONTENT = "public class Test { }";
private static final Report NEW_ISSUES = new Report();
private static final Report OUTSTANDING_ISSUES = new Report();
private static final Report FIXED_ISSUES = new Report();

/**
* Checks that the error message is shown if an affected file could not be read.
*/
@Test
void shouldShowExceptionMessageIfAffectedFileIsNotReadable() throws IOException {
JenkinsFacade jenkins = mock(JenkinsFacade.class);
BuildFolderFacade buildFolder = mock(BuildFolderFacade.class);
when(buildFolder.readFile(any(), anyString(), any())).thenThrow(new IOException("file error"));

var details = createDetails(jenkins, buildFolder, "a-file");

assertThat(details).isInstanceOfSatisfying(SourceCodeViewModel.class,
s -> assertThat(s.getSourceCode()).contains("IOException: file error"));
}

/**
* Checks that a link to a source returns a SourceDetail-View.
*/
@Test
void shouldReturnSourceDetailWhenCalledWithSourceLinkAndIssueNotInConsoleLog() throws IOException {
JenkinsFacade jenkins = mock(JenkinsFacade.class);
BuildFolderFacade buildFolder = mock(BuildFolderFacade.class);
when(buildFolder.readFile(any(), anyString(), any())).thenReturn(new StringReader(AFFECTED_FILE_CONTENT));

var details = createDetails(jenkins, buildFolder, "a-file");

assertThat(details).isInstanceOfSatisfying(SourceCodeViewModel.class,
s -> assertThat(s.getSourceCode()).contains(AFFECTED_FILE_CONTENT));
}

private Object createDetails(final JenkinsFacade jenkins, final BuildFolderFacade buildFolder,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private Object createDetails(final JenkinsFacade jenkins, final BuildFolderFacade buildFolder,
private Object createDetails(final BuildFolderFacade buildFolder,

final String fileName) {
try (var issueBuilder = new IssueBuilder()) {
var detailFactory = new DetailFactory(jenkins, buildFolder);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use new JenkinsFacade() since Jenkins is now running.


issueBuilder.setFileName(fileName);
var issue = issueBuilder.build();

var report = new Report();
report.add(issue);

var project = createFreeStyleProject();
buildSuccessfully(project);
Run<?, ?> run = project.getLastBuild();

return detailFactory.createTrendDetails("source." + issue.getId().toString(),
run, createAnalysisResult(), report, NEW_ISSUES, OUTSTANDING_ISSUES, FIXED_ISSUES, ENCODING,
createParent());
}
}

private AnalysisResult createAnalysisResult() {
AnalysisResult result = mock(AnalysisResult.class);
when(result.getErrorMessages()).thenReturn(org.eclipse.collections.impl.factory.Lists.immutable.empty());
when(result.getInfoMessages()).thenReturn(org.eclipse.collections.impl.factory.Lists.immutable.empty());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
when(result.getErrorMessages()).thenReturn(org.eclipse.collections.impl.factory.Lists.immutable.empty());
when(result.getInfoMessages()).thenReturn(org.eclipse.collections.impl.factory.Lists.immutable.empty());
when(result.getErrorMessages()).thenReturn(Lists.immutable.empty());
when(result.getInfoMessages()).thenReturn(Lists.immutable.empty());

return result;
}

private IssuesDetail createParent() {
IssuesDetail parent = mock(IssuesDetail.class);
StaticAnalysisLabelProvider labelProvider = mock(StaticAnalysisLabelProvider.class);
when(labelProvider.getName()).thenReturn("Test");
when(labelProvider.getSmallIconUrl()).thenReturn("/icon");
when(labelProvider.getLargeIconUrl()).thenReturn("/icon");
when(parent.getLabelProvider()).thenReturn(labelProvider);
return parent;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import edu.hm.hafner.analysis.Report;
import edu.hm.hafner.analysis.Severity;

import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
Expand All @@ -27,7 +25,6 @@
import io.jenkins.plugins.analysis.core.util.BuildFolderFacade;
import io.jenkins.plugins.analysis.core.util.ConsoleLogHandler;
import io.jenkins.plugins.bootstrap5.MessagesViewModel;
import io.jenkins.plugins.prism.SourceCodeViewModel;
import io.jenkins.plugins.util.JenkinsFacade;

import static io.jenkins.plugins.analysis.core.testutil.Assertions.*;
Expand Down Expand Up @@ -230,36 +227,6 @@ RUN, createResult(), report, NEW_ISSUES, OUTSTANDING_ISSUES, FIXED_ISSUES, ENCOD
}
}

/**
* Checks that the error message is shown if an affected file could not be read.
*/
@Test
void shouldShowExceptionMessageIfAffectedFileIsNotReadable() throws IOException {
JenkinsFacade jenkins = mock(JenkinsFacade.class);
BuildFolderFacade buildFolder = mock(BuildFolderFacade.class);
when(buildFolder.readFile(any(), anyString(), any())).thenThrow(new IOException("file error"));

var details = createDetails(jenkins, buildFolder, "a-file");

assertThat(details).isInstanceOfSatisfying(SourceCodeViewModel.class,
s -> assertThat(s.getSourceCode()).contains("IOException: file error"));
}

/**
* Checks that a to a source, returns a SourceDetail-View.
*/
@Test
void shouldReturnSourceDetailWhenCalledWithSourceLinkAndIssueNotInConsoleLog() throws IOException {
JenkinsFacade jenkins = mock(JenkinsFacade.class);
BuildFolderFacade buildFolder = mock(BuildFolderFacade.class);
when(buildFolder.readFile(any(), anyString(), any())).thenReturn(new StringReader(AFFECTED_FILE_CONTENT));

var details = createDetails(jenkins, buildFolder, "a-file");

assertThat(details).isInstanceOfSatisfying(SourceCodeViewModel.class,
s -> assertThat(s.getSourceCode()).contains(AFFECTED_FILE_CONTENT));
}

/**
* Checks that a link with a filter, that results to an non empty set, returns an IssueDetail-View that only
* contains filtered issues.
Expand Down Expand Up @@ -365,4 +332,4 @@ private static Report createReportWith(final int high, final int normal, final i
return issues;
}
}
}
}
Loading