/* * Copyright 2013 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.junit.client.GWTTestCase; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Tests Java 7 features. */ public class Java7Test extends GWTTestCase { @Override public String getModuleName() { return "com.google.gwt.dev.jjs.CompilerSuite"; } // new style class literals int million = 1_000_000; int five = 0b101; public void testNewStyleLiterals() { assertEquals(1000000, million); assertEquals(5, five); } public void testSwitchOnString() { String s = "AA"; int result = -1; switch (s) { case "BB": result = 0; break; case "CC": case "AA": result = 1; break; } assertEquals(1, result); } final List<String> log = new ArrayList<String>(); enum ThrowsWhen { NEVER, ONCONSTRUCTOR, ONCLOSE; } class Resource implements AutoCloseable { final String name; final ThrowsWhen throwsWhen; public Resource(String name) throws E1 { this(name, ThrowsWhen.NEVER); } public Resource(String name, ThrowsWhen throwsWhen) throws E1 { this.name = name; this.throwsWhen = throwsWhen; log.add("Open " + name); if (throwsWhen == ThrowsWhen.ONCONSTRUCTOR) { throwException("ExceptionOnConstructor"); } } public void doSomething() { log.add("doSomething " + name); } public void throwException(String text) throws E1 { throw new E1(text + " in " + name); } public void close() throws Exception { log.add("Close " + name); if (throwsWhen == ThrowsWhen.ONCLOSE) { throwException("ExceptionOnClose"); } } } private void logException(Exception e) { log.add(e.getMessage()); for (Throwable t : e.getSuppressed()) { log.add("Suppressed: " + t.getMessage()); } } public void testTryWithResources_noExceptions() throws Exception { log.clear(); try ( Resource rA = new Resource("A"); Resource rB = new Resource("B"); Resource rC = new Resource("C")) { rA.doSomething(); rB.doSomething(); rC.doSomething(); } assertContentsInOrder(log, "Open A", "Open B", "Open C", "doSomething A", "doSomething B", "doSomething C", "Close C", "Close B", "Close A" ); } public void testTryWithResources_exceptions() throws Exception { log.clear(); try ( Resource rA = new Resource("A"); Resource rB = new Resource("B", ThrowsWhen.ONCLOSE); Resource rC = new Resource("C")) { rA.doSomething(); rB.doSomething(); rC.doSomething(); } catch (Exception e) { log.add(e.getMessage()); } finally { log.add("finally"); } assertContentsInOrder(log, "Open A", "Open B", "Open C", "doSomething A", "doSomething B", "doSomething C", "Close C", "Close B", "Close A", "ExceptionOnClose in B", "finally" ); } public void testTryWithResources_suppressedExceptions() throws Exception { log.clear(); try ( Resource rA = new Resource("A", ThrowsWhen.ONCLOSE); Resource rB = new Resource("B"); Resource rC = new Resource("C", ThrowsWhen.ONCLOSE)) { rA.doSomething(); rB.doSomething(); rC.doSomething(); } catch (Exception e) { logException(e); } assertContentsInOrder(log, "Open A", "Open B", "Open C", "doSomething A", "doSomething B", "doSomething C", "Close C", "Close B", "Close A", "ExceptionOnClose in C", "Suppressed: ExceptionOnClose in A" ); log.clear(); try ( Resource rA = new Resource("A"); Resource rB = new Resource("B", ThrowsWhen.ONCLOSE); Resource rC = new Resource("C")) { rA.doSomething(); rB.throwException("E1 here"); rC.doSomething(); } catch (Exception e) { logException(e); } finally { log.add("finally"); } assertContentsInOrder(log, "Open A", "Open B", "Open C", "doSomething A", "Close C", "Close B", "Close A", "E1 here in B", "Suppressed: ExceptionOnClose in B", "finally" ); } public void testTryWithResources_exceptionInAcquisition() { log.clear(); try ( Resource rA = new Resource("A", ThrowsWhen.ONCLOSE); Resource rB = new Resource("B", ThrowsWhen.ONCONSTRUCTOR); Resource rC = new Resource("C", ThrowsWhen.ONCLOSE)) { rA.doSomething(); rB.doSomething(); rC.doSomething(); } catch (Exception e) { logException(e); } assertContentsInOrder(log, "Open A", "Open B", "Close A", "ExceptionOnConstructor in B", "Suppressed: ExceptionOnClose in A" ); } public void testAddSuppressedExceptions() { Throwable throwable = new Throwable("primary"); assertNotNull(throwable.getSuppressed()); assertEquals(0, throwable.getSuppressed().length); Throwable suppressed1 = new Throwable("suppressed1"); throwable.addSuppressed(suppressed1); assertEquals(1, throwable.getSuppressed().length); assertEquals(suppressed1, throwable.getSuppressed()[0]); Throwable suppressed2 = new Throwable("suppressed2"); throwable.addSuppressed(suppressed2); assertEquals(2, throwable.getSuppressed().length); assertEquals(suppressed1, throwable.getSuppressed()[0]); assertEquals(suppressed2, throwable.getSuppressed()[1]); } static class E1 extends Exception { String name; public E1(String name) { this.name = name; } public int methodE1() { return 0; } @Override public String getMessage() { return name; } } static class E2 extends E1 { public E2(String name) { super(name); } public int methodE2() { return 1; } } static class E3 extends E1 { public E3(String name) { super(name); } public int methodE3() { return 2; } } public void testMultiExceptions() { int choose = 0; try { if (choose == 0) { throw new E1("e1"); } else if (choose == 1) { throw new E2("e2"); } fail("Exception was not trown"); } catch (E2 | E3 x) { // The compiler will assign x a common supertype/superinterface of E2 and E3. // Here we make sure that this clause is not entered when the supertype is thrown. fail("Caught E1 instead of E2|E3"); } catch (E1 x) { } } private Object unoptimizableId(Object o) { if (Math.random() > -10) { return o; } return null; } public void testPrimitiveCastsFromObject() { Object o = unoptimizableId((byte) 2); assertEquals((byte) 2, (byte) o); o = unoptimizableId((short) 3); assertEquals((short) 3, (short) o); o = unoptimizableId(1); assertEquals(1, (int) o); o = unoptimizableId(1L); assertEquals(1L, (long) o); o = unoptimizableId(0.1f); assertEquals(0.1f, (float) o); o = unoptimizableId(0.1); assertEquals(0.1, (double) o); o = unoptimizableId(true); assertEquals(true, (boolean) o); o = unoptimizableId('a'); assertEquals('a', (char) o); // Test cast from supers. Number n = (Number) unoptimizableId(5); assertEquals(5, (int) n); Serializable s = (Serializable) unoptimizableId(6); assertEquals(6, (int) s); Comparable<Integer> c = (Comparable<Integer>) unoptimizableId(7); assertEquals(7, (int) c); // Failing casts. try { Object boxedChar = unoptimizableId('a'); boolean b = (boolean) boxedChar; fail("Should have thrown a ClassCastException"); } catch (ClassCastException e) { // Expected. } try { Object string = unoptimizableId("string"); int num = (int) string; fail("Should have thrown a ClassCastException"); } catch (ClassCastException e) { // Expected. } } private void assertContentsInOrder(Iterable<String> contents, String... elements) { assertEquals(Arrays.asList(elements).toString(), contents.toString()); } }