/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.jjs.test;

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.junit.client.GWTTestCase;

import junit.framework.Assert;

import java.util.EventListener;

/**
 * Miscellaneous tests of the Java to JavaScript compiler.
 */
@SuppressWarnings("unused")
public class CompilerTest extends GWTTestCase {
  interface MyMap {
    Object get(String key);
  }

  interface Silly { }

  interface SillyComparable<T extends Silly> extends Comparable<T> {
    int compareTo(T obj);
  }

  private abstract static class AbstractSuper {
    public static String foo() {
      if (FALSE) {
        // prevent inlining
        return foo();
      }
      return "AbstractSuper";
    }
  }

  private abstract static class Apple implements Fruit {
  }

  private abstract static class Bm2BaseEvent {
  }

  private abstract static class Bm2ComponentEvent extends Bm2BaseEvent {
  }

  private static class Bm2KeyNav<E extends Bm2ComponentEvent> implements
      Bm2Listener<E> {
    public int handleEvent(Bm2ComponentEvent ce) {
      return 5;
    }
  }

  private interface Bm2Listener<E extends Bm2BaseEvent> extends EventListener {
    int handleEvent(E be);
  }

  /**
   * Used in {@link #testSwitchOnEnumTypedThis()}.
   */
  private static  enum ChangeDirection {
    NEGATIVE, POSITIVE;

    public String getText() {
      switch (this) {
        case POSITIVE:
          return "POSITIVE";
        case NEGATIVE:
          return "NEGATIVE";
        default:
          throw new IllegalArgumentException("Unhandled change direction: "
              + this);
      }
    }
  }

  private static class ConcreteSub extends AbstractSuper {
    public static String foo() {
      if (FALSE) {
        // prevent inlining
        return foo();
      }
      return "ConcreteSub";
    }
  }

  private static interface Fruit {
  }

  private static class Fuji extends Apple {
  }

  private static class Granny extends Apple {
  }

  private static class NonSideEffectCauser {
    public static final String NOT_A_COMPILE_TIME_CONSTANT = null;
  }

  private static class SideEffectCauser {
    private static Object instance = new Object();

    static {
      CompilerTest.sideEffectChecker++;
    }

    public static Object causeClinitSideEffect() {
      return instance;
    }
  }

  private static class SideEffectCauser2 {
    static {
      CompilerTest.sideEffectChecker++;
    }

    public static Object causeClinitSideEffect() {
      return null;
    }
  }

  private static class SideEffectCauser3 {
    static {
      CompilerTest.sideEffectChecker++;
    }

    public static void causeClinitSideEffect() {
    }
  }

  private static class SideEffectCauser4 {
    public static String causeClinitSideEffectOnRead = "foo";

    static {
      CompilerTest.sideEffectChecker++;
    }
  }

  private static class SideEffectCauser5 {
    public static String causeClinitSideEffectOnRead = "bar";

    static {
      CompilerTest.sideEffectChecker++;
    }
  }

  private static class SideEffectCauser6 extends SideEffectCauser6Super {
    public static String causeClinitSideEffectOnRead = "bar";
  }

  private static class SideEffectCauser6Super {
    static {
      CompilerTest.sideEffectChecker++;
    }
  }

  /**
   * Ensures that a superclass's clinit is run before supercall arguments are
   * evaluated.
   */
  private static class SideEffectCauser7 extends SideEffectCauser7Super {
    public SideEffectCauser7() {
      super(SideEffectCauser7Super.SHOULD_BE_TRUE);
    }
  }

  private static class SideEffectCauser7Super {
    public static boolean SHOULD_BE_TRUE = false;

    static {
      SHOULD_BE_TRUE = true;
    }

    public SideEffectCauser7Super(boolean should_be_true) {
      if (should_be_true) {
        CompilerTest.sideEffectChecker++;
      }
    }
  }

  /**
   * Used in test {@link #testPrivateOverride()}.
   */
  private static class TpoChild extends TpoParent {
    @Override
    public int foo() {
      return callSuper();
    }

    private int callSuper() {
      return super.foo();
    }
  }

  /**
   * Used in test {@link #testPrivateOverride()}.
   */
  private static class TpoGrandparent {
    public int foo() {
      return 0;
    }
  }

