commits@javamail.java.net

[javamail~mercurial:821] Create common super class for logging tests - bug 7097

From: <shannon_at_java.net>
Date: Tue, 19 Apr 2016 23:02:37 +0000

Project: javamail
Repository: mercurial
Revision: 821
Author: shannon
Date: 2016-04-19 22:41:47 UTC
Link:

Log Message:
------------
Create common super class for logging tests - bug 7097
MailHandler try to unpin super error manager.
MailHandler use singleton empty arrays in all cases.
SeverityComparator dodge WebappClassLoader nulling.
Prefer bitwise OR when used with instanceof.
CollectorFormatterTest add LogManager format pattern test.
CompactFormatterTest add LogManager format pattern test.

(From Jason)


Revisions:
----------
821


Modified Paths:
---------------
doc/release/CHANGES.txt
mail/src/main/java/com/sun/mail/util/logging/LogManagerProperties.java
mail/src/main/java/com/sun/mail/util/logging/MailHandler.java
mail/src/main/java/com/sun/mail/util/logging/SeverityComparator.java
mail/src/test/java/com/sun/mail/util/logging/CollectorFormatterTest.java
mail/src/test/java/com/sun/mail/util/logging/CompactFormatterTest.java
mail/src/test/java/com/sun/mail/util/logging/DurationFilterTest.java
mail/src/test/java/com/sun/mail/util/logging/LogManagerPropertiesTest.java
mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java
mail/src/test/java/com/sun/mail/util/logging/SeverityComparatorTest.java


Added Paths:
------------
mail/src/test/java/com/sun/mail/util/logging/AbstractLogging.java


Diffs:
------
diff -r f34dc211d0fc -r b0d9c4977915 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Fri Apr 15 17:21:37 2016 -0700
+++ b/doc/release/CHANGES.txt Tue Apr 19 15:41:47 2016 -0700
@@ -19,6 +19,7 @@
                   ----------------------------
 The following bugs have been fixed in the 1.5.6 release.
 
+K 7097 Create common super class for logging tests
 K 7140 NPE by APOP detection when no greeting banner
 K 7150 Make IMAPProtocol.handleLoginResult protected
 K 7151 InternetAddress.parse fails for valid domain literal address

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/main/java/com/sun/mail/util/logging/LogManagerProperties.java
--- a/mail/src/main/java/com/sun/mail/util/logging/LogManagerProperties.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/main/java/com/sun/mail/util/logging/LogManagerProperties.java Tue Apr 19 15:41:47 2016 -0700
@@ -633,7 +633,7 @@
             //case insensitive (BUG ID 6196068). In some cases, we allow class
             //names or literal names, this code guards against the case where a
             //literal name happens to match a class name in a different case.
