| /* |
| * 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.junit.client.GWTTestCase; |
| |
| /** |
| * Test direct uses of longs. Mostly this tests that LongLib is in fact being |
| * invoked in various cases. The behavior of LongLib itself is tested in |
| * LongLibTest. |
| */ |
| public class NativeLongTest extends GWTTestCase { |
| /** |
| * A class that wraps an int. See {@link NativeLongTest#testImplicitCastToLong()}. |
| */ |
| private static class IntegerWrapper { |
| private final int i; |
| |
| public IntegerWrapper(int i) { |
| this.i = i; |
| } |
| |
| public long longValue() { |
| return i; // implicit cast to long |
| } |
| } |
| |
| private static class RequestIdFactory { |
| static RequestIdFactory instance = new RequestIdFactory(); |
| |
| static RequestIdFactory getInstance() { |
| return instance; |
| } |
| |
| long nextId; |
| |
| long getNextId() { |
| return nextId++; |
| } |
| } |
| |
| /* |
| * These constants are done as volatile fields so that the compiler will not |
| * constant fold them. The problem is that if you write assertEquals(2L, |
| * 4L/2L), the compiler will emit assertEquals(2L, 2L). |
| */ |
| private static volatile byte BYTE_FOUR = (byte) 4; |
| private static volatile char CHAR_FOUR = (char) 4; |
| private static volatile boolean FALSE = false; |
| private static volatile int INT_FOUR = 4; |
| private static volatile long LONG_100 = 100L; |
| private static volatile long LONG_1234 = 0x1234123412341234L; |
| private static volatile long LONG_1234_DECIMAL = 1234123412341234L; |
| private static volatile long LONG_1234000012340000 = 0x1234000012340000L; |
| private static volatile long LONG_5DEECE66D = 0x5DEECE66DL; |
| private static volatile long LONG_B = 0xBL; |
| private static volatile long LONG_DEADBEEF = 0xdeadbeefdeadbeefL; |
| private static volatile long LONG_DEADBEEF12341234 = 0xdeadbeef12341234L; |
| private static volatile long LONG_FFFFFFFF = 0xFFFFFFFFL; |
| private static volatile long LONG_FOUR = 4L; |
| private static volatile long LONG_ONE = 1L; |
| private static volatile long LONG_THREE = 3L; |
| private static volatile long LONG_TWO = 2L; |
| private static volatile long LONG_TWO_PWR_32 = 0x100000000L; |
| private static volatile long LONG_ZERO = 0L; |
| private static volatile short SHORT_FOUR = (short) 4; |
| |
| @Override |
| public String getModuleName() { |
| return "com.google.gwt.dev.jjs.CompilerSuite"; |
| } |
| |
| public void testArithmetic() { |
| assertEquals(-1089359682551557853L, LONG_1234 + LONG_DEADBEEF); |
| assertEquals(5024439901525534073L, 2 * LONG_1234 - LONG_DEADBEEF); |
| assertEquals(2476047018506819212L, LONG_1234 * LONG_DEADBEEF); |
| assertEquals(-240105308887621659L, LONG_DEADBEEF / 10); |
| assertEquals(-1089359682551557853L, LONG_DEADBEEF % LONG_1234); |
| } |
| |
| public void testArrayInitializer() { |
| long[] longs = new long[3]; |
| assertEquals(0L, longs[1]); |
| long[][] longs2 = new long[3][3]; |
| assertEquals(0L, longs2[1][1]); |
| } |
| |
| public void testCasts() { |
| assertEquals(0x12341234, (int) LONG_1234); |
| assertEquals(0x1234, (short) LONG_1234); |
| } |
| |
| public void testConstants() { |
| assertEquals(LONG_5DEECE66D, LONG_5DEECE66D); |
| assertTrue(LONG_5DEECE66D > 0L); |
| assertTrue(0L < LONG_5DEECE66D); |
| assertEquals(LONG_B, LONG_B); |
| assertTrue(LONG_B > 0L); |
| assertTrue(0L < LONG_B); |
| } |
| |
| public void testFor64Bits() { |
| long x = LONG_1234; |
| long y = LONG_1234 + LONG_ONE; |
| long z = y - x; |
| // with longs implemented as doubles, z will be 0 instead of 1 |
| assertEquals(1L, z); |
| } |
| |
| public void testImplicitCastFromLong() { |
| double d = LONG_ONE; |
| d += LONG_TWO; |
| assertEquals(0.0, 3L, d); |
| assertTrue(3L == d); |
| |
| float f = LONG_ONE; |
| f += LONG_TWO; |
| assertEquals(0.0, 3L, f); |
| assertTrue(3L == f); |
| } |
| |
| public void testImplicitCastToLong() { |
| long l = 10; |
| l += 5; |
| assertEquals(15, l); |
| assertTrue(15 == l); |
| |
| // Issue 3710 |
| IntegerWrapper wrap = new IntegerWrapper(20); |
| assertEquals(400L, wrap.longValue() * wrap.longValue()); |
| } |
| |
| public void testInlinedIntInitializer() { |
| long sum = 0; // int, not long! |
| assertEquals("0", "" + (sum / INT_FOUR)); |
| } |
| |
| public void testLogicalAnd() { |
| assertEquals(LONG_1234, LONG_1234 & -LONG_ONE); |
| assertEquals(0x12341234L, LONG_1234 & LONG_FFFFFFFF); |
| assertEquals(0L, LONG_ONE & LONG_ZERO); |
| assertEquals(1L, LONG_ONE & LONG_THREE); |
| } |
| |
| public void testLogicalOr() { |
| assertEquals(-1L, LONG_1234 | -LONG_ONE); |
| assertEquals(0x12341234FFFFFFFFL, LONG_1234 | LONG_FFFFFFFF); |
| assertEquals(1L, LONG_ONE | LONG_ZERO); |
| assertEquals(3L, LONG_ONE | LONG_THREE); |
| } |
| |
| public void testLogicalXor() { |
| assertTrue((255L ^ LONG_5DEECE66D) != 0); |
| |
| assertEquals(0L, LONG_1234 ^ LONG_1234); |
| assertEquals(0x0000123400001234L, LONG_1234 ^ LONG_1234000012340000); |
| assertEquals(1L, LONG_ONE ^ LONG_ZERO); |
| assertEquals(2L, LONG_ONE ^ LONG_THREE); |
| } |
| |
| public void testModifyingOps() { |
| long l = 20; |
| l += INT_FOUR; |
| assertEquals(25, ++l); |
| assertEquals(25, l++); |
| assertEquals(26, l); |
| l += BYTE_FOUR; |
| assertEquals(30, l); |
| l += CHAR_FOUR; |
| assertEquals(34, l); |
| l += SHORT_FOUR; |
| assertEquals(38, l); |
| l += INT_FOUR; |
| assertEquals(42, l); |
| } |
| |
| public void testShift() { |
| assertEquals(LONG_5DEECE66D, LONG_5DEECE66D & ((LONG_ONE << 48) - 1)); |
| assertEquals(LONG_ONE << 12, (LONG_ONE << 60) >>> (48)); |
| |
| assertTrue((LONG_ONE << 35) > (LONG_ONE << 30)); |
| assertEquals(0x10L, LONG_ONE << BYTE_FOUR); |
| assertEquals(0x10L, LONG_ONE << CHAR_FOUR); |
| assertEquals(0x10L, LONG_ONE << SHORT_FOUR); |
| assertEquals(0x10L, LONG_ONE << INT_FOUR); |
| assertEquals(0x10L, LONG_ONE << LONG_FOUR); |
| |
| assertEquals(1L, LONG_TWO_PWR_32 >> 32); |
| assertEquals(1L, LONG_TWO_PWR_32 >>> 32); |
| } |
| |
| public void testStringAppend() { |
| long x = LONG_100; |
| assertEquals("100 is a long", x + " is a long"); |
| assertEquals("a long: 100", "a long: " + x); |
| } |
| |
| // Issue 1198 |
| public void testToHexString() { |
| assertEquals("deadbeef12341234", Long.toHexString(LONG_DEADBEEF12341234)); |
| } |
| |
| public void testToString() { |
| assertEquals("1234123412341234", "" + LONG_1234_DECIMAL); |
| } |
| |
| /** |
| * It's important when allocating a new temporary that it is marked as in use. |
| */ |
| public void testVariableReuseInCompoundAssignmentNormalizer1() { |
| if (FALSE) { |
| // Prevent inlining, so that CAN allocates temporaries predictably. |
| testVariableReuseInCompoundAssignmentNormalizer1(); |
| } |
| |
| assertEquals("0", |
| Long.toHexString(RequestIdFactory.getInstance().getNextId())); |
| } |
| |
| /** |
| * Using differently typed temp variables can cause JArrayType to throw a |
| * class cast exception. |
| */ |
| public void testVariableReuseInCompoundAssignmentNormalizer2() { |
| if (FALSE) { |
| // Prevent inlining, so that CAN allocates temporaries predictably. |
| testVariableReuseInCompoundAssignmentNormalizer2(); |
| } |
| long ary[][] = new long[10][10]; |
| long i = 3, j = 3; |
| assertEquals(0L, ary[(int) i++][(int) j++]++); |
| assertEquals(4L, i); |
| assertEquals(4L, j); |
| assertEquals(1L, ary[3][3]); |
| } |
| |
| /** |
| * Using differently typed temp variables can cause LongEmulationNormalizer to |
| * fail an assertion. |
| */ |
| public void testVariableReuseInCompoundAssignmentNormalizer3() { |
| if (FALSE) { |
| // Prevent inlining, so that CAN allocates temporaries predictably. |
| testVariableReuseInCompoundAssignmentNormalizer3(); |
| } |
| |
| long ary[] = new long[10]; |
| int i = 3; |
| long j = 5; |
| |
| assertEquals(0L, ary[i++]++); |
| assertEquals(4, i); |
| assertEquals(1L, ary[3]); |
| |
| assertEquals(0L, ary[(int) j++]++); |
| assertEquals(6L, j); |
| assertEquals(1L, ary[5]); |
| } |
| } |