/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * 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 org.inferred.freebuilder.processor;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Set;

import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.WildcardType;

import org.inferred.freebuilder.processor.util.testing.ModelRule;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class UtilTests {

  @Rule public final ModelRule model = new ModelRule();

  @Test
  public void testUpperBound_knownType() {
    // T -> T
    TypeMirror result = Util.upperBound(model.elementUtils(), model.typeMirror("Number"));
    assertEquals(model.typeMirror("Number"), result);
  }

  @Test
  public void testUpperBound_unknownType() {
    // ? -> Object
    TypeMirror result = Util.upperBound(
        model.elementUtils(), model.typeUtils().getWildcardType(null, null));
    assertEquals(model.typeMirror("Object"), result);
  }

  @Test
  public void testUpperBound_extendsBound() {
    // ? extends T -> T
    TypeMirror result = Util.upperBound(
        model.elementUtils(), model.typeUtils().getWildcardType(model.typeMirror("Number"), null));
    assertEquals(model.typeMirror("Number"), result);
  }

  @Test
  public void testUpperBound_superBound() {
    // ? super T -> Object
    TypeMirror result = Util.upperBound(
        model.elementUtils(), model.typeUtils().getWildcardType(null, model.typeMirror("Number")));
    assertEquals(model.typeMirror("Object"), result);
  }

  @Test
  public void testErasesToAnyOf_nonGenericType() {
    assertTrue(Util.erasesToAnyOf((DeclaredType) model.typeMirror("Number"), Number.class));
  }

  @Test
  public void testErasesToAnyOf_subType() {
    assertFalse(Util.erasesToAnyOf((DeclaredType) model.typeMirror("Double"), Number.class));
  }

  @Test
  public void testErasesToAnyOf_superType() {
    assertFalse(Util.erasesToAnyOf((DeclaredType) model.typeMirror("Object"), Number.class));
  }

  @Test
  public void testErasesToAnyOf_boxedType() {
    assertTrue(Util.erasesToAnyOf((DeclaredType) model.typeMirror("Double"), Double.class));
  }

  @Test
  public void testErasesToAnyOf_primitiveType() {
    assertFalse(Util.erasesToAnyOf((DeclaredType) model.typeMirror("Double"), double.class));
  }

  @Test
  public void testErasesToAnyOf_erasedType() {
    assertTrue(Util.erasesToAnyOf((DeclaredType) model.typeMirror("java.util.List"), List.class));
  }

  @Test
  public void testErasesToAnyOf_fullySpecifiedType() {
    assertTrue(Util.erasesToAnyOf(
        (DeclaredType) model.typeMirror("java.util.List<Double>"), List.class));
  }

  @Test
  public void testErasesToAnyOf_wildcardType() {
    WildcardType wildcard = model.typeUtils().getWildcardType(null, null);
    assertTrue(Util.erasesToAnyOf(
        (DeclaredType) model.typeMirror("java.util.List", wildcard), List.class));
  }

  @Test
  public void testErasesToAnyOf_firstOfTwo() {
    assertTrue(Util.erasesToAnyOf(
        (DeclaredType) model.typeMirror("java.util.List"), List.class, Set.class));
  }

  @Test
  public void testErasesToAnyOf_secondOfTwo() {
    assertTrue(Util.erasesToAnyOf(
        (DeclaredType) model.typeMirror("java.util.Set"), List.class, Set.class));
  }

  @Test
  public void testErasesToAnyOf_neitherOfTwo() {
    assertFalse(Util.erasesToAnyOf(
        (DeclaredType) model.typeMirror("java.util.Collection"), List.class, Set.class));
  }

  private static void assertEquals(TypeMirror expected, TypeMirror actual) {
    Assert.assertEquals((expected == null) ? "null" : expected, (actual == null) ? "null" : actual);
  }
}

@@ -995,22 +995,33 @@
 g.junit.
-Assert
+ComparisonFailure
 ;%0Aimport
@@ -1391,38 +1391,40 @@
 r%22));%0A    assert
-Equals
+SameType
 (model.typeMirro
@@ -1643,38 +1643,40 @@
 ll));%0A    assert
-Equals
+SameType
 (model.typeMirro
@@ -1923,38 +1923,40 @@
 ll));%0A    assert
-Equals
+SameType
 (model.typeMirro
@@ -2212,22 +2212,24 @@
   assert
-Equals
+SameType
 (model.t
@@ -4187,23 +4187,16 @@
 private 
-static 
 void ass
@@ -4198,22 +4198,24 @@
 d assert
-Equals
+SameType
 (TypeMir
@@ -4257,103 +4257,666 @@
     
-Assert.assertEquals((expected == null) ? %22null%22 : expected, (actual == null) ? %22null%22 : actual)
+if (!model.typeUtils().isSameType(expected, actual)) %7B%0A      String expectedString = (expected == null) ? %22null%22 : expected.toString();%0A      String actualString = (actual == null) ? %22null%22 : actual.toString();%0A      if (expectedString.equals(actualString)) %7B%0A        expectedString = extendedToString(expected);%0A        actualString = extendedToString(actual);%0A      %7D%0A      throw new ComparisonFailure(%0A          %22%22,%0A          expectedString,%0A          actualString);%0A    %7D%0A  %7D%0A%0A  private static String extendedToString(Object object) %7B%0A    if (object == null) %7B%0A      return null;%0A    %7D%0A    return object.getClass().getCanonicalName() + %22%3C%22 + object + %22%3E%22
 ;%0A  

Fix UtilTests in Eclipse.