Skip to content

Commit

Permalink
add better codecoverage (#134)
Browse files Browse the repository at this point in the history
* add better codecoverage
  • Loading branch information
tilalx authored Jun 29, 2024
1 parent 516f393 commit d2a358c
Show file tree
Hide file tree
Showing 10 changed files with 646 additions and 49 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<repositories>
Expand Down
39 changes: 21 additions & 18 deletions src/main/java/hudson/plugins/msbuild/MsBuildInstaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MsBuildInstaller extends ToolInstaller {

Expand Down Expand Up @@ -111,7 +113,7 @@ public FilePath performInstallation(ToolInstallation tool, Node node, TaskListen
return msBuildBinPath;
}
buildToolsInstallPath.mkdirs();
String url = ((DescriptorImpl) getDescriptor()).getUrlForVersion(selectedVersion);
String url = DescriptorImpl.getUrlForVersion(selectedVersion);
try {
URI uri = new URI(url);
log.getLogger().println("Downloading MSBuild version " + selectedVersion + " from " + url);
Expand Down Expand Up @@ -174,7 +176,7 @@ public FilePath performInstallation(ToolInstallation tool, Node node, TaskListen
*
* @throws IOException
*/
private static boolean isInstallerRunning(String processName) throws IOException {
public static boolean isInstallerRunning(String processName) throws IOException {
ProcessBuilder processBuilder = new ProcessBuilder("jps", "-l");
Process process = processBuilder.start();

Expand All @@ -197,7 +199,7 @@ private static boolean isInstallerRunning(String processName) throws IOException
*
* @return FilePath
*/
private static FilePath buildToolsInstallPath(Node node, String selectedVersion, String givenInstallPath) {
public static FilePath buildToolsInstallPath(Node node, String selectedVersion, String givenInstallPath) {
if (givenInstallPath != null) {
return new FilePath(node.getChannel(), givenInstallPath);
}
Expand All @@ -216,7 +218,7 @@ private static FilePath buildToolsInstallPath(Node node, String selectedVersion,
*
* @return FilePath
*/
private static FilePath msBuildBinPath(Node node, String selectedVersion, String givenInstallPath) {
public static FilePath msBuildBinPath(Node node, String selectedVersion, String givenInstallPath) {
if (givenInstallPath != null && !givenInstallPath.isEmpty()) {
return new FilePath(node.getChannel(), givenInstallPath).child("\\MSBuild\\Current\\Bin");
}
Expand All @@ -230,7 +232,7 @@ private static FilePath msBuildBinPath(Node node, String selectedVersion, String
*
* @return FilePath
*/
private static FilePath getVs_BuildToolsExePath(FilePath expected) {
public static FilePath getVs_BuildToolsExePath(FilePath expected) {
return expected.child("vs_BuildTools.exe");
}

Expand All @@ -241,14 +243,15 @@ private static FilePath getVs_BuildToolsExePath(FilePath expected) {
*
* @return String
*/
private static String extractInstallPath(String givenArguments) {
if (givenArguments != null && StringUtils.contains(givenArguments, "--installPath")) {
// Extract the existing installPath value
String[] args = givenArguments.split(" ");
for (int i = 0; i < args.length - 1; i++) {
if (args[i].equals("--installPath")) {
return args[i + 1];
}
public static String extractInstallPath(String givenArguments) {
if (givenArguments != null) {
// Use a regex to find the --installPath followed by a quoted string or a single word
Pattern pattern = Pattern.compile("--installPath\\s+\"([^\"]*)\"|--installPath\\s+(\\S+)");
Matcher matcher = pattern.matcher(givenArguments);

if (matcher.find()) {
// Check if the path is captured from a quoted string or a non-quoted string
return matcher.group(1) != null ? matcher.group(1) : matcher.group(2);
}
}
return null;
Expand All @@ -265,7 +268,7 @@ private static String extractInstallPath(String givenArguments) {
*
* @throws InterruptedException
*/
private boolean checkIfOsIsWindows(Node node) throws IOException, InterruptedException {
public static boolean checkIfOsIsWindows(Node node) throws IOException, InterruptedException {
Computer computer = node.toComputer();
if (computer != null) {
EnvVars envVars = computer.getEnvironment();
Expand Down Expand Up @@ -348,7 +351,7 @@ private static boolean runVs_BuildToolsExe(FilePath vs_BuildToolsExePath, String
*
* @throws InterruptedException
*/
private static boolean useConfigFile(String vsconfig, FilePath expected)
public static boolean useConfigFile(String vsconfig, FilePath expected)
throws IOException, InterruptedException {
if (vsconfig != null && !vsconfig.isEmpty()) {
FilePath vsConfigFile = expected.child(".vsconfig");
Expand Down Expand Up @@ -401,7 +404,7 @@ private static void logLastUpdated(FilePath expected) throws IOException, Interr
*
* @return boolean
*/
private static boolean needsUpdate(FilePath expected) {
public static boolean needsUpdate(FilePath expected) {
try {
FilePath needsModify = expected.child("config.json");
if (needsModify.exists()) {
Expand Down Expand Up @@ -454,7 +457,7 @@ private static void logNeedsModify(FilePath expected, Boolean updateValue)
*
* @throws InterruptedException
*/
private static boolean needsModify(FilePath expected) throws IOException, InterruptedException {
public static boolean needsModify(FilePath expected) throws IOException, InterruptedException {
FilePath needsModify = expected.child("config.json");
if (needsModify.exists()) {
JSONObject json = JSONObject.fromObject(needsModify.readToString());
Expand Down Expand Up @@ -518,7 +521,7 @@ public static final class DescriptorImpl extends ToolInstallerDescriptor<MsBuild
"https://aka.ms/vs/16/release/vs_buildtools.exe");
}

public String getUrlForVersion(String version) {
public static String getUrlForVersion(String version) {
return VERSION_URL_MAP.get(version);
}

Expand Down
42 changes: 42 additions & 0 deletions src/test/java/hudson/plugins/msbuild/MSBuildErrorNoteTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package hudson.plugins.msbuild;

import hudson.MarkupText;
import org.junit.jupiter.api.Test;

import java.util.regex.Matcher;

import static org.junit.jupiter.api.Assertions.*;

public class MSBuildErrorNoteTest {

@Test
public void testPatternMatchesErrorMessage() {
String errorMessage = "SomeFile.cs(123,45): error CS1234: Some error message";
Matcher matcher = MSBuildErrorNote.PATTERN.matcher(errorMessage);
assertTrue(matcher.matches(), "Pattern should match the error message format");

assertEquals("SomeFile.cs(123,45):", matcher.group(1).trim(), "Filename and position should match");
assertEquals("CS1234", matcher.group(2), "Error code should match");
assertEquals("CS", matcher.group(3), "Error code prefix should match");
assertEquals("Some error message", matcher.group(4), "Error message should match");
}

@Test
public void testAnnotateAddsMarkup() {
String errorMessage = "SomeFile.cs(123,45): error CS1234: Some error message";
MarkupText markupText = new MarkupText(errorMessage);
MSBuildErrorNote note = new MSBuildErrorNote();

note.annotate(null, markupText, 0);

assertEquals("<span class=error-inline>" + errorMessage + "</span>",
markupText.toString(true),
"The markup should be correctly applied");
}

@Test
public void testDescriptorDisplayName() {
MSBuildErrorNote.DescriptorImpl descriptor = new MSBuildErrorNote.DescriptorImpl();
assertEquals("MSBuild error", descriptor.getDisplayName(), "Display name should be 'MSBuild error'");
}
}
36 changes: 35 additions & 1 deletion src/test/java/hudson/plugins/msbuild/MsBuildBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.nio.charset.Charset;

/**
* @author Jonathan Zimmerman
*/
Expand Down Expand Up @@ -58,4 +60,36 @@ public void configRoundtrip() {
}
}

}
@Test
public void testValidCharset() {
// Assuming CHARSET_CODE_MAP is populated with UTF-8 -> 65001
Charset charset = Charset.forName("UTF-8");
int expectedCodePage = 65001;
int actualCodePage = MsBuildBuilder.getCodePageIdentifier(charset);
assertEquals("Code page should match expected for UTF-8", expectedCodePage, actualCodePage);
}

@Test
public void testInvalidCharset() {
// Assuming there's no entry in CHARSET_CODE_MAP for the provided charset
Charset charset = Charset.forName("ISO-8859-16");
int expectedCodePage = 0; // As per method's default case
int actualCodePage = MsBuildBuilder.getCodePageIdentifier(charset);
assertEquals("Code page for unrecognized charset should be 0", expectedCodePage, actualCodePage);
}

@Test(expected = NullPointerException.class)
public void testNullCharset() {
// This should throw NullPointerException as the charset is null
MsBuildBuilder.getCodePageIdentifier(null);
}

@Test
public void testCaseSensitivity() {
// Verify case insensitivity by testing an all-lowercase input
Charset charset = Charset.forName("utf-8");
int expectedCodePage = 65001;
int actualCodePage = MsBuildBuilder.getCodePageIdentifier(charset);
assertEquals("Code page should match expected regardless of case", expectedCodePage, actualCodePage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package hudson.plugins.msbuild;

import org.junit.Before;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;

import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

public class MsBuildConsoleAnnotatorTest {

private ByteArrayOutputStream out;
private MSBuildConsoleAnnotator annotator;

@Before
public void setUp() {
out = new ByteArrayOutputStream();
annotator = new MSBuildConsoleAnnotator(out, StandardCharsets.UTF_8);
}

@Test
public void testNumberOfWarnings() throws IOException {
String warningMessage = "C:\\path\\to\\file(10,20): warning CS1234: This is a warning message";
MockMSBuildWarningNote.PATTERN = Pattern.compile(".*warning.*");
annotator.eol(warningMessage.getBytes(StandardCharsets.UTF_8), warningMessage.length());

assertEquals(1, annotator.getNumberOfWarnings());
assertEquals(0, annotator.getNumberOfErrors());
}

@Test
public void testNumberOfErrors() throws IOException {
String errorMessage = "C:\\path\\to\\file(10,20): error CS1234: This is an error message";
MockMSBuildErrorNote.PATTERN = Pattern.compile(".*error.*");
annotator.eol(errorMessage.getBytes(StandardCharsets.UTF_8), errorMessage.length());

assertEquals(0, annotator.getNumberOfWarnings());
assertEquals(1, annotator.getNumberOfErrors());
}

@Test
public void testBothWarningsAndErrors() throws IOException {
String warningMessage = "C:\\path\\to\\file(10,20): warning CS1234: This is a warning message";
String errorMessage = "C:\\path\\to\\file(10,20): error CS1234: This is an error message";
MockMSBuildWarningNote.PATTERN = Pattern.compile(".*warning.*");
MockMSBuildErrorNote.PATTERN = Pattern.compile(".*error.*");

annotator.eol(warningMessage.getBytes(StandardCharsets.UTF_8), warningMessage.length());
annotator.eol(errorMessage.getBytes(StandardCharsets.UTF_8), errorMessage.length());

assertEquals(1, annotator.getNumberOfWarnings());
assertEquals(1, annotator.getNumberOfErrors());
}

@Test
public void testMultipleCloseCalls() throws IOException {
ByteArrayOutputStream mockOutputStream = new ByteArrayOutputStream();
MSBuildConsoleAnnotator annotator = new MSBuildConsoleAnnotator(mockOutputStream, StandardCharsets.UTF_8);

annotator.close();
try {
annotator.close(); // Trying to close again to see if it handles multiple closes gracefully
} catch (IOException e) {
fail("Should not throw an exception on multiple closes");
}
}

private static class MockMSBuildWarningNote extends MSBuildWarningNote {
@SuppressWarnings("unused")
static Pattern PATTERN = Pattern.compile(".*warning.*");
}

private static class MockMSBuildErrorNote extends MSBuildErrorNote {
@SuppressWarnings("unused")
static Pattern PATTERN = Pattern.compile(".*error.*");
}
}
71 changes: 71 additions & 0 deletions src/test/java/hudson/plugins/msbuild/MsBuildConsoleParserTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package hudson.plugins.msbuild;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

public class MsBuildConsoleParserTest {

private OutputStream mockOutputStream;
private MsBuildConsoleParser parser;

@BeforeEach
public void setUp() {
mockOutputStream = mock(OutputStream.class);
parser = new MsBuildConsoleParser(mockOutputStream, StandardCharsets.UTF_8);
}

@Test
public void testGetNumberOfWarnings() throws Exception {
String line = " 1 Warning(s)";
parser.eol(line.getBytes(StandardCharsets.UTF_8), line.length());

assertEquals(1, parser.getNumberOfWarnings(), "Number of warnings should match");
}

@Test
public void testGetNumberOfErrors() throws Exception {
String line = " 1 Error(s)";
parser.eol(line.getBytes(StandardCharsets.UTF_8), line.length());

assertEquals(1, parser.getNumberOfErrors(), "Number of errors should match");
}

@Test
public void testGetNumberOfWarningsAndErrors() throws Exception {
String line1 = " 3 Warning(s)";
String line2 = " 5 Error(s)";
parser.eol(line1.getBytes(StandardCharsets.UTF_8), line1.length());
parser.eol(line2.getBytes(StandardCharsets.UTF_8), line2.length());

assertEquals(3, parser.getNumberOfWarnings(), "Number of warnings should match");
assertEquals(5, parser.getNumberOfErrors(), "Number of errors should match");
}

@Test
public void testInvalidWarningCount() throws Exception {
String line = " Warnings: not a number";
parser.eol(line.getBytes(StandardCharsets.UTF_8), line.length());

assertEquals(-1, parser.getNumberOfWarnings(), "Number of warnings should be -1");
}

@Test
public void testInvalidErrorCount() throws Exception {
String line = " Errors: not a number";
parser.eol(line.getBytes(StandardCharsets.UTF_8), line.length());

assertEquals(-1, parser.getNumberOfErrors(), "Number of errors should be -1");
}

@Test
public void testClose() throws Exception {
parser.close();
verify(mockOutputStream, times(1)).close();
}
}
Loading

0 comments on commit d2a358c

Please sign in to comment.