/*
 * 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.emultest.java.lang;

import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.testing.TestUtils;

import java.sql.Date;
import java.util.Arrays;

/**
 * Tests java.lang.System.
 */
public class SystemTest extends GWTTestCase {

  private static class Bar extends Foo {
    public Bar() {
    }
  }

  private enum EnumImpl implements Interfaz {
    FOO,
    BAR,
    BAZ
  }

  private static class Foo {
    public Foo() {
    }
  }

  private interface Interfaz {
  }

  private static class InterfazImpl implements Interfaz {

    private final String data;

    /**
     * @param data non-null string
     */
    InterfazImpl(String data) {
      this.data = data;
    }

    @Override
    public boolean equals(Object obj) {
      return (obj instanceof InterfazImpl) && ((InterfazImpl) obj).data.equals(
          data);
    }

    @Override
    public int hashCode() {
      return data.hashCode();
    }

    @Override
    public String toString() {
      return "InterfazImpl[data=" + data + "]";
    }
  }

  @Override
  public String getModuleName() {
    return "com.google.gwt.emultest.EmulSuite";
  }

  public void testArraycopyEnumToInterface() {
    EnumImpl[] src = new EnumImpl[]{ EnumImpl.FOO, null, EnumImpl.BAZ };
    Interfaz[] dest = new Interfaz[5];
    Arrays.fill(dest, null);  // undefined != null, weird.

    System.arraycopy(src, 0, dest, 1, 3);
    assertEquals(
        Arrays.asList(null, EnumImpl.FOO, null, EnumImpl.BAZ, null),
        Arrays.asList(dest));
  }

  public void testArraycopyEnumToObject() {
    EnumImpl[] src = new EnumImpl[]{ EnumImpl.FOO, null, EnumImpl.BAZ };
    Object[] dest = new Object[5];
    Arrays.fill(dest, null);  // undefined != null, weird.

    System.arraycopy(src, 0, dest, 1, 3);
    assertEquals(
        Arrays.asList(null, EnumImpl.FOO, null, EnumImpl.BAZ, null),
        Arrays.asList(dest));
  }

  public void testArraycopyFailures() {
    int[] src = new int[4];
    int[] dest = new int[] {1, 1, 1, 1};
    double[] destDouble = new double[4];
    String[] strings = new String[4];
    try {
      System.arraycopy(src, 5, dest, 0, 7);
      fail("Should have thrown IndexOutOfBoundsException: src past end");
    } catch (IndexOutOfBoundsException e) {
    }
    try {
      System.arraycopy(src, 0, dest, 5, 7);
      fail("Should have thrown IndexOutOfBoundsException: dest past end");
    } catch (IndexOutOfBoundsException e) {
    }
    try {
      System.arraycopy(src, -1, dest, 0, 4);
      fail("Should have thrown IndexOutOfBoundsException: src ofs negative");
    } catch (IndexOutOfBoundsException e) {
    }
    try {
      System.arraycopy(src, 0, dest, -1, 4);
      fail("Should have thrown IndexOutOfBoundsException: dest ofs negative");
    } catch (IndexOutOfBoundsException e) {
    }
    try {
      System.arraycopy(src, 0, dest, 0, -1);
      fail("Should have thrown IndexOutOfBoundsException: negative length");
    } catch (IndexOutOfBoundsException e) {
    }
    try {
      System.arraycopy("test", 0, dest, 0, 4);
      fail("Should have thrown ArrayStoreException: src not array");
    } catch (ArrayStoreException e) {
    }
    try {
      System.arraycopy(src, 0, "test", 0, 4);
      fail("Should have thrown ArrayStoreException: dest not array");
    } catch (ArrayStoreException e) {
    }
    try {
      System.arraycopy(src, 0, destDouble, 0, 4);
      fail("Should have thrown ArrayStoreException: different primitive types");
    } catch (ArrayStoreException e) {
    }
    try {
      System.arraycopy(strings, 0, dest, 0, 4);
      fail("Should have thrown ArrayStoreException: reference/primitive mismatch");
    } catch (ArrayStoreException e) {
    }
    try {
      System.arraycopy(src, 0, strings, 0, 4);
      fail("Should have thrown ArrayStoreException: primitive/reference mismatch");
    } catch (ArrayStoreException e) {
    }
  }

  public void testArraycopyInterfaceToObject() {
    Interfaz[] src = new Interfaz[]{
        new InterfazImpl("foo"), null, new InterfazImpl("bar") };
    Object[] dest = new Object[5];
    Arrays.fill(dest, null);  // undefined != null, weird.

    System.arraycopy(src, 0, dest, 1, 3);
    assertEquals(Arrays.asList(null, new InterfazImpl("foo"), null,
        new InterfazImpl("bar"), null), Arrays.asList(dest));
  }

  public void testArraycopyMultidim() {
    Object[][] objArray = new Object[1][1];
    String[][] strArray = new String[1][1];
    strArray[0][0] = "Test";
    Integer[][] intArray = new Integer[1][1];
    intArray[0][0] = new Integer(1);
    System.arraycopy(strArray, 0, objArray, 0, 1);
    assertEquals("Test", objArray[0][0]);
    try {
      System.arraycopy(strArray, 0, intArray, 0, 1);
      fail("Should have thrown ArrayStoreException: incompatible multidimensional arrays");
    } catch (ArrayStoreException e) {
    }
    try {
      System.arraycopy(new String[] {"T2"}, 0, objArray, 0, 1);
      fail("Should have thrown ArrayStoreException: store string array in multi-dim Object array");
    } catch (ArrayStoreException e) {
    }
  }