  /**
   * Used in test {@link #testPrivateOverride()}.
   */
  private static class TpoJsniChild extends TpoJsniParent {
    @Override
    public native int foo() /*-{
      return this.@com.google.gwt.dev.jjs.test.CompilerTest$TpoJsniChild::callSuper()();
    }-*/;

    private int callSuper() {
      return super.foo();
    }
  }

  /**
   * Used in test {@link #testPrivateOverride()}.
   */
  private static class TpoJsniGrandparent {
    public int foo() {
      return 0;
    }
  }

  /**
   * Used in test {@link #testPrivateOverride()}.
   */
  private static class TpoJsniParent extends TpoJsniGrandparent {
    @Override
    public native int foo() /*-{
      // This should call callSuper in TpoJsniParent, not the one
      // in TpoJsniChild      
      return this.@com.google.gwt.dev.jjs.test.CompilerTest$TpoJsniParent::callSuper()();
    }-*/;

    private int callSuper() {
      return super.foo();
    }
  }

  /**
   * Used in test {@link #testPrivateOverride()}.
   */
  private static class TpoParent extends TpoGrandparent {
    @Override
    public int foo() {
      // This should call the callSuper in TpoJsniParent, not the one
      // in TpoJsniChild
      return callSuper();
    }

    private int callSuper() {
      return super.foo();
    }
  }

  private static final class UninstantiableType {
    public Object field;
    public int intField;

    private UninstantiableType() {
    }

    public int returnInt() {
      return intField;
    }

    public Object returnNull() {
      return null;
    }
  }

  private static volatile boolean FALSE = false;

  private static int sideEffectChecker;

  private static volatile int THREE = 3;

  private static volatile boolean TRUE = true;

  private static volatile boolean volatileBoolean;
  private static volatile int volatileInt;
  private static volatile long volatileLong;
  private static volatile UninstantiableType volatileUninstantiableType;

  private static native void accessUninstantiableField(UninstantiableType u) /*-{
    u.@com.google.gwt.dev.jjs.test.CompilerTest$UninstantiableType::field.toString();
  }-*/;

  private static native void accessUninstantiableMethod(UninstantiableType u) /*-{
    u.@com.google.gwt.dev.jjs.test.CompilerTest$UninstantiableType::returnNull()();
  }-*/;

  private static String barShouldInline() {
    return "bar";
  }

  private static void foo(String string) {
  }

  private static void foo(Throwable throwable) {
  }

  private static native String jsniReadSideEffectCauser5() /*-{
    return @com.google.gwt.dev.jjs.test.CompilerTest$SideEffectCauser5::causeClinitSideEffectOnRead;
  }-*/;

  private Integer boxedInteger = 0;

  @Override
  public String getModuleName() {
    return "com.google.gwt.dev.jjs.CompilerSuite";
  }

  public void testArrayAccessSideEffect() {
    int index = 1;
    int[] array = null;
    try {
      // index should be set before exception is thrown
      array[index = 2]++;
      fail("null reference expected");
    } catch (Exception e) {
      // expected
    }
    assertEquals(2, index);
  }

  public void testArrayStore() {
    Object[][] oaa;
    oaa = new Object[4][4];
    oaa[0][0] = "foo";
    assertEquals(oaa[0][0], "foo");

    oaa = new Object[4][];
    oaa[0] = new Object[4];
    oaa[0][0] = "bar";
    assertEquals(oaa[0][0], "bar");

    Apple[] apple = TRUE ? new Granny[3] : new Apple[3];
    Apple g = TRUE ? (Apple) new Granny() : (Apple) new Fuji();
    Apple a = apple[0] = g;
    assertEquals(g, a);

    byte[] bytes = new byte[10];
    bytes[0] = (byte) '1';
    assertEquals(49, bytes[0]);
  }

  /**
   * Issue 3064: when the implementation of an interface comes from a
   * superclass, it can be necessary to add a bridge method that overrides the
   * interface method and calls the inherited method.
   */
  public void testBridgeMethods1() {
    abstract class AbstractFoo {
      public int compareTo(AbstractFoo o) {
        return 0;
      }
    }

    class MyFoo extends AbstractFoo implements Comparable<AbstractFoo> {
    }

    /*
     * This subclass adds an extra curve ball: only one bridge method should be
     * created, in class MyFoo. MyFooSub should not get its own but instead use
     * the inherited one. Otherwise, two final methods with identical signatures
     * would override each other.
     */
    class MyFooSub extends MyFoo {
    }

    Comparable<AbstractFoo> comparable1 = new MyFooSub();
    assertEquals(0, comparable1.compareTo(new MyFoo()));

    Comparable<AbstractFoo> comparable2 = new MyFoo();
    assertEquals(0, comparable2.compareTo(new MyFooSub()));
  }

