Skip to content

Commit 4a7ae3e

Browse files
authored
Proper ascii switching (#20)
* Proper ASCII switching * Small test cleanup * Try to fix recursed test * Adding default tests * WIP * 100% coverage for Defaults * WIP * WIP * Fixed test. * Fixed test for both utf8 and others. * Depend on OS * Fix tests * Fix last tests
1 parent c4caf1d commit 4a7ae3e

17 files changed

+466
-95
lines changed

jacoco-console-reporter/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@
100100
<groupId>org.mockito</groupId>
101101
<artifactId>mockito-core</artifactId>
102102
</dependency>
103+
104+
<dependency>
105+
<groupId>net.java.dev.jna</groupId>
106+
<artifactId>jna</artifactId>
107+
</dependency>
103108
</dependencies>
104109

105110
<build>
@@ -108,6 +113,10 @@
108113
<plugin>
109114
<groupId>org.apache.maven.plugins</groupId>
110115
<artifactId>maven-compiler-plugin</artifactId>
116+
<configuration>
117+
<source>11</source>
118+
<target>11</target>
119+
</configuration>
111120
</plugin>
112121

113122
<!-- CI -->
@@ -139,6 +148,7 @@
139148
<groupId>org.jacoco</groupId>
140149
<artifactId>jacoco-maven-plugin</artifactId>
141150
</plugin>
151+
142152
</plugins>
143153
</build>
144154

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package io.github.svaningelgem;
2+
3+
import com.sun.jna.Library;
4+
import com.sun.jna.Native;
5+
import org.jetbrains.annotations.NotNull;
6+
7+
import java.nio.charset.Charset;
8+
import java.nio.charset.StandardCharsets;
9+
10+
public class CharsetDetector {
11+
static CharsetDetector instance = null;
12+
13+
private CharsetDetector() { }
14+
15+
public static CharsetDetector getInstance() {
16+
if (instance == null) {
17+
instance = new CharsetDetector();
18+
}
19+
return instance;
20+
}
21+
22+
public interface Kernel32 extends Library {
23+
int GetConsoleOutputCP();
24+
}
25+
26+
static class Kernel32Holder {
27+
static final Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class);
28+
}
29+
30+
Kernel32 getKernel32Instance() {
31+
return Kernel32Holder.INSTANCE;
32+
}
33+
34+
@NotNull String getOsName() {
35+
return System.getProperty("os.name").toLowerCase();
36+
}
37+
38+
int getConsoleCP() {
39+
return getKernel32Instance().GetConsoleOutputCP();
40+
}
41+
42+
Charset getCharsetForCodePage(int cp) {
43+
if (cp == 65001) return StandardCharsets.UTF_8;
44+
45+
try {
46+
return Charset.forName("CP" + cp);
47+
} catch (Exception ignored) {
48+
return StandardCharsets.UTF_8;
49+
}
50+
}
51+
52+
@NotNull Charset getCharset() {
53+
if (getOsName().contains("win")) {
54+
int cp = getConsoleCP();
55+
return getCharsetForCodePage(cp);
56+
}
57+
58+
// on non-Windows, assume UTF-8 (most Linux/macOS terminals use UTF-8)
59+
return StandardCharsets.UTF_8;
60+
}
61+
}

jacoco-console-reporter/src/main/java/io/github/svaningelgem/Defaults.java

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,52 @@
33
import org.jetbrains.annotations.Contract;
44
import org.jetbrains.annotations.NotNull;
55

