| // Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | package stringconcat; | 
 |  | 
 | public class StringConcat { | 
 |   private static void check(String actual, String expected) { | 
 |     if (expected.equals(actual)) { | 
 |       return; | 
 |     } | 
 |     throw new AssertionError( | 
 |         "Test method failed: expected=[" + expected + "], actual=[" + actual + "]"); | 
 |   } | 
 |  | 
 |   // --------- used 'makeConcat' signatures --------- | 
 |  | 
 |   private static String makeConcat() { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(String s) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(char[] s) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(Object o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(boolean o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(char o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(byte o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(short o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(int o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(long o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(float o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(double o) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcat(Object o, String st, boolean z, | 
 |       char c, byte b, short s, int i, long l, float f, double d) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   // --------- used 'makeConcatWithConstants' signatures --------- | 
 |  | 
 |   private static String makeConcatWithConstants(String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(String s, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(char[] s, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(Object o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(boolean o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(char o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(byte o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(short o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(int o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(long o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(float o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(double o, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(Object o, String st, boolean z, | 
 |       char c, byte b, short s, int i, long l, float f, double d, String recipe) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants(int i, String s, String recipe, String sConst) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   private static String makeConcatWithConstants( | 
 |       int i, String s, String recipe, String sConstA, String sConstB, String sConstC) { | 
 |     throw new AssertionError("unreachable"); | 
 |   } | 
 |  | 
 |   // ------------------------------------------------ | 
 |  | 
 |   private static void testEmpty() { | 
 |     check(makeConcat(), ""); | 
 |     makeConcat(); | 
 |  | 
 |     check(makeConcatWithConstants("RECIPE:"), ""); | 
 |     check(makeConcatWithConstants("RECIPE:12-34"), "12-34"); | 
 |     makeConcatWithConstants("RECIPE:a"); | 
 |   } | 
 |  | 
 |   private static void testSingleValueString() { | 
 |     check(makeConcat("str"), "str"); | 
 |     check(makeConcat((String) null), "null"); | 
 |  | 
 |     check(makeConcatWithConstants("()", "RECIPE:prefix\u0001suffix"), "prefix()suffix"); | 
 |     check(makeConcatWithConstants("()", "RECIPE:prefix\u0001"), "prefix()"); | 
 |     check(makeConcatWithConstants("()", "RECIPE:\u0001suffix"), "()suffix"); | 
 |     check(makeConcatWithConstants("()", "RECIPE:\u0001"), "()"); | 
 |   } | 
 |  | 
 |   private static void testSingleValueArray() { | 
 |     // Unchecked since Array.toString() is non-deterministic. | 
 |     makeConcat(new char[] { 'a', 'b' }); | 
 |     makeConcatWithConstants(new char[] { 'a', 'b' }, "RECIPE:prefix\u0001suffix"); | 
 |   } | 
 |  | 
 |   private static void testSingleValueObject() { | 
 |     check(makeConcat((Object) "object"), "object"); | 
 |     check(makeConcat((Object) 1.234), "1.234"); | 
 |     check(makeConcat((Object) null), "null"); | 
 |  | 
 |     check( | 
 |         makeConcatWithConstants((Object) "object", "RECIPE:prefix\u0001suffix"), | 
 |         "prefixobjectsuffix"); | 
 |     check( | 
 |         makeConcatWithConstants((Object) 1.234, "RECIPE:prefix\u0001suffix"), | 
 |         "prefix1.234suffix"); | 
 |     check( | 
 |         makeConcatWithConstants((Object) null, "RECIPE:prefix\u0001suffix"), | 
 |         "prefixnullsuffix"); | 
 |   } | 
 |  | 
 |   private static void testSingleValuePrimitive() { | 
 |     check(makeConcat(true), "true"); | 
 |     check(makeConcat((char) 65), "A"); | 
 |     check(makeConcat((byte) 1), "1"); | 
 |     check(makeConcat((short) 2), "2"); | 
 |     check(makeConcat(3), "3"); | 
 |     check(makeConcat((long) 4), "4"); | 
 |     check(makeConcat((float) 5), "5.0"); | 
 |     check(makeConcat((double) 6), "6.0"); | 
 |  | 
 |     check(makeConcatWithConstants(true, "RECIPE:prefix\u0001suffix"), "prefixtruesuffix"); | 
 |     check(makeConcatWithConstants((char) 65, "RECIPE:prefix\u0001suffix"), "prefixAsuffix"); | 
 |     check(makeConcatWithConstants((byte) 1, "RECIPE:prefix\u0001suffix"), "prefix1suffix"); | 
 |     check(makeConcatWithConstants((short) 2, "RECIPE:prefix\u0001suffix"), "prefix2suffix"); | 
 |     check(makeConcatWithConstants(3, "RECIPE:prefix\u0001suffix"), "prefix3suffix"); | 
 |     check(makeConcatWithConstants((long) 4, "RECIPE:prefix\u0001suffix"), "prefix4suffix"); | 
 |     check(makeConcatWithConstants((float) 5, "RECIPE:prefix\u0001suffix"), "prefix5.0suffix"); | 
 |     check(makeConcatWithConstants((double) 6, "RECIPE:prefix\u0001suffix"), "prefix6.0suffix"); | 
 |   } | 
 |  | 
 |   private static void testAllTypes(Object o, String st, boolean z, | 
 |       char c, byte b, short s, int i, long l, float f, double d) { | 
 |     check(makeConcat(o, st, z, c, b, s, i, l, f, d), "nullstrtrueA12345.06.0"); | 
 |     check(makeConcatWithConstants(o, st, z, c, b, s, i, l, f, d, | 
 |         "RECIPE:[\u0001-\u0001>\u0001===\u0001\u0001\u0001alpha\u0001beta\u0001\u0001]\u0001"), | 
 |         "[null-str>true===A12alpha3beta45.0]6.0"); | 
 |   } | 
 |  | 
 |   private static void testInExceptionContext(Object o, String st, boolean z, | 
 |       char c, byte b, short s, int i, long l, float f, double d) { | 
 |     check(makeConcat((long) 4), "4"); | 
 |     try { | 
 |       check(makeConcat(o, st, z, c, b, s, i, l, f, d), "nullstrtrueA12345.06.0"); | 
 |       check(makeConcatWithConstants(o, st, z, c, b, s, i, l, f, d, | 
 |           "RECIPE:\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"), | 
 |           "nullstrtrueA12345.06.0"); | 
 |       try { | 
 |         check(makeConcat("try-try"), "try-try"); | 
 |         throw new IndexOutOfBoundsException(); | 
 |       } catch (NullPointerException re) { | 
 |         throw new AssertionError("UNREACHABLE"); | 
 |       } catch (Exception re) { | 
 |         check(makeConcatWithConstants(o, st, z, c, b, s, i, l, f, d, | 
 |             "RECIPE:(\u0001, \u0001, \u0001, \u0001, \u0001, " | 
 |                 + "\u0001, \u0001, \u0001, \u0001, \u0001)"), | 
 |             "(null, str, true, A, 1, 2, 3, 4, 5.0, 6.0)"); | 
 |         throw new IndexOutOfBoundsException(); | 
 |       } | 
 |     } catch (IndexOutOfBoundsException re) { | 
 |       check(makeConcat("bar"), "bar"); | 
 |       check(makeConcatWithConstants("foo", "RECIPE:bar -> \u0001"), "bar -> foo"); | 
 |       try { | 
 |         check(makeConcatWithConstants("inside", "RECIPE:try \u0001 try"), "try inside try"); | 
 |         throw new NullPointerException(); | 
 |       } catch (IndexOutOfBoundsException e) { | 
 |         throw new AssertionError("UNREACHABLE"); | 
 |       } catch (NullPointerException npe) { | 
 |         check(makeConcat(o, st, z, c, b, s, i, l, f, d), "nullstrtrueA12345.06.0"); | 
 |       } | 
 |     } catch (Exception re) { | 
 |       throw new AssertionError("UNREACHABLE"); | 
 |     } | 
 |   } | 
 |  | 
 |   private static void testConcatWitConstants() { | 
 |     check( | 
 |         makeConcatWithConstants( | 
 |             123, "abc", "RECIPE:arg=\u0001; const=\u0002; arg=\u0001", "str" | 
 |         ), | 
 |         "arg=123; const=str; arg=abc"); | 
 |     check( | 
 |         makeConcatWithConstants( | 
 |             123, "abc", "RECIPE:\u0002arg=\u0001\u0002arg=\u0001\u0002", | 
 |             "prefix-", "-infix-", "-suffix" | 
 |         ), | 
 |         "prefix-arg=123-infix-arg=abc-suffix"); | 
 |   } | 
 |  | 
 |   // ------------------------------------------------ | 
 |  | 
 |   public static void main(String[] args) { | 
 |     testEmpty(); | 
 |     testSingleValueString(); | 
 |     testSingleValueArray(); | 
 |     testSingleValueObject(); | 
 |     testSingleValuePrimitive(); | 
 |     testAllTypes(null, "str", true, (char) 65, | 
 |         (byte) 1, (short) 2, 3, (long) 4, (float) 5, (double) 6); | 
 |     testInExceptionContext(null, "str", true, (char) 65, | 
 |         (byte) 1, (short) 2, 3, (long) 4, (float) 5, (double) 6); | 
 |     testConcatWitConstants(); | 
 |   } | 
 | } |