  /**
   * Issue 3304. Doing superclasses first is tricky when the superclass is a raw
   * type.
   */
  @SuppressWarnings("unchecked")
  public void testBridgeMethods2() {
    Bm2KeyNav<?> obs = new Bm2KeyNav() {
    };
    assertEquals(5, obs.handleEvent(null));
  }

  /**
   * When adding a bridge method, be sure to handle transitive overrides
   * relationships.
   */
  public void testBridgeMethods3() {
    class AbstractFoo implements Silly {
      public int compareTo(AbstractFoo obj) {
        if (FALSE) {
          return compareTo(obj);
        }
        return 0;
      }
    }
    class MyFoo extends AbstractFoo implements SillyComparable<AbstractFoo> {
    }
    
    assertEquals(0, new MyFoo().compareTo(new MyFoo()));
  }

  /**
   * Issue 3517. Sometimes JDT adds a bridge method when a subclass's method
   * differs only by return type. In some versions of GWT, this has resulted in
   * a bridge method overriding its own target, and eventually TypeTightener
   * producing an infinite recursion.
   */
  public void testBridgeMethods4() {
    abstract class MyMapAbstract<V> implements MyMap {
      public String get(String key) {
        return null;
      }
    }

    final class MyMapImpl<V> extends MyMapAbstract<V> {
    }

    MyMapImpl<String> mmap = new MyMapImpl<String>();
    assertNull(mmap.get("foo"));
  }

  public void testCastOptimizer() {
    Granny g = new Granny();
    Apple a = g;
    Fruit f = g;
    a = (Apple) f;
    g = (Granny) a;
    g = (Granny) f;
  }

  public void testClassLiterals() {
    if (Object.class.getName().startsWith("Class$")) {
      // If class metadata is disabled
      return;
    }

    assertEquals("void", void.class.toString());
    assertEquals("int", int.class.toString());
    assertEquals("class java.lang.String", String.class.toString());
    assertEquals("class com.google.gwt.dev.jjs.test.CompilerTest",
        CompilerTest.class.toString());
    assertEquals(
        "class com.google.gwt.dev.jjs.test.CompilerTest$UninstantiableType",
        UninstantiableType.class.toString());
    assertEquals("interface com.google.gwt.dev.jjs.test.CompilerTest$Fruit",
        Fruit.class.toString());
    assertEquals("class [I", int[].class.toString());
    assertEquals("class [Ljava.lang.String;", String[].class.toString());
    assertEquals("class [Lcom.google.gwt.dev.jjs.test.CompilerTest;",
        CompilerTest[].class.toString());
    assertEquals(
        "class [Lcom.google.gwt.dev.jjs.test.CompilerTest$UninstantiableType;",
        UninstantiableType[].class.toString());
    assertEquals("class [Lcom.google.gwt.dev.jjs.test.CompilerTest$Fruit;",
        Fruit[].class.toString());
  }

  public void testClinitSideEffectInlining() {
    sideEffectChecker = 0;
    SideEffectCauser.causeClinitSideEffect();
    assertEquals(1, sideEffectChecker);
    SideEffectCauser2.causeClinitSideEffect();
    assertEquals(2, sideEffectChecker);
    SideEffectCauser3.causeClinitSideEffect();
    assertEquals(3, sideEffectChecker);
    String foo = SideEffectCauser4.causeClinitSideEffectOnRead;
    assertEquals(4, sideEffectChecker);
    jsniReadSideEffectCauser5();
    assertEquals(5, sideEffectChecker);
    foo = SideEffectCauser6.causeClinitSideEffectOnRead;
    assertEquals(6, sideEffectChecker);
    new SideEffectCauser7();
    assertEquals(7, sideEffectChecker);
    String checkRescued = NonSideEffectCauser.NOT_A_COMPILE_TIME_CONSTANT;
    assertEquals(null, checkRescued);
  }

