/*
 * 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.javac;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.javac.CompilationUnit.GeneratedClassnameFinder;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import junit.framework.TestCase;

import java.util.List;

/**
 * Test-cases to check that we indeed obtain the correct list of nested types
 * with generated classNames by examining bytecodes using ASM.
 * 
 */
public class GeneratedClassnameFinderTest extends TestCase {
  enum EnumClass {
    A, B, C,
  }

  static class MainClass {
    static class NestedClass {
      void foo() {
        TestInterface c = new TestInterface() {
          public void foo() {
          }
        };
        EnumClass et = EnumClass.A;
        switch (et) {
          case A:
            break;
        }
        TestInterface d = new TestInterface() {
          public void foo() {
          }
        };
      }
    }

    void foo() {
      TestInterface a = new TestInterface() {
        public void foo() {
        }
      };
      EnumClass et = EnumClass.A;
      switch (et) {
        case A:
          break;
      }
      TestInterface b = new TestInterface() {
        public void foo() {
        }
      };
    }
  }
  interface TestInterface {
    void foo();
  }

  static final TreeLogger logger = new PrintWriterTreeLogger();

  public void test() {
    String mainClassName = this.getClass().getName().replace('.', '/');
    assertEquals(
        4,
        new GeneratedClassnameFinder(logger, mainClassName).getClassNames().size());
    assertEquals(0, new GeneratedClassnameFinder(logger, mainClassName
        + "$EnumClass").getClassNames().size());
    assertEquals(0, new GeneratedClassnameFinder(logger, mainClassName
        + "$TestInterface").getClassNames().size());
    assertEquals(4, new GeneratedClassnameFinder(logger, mainClassName
        + "$MainClass").getClassNames().size());
    assertEquals(2, new GeneratedClassnameFinder(logger, mainClassName
        + "$MainClass$NestedClass").getClassNames().size());
  }

  public void testAbstractNative() {
    assertEquals(2, new AbstractNativeTester().getGeneratedClasses().size());
  }

  public void testAnonymous() {
    assertEquals(1, new AnonymousTester().getGeneratedClasses().size());
  }

  public void testEnum() {
    assertEquals(0, new EnumTester().getGeneratedClasses().size());
  }

  public void testJavacWeirdness() {
    List<String> classNames = new JavacWeirdnessTester().getGeneratedClasses();
    assertEquals(3, classNames.size());
    assertTrue(classNames.get(0) + " should not contain Foo",
        classNames.get(0).indexOf("Foo") == -1);
    assertTrue(classNames.get(1) + " should contain Foo",
        classNames.get(1).indexOf("Foo") != -1);
    assertTrue(classNames.get(2) + " should contain Foo",
        classNames.get(2).indexOf("Foo") != -1);
  }

  public void testNamedLocal() {
    assertEquals(2, new NamedLocalTester().getGeneratedClasses().size());
  }

  public void testNested() {
    assertEquals(2, new NestedTester().getGeneratedClasses().size());
  }

  public void testStatic() {
    assertEquals(0, new StaticTester().getGeneratedClasses().size());
  }

  public void testTopLevel() {
    assertEquals(1, new TopLevelTester().getGeneratedClasses().size());
  }


}

/**
 * For testing a class containing anonymous inner classes with abstract and
 * native methods.
 */
class AbstractNativeTester {
  void foo() {
    abstract class Fooer {
      abstract void foo();
    }
    Fooer a = new Fooer() {
      native void foo();
    };
    a.foo();
  }

  List<String> getGeneratedClasses() {
    return (new GeneratedClassnameFinder(GeneratedClassnameFinderTest.logger,
        this.getClass().getName().replace('.', '/'))).getClassNames();
  }
}

/**
 * For testing a class containing an anonymous inner class.
 */
class AnonymousTester {
  interface TestInterface {
    void foo();
  }

  void foo() {
    TestInterface a = new TestInterface() {
      public void foo() {
      }
    };
    a.foo();
  }

