Ticket #16010: v2-0016-logging-add-ReacquiringConsoleHandler-which-shoul.patch
File v2-0016-logging-add-ReacquiringConsoleHandler-which-shoul.patch, 6.7 KB (added by , 6 years ago) |
---|
-
src/org/openstreetmap/josm/tools/Logging.java
From bef9ade57299ca2bf293f818e8894208caf4a69d Mon Sep 17 00:00:00 2001 From: Robert Scott <code@humanleg.org.uk> Date: Fri, 30 Mar 2018 18:50:29 +0100 Subject: [PATCH v2 16/28] logging: add ReacquiringConsoleHandler, which should allow tests to correctly receive log output this integrates functionality previously used for the existing `ConsoleHandler`s in a hopefully-sane way --- src/org/openstreetmap/josm/tools/Logging.java | 78 +++++++++++++++++----- .../josm/testutils/JOSMTestRules.java | 10 +++ 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/org/openstreetmap/josm/tools/Logging.java b/src/org/openstreetmap/josm/tools/Logging.java index 57f0f6b1d..28ca931c5 100644
a b public final class Logging { 50 50 private static final Logger LOGGER = Logger.getAnonymousLogger(); 51 51 private static final RememberWarningHandler WARNINGS = new RememberWarningHandler(); 52 52 53 /** 54 * A {@link ConsoleHandler} with a couple of extra features, allowing it to be targeted at an 55 * an arbitrary {@link OutputStream} which it can be asked to reaquire the reference for on demand 56 * through {@link #reacquireOutputStream()}. It can also prevent a LogRecord's output if a 57 * specified {@code prioritizedHandler} would have outputted it. 58 * @since xxx 59 */ 60 public static class ReacquiringConsoleHandler extends ConsoleHandler { 61 private final Supplier<OutputStream> outputStreamSupplier; 62 private final Handler prioritizedHandler; 63 private OutputStream outputStreamMemo; 64 65 /** 66 * Construct a new {@link ReacquiringConsoleHandler}. 67 * @param outputStreamSupplier A {@link Supplier} which will return the desired 68 * {@link OutputStream} for this handler when called. Particularly useful if you happen to be 69 * using a test framework which will switch out references to the stderr/stdout streams with 70 * new dummy ones from time to time. 71 * @param prioritizedHandler If non-null, will suppress output of any log records which pass this 72 * handler's {@code Handler#isLoggable(LogRecord)} method. 73 */ 74 public ReacquiringConsoleHandler( 75 final Supplier<OutputStream> outputStreamSupplier, 76 final Handler prioritizedHandler 77 ) { 78 this.outputStreamSupplier = outputStreamSupplier; 79 this.prioritizedHandler = prioritizedHandler; 80 81 this.reacquireOutputStream(); 82 } 83 84 /** 85 * Set output stream to one acquired from calling outputStreamSupplier 86 */ 87 public void reacquireOutputStream() { 88 final OutputStream reacquiredStream = this.outputStreamSupplier.get(); 89 90 // only bother calling setOutputStream if it's actually different, as setOutputStream 91 // has the nasty side effect of closing any previous output stream, which is certainly not 92 // what we would want were the new stream the same one 93 if (reacquiredStream != this.outputStreamMemo) { 94 this.setOutputStream(reacquiredStream); 95 } 96 } 97 98 @Override 99 public synchronized void setOutputStream(final OutputStream outputStream) { 100 // this wouldn't be necessary if StreamHandler made it possible to see what the current 101 // output stream is set to 102 this.outputStreamMemo = outputStream; 103 super.setOutputStream(outputStream); 104 } 105 106 @Override 107 public synchronized void publish(LogRecord record) { 108 if (this.prioritizedHandler == null || !this.prioritizedHandler.isLoggable(record)) { 109 super.publish(record); 110 } 111 } 112 } 113 53 114 static { 54 115 // We need to be sure java.locale.providers system property is initialized by JOSM, not by JRE 55 116 // The call to ConsoleHandler constructor makes the JRE access this property by side effect … … public final class Logging { 61 122 // for a more concise logging output via java.util.logging.SimpleFormatter 62 123 Utils.updateSystemProperty("java.util.logging.SimpleFormatter.format", "%1$tF %1$tT.%1$tL %4$s: %5$s%6$s%n"); 63 124 64 ConsoleHandler stderr = new ConsoleHandler();125 ConsoleHandler stderr = new ReacquiringConsoleHandler(() -> System.err, null); 65 126 LOGGER.addHandler(stderr); 66 127 try { 67 128 stderr.setLevel(LEVEL_WARN); … … public final class Logging { 69 130 System.err.println("Unable to set logging level: " + e.getMessage()); 70 131 } 71 132 72 ConsoleHandler stdout = new ConsoleHandler() { 73 @Override 74 protected synchronized void setOutputStream(OutputStream out) { 75 // overwrite output stream. 76 super.setOutputStream(System.out); 77 } 78 79 @Override 80 public synchronized void publish(LogRecord record) { 81 if (!stderr.isLoggable(record)) { 82 super.publish(record); 83 } 84 } 85 }; 133 ConsoleHandler stdout = new ReacquiringConsoleHandler(() -> System.out, stderr); 86 134 LOGGER.addHandler(stdout); 87 135 try { 88 136 stdout.setLevel(Level.ALL); -
test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java
diff --git a/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java b/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java index d455e8e19..048e87c6f 100644
a b import java.security.GeneralSecurityException; 11 11 import java.text.MessageFormat; 12 12 import java.util.Arrays; 13 13 import java.util.TimeZone; 14 import java.util.logging.Handler; 14 15 15 16 import org.junit.rules.TemporaryFolder; 16 17 import org.junit.rules.TestRule; … … public class JOSMTestRules implements TestRule { 413 414 Config.setBaseDirectoriesProvider(JosmBaseDirectories.getInstance()); 414 415 // All tests use the same timezone. 415 416 TimeZone.setDefault(DateUtils.UTC); 417 418 // Force log handers to reacquire reference to (junit's fake) stdout/stderr 419 for (Handler handler : Logging.getLogger().getHandlers()) { 420 if (handler instanceof Logging.ReacquiringConsoleHandler) { 421 handler.flush(); 422 ((Logging.ReacquiringConsoleHandler) handler).reacquireOutputStream(); 423 } 424 } 416 425 // Set log level to info 417 426 Logging.setLogLevel(Logging.LEVEL_INFO); 427 418 428 // Assume anonymous user 419 429 UserIdentityManager.getInstance().setAnonymous(); 420 430 User.clearUserMap();