  public void testConditionals() {
    assertTrue(TRUE ? TRUE : FALSE);
    assertFalse(FALSE ? TRUE : FALSE);
    assertFalse(TRUE ? FALSE : TRUE);
    assertTrue(FALSE ? FALSE : TRUE);

    assertTrue(true ? TRUE : FALSE);
    assertFalse(false ? TRUE : FALSE);
    assertFalse(true ? FALSE : TRUE);
    assertTrue(false ? FALSE : TRUE);

    assertTrue(TRUE ? true : FALSE);
    assertFalse(FALSE ? true : FALSE);
    assertFalse(TRUE ? false : TRUE);
    assertTrue(FALSE ? false : TRUE);

    assertTrue(TRUE ? TRUE : false);
    assertFalse(FALSE ? TRUE : false);
    assertFalse(TRUE ? FALSE : true);
    assertTrue(FALSE ? FALSE : true);
  }

  public void testDeadCode() {
    while (returnFalse()) {
      break;
    }

    do {
      break;
    } while (false);

    do {
      break;
    } while (returnFalse());

    for (; returnFalse();) {
    }

    boolean check = false;
    for (check = true; returnFalse(); fail()) {
      fail();
    }
    assertTrue(check);

    if (returnFalse()) {
      fail();
    } else {
    }

    if (!returnFalse()) {
    } else {
      fail();
    }

    // For these following tests, make sure that side effects in conditions
    // get propagated, even if they cause introduction of dead code.
    // 
    boolean b = false;
    if ((b = true) ? true : true) {
    }
    assertTrue(b);

    boolean c = true;
    int val = 0;
    for (val = 1; c = false; ++val) {
    }
    assertFalse(c);

    boolean d = true;
    while (d = false) {
    }
    assertFalse(d);

    boolean e = true;
    if (true | (e = false)) {
    }
    assertFalse(e);
  }

  /**
   * Test that code considered unreachable by the JDT does not crash the GWT
   * compiler.
   */
  public void testDeadCode2() {
    class SillyList {
    }

    final SillyList outerLocalVariable = new SillyList();

    new SillyList() {
      private void pretendToUse(SillyList x) {
      }

      void blah() {
        if (true) {
          throw new RuntimeException();
        }
        /*
         * This code is unreachable, and so outerLocalVariable is never actually
         * read by reachable code.
         */
        pretendToUse(outerLocalVariable);
      }
    };
  }

  public void testDeadTypes() {
    if (false) {
      new Object() {
      }.toString();

      class Foo {
        void a() {
        }
      }
      new Foo().a();
    }
  }

  /**
   * Make sure that the compiler does not crash itself on user code that divides
   * by zero. The actual behavior varies by the numeric type and whether it is
   * hosted mode or web mode, but the important thing is that the compiler does
   * not crash.
   */
  public void testDivByZero() {
    assertTrue(Double.isNaN(0.0 / 0.0));

    try {
      // 0 / 0 is currently 0 in web mode.
      assertEquals(0, 0 / 0);
    } catch (ArithmeticException expected) {
      // expected in hosted mode
    }

    try {
      volatileLong = 0L / 0;
      fail("expected an ArithmeticException");
    } catch (ArithmeticException expected) {
      // expected
    }

    assertTrue(Double.isNaN(0.0 % 0.0));

    try {
      // 0 % 0 is currently NaN in web mode.
      assertTrue(Double.isNaN(0 % 0));
    } catch (ArithmeticException expected) {
      // expected in hosted mode
    }

    try {
      volatileLong = 0L % 0;
      fail("expected an ArithmeticException");
    } catch (ArithmeticException expected) {
      // expected
    }
  }

  public void testEmptyBlockStatements() {
    boolean b = false;
    while (b) {
    }

    do {
    } while (b);

    for (; b;) {
    }

    for (;;) {
      break;
    }

    if (b) {
    }

    if (b) {
    } else {
      b = false;
    }

    if (b) {
    } else {
    }
  }

  public native void testEmptyBlockStatementsNative() /*-{
    var b = false;
    while (b) {
    }

    do {
    } while (b);

    for (; b; ) {
    }

    for (;;) {
      break;
    }

    if (b) {
    }

    if (b) {
    } else {
      b = false;
    }

    if (b) {
    } else {
    }
  }-*/;

  // CHECKSTYLE_OFF