  public void testArraycopyNulls() {
    int[] src = new int[4];
    int[] dest = new int[] {1, 1, 1, 1};
    try {
      System.arraycopy(null, 0, dest, 0, 4);
      fail("Should have thrown NullPointerException: src null");
    } catch (NullPointerException e) {
      // verify dest unchanged
      for (int i = 0; i < dest.length; ++i) {
        assertEquals(1, dest[i]);
      }
    }
    try {
      System.arraycopy(src, 0, null, 0, 4);
      fail("Should have thrown NullPointerException: dest null");
    } catch (NullPointerException e) {
    }
  }

  public void testArraycopyObjects() {
    Foo[] fooArray = new Foo[4];
    Bar[] barArray = new Bar[4];
    Object[] src = new Object[] {new Bar(), new Bar(), new Foo(), new Bar()};
    System.arraycopy(src, 0, fooArray, 0, src.length);
    for (int i = 0; i < src.length; ++i) {
      assertEquals(src[i], fooArray[i]);
    }
    try {
      System.arraycopy(src, 0, barArray, 0, 4);
      fail("Should have thrown ArrayStoreException: foo into bar");
    } catch (ArrayStoreException e) {
      // verify we changed only up to the element causing the exception
      assertEquals(src[0], barArray[0]);
      assertEquals(src[1], barArray[1]);
      assertNull(barArray[2]);
      assertNull(barArray[3]);
    }
  }

  public void testArraycopyOverlap() {
    int[] intArray = new int[] {0, 1, 2, 3};
    String[] strArray = new String[] {"0", "1", "2", "3"};

    System.arraycopy(intArray, 0, intArray, 1, intArray.length - 1);
    assertEquals(0, intArray[0]);
    for (int i = 1; i < intArray.length; ++i) {
      assertEquals("rev int copy index " + i, i - 1, intArray[i]);
    }
    System.arraycopy(intArray, 1, intArray, 0, intArray.length - 1);
    for (int i = 0; i < intArray.length - 1; ++i) {
      assertEquals("fwd int copy index " + i, i, intArray[i]);
    }
    assertEquals("fwd int copy index " + (intArray.length - 2),
        intArray.length - 2, intArray[intArray.length - 1]);
    System.arraycopy(strArray, 0, strArray, 1, strArray.length - 1);
    assertEquals(0, Integer.valueOf(strArray[0]).intValue());
    for (int i = 1; i < strArray.length; ++i) {
      assertEquals("rev str copy index " + i, i - 1, Integer.valueOf(
          strArray[i]).intValue());
    }
    System.arraycopy(strArray, 1, strArray, 0, strArray.length - 1);
    for (int i = 0; i < strArray.length - 1; ++i) {
      assertEquals("fwd str copy index " + i, i, Integer.valueOf(
          strArray[i]).intValue());
    }
    assertEquals("fwd str copy index " + (strArray.length - 2),
        strArray.length - 2,
        Integer.valueOf(strArray[strArray.length - 1]).intValue());
    /*
     * TODO(jat): how is it supposed to behave with overlapped copies if there
     * is a failure in the middle of the copy? We should figure that out and
     * test for it.
     */
  }

  public void testArraycopyPrimitives() {
    int[] src = new int[] {0, 1, 2, 3, 4, 5, 6, 7};
    int[] dest = new int[8];

    System.arraycopy(src, 0, dest, 0, src.length);
    for (int i = 0; i < src.length; ++i) {
      assertEquals(src[i], dest[i]);
    }
    System.arraycopy(src, 2, dest, 1, 5);
    assertEquals(0, dest[0]);
    for (int i = 1; i < 6; ++i) {
      assertEquals(src[i + 1], dest[i]);
    }
  }

  public void testArraycopyLargeArray() {
    char[] largeCharArrayValue = C.getLargeCharArrayValue();
    char[] charDest = new char[largeCharArrayValue.length];
    System.arraycopy(largeCharArrayValue, 0, charDest, 0, largeCharArrayValue.length);
    for (int i = 0; i < largeCharArrayValue.length; ++i) {
      assertEquals("index " + i, largeCharArrayValue[i], charDest[i]);
    }

    int offset = largeCharArrayValue.length / 2;
    char[] manyNulls = new char[offset / 2];
    System.arraycopy(manyNulls, 0, charDest, offset, manyNulls.length);
    assertEquals('f', charDest[offset - 1]);
    for (int i = offset; i < offset + manyNulls.length; ++i) {
      assertEquals("index " + i, '\0', charDest[i]);
    }
    assertEquals('a', charDest[offset + manyNulls.length]);
  }

  public void testIdentityHashCode() {
    String s = "str";
    assertEquals(System.identityHashCode(s), System.identityHashCode(s));

    Double d = 42d;
    assertEquals(System.identityHashCode(d), System.identityHashCode(d));

    Boolean b = true;
    assertEquals(System.identityHashCode(b), System.identityHashCode(b));

    Object o = new Object();
    assertEquals(System.identityHashCode(o), System.identityHashCode(o));
    assertNotSame(System.identityHashCode(o), System.identityHashCode(new Object()));
  }

  public void testGetProperty() {
    if (TestUtils.isJvm()) {
      return;
    }
    assertEquals("conf", System.getProperty("someConfigurationProperty"));
    assertEquals("conf", System.getProperty("someConfigurationProperty", "default"));

    String someConf = System.getProperty("nonExistent", "default");
    assertEquals("default", someConf);

    // Note that default is not a String literal.
    assertEquals("default", System.getProperty("otherNonExistent", someConf));
  }

  public void testNanoTime() {
    assertTrue(System.nanoTime() > 0);
  }

  public void testCurrentTimeMillis() {
    assertTrue(System.currentTimeMillis() > Date.parse("1-1-2021"));
  }
}