6-
public class Defaults {
7-
private static final boolean USE_ASCII = false; // disabled for now
6+
import java.nio.charset.Charset;
7+
import java.nio.charset.StandardCharsets;
88

9+
public class Defaults {
910
// Define column widths
10-
static final int PACKAGE_WIDTH = 50;
11-
static final int METRICS_WIDTH = 20;
11+
final static int PACKAGE_WIDTH = 50;
12+
final static int METRICS_WIDTH = 20;
13+
14+
private final boolean useAscii;
1215

1316
// Define tree characters based on terminal capabilities
14-
static final String LAST_DIR_SPACE = " ";
15-
static final String VERTICAL_LINE = USE_ASCII ? "| " : "│ ";
16-
static final String TEE = USE_ASCII ? "+-" : "├─";
17-
static final String CORNER = USE_ASCII ? "\\-" : "└─";
17+
final String lastDirSpace = " ";
18+
final String verticalLine;
19+
final String tee;
20+
final String corner;
21+
22+
final String lineFormat;
23+
final String divider;
24+
25+
static Defaults instance = null;
26+
public static Defaults getInstance() {
27+
if (instance == null) {
28+
instance = new Defaults();
29+
}
30+
return instance;
31+
}
32+
33+
public Defaults() {
34+
this(CharsetDetector.getInstance().getCharset());
35+
}
36+
37+
public Defaults(Charset currentCharset) {
38+
useAscii = currentCharset != StandardCharsets.UTF_8;
1839

19-
static final String DIVIDER = getDivider();
20-
static final String LINE_FORMAT = "%-" + PACKAGE_WIDTH + "s " + VERTICAL_LINE + "%-" + METRICS_WIDTH + "s " + VERTICAL_LINE + "%-" + METRICS_WIDTH + "s " + VERTICAL_LINE + "%-" + METRICS_WIDTH + "s " + VERTICAL_LINE + "%-" + METRICS_WIDTH + "s";
40+
verticalLine = this.useAscii ? "| " : "│ ";
41+
tee = this.useAscii ? "+-" : "├─";
42+
corner = this.useAscii ? "\\-" : "└─";
43+
lineFormat = "%-" + PACKAGE_WIDTH + "s " + verticalLine + "%-" + METRICS_WIDTH + "s " + verticalLine + "%-" + METRICS_WIDTH + "s " + verticalLine + "%-" + METRICS_WIDTH + "s " + verticalLine + "%-" + METRICS_WIDTH + "s";
44+
divider = String.format(lineFormat, "", "", "", "", "").replace(' ', '-');
45+
}
2146

2247
/**
2348
* Truncates a string in the middle if it exceeds maxLength
2449
* Example: "com.example.very.long.package.name" -> "com.example...kage.name"
2550
*/
26-
static @NotNull String truncateMiddle(@NotNull String input) {
51+
@NotNull String truncateMiddle(@NotNull String input) {
2752
if (input.length() <= PACKAGE_WIDTH) {
2853
return input;
2954
}
@@ -43,18 +68,9 @@ public class Defaults {
4368
* @return Formatted string showing percentage and ratio (e.g., "75.00% (3/4)")
4469
*/
4570
@Contract(pure = true)
46-
static @NotNull String formatCoverage(double covered, double total) {
71+
@NotNull String formatCoverage(double covered, double total) {
4772
if (total <= 0) return " ***** (0/0)";
4873
double percentage = covered / total * 100;
4974
return String.format("%5.2f%% (%d/%d)", percentage, (int)covered, (int)total);
5075
}
51-
52-
/**
53-
* Build a divider with certain widths
54-
*/
55-
private static @NotNull String getDivider() {
56-
return String.format(Defaults.LINE_FORMAT, "", "", "", "", "").replace(' ', '-');
57-
}
58-
59-
private Defaults() { }
6076
}

jacoco-console-reporter/src/main/java/io/github/svaningelgem/DirectoryNode.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ private <T extends FileSystemNode> void printNodes(org.apache.maven.plugin.loggi
5656
private @NotNull String determineNewPrefix(@NotNull String oldPrefix, boolean isLast) {
5757
String prefix = oldPrefix;
5858

59-
if (prefix.endsWith(Defaults.CORNER)) {
60-
prefix = prefix.substring(0, prefix.length() - Defaults.CORNER.length()) + Defaults.LAST_DIR_SPACE;
59+
if (prefix.endsWith(Defaults.getInstance().corner)) {
60+
prefix = prefix.substring(0, prefix.length() - Defaults.getInstance().corner.length()) + Defaults.getInstance().lastDirSpace;
6161
}
62-
else if (prefix.endsWith(Defaults.TEE)) {
63-
prefix = prefix.substring(0, prefix.length() - Defaults.TEE.length()) + Defaults.VERTICAL_LINE;
62+
else if (prefix.endsWith(Defaults.getInstance().tee)) {
63+
prefix = prefix.substring(0, prefix.length() - Defaults.getInstance().tee.length()) + Defaults.getInstance().verticalLine;
6464
}
6565

66-
String connector = isLast ? Defaults.CORNER : Defaults.TEE;
66+
String connector = isLast ? Defaults.getInstance().corner : Defaults.getInstance().tee;
6767
return prefix + connector;
6868
}
6969

@@ -93,11 +93,11 @@ public void printTree(org.apache.maven.plugin.logging.@NotNull Log log, String p
9393

9494
String printableName = isRoot ? "<root>" : prefix + packagePath + (packagePath.isEmpty() ? "" : ".") + name;
9595
log.info(String.format(format,
96-
Defaults.truncateMiddle(printableName),
97-
Defaults.formatCoverage(getMetrics().getCoveredClasses(), getMetrics().getTotalClasses()),
98-
Defaults.formatCoverage(getMetrics().getCoveredMethods(), getMetrics().getTotalMethods()),
99-
Defaults.formatCoverage(getMetrics().getCoveredBranches(), getMetrics().getTotalBranches()),
100-
Defaults.formatCoverage(getMetrics().getCoveredLines(), getMetrics().getTotalLines())));
96+
Defaults.getInstance().truncateMiddle(printableName),
97+
Defaults.getInstance().formatCoverage(getMetrics().getCoveredClasses(), getMetrics().getTotalClasses()),
98+
Defaults.getInstance().formatCoverage(getMetrics().getCoveredMethods(), getMetrics().getTotalMethods()),
99+
Defaults.getInstance().formatCoverage(getMetrics().getCoveredBranches(), getMetrics().getTotalBranches()),
100+
Defaults.getInstance().formatCoverage(getMetrics().getCoveredLines(), getMetrics().getTotalLines())));
101101

102102
packagePath = ""; // Reset because we shouldn't collapse now anymore
103103

jacoco-console-reporter/src/main/java/io/github/svaningelgem/FileSystemNode.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ default void printTree(@NotNull org.apache.maven.plugin.logging.Log log, String
3131
CoverageMetrics metrics = getMetrics();
3232

3333
log.info(String.format(format,
34-
Defaults.truncateMiddle(prefix + getName()),
35-
Defaults.formatCoverage(metrics.getCoveredClasses(), metrics.getTotalClasses()),
36-
Defaults.formatCoverage(metrics.getCoveredMethods(), metrics.getTotalMethods()),
37-
Defaults.formatCoverage(metrics.getCoveredBranches(), metrics.getTotalBranches()),
38-
Defaults.formatCoverage(metrics.getCoveredLines(), metrics.getTotalLines())));
34+
Defaults.getInstance().truncateMiddle(prefix + getName()),
35+
Defaults.getInstance().formatCoverage(metrics.getCoveredClasses(), metrics.getTotalClasses()),
36+
Defaults.getInstance().formatCoverage(metrics.getCoveredMethods(), metrics.getTotalMethods()),
37+
Defaults.getInstance().formatCoverage(metrics.getCoveredBranches(), metrics.getTotalBranches()),
38+
Defaults.getInstance().formatCoverage(metrics.getCoveredLines(), metrics.getTotalLines())));
3939
}
4040

4141
/**

jacoco-console-reporter/src/main/java/io/github/svaningelgem/JacocoConsoleReporterMojo.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,10 @@ private void printSummary(@NotNull DirectoryNode root) {
355355

356356
getLog().info("Overall Coverage Summary");
357357
getLog().info("------------------------");
358-
getLog().info("Class coverage : " + Defaults.formatCoverage(total.getCoveredClasses(), total.getTotalClasses()));
359-
getLog().info("Method coverage: " + Defaults.formatCoverage(total.getCoveredMethods(), total.getTotalMethods()));
360-
getLog().info("Branch coverage: " + Defaults.formatCoverage(total.getCoveredBranches(), total.getTotalBranches()));
361-
getLog().info("Line coverage : " + Defaults.formatCoverage(total.getCoveredLines(), total.getTotalLines()));
358+
getLog().info("Class coverage : " + Defaults.getInstance().formatCoverage(total.getCoveredClasses(), total.getTotalClasses()));
359+
getLog().info("Method coverage: " + Defaults.getInstance().formatCoverage(total.getCoveredMethods(), total.getTotalMethods()));
360+
getLog().info("Branch coverage: " + Defaults.getInstance().formatCoverage(total.getCoveredBranches(), total.getTotalBranches()));
361+
getLog().info("Line coverage : " + Defaults.getInstance().formatCoverage(total.getCoveredLines(), total.getTotalLines()));
362362

363363
double combinedCoverage = 0;
364364
double combinedTotalCoverage = 0;
@@ -387,21 +387,21 @@ private void printTree(@NotNull DirectoryNode root) {
387387

388388
// Print header
389389
getLog().info("Overall Coverage Summary");
390-
getLog().info(String.format(Defaults.LINE_FORMAT, "Package", "Class, %", "Method, %", "Branch, %", "Line, %"));
391-
getLog().info(Defaults.DIVIDER);
390+
getLog().info(String.format(Defaults.getInstance().lineFormat, "Package", "Class, %", "Method, %", "Branch, %", "Line, %"));
391+
getLog().info(Defaults.getInstance().divider);
392392

393393
// Print the tree structure - start with an empty prefix for root
394-
root.printTree(getLog(), "", Defaults.LINE_FORMAT, "", showFiles);
394+
root.printTree(getLog(), "", Defaults.getInstance().lineFormat, "", showFiles);
395395

396396
// Print total metrics
397-
getLog().info(Defaults.DIVIDER);
397+
getLog().info(Defaults.getInstance().divider);
398398
CoverageMetrics total = root.getMetrics();
399-
getLog().info(String.format(Defaults.LINE_FORMAT,
399+
getLog().info(String.format(Defaults.getInstance().lineFormat,
400400
"all classes",
401-
Defaults.formatCoverage(total.getCoveredClasses(), total.getTotalClasses()),
402-
Defaults.formatCoverage(total.getCoveredMethods(), total.getTotalMethods()),
403-
Defaults.formatCoverage(total.getCoveredBranches(), total.getTotalBranches()),
404-
Defaults.formatCoverage(total.getCoveredLines(), total.getTotalLines())));
401+
Defaults.getInstance().formatCoverage(total.getCoveredClasses(), total.getTotalClasses()),
402+
Defaults.getInstance().formatCoverage(total.getCoveredMethods(), total.getTotalMethods()),
403+
Defaults.getInstance().formatCoverage(total.getCoveredBranches(), total.getTotalBranches()),
404+
Defaults.getInstance().formatCoverage(total.getCoveredLines(), total.getTotalLines())));
405405
}
406406

407407
/**

jacoco-console-reporter/src/test/java/io/github/svaningelgem/BaseTestClass.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ protected String getBasedir() {
7272
@Before
7373
public void setUp() throws Exception {
7474
Locale.setDefault(Locale.US);
75+
Defaults.instance = null;
7576

7677
fileCounter = 0;
7778

@@ -171,17 +172,19 @@ protected void assertLogContains(@NotNull String @NotNull [] expected) {
171172
final int begin = line;
172173
assertTrue("We should have at least enough lines left to check the whole expected array", line <= log.writtenData.size() - expected.length);
173174
for (; line < log.writtenData.size(); line++) {
174-
if (!log.writtenData.get(line).startsWith(expected[line - begin])) {
175-
failLog(expected);
175+
String expectedAsUtf8 = expected[line - begin];
176+
String expectedAsAscii = expectedAsUtf8.replace("│", "|").replace("├─", "+-").replace("└─", "\\-");
177+
178+
String currentLine = log.writtenData.get(line);
179+
if (currentLine.startsWith(expectedAsUtf8) || currentLine.startsWith(expectedAsAscii)) {
180+
continue;
176181
}
182+
183+
failLog(expected);
177184
}
178185
}
179186

180187
protected void failLog(String @NotNull [] expected) {
181-
failLog(expected, null);
182-
}
183-
184-
protected void failLog(String @NotNull [] expected, @Nullable String message) {
185188
StringBuilder builder = new StringBuilder();
186189
builder.append("Expected log to contain:\n");
187190
for (String line : expected) {
@@ -194,11 +197,7 @@ protected void failLog(String @NotNull [] expected, @Nullable String message) {
194197
}
195198
builder.append("\n");
196199

197-
if (message != null) {
198-
fail(builder + message);
199-
} else {
200-
fail(builder.toString());
201-
}
200+
fail(builder.toString());
202201
}
203202

204203
/**

0 commit comments

Comments
 (0)