  public void testEmptyStatements() {
    boolean b = false;

    while (b);

    do; while (b);

    for (; b;);

    for (;;)
      break;

    if (b)
      ;

    if (b)
      ;
    else
      b = false;

    if (b)
      ;
    else
      ;
  }

  // CHECKSTYLE_ON

  public native void testEmptyStatementsNative() /*-{
    var b = false;

    while (b);

    do; while (b);

    for (; b;);

    for (;;)
      break;

    if (b)
      ;

    if (b)
      ;
    else
      b = false;

    if (b)
      ;
    else
      ;
  }-*/;

  public void testEmptyTryBlock() {
    int x = 0;
    try {
    } finally {
      x = 1;
    }
    assertEquals(1, x);
  }

  public void testForStatement() {
    {
      int i;
      for (i = 0; i < 10; ++i) {
      }
      assertEquals(i, 10);
    }
    {
      int i, c;
      for (i = 0, c = 10; i < c; ++i) {
      }
      assertEquals(i, 10);
      assertEquals(c, 10);
    }
    {
      int j = 0;
      for (int i = 0; i < 10; ++i) {
        ++j;
      }
      assertEquals(j, 10);
    }
    {
      int j = 0;
      for (int i = 0, c = 10; i < c; ++i) {
        ++j;
      }
      assertEquals(j, 10);
    }
  }

  /**
   * Issue #615: Internal Compiler Error.
   */
  public void testImplicitNull() {
    boolean b;
    String test = ((((b = true) ? null : null) + " ") + b);
    assertTrue(b);
    assertEquals("null true", test);
  }

  /**
   * Issue 2886: inlining should cope with local variables that do not have an
   * explicit declaration node.
   */
  public void testInliningBoxedIncrement() {
    // should not actually inline, because it has a temp variable
    incrementBoxedInteger();
    assertEquals((Integer) 1, boxedInteger);
  }

  public void testJavaScriptReservedWords() {
    boolean delete = TRUE;
    for (int in = 0; in < 10; ++in) {
      assertTrue(in < 10);
      assertTrue(delete);
    }
  }

  public void testLabels() {
    int i = 0, j = 0;
    outer : for (i = 0; i < 1; ++i) {
      inner : for (j = 0; j < 1; ++j) {
        break outer;
      }
      fail();
    }
    assertEquals(0, i);
    assertEquals(0, j);

    outer : for (i = 0; i < 1; ++i) {
      inner : for (j = 0; j < 1; ++j) {
        continue outer;
      }
      fail();
    }
    assertEquals(1, i);
    assertEquals(0, j);

    outer : for (i = 0; i < 1; ++i) {
      inner : for (j = 0; j < 1; ++j) {
        break inner;
      }
    }
    assertEquals(1, i);
    assertEquals(0, j);

    outer : for (i = 0; i < 1; ++i) {
      inner : for (j = 0; j < 1; ++j) {
        continue inner;
      }
    }
    assertEquals(1, i);
    assertEquals(1, j);

    /*
     * Issue 2069: a default with a break should not be stripped unless the
     * break has no label.
     */
    outer : while (true) {
      switch (THREE) {
        case 0:
        case 1:
          break;
        default:
          break outer;
      }
      fail("should not be reached");
    }

    /*
     * Issue 2770: labeled breaks in a switch statement with no default case
     * should not be pruned.
     */
    outer : while (true) {
      switch (THREE) {
        case 0:
        case 1:
        case 2:
        case 3:
          break outer;
        case 4:
        case 5:
          break;
      }
    }
  }

  public void testLocalClasses() {
    class Foo {
      public Foo(int j) {
        assertEquals(1, j);
      };
    }
    final int i;
    new Foo(i = 1) {
      {
        assertEquals(1, i);
      }
    };
    assertEquals(1, i);
  }

  public void testLocalRefs() {
    final String foo = TRUE ? "foo" : "bar";
    final String bar = TRUE ? "bar" : "foo";
    String result = new Object() {

      private String a = foo;

      {
        a = foo;
      }

      @Override
      public String toString() {
        return new Object() {

          private static final String constantString = "wallawalla";

          private String ai = foo;

          {
            ai = foo;
          }

          @Override
          public String toString() {
            // this line used to cause ICE due to no synthetic path to bar
            bar.valueOf(false);

            assertEquals("wallawalla", constantString);
            return foo + a + ai;
          }

        }.toString() + a;
      }

    }.toString();
    assertEquals(result, "foofoofoofoo");
  }