  List<String> getGeneratedClasses() {
    return (new GeneratedClassnameFinder(GeneratedClassnameFinderTest.logger,
        this.getClass().getName().replace('.', '/'))).getClassNames();
  }
}

/**
 * For testing a class with an Enum (for which javac generates a synthetic
 * class).
 */
class EnumTester {
  enum EnumClass {
    A, B, C,
  }

  void foo() {
    EnumClass et = EnumClass.A;
    switch (et) {
      case A:
        break;
    }
  }

  List<String> getGeneratedClasses() {
    return (new GeneratedClassnameFinder(GeneratedClassnameFinderTest.logger,
        this.getClass().getName().replace('.', '/'))).getClassNames();
  }
}

/**
 * Javac generates weird code for the following class. It passes a synthetic
 * class ...Tester$1 as a first parameter to constructors of Fuji and Granny.
 * Normally, it generates the synthetic class, but in this case, it decides not
 * to generate the class. However, the bytecode still has reference to the
 * synthetic class -- it just passes null for the synthetic class.
 * 
 * This code also tests for an anonymous class extending a named local class.
 */
class JavacWeirdnessTester {
  private abstract static class Apple implements Fruit {
  }

  private static interface Fruit {
  }

  private static class Fuji extends Apple {
  }

  private static class Granny extends Apple {
  }

  private static volatile boolean TRUE = true;

  List<String> getGeneratedClasses() {
    return (new GeneratedClassnameFinder(GeneratedClassnameFinderTest.logger,
        this.getClass().getName().replace('.', '/'))).getClassNames();
  }

  private void assertEquals(Object a, Object b) {
  }

  private void testArrayStore() {
    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);
  }

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

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

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

  private 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);
  }
}

/**
 * For testing a class with a generated name like $1Foo.
 */
class NamedLocalTester {
  void foo1() {
    if (false) {
      class Foo {
        void foo() {
        }
      }
      new Foo().foo();
    }
  }

  void foo2() {
    class Foo {
      void foo() {
      }
    }
    new Foo().foo();
  }

  void foo3() {
    class Foo {
      void foo() {
      }
    }
    new Foo().foo();
  }

  List<String> getGeneratedClasses() {
    return (new GeneratedClassnameFinder(GeneratedClassnameFinderTest.logger,
        this.getClass().getName().replace('.', '/'))).getClassNames();
  }
}

/**
 * For testing that nested classes are examined recursively for classes with
 * generated names.
 */
class NestedTester {
  class MainClass {
    class NestedClass {
      void foo() {
        class Foo {
          void bar() {
          }
        }
        new Foo().bar();
      }
    }

    void foo() {
      class Foo {
        void bar() {
        }
      }
      new Foo().bar();
    }
  }

  List<String> getGeneratedClasses() {
    return (new GeneratedClassnameFinder(GeneratedClassnameFinderTest.logger,
        this.getClass().getName().replace('.', '/'))).getClassNames();
  }
}

/**
 * For testing classes with private static members (javac generates a synthetic
 * class here but the jdt does not).
 */
class StaticTester {
  private abstract static class Apple implements Fruit {
  }

  private static interface Fruit {
    void bar();
  }

  private static class Fuji extends Apple {
    public void bar() {
    }
  }

  private static class Granny extends Apple {
    public void bar() {
    }
  }

  List<String> getGeneratedClasses() {
    return (new GeneratedClassnameFinder(GeneratedClassnameFinderTest.logger,
        this.getClass().getName().replace('.', '/'))).getClassNames();
  }

}

/**
 * For testing that a class with a generated name inside another top-level class
 * is found.
 */
class TopLevelTester {
  public void foo() {
    GeneratedClassnameFinderTest.TestInterface a = new GeneratedClassnameFinderTest.TestInterface() {
      public void foo() {
      }
    };
  }

  List<String> getGeneratedClasses() {
    return (new GeneratedClassnameFinder(GeneratedClassnameFinderTest.logger,
        this.getClass().getName().replace('.', '/'))).getClassNames();
  }
}
