Ticket #16010: v2-0016-logging-add-ReacquiringConsoleHandler-which-shoul.patch

File v2-0016-logging-add-ReacquiringConsoleHandler-which-shoul.patch, 6.7 KB (added by ris, 15 months 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 { 
    5050    private static final Logger LOGGER = Logger.getAnonymousLogger();
    5151    private static final RememberWarningHandler WARNINGS = new RememberWarningHandler();
    5252
     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
    53114    static {
    54115        // We need to be sure java.locale.providers system property is initialized by JOSM, not by JRE
    55116        // The call to ConsoleHandler constructor makes the JRE access this property by side effect
    public final class Logging { 
    61122        // for a more concise logging output via java.util.logging.SimpleFormatter
    62123        Utils.updateSystemProperty("java.util.logging.SimpleFormatter.format", "%1$tF %1$tT.%1$tL %4$s: %5$s%6$s%n");
    63124
    64         ConsoleHandler stderr = new ConsoleHandler();
     125        ConsoleHandler stderr = new ReacquiringConsoleHandler(() -> System.err, null);
    65126        LOGGER.addHandler(stderr);
    66127        try {
    67128            stderr.setLevel(LEVEL_WARN);
    public final class Logging { 
    69130            System.err.println("Unable to set logging level: " + e.getMessage());
    70131        }
    71132
    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);
    86134        LOGGER.addHandler(stdout);
    87135        try {
    88136            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; 
    1111import java.text.MessageFormat;
    1212import java.util.Arrays;
    1313import java.util.TimeZone;
     14import java.util.logging.Handler;
    1415
    1516import org.junit.rules.TemporaryFolder;
    1617import org.junit.rules.TestRule;
    public class JOSMTestRules implements TestRule { 
    413414        Config.setBaseDirectoriesProvider(JosmBaseDirectories.getInstance());
    414415        // All tests use the same timezone.
    415416        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        }
    416425        // Set log level to info
    417426        Logging.setLogLevel(Logging.LEVEL_INFO);
     427
    418428        // Assume anonymous user
    419429        UserIdentityManager.getInstance().setAnonymous();
    420430        User.clearUserMap();