source: josm/trunk/test/unit/org/openstreetmap/josm/tools/bugreport/BugReportTest.java

Last change on this file was 18670, checked in by taylor.smock, 14 months ago

Fix #22753: Fix GitHub Actions

This uses actions from https://github.com/JOSM/JOSMPluginAction, updates
other external actions and fixes many deprecation warnings.

  • Property svn:eol-style set to native
File size: 8.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools.bugreport;
3
4import static org.junit.jupiter.api.Assertions.assertAll;
5import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
6import static org.junit.jupiter.api.Assertions.assertEquals;
7import static org.junit.jupiter.api.Assertions.assertFalse;
8import static org.junit.jupiter.api.Assertions.assertSame;
9import static org.junit.jupiter.api.Assertions.assertTrue;
10
11import java.io.IOException;
12import java.io.PrintWriter;
13import java.io.StringWriter;
14import java.lang.reflect.Field;
15import java.util.concurrent.TimeUnit;
16import java.util.function.Consumer;
17import java.util.logging.Handler;
18import java.util.regex.Matcher;
19import java.util.regex.Pattern;
20import java.util.stream.Stream;
21
22import org.junit.jupiter.api.AfterAll;
23import org.junit.jupiter.api.BeforeAll;
24import org.junit.jupiter.api.Test;
25import org.junit.jupiter.params.ParameterizedTest;
26import org.junit.jupiter.params.provider.Arguments;
27import org.junit.jupiter.params.provider.MethodSource;
28import org.junit.platform.commons.util.ReflectionUtils;
29import org.openstreetmap.josm.actions.ShowStatusReportAction;
30import org.openstreetmap.josm.gui.MainApplication;
31import org.openstreetmap.josm.gui.util.GuiHelper;
32import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
33import org.openstreetmap.josm.tools.Logging;
34
35/**
36 * Tests the bug report class.
37 * @author Michael Zangl
38 */
39// Preferences for the report text
40@BasicPreferences
41class BugReportTest {
42 private static Handler[] handlers;
43
44 @AfterAll
45 static void cleanup() {
46 // Clear queue
47 new BugReport(BugReport.intercept(new NullPointerException())).getReportText("");
48 Logging.clearLastErrorAndWarnings();
49 for (Handler handler : handlers) {
50 Logging.getLogger().addHandler(handler);
51 }
52 }
53
54 @BeforeAll
55 static void setup() {
56 handlers = Logging.getLogger().getHandlers();
57 // Avoid console spam
58 for (Handler handler : handlers) {
59 Logging.getLogger().removeHandler(handler);
60 }
61 }
62
63 /**
64 * Test {@link BugReport#getReportText}
65 */
66 @Test
67 void testReportText() {
68 ReportedException e = interceptInChildMethod(new IOException("test-exception-message"));
69 e.put("test-key", "test-value");
70 String text = new BugReport(e).getReportText(ShowStatusReportAction.getReportHeader());
71
72 assertTrue(text.contains("test-exception-message"));
73 assertTrue(text.contains("interceptInChildMethod"));
74 assertTrue(text.contains("testReportText")); // stack trace
75 assertTrue(text.contains("test-key: test-value"));
76 }
77
78 /**
79 * Test {@link BugReport#intercept(Throwable)}
80 */
81 @Test
82 void testIntercept() {
83 IOException base = new IOException("test");
84 ReportedException intercepted = interceptInChildMethod(base);
85 assertEquals(intercepted.getCause(), base);
86
87 StringWriter out = new StringWriter();
88 intercepted.printReportDataTo(new PrintWriter(out));
89
90 assertTrue(out.toString().contains("interceptInChildMethod")); // calling method.
91
92 assertSame(intercepted, BugReport.intercept(intercepted));
93 }
94
95 private ReportedException interceptInChildMethod(IOException base) {
96 return BugReport.intercept(base);
97 }
98
99 /**
100 * Test {@link BugReport#getCallingMethod(int)}
101 */
102 @Test
103 void testGetCallingMethod() {
104 assertEquals("BugReportTest#testGetCallingMethod", BugReport.getCallingMethod(1));
105 assertEquals("BugReportTest#testGetCallingMethod", testGetCallingMethod2());
106 assertEquals("?", BugReport.getCallingMethod(100));
107 }
108
109 private String testGetCallingMethod2() {
110 return BugReport.getCallingMethod(2);
111 }
112
113 @Test
114 void testSuppressedExceptionsOrder() {
115 final String methodName = "testSuppressedExceptionsOrder";
116 BugReport.addSuppressedException(new NullPointerException(methodName));
117 BugReport.addSuppressedException(new IllegalStateException(methodName));
118 BugReport bugReport = new BugReport(BugReport.intercept(new IOException(methodName)));
119 final String report = assertDoesNotThrow(() -> bugReport.getReportText(methodName));
120 assertAll(() -> assertTrue(report.contains("NullPointerException")),
121 () -> assertTrue(report.contains("IOException")),
122 () -> assertTrue(report.contains("IllegalStateException")));
123 int ioe = report.indexOf("IOException");
124 int npe = report.indexOf("NullPointerException");
125 int ise = report.indexOf("IllegalStateException");
126 assertAll("Ordering of exceptions is wrong",
127 () -> assertTrue(ioe < npe, "IOException should be reported before NullPointerException"),
128 () -> assertTrue(npe < ise, "NullPointerException should be reported before IllegalStateException"));
129 }
130
131 static Stream<Arguments> testSuppressedExceptions() {
132 return Stream.of(
133 Arguments.of("GuiHelper::runInEDTAndWaitAndReturn",
134 (Consumer<Runnable>) r -> GuiHelper.runInEDTAndWaitAndReturn(() -> {
135 r.run();
136 return null;
137 })),
138 Arguments.of("GuiHelper::runInEDTAndWait", (Consumer<Runnable>) GuiHelper::runInEDTAndWait),
139 Arguments.of("MainApplication.worker", (Consumer<Runnable>) runnable -> {
140 MainApplication.worker.execute(runnable);
141 assertDoesNotThrow(() -> MainApplication.worker.submit(() -> { /* Sync thread */ }).get(1, TimeUnit.SECONDS));
142 })
143 );
144 }
145
146 @ParameterizedTest
147 @MethodSource
148 void testSuppressedExceptions(String workerName, Consumer<Runnable> worker) {
149 // Throw a npe in the worker. Workers might give us the exception, wrapped or otherwise.
150 try {
151 worker.accept(() -> {
152 throw new NullPointerException();
153 });
154 } catch (Exception e) {
155 // pass. MainApplication.worker can continue throwing the NPE;
156 Logging.trace(e);
157 }
158 // Now throw an exception
159 BugReport bugReport = new BugReport(BugReport.intercept(new IOException("testSuppressedExceptions")));
160 String report = bugReport.getReportText(workerName);
161 assertTrue(report.contains("IOException"));
162 assertTrue(report.contains("NullPointerException"));
163 }
164
165 @Test
166 void testSuppressedExceptionsReportedOnce() {
167 // Add the exception
168 BugReport.addSuppressedException(new NullPointerException("testSuppressedExceptionsReportedOnce"));
169 BugReport bugReport = new BugReport(BugReport.intercept(new IOException("testSuppressedExceptionsReportedOnce")));
170 // Get the report which clears the suppressed exceptions
171 String report = bugReport.getReportText("");
172 assertTrue(report.contains("IOException"));
173 assertTrue(report.contains("NullPointerException"));
174
175 BugReport bugReport2 = new BugReport(BugReport.intercept(new IOException("testSuppressedExceptionsReportedOnce")));
176 String report2 = bugReport2.getReportText("");
177 assertTrue(report2.contains("IOException"));
178 assertFalse(report2.contains("NullPointerException"));
179 }
180
181 @Test
182 void testManyExceptions() throws ReflectiveOperationException {
183 Field suppressedExceptions = BugReport.class.getDeclaredField("MAXIMUM_SUPPRESSED_EXCEPTIONS");
184 ReflectionUtils.makeAccessible(suppressedExceptions);
185 final byte expected = suppressedExceptions.getByte(null);
186 final int end = 2 * expected;
187 // Add many suppressed exceptions
188 for (int i = 0; i < end; i++) {
189 BugReport.addSuppressedException(new NullPointerException("NPE: " + i));
190 }
191 BugReport bugReport = new BugReport(BugReport.intercept(new IOException("testManyExceptions")));
192 String report = bugReport.getReportText("");
193 Matcher matcher = Pattern.compile("NPE: (\\d+)").matcher(report);
194 for (int i = end - expected; i < end; ++i) {
195 assertTrue(matcher.find());
196 assertEquals(Integer.toString(i), matcher.group(1));
197 }
198 assertFalse(matcher.find());
199 }
200
201 @Test
202 void testNullException() {
203 // This should add a NPE to the suppressed exceptions
204 assertDoesNotThrow(() -> BugReport.addSuppressedException(null));
205 BugReport bugReport = new BugReport(BugReport.intercept(new IOException("testNullException")));
206 // Getting the report text should not throw an exception.
207 String report = assertDoesNotThrow(() -> bugReport.getReportText(""));
208 assertTrue(report.contains("IOException"));
209 assertTrue(report.contains("NullPointerException"));
210 }
211}
Note: See TracBrowser for help on using the repository browser.