/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* 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 com.alibaba.citrus.generictype;
import static com.alibaba.citrus.generictype.TypeInfo.*;
import static java.lang.reflect.Modifier.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.util.List;
import com.alibaba.citrus.test.runner.Prototyped;
import com.alibaba.citrus.test.runner.Prototyped.Prototypes;
import com.alibaba.citrus.test.runner.Prototyped.TestData;
import com.alibaba.citrus.test.runner.Prototyped.TestName;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* 测试{@link FieldInfo}。
*
* @author Michael Zhou
*/
@RunWith(Prototyped.class)
public class FieldTests extends BaseTypeTests implements Cloneable {
private transient FieldInfo field;
private Class<?> topType; // 字段所在类的子类
private Class<?> declaringType; // 字段所在类
private String fieldName; // 字段名
private int modifiers; // 限定符
private String type; // 字段类型
private String toString; // toString结果
private String resolved; // resolve的结果
private boolean resolveChanged; // 如果为false,代表resolve返回this
private String getFieldFromClassTypeInfo; // ClassTypeInfo.getField的结果
@Before
public void init() throws Exception {
this.topType = topType == null ? declaringType : topType;
this.field = factory.getField(declaringType.getDeclaredField(fieldName));
this.resolved = resolved == null ? toString : resolved;
this.getFieldFromClassTypeInfo = getFieldFromClassTypeInfo == null ? resolved : getFieldFromClassTypeInfo;
}
@TestName
public String testName() throws Exception {
return declaringType.getDeclaredField(fieldName).toGenericString();
}
@SuppressWarnings("unused")
private static class TestClassBase<T extends Number> {
public final Number a = 1;
protected int b;
Object c;
private String d;
private List<T> e;
}
@SuppressWarnings("unused")
private static class TestClass<S extends Number> extends TestClassBase<S> {
public String a;
private static int d;
}
@Prototypes
public static TestData<FieldTests> data() {
TestData<FieldTests> data = TestData.getInstance(FieldTests.class);
FieldTests prototype;
// -----------------
prototype = data.newPrototype();
prototype.topType = TestClass.class;
prototype.declaringType = TestClassBase.class;
prototype.fieldName = "a";
prototype.modifiers = PUBLIC;
prototype.type = "Number";
prototype.toString = "public Number FieldTests$TestClassBase.a";
prototype.resolved = null;
// -----------------
prototype = data.newPrototype();
prototype.topType = TestClass.class;
prototype.declaringType = TestClassBase.class;
prototype.fieldName = "b";
prototype.modifiers = PROTECTED;
prototype.type = "int";
prototype.toString = "protected int FieldTests$TestClassBase.b";
prototype.resolved = null;
// -----------------
prototype = data.newPrototype();
prototype.topType = TestClass.class;
prototype.declaringType = TestClassBase.class;
prototype.fieldName = "c";
prototype.modifiers = 0;
prototype.type = "Object";
prototype.toString = "Object FieldTests$TestClassBase.c";
prototype.resolved = null;
// -----------------
prototype = data.newPrototype();
prototype.topType = TestClass.class;
prototype.declaringType = TestClassBase.class;
prototype.fieldName = "d";
prototype.modifiers = PRIVATE;
prototype.type = "String";
prototype.toString = "private String FieldTests$TestClassBase.d";
prototype.resolved = null;
// -----------------
prototype = data.newPrototype();
prototype.topType = TestClass.class;
prototype.declaringType = TestClassBase.class;
prototype.fieldName = "e";
prototype.modifiers = PRIVATE;
prototype.type = "List<E=T>";
prototype.toString = "private List<E=T> FieldTests$TestClassBase.e";
prototype.resolved = "private List<E=Number> FieldTests$TestClassBase.e";
prototype.resolveChanged = true;
prototype.getFieldFromClassTypeInfo = "private List<E=S> FieldTests$TestClassBase.e";
// -----------------
prototype = data.newPrototype();
prototype.topType = TestClassBase.class;
prototype.declaringType = TestClassBase.class;
prototype.fieldName = "e";
prototype.modifiers = PRIVATE;
prototype.type = "List<E=T>";
prototype.toString = "private List<E=T> FieldTests$TestClassBase.e";
prototype.resolved = "private List<E=Number> FieldTests$TestClassBase.e";
prototype.resolveChanged = true;
prototype.getFieldFromClassTypeInfo = "private List<E=T> FieldTests$TestClassBase.e";
// -----------------
prototype = data.newPrototype();
prototype.topType = TestClass.class;
prototype.declaringType = TestClass.class;
prototype.fieldName = "a";
prototype.modifiers = PUBLIC;
prototype.type = "String";
prototype.toString = "public String FieldTests$TestClass.a";
prototype.resolved = null;
// -----------------
prototype = data.newPrototype();
prototype.topType = TestClass.class;
prototype.declaringType = TestClass.class;
prototype.fieldName = "d";
prototype.modifiers = PRIVATE | STATIC;
prototype.type = "int";
prototype.toString = "private static int FieldTests$TestClass.d";
prototype.resolved = null;
return data;
}
@Test
public void getField() {
assertNotNull(field.getField());
}
@Test
public void getDeclaringType() {
assertSame(factory.getType(declaringType), field.getDeclaringType());
}
@Test
public void getModifiers() {
assertEquals(modifiers, field.getModifiers());
}
@Test
public void getType() {
assertEquals(type, field.getType().toString());
}
@Test
public void getName() {
assertEquals(fieldName, field.getName());
}
@Test
public void resolve() {
assertEquals(resolved, field.resolve(null).toString());
assertEquals(resolved, field.resolve(null, true).toString());
assertEquals(resolveChanged, field != field.resolve(null));
}
@Test
public void getField_from_ClassTypeInfo() {
ClassTypeInfo topType = TypeInfo.factory.getClassType(this.topType);
ClassTypeInfo declaringType = TypeInfo.factory.getClassType(this.declaringType);
assertEquals(getFieldFromClassTypeInfo, topType.getField(declaringType, fieldName).toString());
if (topType.equals(declaringType)) {
assertEquals(getFieldFromClassTypeInfo, topType.getField(fieldName).toString());
}
}
@Test
public void equalsHashCode() throws Exception {
FieldInfo newField = factory.getField(declaringType.getDeclaredField(fieldName));
assertEquals(newField, field);
assertNotSame(newField, field);
assertEquals(newField.hashCode(), field.hashCode());
newField = factory.getField(getClass().getDeclaredField("field"));
assertThat(field, not(equalTo(newField)));
assertNotSame(newField, field);
assertThat(field.hashCode(), not(equalTo(newField.hashCode())));
}
@Test
public void toString_() {
assertEquals(toString, field.toString());
}
}