| /* |
| * Copyright 2007 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; |
| |
| /** |
| * Tests enum functionality. |
| */ |
| public class EnumsTest extends GWTTestCase { |
| |
| enum Basic { |
| A, B, C |
| } |
| |
| enum Complex { |
| A("X"), B("Y"), C("Z"); |
| |
| String value; |
| |
| Complex(String value) { |
| this.value = value; |
| } |
| |
| public String value() { |
| return value; |
| } |
| } |
| |
| enum Subclassing { |
| A { |
| @Override |
| public String value() { |
| return "X"; |
| } |
| }, |
| B { |
| @Override |
| public String value() { |
| return "Y"; |
| } |
| }, |
| C { |
| @Override |
| public String value() { |
| return "Z"; |
| } |
| }; |
| |
| public abstract String value(); |
| } |
| |
| enum BasicWithOverloadedValueOf { |
| A(1), B(2), C(3); |
| |
| private final int id; |
| |
| private BasicWithOverloadedValueOf(int id) { |
| this.id = id; |
| } |
| |
| public static BasicWithOverloadedValueOf valueOf(Integer id) { |
| for (BasicWithOverloadedValueOf val : BasicWithOverloadedValueOf.values()) { |
| if (val.id == id) { |
| return val; |
| } |
| } |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| /* |
| * An enum that will have a static impl generated, which will allow it to |
| * become ordinalizable. Once ordinalized, need to make sure it's clinit |
| * is handled properly. |
| */ |
| enum EnumWithStaticImpl { |
| VALUE1; |
| |
| // a mock formatter, to simulate the case that inspired this test |
| private static class MockFormat { |
| private String pattern; |
| |
| public MockFormat(String pattern) { |
| this.pattern = pattern; |
| } |
| |
| public String format(Long date) { |
| return pattern + date.toString(); |
| } |
| } |
| |
| private static final MockFormat FORMATTER = new MockFormat("asdf"); |
| |
| public String formatDate(long date) { |
| switch (this) { |
| case VALUE1: |
| return FORMATTER.format(new Long(date)); |
| default: |
| return null; |
| } |
| } |
| } |
| |
| @Override |
| public String getModuleName() { |
| return "com.google.gwt.dev.jjs.EnumsSuite"; |
| } |
| |
| public void testCompareTo() { |
| assertTrue(Basic.A.compareTo(Basic.valueOf("A")) == 0); |
| assertTrue(Basic.B.compareTo(Basic.A) > 0); |
| assertTrue(Basic.A.compareTo(Basic.B) < 0); |
| |
| assertTrue(Complex.A.compareTo(Complex.valueOf("A")) == 0); |
| assertTrue(Complex.B.compareTo(Complex.A) > 0); |
| assertTrue(Complex.A.compareTo(Complex.B) < 0); |
| |
| assertTrue(Subclassing.A.compareTo(Subclassing.valueOf("A")) == 0); |
| assertTrue(Subclassing.B.compareTo(Subclassing.A) > 0); |
| assertTrue(Subclassing.A.compareTo(Subclassing.B) < 0); |
| } |
| |
| public void testField() { |
| assertEquals("X", Complex.A.value); |
| assertEquals("Y", Complex.B.value); |
| assertEquals("Z", Complex.C.value); |
| } |
| |
| public void testGetDeclaringClass() { |
| assertEquals(Basic.class, Basic.A.getDeclaringClass()); |
| assertEquals(Complex.class, Complex.A.getDeclaringClass()); |
| assertEquals(Subclassing.class, Subclassing.A.getDeclaringClass()); |
| } |
| |
| public void testMethod() { |
| assertEquals("X", Complex.A.value()); |
| assertEquals("Y", Complex.B.value()); |
| assertEquals("Z", Complex.C.value()); |
| |
| assertEquals("X", Subclassing.A.value()); |
| assertEquals("Y", Subclassing.B.value()); |
| assertEquals("Z", Subclassing.C.value()); |
| } |
| |
| public void testName() { |
| assertEquals("A", Basic.A.name()); |
| assertEquals("B", Basic.B.name()); |
| assertEquals("C", Basic.C.name()); |
| |
| assertEquals("A", Complex.A.name()); |
| assertEquals("B", Complex.B.name()); |
| assertEquals("C", Complex.C.name()); |
| |
| assertEquals("A", Subclassing.A.name()); |
| assertEquals("B", Subclassing.B.name()); |
| assertEquals("C", Subclassing.C.name()); |
| } |
| |
| public void testOrdinals() { |
| assertEquals(0, Basic.A.ordinal()); |
| assertEquals(1, Basic.B.ordinal()); |
| assertEquals(2, Basic.C.ordinal()); |
| |
| assertEquals(0, Complex.A.ordinal()); |
| assertEquals(1, Complex.B.ordinal()); |
| assertEquals(2, Complex.C.ordinal()); |
| |
| assertEquals(0, Subclassing.A.ordinal()); |
| assertEquals(1, Subclassing.B.ordinal()); |
| assertEquals(2, Subclassing.C.ordinal()); |
| } |
| |
| public void testSwitch() { |
| switch (Basic.A) { |
| case A: |
| break; |
| case B: |
| fail("Switch failed"); |
| break; |
| case C: |
| fail("Switch failed"); |
| break; |
| default: |
| fail("Switch failed"); |
| break; |
| } |
| switch (Complex.B) { |
| case A: |
| fail("Switch failed"); |
| break; |
| case B: |
| break; |
| case C: |
| fail("Switch failed"); |
| break; |
| default: |
| fail("Switch failed"); |
| break; |
| } |
| switch (Subclassing.C) { |
| case A: |
| fail("Switch failed"); |
| break; |
| case B: |
| fail("Switch failed"); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void testValueOf() { |
| assertEquals(Basic.A, Basic.valueOf("A")); |
| assertEquals(Basic.B, Basic.valueOf("B")); |
| assertEquals(Basic.C, Basic.valueOf("C")); |
| try { |
| Basic.valueOf("D"); |
| fail("Basic.valueOf(\"D\") -- expected IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| } |
| |
| assertEquals(Complex.A, Complex.valueOf("A")); |
| assertEquals(Complex.B, Complex.valueOf("B")); |
| assertEquals(Complex.C, Complex.valueOf("C")); |
| try { |
| Complex.valueOf("D"); |
| fail("Complex.valueOf(\"D\") -- expected IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| } |
| |
| assertEquals(Subclassing.A, Subclassing.valueOf("A")); |
| assertEquals(Subclassing.B, Subclassing.valueOf("B")); |
| assertEquals(Subclassing.C, Subclassing.valueOf("C")); |
| try { |
| Subclassing.valueOf("D"); |
| fail("Subclassing.valueOf(\"D\") -- expected IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| } |
| |
| enumValuesTest(Basic.class); |
| enumValuesTest(Complex.class); |
| enumValuesTest(Subclassing.class); |
| |
| try { |
| Enum.valueOf(Basic.class, "foo"); |
| fail("Passed an invalid enum constant name to Enum.valueOf; expected " |
| + "IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| } |
| |
| try { |
| @SuppressWarnings("all") |
| Class fakeEnumClass = String.class; |
| Enum.valueOf(fakeEnumClass, "foo"); |
| fail("Passed a non enum class to Enum.valueOf; expected " |
| + "IllegalArgumentException"); |
| } catch (IllegalArgumentException e) { |
| } |
| |
| try { |
| Class<Basic> nullEnumClass = null; |
| Enum.valueOf(nullEnumClass, "foo"); |
| fail("Passed a null enum class to Enum.valueOf; expected " |
| + "NullPointerException"); |
| } catch (JavaScriptException e) { |
| } catch (NullPointerException e) { |
| } |
| |
| try { |
| Enum.valueOf(Basic.class, null); |
| fail("Passed a null enum constant to Enum.valueOf; expected " |
| + "NullPointerException"); |
| } catch (NullPointerException e) { |
| } |
| } |
| |
| public void testValueOfOverload() { |
| BasicWithOverloadedValueOf val1 = Enum.valueOf(BasicWithOverloadedValueOf.class,"A"); |
| BasicWithOverloadedValueOf val2 = BasicWithOverloadedValueOf.valueOf("B"); |
| BasicWithOverloadedValueOf valById1 = BasicWithOverloadedValueOf.valueOf(1); |
| BasicWithOverloadedValueOf valById2 = BasicWithOverloadedValueOf.valueOf(2); |
| assertEquals(val1, valById1); |
| assertEquals(val2, valById2); |
| } |
| |
| public void testValues() { |
| Basic[] simples = Basic.values(); |
| assertEquals(3, simples.length); |
| assertEquals(Basic.A, simples[0]); |
| assertEquals(Basic.B, simples[1]); |
| assertEquals(Basic.C, simples[2]); |
| |
| Complex[] complexes = Complex.values(); |
| assertEquals(3, complexes.length); |
| assertEquals(Complex.A, complexes[0]); |
| assertEquals(Complex.B, complexes[1]); |
| assertEquals(Complex.C, complexes[2]); |
| |
| Subclassing[] subs = Subclassing.values(); |
| assertEquals(3, subs.length); |
| assertEquals(Subclassing.A, subs[0]); |
| assertEquals(Subclassing.B, subs[1]); |
| assertEquals(Subclassing.C, subs[2]); |
| } |
| |
| /* |
| * Test that a call to an enum instance method, which gets transformed to a |
| * static impl, produces valid executable javascript, once the enum gets |
| * ordinalized. This test is in response to a case where invalid javascript |
| * was being generated, by not generating a clinit for the enum prior to |
| * referencing a static impl method. |
| */ |
| public void testEnumWithStaticImpl() { |
| EnumWithStaticImpl ewsi = EnumWithStaticImpl.VALUE1; |
| Long submitTime = new Long(1234567890); |
| String fmtDate = ewsi.formatDate(submitTime); |
| // we just need to make sure we get to this point without timing out |
| assertTrue(fmtDate != null); |
| } |
| |
| private <T extends Enum<T>> void enumValuesTest(Class<T> enumClass) { |
| T[] constants = enumClass.getEnumConstants(); |
| for (T constant : constants) { |
| assertEquals(constant, Enum.valueOf(enumClass, constant.name())); |
| } |
| } |
| } |