  public void testNotOptimizations() {
    assertFalse(!true);
    assertTrue(!false);

    assertTrue(!(TRUE == FALSE));
    assertFalse(!(TRUE != FALSE));

    assertFalse(!(3 < 4));
    assertFalse(!(3 <= 4));
    assertTrue(!(3 > 4));
    assertTrue(!(3 >= 4));

    assertTrue(!(4 < 3));
    assertTrue(!(4 <= 3));
    assertFalse(!(4 > 3));
    assertFalse(!(4 >= 3));

    assertTrue(!!TRUE);
    assertFalse(!!FALSE);
  }

  public void testNullFlow() {
    UninstantiableType f = null;

    try {
      f.returnNull().toString();
      fail();
    } catch (NullPointerException e) {
      // hosted mode
    } catch (JavaScriptException e) {
      // web mode
    }

    try {
      UninstantiableType[] fa = null;
      fa[4] = null;
      fail();
    } catch (NullPointerException e) {
      // hosted mode
    } catch (JavaScriptException e) {
      // web mode
    }
  }

  public void testNullFlowArray() {
    UninstantiableType[] uta = new UninstantiableType[10];
    assertEquals(uta.length, 10);
    assertEquals(uta[0], null);
    uta[1] = null;
    assertEquals(uta[1], null);
  }

  public void testNullFlowOverloads() {
    foo((Throwable) null);
    foo((String) null);
  }

  public void testNullFlowVsClassCastPrecedence() {
    try {
      ((UninstantiableType) new Object()).returnNull();
      fail();
    } catch (ClassCastException e) {
      // success
    }
  }

  public void testOuterSuperThisRefs() {
    new B();
  }

  /**
   * Test that calling a private instance method does not accidentally call
   * another private method that appears to override it. Private methods don't
   * truly override each other.
   */
  public void testPrivateOverride() {
    assertEquals(0, new TpoChild().foo());
    assertEquals(0, new TpoJsniChild().foo());
  }

  public void testReturnStatementInCtor() {
    class Foo {
      int i;

      Foo(int i) {
        this.i = i;
        if (i == 0) {
          return;
        } else if (i == 1) {
          return;
        }
        return;
      }
    }
    assertEquals(new Foo(0).i, 0);
    assertEquals(new Foo(1).i, 1);
    assertEquals(new Foo(2).i, 2);
  }

  public void testStaticMethodResolution() {
    // Issue 2922
    assertEquals("AbstractSuper", AbstractSuper.foo());
  }

  public void testStringOptimizations() {
    assertEquals("Herro, AJAX", "Hello, AJAX".replace('l', 'r'));
    assertEquals('J', "Hello, AJAX".charAt(8));
    assertEquals(11, "Hello, AJAX".length());
    assertFalse("Hello, AJAX".equals("me"));
    assertTrue("Hello, AJAX".equals("Hello, AJAX"));
    assertTrue("Hello, AJAX".equalsIgnoreCase("HELLO, ajax"));
    assertEquals("hello, ajax", "Hello, AJAX".toLowerCase());

    assertEquals("foobar", "foo" + barShouldInline());
    assertEquals("1bar", 1 + barShouldInline());
    assertEquals("fbar", 'f' + barShouldInline());
    assertEquals("truebar", true + barShouldInline());
    assertEquals("3.5bar", 3.5 + barShouldInline());
    assertEquals("3.5bar", 3.5f + barShouldInline());
    assertEquals("27bar", 27L + barShouldInline());
    assertEquals("nullbar", null + barShouldInline());
  }

  public void testSubclassStaticInnerAndClinitOrdering() {
    new CheckSubclassStaticInnerAndClinitOrdering();
  }
  
  public void testSwitchOnEnumTypedThis() {
    assertEquals("POSITIVE", ChangeDirection.POSITIVE.getText());
    assertEquals("NEGATIVE", ChangeDirection.NEGATIVE.getText());
  }
  
  public void testSwitchStatement() {
    switch (0) {
      case 0:
        // Once caused an ICE.
        int test;
        break;
    }
  }