- //This is also a nice way to adap this error for the error manager.
+ //This is also a nice way to adapt this error for the error manager.
             throw new ClassNotFoundException(NCDFE.toString(), NCDFE);
         } catch (final ExceptionInInitializerError EIIE) {
             throw wrapOrThrow(EIIE);
@@ -652,8 +652,10 @@
     private static Exception paramOrError(InvocationTargetException ite) {
         final Throwable cause = ite.getCause();
         if (cause != null) {
+ //Bitwise inclusive OR produces tighter bytecode for instanceof
+ //and matches with multicatch syntax.
             if (cause instanceof VirtualMachineError
- || cause instanceof ThreadDeath) {
+ | cause instanceof ThreadDeath) {
                 throw (Error) cause;
             }
         }

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/main/java/com/sun/mail/util/logging/MailHandler.java
--- a/mail/src/main/java/com/sun/mail/util/logging/MailHandler.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/main/java/com/sun/mail/util/logging/MailHandler.java Tue Apr 19 15:41:47 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2009-2015 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2009-2015 Jason Mehrens. All rights reserved.
+ * Copyright (c) 2009-2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009-2016 Jason Mehrens. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -923,11 +923,29 @@
     @Override
     public void setErrorManager(final ErrorManager em) {
         checkAccess();
+ setErrorManager0(em);
+ }
+
+ /**
+ * Sets the error manager on this handler and the super handler. In secure
+ * environments the super call may not be allowed which is not a failure
+ * condition as it is an attempt to free the unused the error manager.
+ *
+ * @param em a non null error manager.
+ * @throws NullPointerException if the given error manager is null.
+ * @since JavaMail 1.5.6
+ */
+ private void setErrorManager0(final ErrorManager em) {
         if (em == null) {
            throw new NullPointerException();
         }
- synchronized (this) { //Wait for writeLogRecords.
- this.errorManager = em;
+ try {
+ synchronized (this) { //Wait for writeLogRecords.
+ this.errorManager = em;
+ super.setErrorManager(em); //Try to free super error manager.
+ }
+ } catch (final RuntimeException ignore) {
+ } catch (final LinkageError ignore) {
         }
     }
 
@@ -1272,7 +1290,11 @@
      */
     public final void setAttachmentFilters(Filter... filters) {
         checkAccess();
- filters = copyOf(filters, filters.length, Filter[].class);
+ if (filters.length == 0) {
+ filters = emptyFilterArray();
+ } else {
+ filters = copyOf(filters, filters.length, Filter[].class);
+ }
         synchronized (this) {
             if (this.attachmentFormatters.length != filters.length) {
                 throw attachmentMismatch(this.attachmentFormatters.length, filters.length);
@@ -1433,7 +1455,12 @@
     public final void setAttachmentNames(Formatter... formatters) {
         checkAccess();
 
- formatters = copyOf(formatters, formatters.length, Formatter[].class);
+ if (formatters.length == 0) {
+ formatters = emptyFormatterArray();
+ } else {
+ formatters = copyOf(formatters, formatters.length, Formatter[].class);
+ }
+
         for (int i = 0; i < formatters.length; ++i) {
             if (formatters[i] == null) {
                 throw new NullPointerException(atIndexMsg(i));
@@ -2424,6 +2451,8 @@
             em = super.getErrorManager();
         } catch (final RuntimeException ignore) {
             em = null;
+ } catch (final LinkageError ignore) {
+ em = null;
         }
 
         //Don't assume that the super call is not null.
@@ -2444,7 +2473,7 @@
         try {
             String name = fromLogManager(p.concat(".errorManager"));
             if (name != null) {
- this.errorManager = LogManagerProperties.newErrorManager(name);
+ setErrorManager0(LogManagerProperties.newErrorManager(name));
             }
         } catch (final SecurityException SE) {
             throw SE; //Avoid catch all.

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/main/java/com/sun/mail/util/logging/SeverityComparator.java
--- a/mail/src/main/java/com/sun/mail/util/logging/SeverityComparator.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/main/java/com/sun/mail/util/logging/SeverityComparator.java Tue Apr 19 15:41:47 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013-2015 Jason Mehrens. All rights reserved.
+ * Copyright (c) 2013-2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013-2016 Jason Mehrens. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -97,8 +97,12 @@
 
     /**
      * A single instance that is shared among the logging package.
+ * The field is declared as java.util.Comparator so
+ * WebappClassLoader.clearReferencesStaticFinal() method will ignore this
+ * field.
      */
- private static final SeverityComparator INSTANCE = new SeverityComparator();
+ private static final Comparator<LogRecord> INSTANCE
+ = new SeverityComparator();
 
     /**
      * A shared instance of a SeverityComparator. This is package private so the
@@ -107,7 +111,7 @@
      * @return a shared instance of a SeverityComparator.
      */
     static SeverityComparator getInstance() {
- return INSTANCE;
+ return (SeverityComparator) INSTANCE;
     }
 
     /**
@@ -212,8 +216,10 @@
                 return t2 instanceof Error ? -1
                         : t2 instanceof RuntimeException ? 0 : 1;
             } else {
+ //Bitwise inclusive OR produces tighter bytecode for instanceof
+ //and matches with multicatch syntax.
                 return t2 instanceof Error
- || t2 instanceof RuntimeException ? -1 : 0;
+ | t2 instanceof RuntimeException ? -1 : 0;
             }
         }
     }

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/test/java/com/sun/mail/util/logging/AbstractLogging.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/test/java/com/sun/mail/util/logging/AbstractLogging.java Tue Apr 19 15:41:47 2016 -0700
@@ -0,0 +1,264 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 Jason Mehrens. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package com.sun.mail.util.logging;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Common super class for the logging test suite.
+ *
+ * @author Jason Mehrens
+ * @since JavaMail 1.5.6
+ */
+abstract class AbstractLogging {
+
+ /**
+ * Used to print debug information about the given throwable.
+ *
+ * @param t the throwable.
+ * @throws NullPointerException if given throwable is null.
+ */
+ @SuppressWarnings({"CallToThreadDumpStack", "CallToPrintStackTrace"})
+ static void dump(final Throwable t) {
+ t.printStackTrace();
+ }
+
+ /**
+ * Gets all of the predefined Levels.
+ *
+ * @return an array of log levels.
+ */
+ static Level[] getAllLevels() {
+ final Field[] fields = Level.class.getFields();
+ List<Level> a = new ArrayList<Level>(fields.length);
+ for (Field field : fields) {
+ if (Modifier.isStatic(field.getModifiers())
+ && Level.class.isAssignableFrom(field.getType())) {
+ try {
+ a.add((Level) field.get((Object) null));
+ } catch (IllegalArgumentException ex) {
+ fail(ex.toString());
+ } catch (IllegalAccessException ex) {
+ fail(ex.toString());
+ }
+ }
+ }
+ return a.toArray(new Level[a.size()]);
+ }
+
+ /**
+ * Reinitialize the logging properties using the given properties.
+ *
+ * @param manager the log manager.
+ * @param props the properties.
+ * @throws IOException if there is a problem.
+ * @throws NullPointerException if either argument is null.
+ */
+ final void read(LogManager manager, Properties props) throws IOException {
+ //JDK-4810637
+ ByteArrayOutputStream out = new ByteArrayOutputStream(512);
+ props.store(out, getClass().getName());
+ manager.readConfiguration(new ByteArrayInputStream(out.toByteArray()));
+ }
+
+ /**
+ * Fails if any declared types are outside of the logging-mailhandler.jar.
+ *
+ * @param k the type to check for dependencies.
+ * @throws Exception if there is a problem.
+ */
+ final void testJavaMailLinkage(final Class<?> k) throws Exception {
+ assertFalse(k.getName(), isFromJavaMail(k));
+ for (Annotation an : k.getDeclaredAnnotations()) {
+ assertFalse(an.toString(), isFromJavaMail(an.annotationType()));
+ }
+
+ for (Method m : k.getDeclaredMethods()) {
+ assertFalse(m.getReturnType().getName(),
+ isFromJavaMail(m.getReturnType()));
+ for (Class<?> p : m.getParameterTypes()) {
+ assertFalse(p.getName(), isFromJavaMail(p));
+ }
+
+ for (Class<?> e : m.getExceptionTypes()) {
+ assertFalse(e.getName(), isFromJavaMail(e));
+ }
+
+ for (Annotation an : m.getDeclaredAnnotations()) {
+ assertFalse(an.toString(), isFromJavaMail(an.annotationType()));
+ }
+ }
+
+ for (Constructor<?> c : k.getDeclaredConstructors()) {
+ for (Class<?> p : c.getParameterTypes()) {
+ assertFalse(p.getName(), isFromJavaMail(p));
+ }
+
+ for (Class<?> e : c.getExceptionTypes()) {
+ assertFalse(e.getName(), isFromJavaMail(e));
+ }
+
+ for (Annotation an : c.getDeclaredAnnotations()) {
+ assertFalse(an.toString(), isFromJavaMail(an.annotationType()));
+ }
+ }
+
+ for (Field f : k.getDeclaredFields()) {
+ for (Annotation an : k.getDeclaredAnnotations()) {
+ assertFalse(an.toString(), isFromJavaMail(an.annotationType()));
+ }
+ assertFalse(f.getName(), isFromJavaMail(f.getType()));
+ }
+ }
+
+ /**
+ * Checks that the given class is visible to the LogManager.
+ *
+ * @param c the class to check.
+ * @throws Exception if there is a problem.
+ */
+ final void testLogManagerModifiers(final Class<?> c) throws Exception {
+ assertTrue(Modifier.isPublic(c.getModifiers()));
+ assertTrue(Modifier.isPublic(c.getConstructor().getModifiers()));
+ }
+
+ /**
+ * WebappClassLoader.clearReferencesStaticFinal() method will ignore fields
+ * that have type names that start with 'java.' or 'javax.'. This test
+ * checks that the given class conforms to this rule so it doesn't become a
+ * target that will be nullified by the WebappClassLoader.
+ *
+ * @param c the class to check.
+ * @throws Exception if there is a problem.
+ */
+ final void testWebappClassLoaderFieldNames(Class<?> c) throws Exception {
+ for (Field f : c.getDeclaredFields()) {
+ Class<?> k = f.getType();
+ while (k.isArray()) {
+ k = k.getComponentType();
+ }
+
+ /**
+ * The WebappClassLoader ignores primitives, non-static, and
+ * synthetic fields. For the logging API, this test is stricter than
+ * what the WebappClassLoader actually clears. This restricts the
+ * logging API to standard field types for both static and
+ * non-static fields. The idea is to try to stay forward compatible
+ * with WebappClassLoader.
+ */
+ if (f.getName().indexOf('$') < 0 && !k.isPrimitive()
+ && !k.getName().startsWith("java.")
+ && !k.getName().startsWith("javax.")) {
+ fail(f.toString());
+ }
+ }
+
+ for (Class<?> ic : c.getDeclaredClasses()) {
+ testWebappClassLoaderFieldNames(ic);
+ }
+ }
+
+ /**
+ * Blocks the current thread until current time has elapsed by one
+ * millisecond.
+ *
+ * @throws InterruptedException if the current thread is interrupted.
+ */
+ static void tick() throws InterruptedException {
+ tick(1L);
+ }
+
+ /**
+ * Blocks the current thread until current time has elapsed by the given
+ * delay in milliseconds.
+ *
+ * @param delay the number of milliseconds that have to elapse.
+ * @throws IllegalArgumentException if the given delay is zero or less.
+ * @throws InterruptedException if the current thread is interrupted.
+ */
+ @SuppressWarnings("SleepWhileInLoop")
+ static void tick(long delay) throws InterruptedException {
+ if (delay <= 0L) {
+ throw new IllegalArgumentException(Long.toString(delay));
+ }
+ long then = System.currentTimeMillis();
+ for (int i = 0; i < Short.MAX_VALUE; i++) {
+ long now = System.currentTimeMillis();
+ long delta = (now - then);
+ if (delta >= delay) {
+ return;
+ }
+ Thread.sleep(delay - delta);
+ }
+ throw new AssertionError(then + " " + System.currentTimeMillis());
+ }
+
+ private boolean isFromJavaMail(Class<?> k) throws Exception {
+ for (Class<?> t = k; t != null; t = t.getSuperclass()) {
+ final String n = t.getName();
+ if (n.startsWith("javax.mail.")) {
+ return true;
+ }
+
+ //Not included with logging-mailhandler.jar.
+ if (n.startsWith("com.sun.mail.")
+ && !n.startsWith("com.sun.mail.util.logging.")) {
+ return true;
+ }
+ }
+ return false;
+ }
+}

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/test/java/com/sun/mail/util/logging/CollectorFormatterTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/CollectorFormatterTest.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/test/java/com/sun/mail/util/logging/CollectorFormatterTest.java Tue Apr 19 15:41:47 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013-2015 Jason Mehrens. All rights reserved.
+ * Copyright (c) 2013-2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013-2016 Jason Mehrens. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -60,7 +60,7 @@
  * @author Jason Mehrens
  * @since JavaMail 1.5.2
  */
-public class CollectorFormatterTest {
+public class CollectorFormatterTest extends AbstractLogging {
 
     /**
      * See LogManager.
@@ -88,21 +88,6 @@
         LogManager.getLogManager().getProperty("");
     }
 
- @SuppressWarnings("SleepWhileInLoop")
- private static void tick() throws InterruptedException {
- final long delay = 1L;
- long then = System.currentTimeMillis();
- for (int i = 0; i < Short.MAX_VALUE; i++) {
- long now = System.currentTimeMillis();
- long delta = (now - then);
- if (delta >= delay) {
- return;
- }
- Thread.sleep(delay - delta);
- }
- throw new AssertionError(then + " " + System.currentTimeMillis());
- }
-
     @BeforeClass
     public static void setUpClass() throws Exception {
         checkJVMOptions();
@@ -159,6 +144,7 @@
         private static final long serialVersionUID = 1L;
 
         int inferred;
+ @SuppressWarnings("FieldMayBeFinal")
         private transient Formatter f;
 
         TestFormatterAccept(Level level, CollectorFormatter f) {
@@ -206,6 +192,7 @@
 
         private static final long serialVersionUID = 1L;
         int inferred;
+ @SuppressWarnings("FieldMayBeFinal")
         private transient Formatter f;
 
         public TestFormatAcceptAndUpdate(Level level, CollectorFormatter f) {
@@ -864,6 +851,25 @@
     }
 
     @Test
+ public void testFormat() throws Exception {
+ final String p = CollectorFormatter.class.getName();
+ Properties props = new Properties();
+ final String expect = CollectorFormatterTest.class.getName();
+ props.put(p.concat(".format"), expect);
+ LogManager manager = LogManager.getLogManager();
+ try {
+ read(manager, props);
+ CollectorFormatter cf = new CollectorFormatter();
+ LogRecord first = new LogRecord(Level.SEVERE, Level.SEVERE.getName());
+ assertEquals("", cf.format(first));
+ String result = cf.getTail((Handler) null);
+ assertEquals(expect, result);
+ } finally {
+ manager.reset();
+ }
+ }
+
+ @Test
     public void testFormatter() throws Exception {
         final String p = CollectorFormatter.class.getName();
         Properties props = new Properties();
@@ -1038,10 +1044,19 @@
         }
     }
 
- private void read(LogManager manager, Properties props) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream(512);
- props.store(out, CollectorFormatterTest.class.getName());
- manager.readConfiguration(new ByteArrayInputStream(out.toByteArray()));
+ @Test
+ public void testJavaMailLinkage() throws Exception {
+ testJavaMailLinkage(CollectorFormatter.class);
+ }
+
+ @Test
+ public void testLogManagerModifiers() throws Exception {
+ testLogManagerModifiers(CollectorFormatter.class);
+ }
+
+ @Test
+ public void testWebappClassLoaderFieldNames() throws Exception {
+ testWebappClassLoaderFieldNames(CollectorFormatter.class);
     }
 
     /**

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/test/java/com/sun/mail/util/logging/CompactFormatterTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/CompactFormatterTest.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/test/java/com/sun/mail/util/logging/CompactFormatterTest.java Tue Apr 19 15:41:47 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013-2015 Jason Mehrens. All rights reserved.
+ * Copyright (c) 2013-2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013-2016 Jason Mehrens. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -57,7 +57,7 @@
  * @author Jason Mehrens
  * @since JavaMail 1.5.2
  */
-public class CompactFormatterTest {
+public class CompactFormatterTest extends AbstractLogging {
 
     private static final String UNKNOWN_CLASS_NAME
             = CompactFormatterTest.class.getName().concat("Foo");
@@ -120,6 +120,24 @@
     }
 
     @Test
+ public void testFormat() throws Exception {
+ final String p = CompactFormatter.class.getName();
+ Properties props = new Properties();
+ props.put(p.concat(".format"), "%9$s");
+ LogManager manager = LogManager.getLogManager();
+ try {
+ read(manager, props);
+ CompactFormatter cf = new CompactFormatter();
+ LogRecord first = new LogRecord(Level.SEVERE, Level.INFO.getName());
+ first.setSequenceNumber(Short.MAX_VALUE);
+ String result = cf.format(first);
+ assertEquals(String.valueOf((int) Short.MAX_VALUE), result);
+ } finally {
+ manager.reset();
+ }
+ }
+
+ @Test
     public void testNewFormatterWithPattern() {
         CompactFormatter cf = new CompactFormatter("%4$s");
         String result = cf.format(new LogRecord(Level.SEVERE, ""));
@@ -1051,6 +1069,21 @@
         assertNull(cf.toAlternate((String) null));
     }
 
+ @Test
+ public void testJavaMailLinkage() throws Exception {
+ testJavaMailLinkage(CompactFormatter.class);
+ }
+
+ @Test
+ public void testLogManagerModifiers() throws Exception {
+ testLogManagerModifiers(CompactFormatter.class);
+ }
+
+ @Test
+ public void testWebappClassLoaderFieldNames() throws Exception {
+ testWebappClassLoaderFieldNames(CompactFormatter.class);
+ }
+
     private static String rpad(String s, int len, String p) {
         if (s.length() < len) {
             StringBuilder sb = new StringBuilder(len);

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/test/java/com/sun/mail/util/logging/DurationFilterTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/DurationFilterTest.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/test/java/com/sun/mail/util/logging/DurationFilterTest.java Tue Apr 19 15:41:47 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015 Jason Mehrens. All rights reserved.
+ * Copyright (c) 2015-2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015-2016 Jason Mehrens. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -40,7 +40,6 @@
  */
 package com.sun.mail.util.logging;
 
-import java.io.*;
 import java.lang.reflect.Field;
 import java.util.Properties;
 import java.util.logging.*;
@@ -52,7 +51,7 @@
  *
  * @author Jason Mehrens
  */
-public class DurationFilterTest {
+public class DurationFilterTest extends AbstractLogging {
 
     public DurationFilterTest() {
     }
@@ -119,7 +118,6 @@
     }
 
     @Test(timeout = 15000)
- @SuppressWarnings("SleepWhileInLoop")
     public void testIsLoggableNow() throws Exception {
         final int records = 10;
         final int duration = 1000;
@@ -142,11 +140,7 @@
         assertFalse(sf.isLoggable());
         assertFalse(sf.isLoggable(r));
 
- //Cool down and allow.
- final long then = System.currentTimeMillis();
- do {
- Thread.sleep(duration + 100);
- } while ((System.currentTimeMillis() - then) < duration);
+ tick(duration + 100); //Cool down and allow.
 
         for (int i = 0; i < records; i++) {
             r = new LogRecord(lvl, "");
@@ -160,7 +154,6 @@
     }
 
     @Test(timeout = 15000)
- @SuppressWarnings("SleepWhileInLoop")
     public void testIsIdleNow() throws Exception {
         final int records = 10;
         final int duration = 1000;
@@ -182,11 +175,7 @@
         assertFalse(sf.isIdle());
         assertFalse(sf.isLoggable(r));
 
- //Cool down and allow.
- final long then = System.currentTimeMillis();
- do {
- Thread.sleep(duration + 100);
- } while ((System.currentTimeMillis() - then) < duration);
+ tick(duration + 100); //Cool down and allow.
 
         assertTrue(sf.isIdle());
         for (int i = 0; i < records; i++) {
@@ -572,6 +561,21 @@
     }
 
     @Test
+ public void testJavaMailLinkage() throws Exception {
+ testJavaMailLinkage(DurationFilter.class);
+ }
+
+ @Test
+ public void testLogManagerModifiers() throws Exception {
+ testLogManagerModifiers(DurationFilter.class);
+ }
+
+ @Test
+ public void testWebappClassLoaderFieldNames() throws Exception {
+ testWebappClassLoaderFieldNames(DurationFilter.class);
+ }
+
+ @Test
     public void testInitRecords() throws Exception {
         testInitRecords("210", 210);
     }
@@ -751,12 +755,6 @@
         return false;
     }
 
- private void read(LogManager manager, Properties props) throws IOException {
- final ByteArrayOutputStream out = new ByteArrayOutputStream(512);
- props.store(out, "No comment");
- manager.readConfiguration(new ByteArrayInputStream(out.toByteArray()));
- }
-
     public static final class DurationFilterExt extends DurationFilter
             implements Cloneable {
 

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/test/java/com/sun/mail/util/logging/LogManagerPropertiesTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/LogManagerPropertiesTest.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/test/java/com/sun/mail/util/logging/LogManagerPropertiesTest.java Tue Apr 19 15:41:47 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2009-2015 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2009-2015 Jason Mehrens. All rights reserved.
+ * Copyright (c) 2009-2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009-2016 Jason Mehrens. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -60,7 +60,7 @@
  *
  * @author Jason Mehrens
  */
-public class LogManagerPropertiesTest {
+public class LogManagerPropertiesTest extends AbstractLogging {
 
     /**
      * Holder used to inject Throwables into other APIs.
@@ -268,47 +268,12 @@
 
     @Test
     public void testJavaMailLinkage() throws Exception {
- for (Method m : LogManagerProperties.class.getDeclaredMethods()) {
- assertFalse(m.getReturnType().getName(),
- isFromJavaMail(m.getReturnType()));
- for (Class<?> p : m.getParameterTypes()) {
- assertFalse(p.getName(), isFromJavaMail(p));
- }
-
- for (Class<?> e : m.getExceptionTypes()) {
- assertFalse(e.getName(), isFromJavaMail(e));
- }
- }
-
- for (Constructor<?> c : LogManagerProperties.class.getDeclaredConstructors()) {
- for (Class<?> p : c.getParameterTypes()) {
- assertFalse(p.getName(), isFromJavaMail(p));
- }
-
- for (Class<?> e : c.getExceptionTypes()) {
- assertFalse(e.getName(), isFromJavaMail(e));
- }
- }
-
- for (Field f : LogManagerProperties.class.getDeclaredFields()) {
- assertFalse(f.getName(), isFromJavaMail(f.getType()));
- }
+ testJavaMailLinkage(LogManagerProperties.class);
     }
 
- private boolean isFromJavaMail(Class<?> k) throws Exception {
- for (Class<?> t = k; t != null; t = t.getSuperclass()) {
- final String n = t.getName();
- if (n.startsWith("javax.mail.")) {
- return true;
- }
-
- //Not included with logging-mailhandler.jar.
- if (n.startsWith("com.sun.mail.")
- && !n.startsWith("com.sun.mail.util.logging.")) {
- return true;
- }
- }
- return false;
+ @Test
+ public void testWebappClassLoaderFieldNames() throws Exception {
+ testWebappClassLoaderFieldNames(LogManagerProperties.class);
     }
 
     @Test
@@ -462,7 +427,7 @@
         }
         Assert.assertFalse(fail);
     }
-
+
     @Test
     public void testParseDurationMs() throws Exception {
         try {
@@ -1218,12 +1183,6 @@
         throw new AssertionError();
     }
 
- private void read(LogManager manager, Properties props) throws IOException {
- final ByteArrayOutputStream out = new ByteArrayOutputStream(512);
- props.store(out, "No comment");
- manager.readConfiguration(new ByteArrayInputStream(out.toByteArray()));
- }
-
     private boolean contains(Properties props, String key, String value) {
         if (key == null) {
             throw new NullPointerException();
@@ -1281,6 +1240,7 @@
             throw new UnsupportedOperationException();
         }
 
+ @SuppressWarnings("override")
         public Comparator<LogRecord> reversed() {
             return new DescComparator();
         }
@@ -1295,6 +1255,7 @@
             throw new UnsupportedOperationException();
         }
 
+ @SuppressWarnings("override")
         public Comparator<LogRecord> reversed() {
             return new AscComparator();
         }

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java Tue Apr 19 15:41:47 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2009-2015 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2009-2015 Jason Mehrens. All rights reserved.
+ * Copyright (c) 2009-2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009-2016 Jason Mehrens. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -64,7 +64,7 @@
  *
  * @author Jason Mehrens
  */
-public class MailHandlerTest {
+public class MailHandlerTest extends AbstractLogging {
 
     /**
      * See LogManager.
@@ -163,11 +163,6 @@
         }
     }
 
- @SuppressWarnings({"CallToThreadDumpStack", "CallToPrintStackTrace"})
- private static void dump(Throwable t) {
- t.printStackTrace();
- }
-
     private static Throwable getPending() {
         return PENDING.get();
     }
@@ -335,47 +330,15 @@
     }
 
     @Test
+ public void testLogManagerModifiers() throws Exception {
+ testLogManagerModifiers(MailHandler.class);
+ }
+
+ @Test
     public void testWebappClassLoaderFieldNames() throws Exception {
- /**
- * Test that the MailHandler is using field types from the java.* or
- * javax.* packages only.
- */
         testWebappClassLoaderFieldNames(MailHandler.class);
     }
 
- private void testWebappClassLoaderFieldNames(Class<?> c) throws Exception {
- /**
- * WebappClassLoader.clearReferencesStaticFinal() method will ignore
- * fields that have type names that start with 'java.' or 'javax.'. The
- * MailHandler conforms to this rule so it doesn't become a target for
- * the WebappClassLoader.
- */
- for (Field f : c.getDeclaredFields()) {
- Class<?> k = f.getType();
- while (k.isArray()) {
- k = k.getComponentType();
- }
-
- /**
- * The WebappClassLoader ignores primitives, non-static, and
- * synthetic fields. For the MailHandler, the test is stricter than
- * what the WebappClassLoader actually clears. This restricts the
- * MailHandler to standard field types for both static and
- * non-static fields and named static inner class to avoid synthetic
- * fields. The idea is to try to stay forward compatible with
- * WebappClassLoader.
- */
- if (!k.isPrimitive() && !k.getName().startsWith("java.")
- && !k.getName().startsWith("javax.")) {
- fail(f.toString());
- }
- }
-
- for (Class<?> ic : c.getDeclaredClasses()) {
- testWebappClassLoaderFieldNames(ic);
- }
- }
-
     private void testVerify(ClassLoaderSecurityManager sm, ClassLoader expect) throws Exception {
         final LogManager manager = LogManager.getLogManager();
         InternalErrorManager em = null;
@@ -1494,7 +1457,7 @@
                     new Filter() {
                         public boolean isLoggable(LogRecord record) {
                             h.setAttachmentFormatters(new SimpleFormatter(),
- new SimpleFormatter());
+ new SimpleFormatter());
                             h.setAttachmentFilters(one, push);
                             return push.isLoggable(record);
                         }
@@ -6380,12 +6343,6 @@
         }
     }
 
- private void read(LogManager manager, Properties props) throws IOException {
- ByteArrayOutputStream out = new ByteArrayOutputStream(512);
- props.store(out, MailHandlerTest.class.getName());
- manager.readConfiguration(new ByteArrayInputStream(out.toByteArray()));
- }
-
     static Properties createInitProperties(String p) {
         final Properties props = new Properties();
         if (p.length() != 0) {
@@ -6661,23 +6618,6 @@
         h.close();
     }
 
- private Level[] getAllLevels() {
- final Field[] fields = Level.class.getFields();
- List<Level> a = new ArrayList<Level>(fields.length);
- for (Field field : fields) {
- if (Modifier.isStatic(field.getModifiers()) && Level.class.isAssignableFrom(field.getType())) {
- try {
- a.add((Level) field.get((Object) null));
- } catch (IllegalArgumentException ex) {
- fail(ex.toString());
- } catch (IllegalAccessException ex) {
- fail(ex.toString());
- }
- }
- }
- return a.toArray(new Level[a.size()]);
- }
-
     private static boolean isConnectOrTimeout(Throwable t) {
         if (t instanceof MessagingException || t instanceof SocketConnectException) {
             return isConnectOrTimeout(t.getCause());
@@ -6984,6 +6924,7 @@
             return s1 < s2 ? -1 : s1 > s2 ? 1 : 0;
         }
 
+ @SuppressWarnings("override")
         public Comparator<LogRecord> reversed() {
             return new SequenceDescComparator();
         }
@@ -7886,6 +7827,7 @@
             super(capacity);
         }
 
+ @SuppressWarnings("override")
         public boolean isLoggable(LogRecord record) {
             int levelValue = getLevel().intValue();
             if (record.getLevel().intValue() < levelValue
@@ -8010,6 +7952,7 @@
             this.expect = loader;
         }
 
+ @SuppressWarnings("override")
         protected PasswordAuthentication getPasswordAuthentication() {
             checkContextClassLoader(expect);
             for (StackTraceElement se : new Throwable().getStackTrace()) {
@@ -8042,17 +7985,19 @@
             return new SequenceComparator().compare(o1, o2);
         }
 
- @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
+ @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass", "override"})
         public boolean equals(Object o) {
             checkContextClassLoader(expect);
             return super.equals(o);
         }
 
+ @SuppressWarnings("override")
         public int hashCode() {
             checkContextClassLoader(expect);
             return super.hashCode();
         }
 
+ @SuppressWarnings("override")
         public String toString() {
             checkContextClassLoader(expect);
             return super.toString();

diff -r f34dc211d0fc -r b0d9c4977915 mail/src/test/java/com/sun/mail/util/logging/SeverityComparatorTest.java
--- a/mail/src/test/java/com/sun/mail/util/logging/SeverityComparatorTest.java Fri Apr 15 17:21:37 2016 -0700
+++ b/mail/src/test/java/com/sun/mail/util/logging/SeverityComparatorTest.java Tue Apr 19 15:41:47 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2013-2014 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013-2014 Jason Mehrens. All rights reserved.
+ * Copyright (c) 2013-2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013-2016 Jason Mehrens. All rights reserved.
  *
  * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common Development
@@ -42,7 +42,6 @@
 
 import java.io.*;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
 import java.lang.reflect.UndeclaredThrowableException;
 import java.nio.channels.ClosedByInterruptException;
 import java.nio.channels.FileLockInterruptionException;
@@ -58,7 +57,7 @@
  * @author Jason Mehrens
  * @since JavaMail 1.5.2
  */
-public class SeverityComparatorTest {
+public class SeverityComparatorTest extends AbstractLogging {
 
     @Test
     public void testApplyNull() {
@@ -584,6 +583,7 @@
         LogRecord r1 = new LogRecord(Level.INFO, Level.INFO.toString());
         LogRecord r2 = new LogRecord(Level.INFO, Level.INFO.toString());
         r1.setSequenceNumber(r2.getSequenceNumber());
+ r2.setMillis(System.currentTimeMillis()); //Truncate nanos.
         r1.setMillis(r2.getMillis());
 
         assertEquals(r1.getLevel(), r2.getLevel());
@@ -1130,11 +1130,18 @@
     }
 
     @Test
+ public void testJavaMailLinkage() throws Exception {
+ testJavaMailLinkage(SeverityComparator.class);
+ }
+
+ @Test
     public void testLogManagerModifiers() throws Exception {
- final Class<?> c = SeverityComparator.class;
- assertTrue(Modifier.isPublic(c.getModifiers()));
- assertFalse(Modifier.isStatic(c.getModifiers()));
- assertTrue(Modifier.isPublic(c.getConstructor().getModifiers()));
+ testLogManagerModifiers(SeverityComparator.class);
+ }
+
+ @Test
+ public void testWebappClassLoaderFieldNames() throws Exception {
+ testWebappClassLoaderFieldNames(SeverityComparator.class);
     }
 
     @Test