1 
   2 import java.util.ResourceBundle;
   3 import java.util.function.Consumer;
   4 import java.lang.System.Logger.Level;
   5 import java.util.Arrays;
   6 import java.util.LinkedList;
   7 import java.util.Objects;
   8 import java.util.Queue;
   9 import java.util.function.Supplier;
  10 
  11 /*
  12  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  13  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  14  *
  15  * This code is free software; you can redistribute it and/or modify it
  16  * under the terms of the GNU General Public License version 2 only, as
  17  * published by the Free Software Foundation.
  18  *
  19  * This code is distributed in the hope that it will be useful, but WITHOUT
  20  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  21  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  22  * version 2 for more details (a copy is included in the LICENSE file that
  23  * accompanied this code).
  24  *
  25  * You should have received a copy of the GNU General Public License version
  26  * 2 along with this work; if not, write to the Free Software Foundation,
  27  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  28  *
  29  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  30  * or visit www.oracle.com if you need additional information or have any
  31  * questions.
  32  */
  33 
  34 /**
  35  * @test
  36  * @bug 8046565
  37  * @summary Tests the default body of the System.Logger interface.
  38  * @author danielfuchs
  39  */
  40 public class LoggerInterfaceTest {
  41 
  42     public static class LoggerImpl implements System.Logger {
  43 
  44         public static class LogEvent implements Cloneable {
  45             Level level;
  46             ResourceBundle bundle;
  47             String msg;
  48             Throwable thrown;
  49             Object[] params;
  50             StackTraceElement[] callStack;
  51 
  52             @Override
  53             protected LogEvent clone() {
  54                 try {
  55                     return (LogEvent)super.clone();
  56                 } catch (CloneNotSupportedException x) {
  57                     throw new RuntimeException(x);
  58                 }
  59             }
  60 
  61 
  62         }
  63 
  64         public static class LogEventBuilder {
  65             private LogEvent event = new LogEvent();
  66             public LogEventBuilder level(Level level) {
  67                 event.level = level;
  68                 return this;
  69             }
  70             public LogEventBuilder stack(StackTraceElement... stack) {
  71                 event.callStack = stack;
  72                 return this;
  73             }
  74             public LogEventBuilder bundle(ResourceBundle bundle) {
  75                 event.bundle = bundle;
  76                 return this;
  77             }
  78             public LogEventBuilder msg(String msg) {
  79                 event.msg = msg;
  80                 return this;
  81             }
  82             public LogEventBuilder thrown(Throwable thrown) {
  83                 event.thrown = thrown;
  84                 return this;
  85             }
  86             public LogEventBuilder params(Object... params) {
  87                 event.params = params;
  88                 return this;
  89             }
  90             public LogEvent build() {
  91                 return event.clone();
  92             }
  93 
  94             public LogEventBuilder clear() {
  95                 event = new LogEvent();
  96                 return this;
  97             }
  98 
  99         }
 100 
 101         Level level = Level.WARNING;
 102         Consumer<LogEvent> consumer;
 103         final LogEventBuilder builder = new LogEventBuilder();
 104 
 105         @Override
 106         public String getName() {
 107             return "noname";
 108         }
 109 
 110         @Override
 111         public boolean isLoggable(Level level) {
 112             return level.getSeverity() >= this.level.getSeverity();
 113         }
 114 
 115         @Override
 116         public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
 117             builder.clear().level(level).bundle(bundle).msg(msg).thrown(thrown)
 118                     .stack(new Exception().getStackTrace());
 119             consumer.accept(builder.build());
 120         }
 121 
 122         @Override
 123         public void log(Level level, ResourceBundle bundle, String format, Object... params) {
 124             builder.clear().level(level).bundle(bundle).msg(format).params(params)
 125                     .stack(new Exception().getStackTrace());
 126             consumer.accept(builder.build());
 127         }
 128 
 129     }
 130 
 131     static class Throwing {
 132         @Override
 133         public String toString() {
 134             throw new RuntimeException("should not have been called");
 135         }
 136     }
 137     static class NotTrowing {
 138         private final String toString;
 139         private int count = 0;
 140         public NotTrowing(String toString) {
 141             this.toString = toString;
 142         }
 143 
 144         @Override
 145         public String toString() {
 146             return toString + "[" + (++count) + "]";
 147         }
 148     }
 149 
 150     public static void main(String[] args) {
 151         final LoggerImpl loggerImpl = new LoggerImpl();
 152         final System.Logger logger = loggerImpl;
 153         final Queue<LoggerImpl.LogEvent> events = new LinkedList<>();
 154         loggerImpl.consumer = (x) -> events.add(x);
 155 
 156         System.out.println("\nlogger.isLoggable(Level)");
 157         assertTrue(logger.isLoggable(Level.WARNING), "logger.isLoggable(Level.WARNING)","  ");
 158         assertFalse(logger.isLoggable(Level.INFO), "logger.isLoggable(Level.INFO)", "  ");
 159 
 160 
 161         System.out.println("\nlogger.log(Level, Object)");
 162         for (Level l : Level.values()) {
 163             boolean logged = l.compareTo(Level.WARNING) >= 0;
 164             Object[][] cases = new Object[][] {
 165                 {null}, {"baz"}
 166             };
 167             for (Object[] p : cases) {
 168                 String msg = (String)p[0];
 169                 final Object obj = msg == null ? null : logged ? new NotTrowing(msg) : new Throwing();
 170                 String par1 = msg == null ? "(Object)null"
 171                         : logged ? "new NotTrowing(\""+ msg+"\")" : "new Throwing()";
 172                 System.out.println("  logger.log(" + l + ", " +  par1 + ")");
 173                 try {
 174                     logger.log(l, obj);
 175                     if (logged && obj == null) {
 176                         throw new RuntimeException("Expected NullPointerException not thrown for"
 177                                   + " logger.log(" + l + ", " +  par1 + ")");
 178                     }
 179                 } catch (NullPointerException x) {
 180                     if (logged && obj == null) {
 181                         System.out.println("    Got expected exception: " + x);
 182                         continue;
 183                     } else {
 184                         throw x;
 185                     }
 186                 }
 187                 LoggerImpl.LogEvent e = events.poll();
 188                 if (logged) {
 189                     assertNonNull(e, "e", "    ");
 190                     assertEquals(l, e.level, "e.level", "    ");
 191                     assertToString(e.msg, msg, 1, "e.msg", "    ");
 192                     assertEquals(e.bundle, null, "e.bundle", "    ");
 193                     assertEquals(e.params, null, "e.params", "    ");
 194                     assertEquals(e.thrown, null, "e.thrown", "    ");
 195                     assertEquals(e.bundle, null, "e.bundle", "    ");
 196                     assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 197                     assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 198                     assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 199                     assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 200                     assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 201                 } else {
 202                     assertEquals(e, null, "e", "    ");
 203                 }
 204             }
 205         }
 206 
 207 
 208         System.out.println("\nlogger.log(Level, String)");
 209         for (Level l : Level.values()) {
 210             boolean logged = l.compareTo(Level.WARNING) >= 0;
 211             String par = "bar";
 212             System.out.println("  logger.log(" + l + ", \"" +  par +"\");");
 213             logger.log(l, par);
 214             LoggerImpl.LogEvent e = events.poll();
 215             assertNonNull(e, "e", "    ");
 216             assertEquals(e.level, l, "e.level", "    ");
 217             assertEquals(e.msg, "bar", "e.msg", "    ");
 218             assertEquals(e.bundle, null, "e.bundle", "    ");
 219             assertEquals(e.params, null, "e.params", "    ");
 220             assertEquals(e.thrown, null, "e.thrown", "    ");
 221             assertEquals(e.bundle, null, "e.bundle", "    ");
 222             assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 223             assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 224             assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 225             assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 226             assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 227 
 228             System.out.println("  logger.log(" + l + ", (String)null);");
 229             logger.log(l, (String)null);
 230             e = events.poll();
 231             assertNonNull(e, "e", "    ");
 232             assertEquals(e.level, l, "e.level", "    ");
 233             assertEquals(e.msg, null, "e.msg", "    ");
 234             assertEquals(e.bundle, null, "e.bundle", "    ");
 235             assertEquals(e.params, null, "e.params", "    ");
 236             assertEquals(e.thrown, null, "e.thrown", "    ");
 237             assertEquals(e.bundle, null, "e.bundle", "    ");
 238             assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 239             assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 240             assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 241             assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 242             assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 243         }
 244 
 245         System.out.println("\nlogger.log(Level, Supplier<String>)");
 246         for (Level l : Level.values()) {
 247             boolean logged = l.compareTo(Level.WARNING) >= 0;
 248             Object[][] cases = new Object[][] {
 249                 {null}, {"baz"}
 250             };
 251             for (Object[] p : cases) {
 252                 String msg = (String)p[0];
 253                 final Object obj = msg == null ? null : logged ? new NotTrowing(msg) : new Throwing();
 254                 final Supplier<String> s = msg == null ? null : () -> obj.toString();
 255                 String par1 = msg == null ? "(Supplier<String>)null"
 256                         : logged ? "() -> new NotTrowing(\""+ msg+"\").toString()" : "new Throwing()";
 257                 System.out.println("  logger.log(" + l + ", " +  par1 + ")");
 258                 try {
 259                     logger.log(l, s);
 260                     if (logged && s == null) {
 261                         throw new RuntimeException("Expected NullPointerException not thrown for"
 262                                   + " logger.log(" + l + ", " +  par1 + ")");
 263                     }
 264                 } catch (NullPointerException x) {
 265                     if (logged && s == null) {
 266                         System.out.println("    Got expected exception: " + x);
 267                         continue;
 268                     } else {
 269                         throw x;
 270                     }
 271                 }
 272                 LoggerImpl.LogEvent e = events.poll();
 273                 if (logged) {
 274                     assertNonNull(e, "e", "    ");
 275                     assertEquals(l, e.level, "e.level", "    ");
 276                     assertToString(e.msg, msg, 1, "e.msg", "    ");
 277                     assertEquals(e.bundle, null, "e.bundle", "    ");
 278                     assertEquals(e.params, null, "e.params", "    ");
 279                     assertEquals(e.thrown, null, "e.thrown", "    ");
 280                     assertEquals(e.bundle, null, "e.bundle", "    ");
 281                     assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 282                     assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 283                     assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 284                     assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 285                     assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 286                 } else {
 287                     assertEquals(e, null, "e", "    ");
 288                 }
 289             }
 290         }
 291 
 292         System.out.println("\nlogger.log(Level, String, Object...)");
 293         for (Level l : Level.values()) {
 294             boolean logged = l.compareTo(Level.WARNING) >= 0;
 295             String par = "bam";
 296             Object[] params = null;
 297             System.out.println("  logger.log(" + l + ", \"" +  par +"\", null);");
 298             logger.log(l, par, params);
 299             LoggerImpl.LogEvent e = events.poll();
 300             assertNonNull(e, "e", "    ");
 301             assertEquals(l, e.level, "e.level", "    ");
 302             assertEquals(e.msg, "bam", "e.msg", "    ");
 303             assertEquals(e.bundle, null, "e.bundle", "    ");
 304             assertEquals(e.params, null, "e.params", "    ");
 305             assertEquals(e.thrown, null, "e.thrown", "    ");
 306             assertEquals(e.bundle, null, "e.bundle", "    ");
 307             assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 308             assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 309             assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 310             assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 311             assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 312 
 313             params = new Object[] {new NotTrowing("one")};
 314             par = "bam {0}";
 315             System.out.println("  logger.log(" + l + ", \"" +  par +"\", new NotTrowing(\"one\"));");
 316             logger.log(l, par, params[0]);
 317             e = events.poll();
 318             assertNonNull(e, "e", "    ");
 319             assertEquals(l, e.level, "e.level", "    ");
 320             assertEquals(e.msg, par, "e.msg", "    ");
 321             assertEquals(e.bundle, null, "e.bundle", "    ");
 322             assertArrayEquals(e.params, params, "e.params", "    ");
 323             assertEquals(e.thrown, null, "e.thrown", "    ");
 324             assertEquals(e.bundle, null, "e.bundle", "    ");
 325             assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 326             assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 327             assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 328             assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 329             assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 330 
 331             params = new Object[] {new NotTrowing("fisrt"), new NotTrowing("second")};
 332             par = "bam {0} {1}";
 333             System.out.println("  logger.log(" + l + ", \"" +  par +"\", new NotTrowing(\"fisrt\"), new NotTrowing(\"second\"));");
 334             logger.log(l, par, params[0], params[1]);
 335             e = events.poll();
 336             assertNonNull(e, "e", "    ");
 337             assertEquals(l, e.level, "e.level", "    ");
 338             assertEquals(e.msg, par, "e.msg", "    ");
 339             assertEquals(e.bundle, null, "e.bundle", "    ");
 340             assertArrayEquals(e.params, params, "e.params", "    ");
 341             assertEquals(e.thrown, null, "e.thrown", "    ");
 342             assertEquals(e.bundle, null, "e.bundle", "    ");
 343             assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 344             assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 345             assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 346             assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 347             assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 348 
 349             params = new Object[] {new NotTrowing("third"), new NotTrowing("fourth")};
 350             par = "bam {2}";
 351             System.out.println("  logger.log(" + l + ", \"" +  par +"\", new Object[] {new NotTrowing(\"third\"), new NotTrowing(\"fourth\")});");
 352             logger.log(l, par, params);
 353             e = events.poll();
 354             assertNonNull(e, "e", "    ");
 355             assertEquals(l, e.level, "e.level", "    ");
 356             assertEquals(e.msg, par, "e.msg", "    ");
 357             assertEquals(e.bundle, null, "e.bundle", "    ");
 358             assertArrayEquals(e.params, params, "e.params", "    ");
 359             assertEquals(e.thrown, null, "e.thrown", "    ");
 360             assertEquals(e.bundle, null, "e.bundle", "    ");
 361             assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 362             assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 363             assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 364             assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 365             assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 366         }
 367 
 368         System.out.println("\nlogger.log(Level, String, Throwable)");
 369         for (Level l : Level.values()) {
 370             boolean logged = l.compareTo(Level.WARNING) >= 0;
 371             Object[][] cases = new Object[][] {
 372                 {null, null}, {null, new Throwable()}, {"biz", null}, {"boz", new Throwable()}
 373             };
 374             for (Object[] p : cases) {
 375                 String msg = (String)p[0];
 376                 Throwable thrown = (Throwable)p[1];
 377                 String par1 = msg == null ? "(String)null" : "\"" + msg + "\"";
 378                 String par2 = thrown == null ? "(Throwable)null" : "new Throwable()";
 379                 System.out.println("  logger.log(" + l + ", " +  par1 +", " + par2 + ")");
 380                 logger.log(l, msg, thrown);
 381                 LoggerImpl.LogEvent e = events.poll();
 382                 assertNonNull(e, "e", "    ");
 383                 assertEquals(e.level, l, "e.level", "    ");
 384                 assertEquals(e.msg, msg, "e.msg", "    ");
 385                 assertEquals(e.bundle, null, "e.bundle", "    ");
 386                 assertEquals(e.params, null, "e.params", "    ");
 387                 assertEquals(e.thrown, thrown, "e.thrown", "    ");
 388                 assertEquals(e.bundle, null, "e.bundle", "    ");
 389                 assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 390                 assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 391                 assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 392                 assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 393                 assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 394             }
 395         }
 396 
 397         System.out.println("\nlogger.log(Level, Supplier<String>, Throwable)");
 398         for (Level l : Level.values()) {
 399             boolean logged = l.compareTo(Level.WARNING) >= 0;
 400             Object[][] cases = new Object[][] {
 401                 {null, null}, {null, new Throwable()}, {"biz", null}, {"boz", new Throwable()}
 402             };
 403             for (Object[] p : cases) {
 404                 String msg = (String)p[0];
 405                 Throwable thrown = (Throwable)p[1];
 406                 final Object obj = msg == null ? null : logged ? new NotTrowing(msg) : new Throwing();
 407                 final Supplier<String> s = msg == null ? null : () -> obj.toString();
 408                 String par1 = msg == null ? "(Supplier<String>)null"
 409                         : logged ? "() -> new NotTrowing(\""+ msg+"\").toString()" : "new Throwing()";
 410                 String par2 = thrown == null ? "(Throwable)null" : "new Throwable()";
 411                 System.out.println("  logger.log(" + l + ", " +  par1 +", " + par2 + ")");
 412                 try {
 413                     logger.log(l, s, thrown);
 414                     if (logged && s == null) {
 415                         throw new RuntimeException("Expected NullPointerException not thrown for"
 416                                   + " logger.log(" + l + ", " +  par1 +", " + par2 + ")");
 417                     }
 418                 } catch (NullPointerException x) {
 419                     if (logged && s == null) {
 420                         System.out.println("    Got expected exception: " + x);
 421                         continue;
 422                     } else {
 423                         throw x;
 424                     }
 425                 }
 426                 LoggerImpl.LogEvent e = events.poll();
 427                 if (logged) {
 428                     assertNonNull(e, "e", "    ");
 429                     assertEquals(l, e.level, "e.level", "    ");
 430                     assertToString(e.msg, msg, 1, "e.msg", "    ");
 431                     assertEquals(e.bundle, null, "e.bundle", "    ");
 432                     assertEquals(e.params, null, "e.params", "    ");
 433                     assertEquals(e.thrown, thrown, "e.thrown", "    ");
 434                     assertEquals(e.bundle, null, "e.bundle", "    ");
 435                     assertEquals(e.callStack[0].getMethodName(), "log", "e.callStack[0].getMethodName()", "    ");
 436                     assertEquals(e.callStack[0].getClassName(), logger.getClass().getName(), "e.callStack[0].getClassName() ", "    ");
 437                     assertEquals(e.callStack[1].getMethodName(), "log", "e.callStack[1].getMethodName()", "    ");
 438                     assertEquals(e.callStack[1].getClassName(), System.Logger.class.getName(), "e.callStack[1].getClassName() ", "    ");
 439                     assertEquals(e.callStack[2].getMethodName(), "main", "e.callStack[2].getMethodName()", "    ");
 440                 } else {
 441                     assertEquals(e, null, "e", "    ");
 442                 }
 443             }
 444         }
 445 
 446         System.out.println("Checking that we have no spurious events in the queue");
 447         assertEquals(events.poll(), null, "events.poll()", "  ");
 448     }
 449 
 450     static void assertTrue(boolean test, String what, String prefix) {
 451         if (!test) {
 452             throw new RuntimeException("Expected true for " + what);
 453         }
 454         System.out.println(prefix + "Got expected " + what + ": " + test);
 455     }
 456     static void assertFalse(boolean test, String what, String prefix) {
 457         if (test) {
 458             throw new RuntimeException("Expected false for " + what);
 459         }
 460         System.out.println(prefix + "Got expected " + what + ": " + test);
 461     }
 462     static void assertToString(String actual, String expected, int count, String what, String prefix) {
 463         assertEquals(actual, expected + "["+count+"]", what, prefix);
 464     }
 465     static void assertEquals(Object actual, Object expected, String what, String prefix) {
 466         if (!Objects.equals(actual, expected)) {
 467             throw new RuntimeException("Bad " + what + ":"
 468                     + "\n\t expected: " + expected
 469                     + "\n\t   actual: " + actual);
 470         }
 471         System.out.println(prefix + "Got expected " + what + ": " + actual);
 472     }
 473     static void assertArrayEquals(Object[] actual, Object[] expected, String what, String prefix) {
 474         if (!Objects.deepEquals(actual, expected)) {
 475             throw new RuntimeException("Bad " + what + ":"
 476                     + "\n\t expected: " + expected == null ? "null" : Arrays.deepToString(expected)
 477                     + "\n\t   actual: " + actual == null ? "null" : Arrays.deepToString(actual));
 478         }
 479         System.out.println(prefix + "Got expected " + what + ": " + Arrays.deepToString(actual));
 480     }
 481     static void assertNonNull(Object actual, String what, String prefix) {
 482         if (Objects.equals(actual, null)) {
 483             throw new RuntimeException("Bad " + what + ":"
 484                     + "\n\t expected: non null"
 485                     + "\n\t   actual: " + actual);
 486         }
 487         System.out.println(prefix + "Got expected " + what + ": " + "non null");
 488     }
 489 }