  /**
   * Tests cases where the compiler will convert to a simple if or block.
   */
  public void testSwitchStatementConversions() {
    int i = 1;

    switch (i) {
      case 1:
        i = 2;
    }
    assertEquals(2, i);

    switch (i) {
      case 1:
        i = 3;
    }
    assertEquals(2, i);

    switch (i) {
      default:
        i = 3;
    }
    assertEquals(3, i);
  }

  public void testSwitchStatementEmpty() {
    switch (0) {
    }
  }

  public void testSwitchStatementFallthroughs() {
    int i = 1;
    switch (i) {
      case 1:
        i = 2;
        // fallthrough
      case 2:
        break;
      case 3:
        fail("Shouldn't get here");
    }
    assertEquals(2, i);

    switch (i) {
      case 1:
        break;
      case 2:
        i = 3;
        break;
      case 3:
        break;
      case 4:
        fail("Shouldn't get here");
        break;
    }
    assertEquals(3, i);
  }

  public void testSwitchStatementWithUsefulDefault() {
    switch (1) {
      case 1:
      case 2:
      case 3: {
        break;
      }
      case 4:
      case 5:
      case 6:
      default:
        fail("Shouldn't get here");
        break;
    }
  }

  public void testSwitchStatementWithUselessCases() {
    switch (1) {
      case 1:
      case 2:
      case 3: {
        break;
      }
      case 4:
      case 5:
      case 6:
      default:
        break;
    }
  }

  public void testSwitchStatementWontRemoveExpression() {
    class Foo {
      boolean setFlag;

      int setFlag() {
        setFlag = true;
        return 3;
      }
    }

    Foo foo = new Foo();
    switch (foo.setFlag()) {
      case 3:
        break;
    }

    // Make sure that compiler didn't optimize away the switch statement's
    // expression
    assertTrue(foo.setFlag);
  }

  public void testUnaryPlus() {
    int x, y = -7;
    x = +y;
    assertEquals(-7, x);
  }

  public void testUninstantiableAccess() {
    UninstantiableType u = null;

    try {
      accessUninstantiableField(u);
      fail("Expected JavaScriptException");
    } catch (JavaScriptException expected) {
    }

    try {
      accessUninstantiableMethod(u);
      fail("Expected JavaScriptException");
    } catch (JavaScriptException expected) {
    }

    try {
      volatileUninstantiableType = (UninstantiableType) (new Object());
      fail("Expected ClassCastException");
    } catch (ClassCastException expected) {
    }

    try {
      volatileInt = u.intField++;
      fail("Expected NullPointerException (1)");
    } catch (Exception expected) {
    }

    try {
      volatileInt = u.intField--;
      fail("Expected NullPointerException (2)");
    } catch (Exception expected) {
    }

    try {
      volatileInt = ++u.intField;
      fail("Expected NullPointerException (3)");
    } catch (Exception expected) {
    }

    try {
      volatileInt = --u.intField;
      fail("Expected NullPointerException (4)");
    } catch (Exception expected) {
    }

    try {
      u.intField = 0;
      /*
       * Currently, null.nullField gets pruned rather than being allowed to
       * execute its side effect of tripping an NPE.
       */
      // fail("Expected NullPointerException (5)");
    } catch (Exception expected) {
    }

    try {
      volatileBoolean = u.intField == 0;
      fail("Expected NullPointerException (6)");
    } catch (Exception expected) {
    }

    try {
      volatileBoolean = u.returnInt() == 0;
      fail("Expected NullPointerException (7)");
    } catch (Exception expected) {
    }
  }

  private void incrementBoxedInteger() {
    // the following will need a temporary variable created
    boxedInteger++;
  }

  private boolean returnFalse() {
    return false;
  }

}

class A {
  public abstract class AA {
  }
}

class B extends A {
  {
    new AA() {
    };
  }
}

// This construct used to cause an ICE
class CheckSubclassStaticInnerAndClinitOrdering extends Outer.StaticInner {
  private static class Foo {
  }

  private static final Foo FOO = new Foo();

  public CheckSubclassStaticInnerAndClinitOrdering() {
    this(FOO);
  }

  public CheckSubclassStaticInnerAndClinitOrdering(Foo foo) {
    // This used to be null due to clinit ordering issues
    Assert.assertNotNull(foo);
  }
}

class Outer {
  public static class StaticInner {
  }
}
