package org.mutabilitydetector.checkers;
/*
* #%L
* MutabilityDetector
* %%
* Copyright (C) 2008 - 2014 Graham Allan
* %%
* 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.
* #L%
*/
import org.junit.Ignore;
import org.junit.Test;
import org.mutabilitydetector.benchmarks.mutabletofield.CollectionFields;
import org.mutabilitydetector.checkers.CollectionField.GenericType;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
import java.io.IOException;
import java.lang.ref.Reference;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.mutabilitydetector.checkers.CollectionField.GenericType.exact;
import static org.mutabilitydetector.checkers.CollectionField.GenericType.wildcard;
import static org.mutabilitydetector.locations.Dotted.fromClass;
@SuppressWarnings("unused")
public class CollectionFieldTest {
@Test
public void retrievesGenericTypeOfListField() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(WithGenericListField.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.collectionType, equalTo(fromClass(List.class)));
assertThat(collectionField.getGenericParameterTypes(), contains(GenericType.exact(fromClass(String.class))));
assertThat(collectionField.asString(), equalTo("java.util.List<java.lang.String>"));
}
@Test
public void retrievesGenericTypeOfRawListField() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(WithRawListField.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.collectionType, equalTo(fromClass(List.class)));
assertThat(collectionField.getGenericParameterTypes(), is(nullValue()));
assertThat(collectionField.asString(), equalTo("raw java.util.List"));
}
@Test
public void retrievesGenericTypeOfListFieldWithExtendsWildcard() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(WithExtendsWildcardsGenericsListField.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.collectionType, equalTo(fromClass(List.class)));
assertThat(collectionField.getGenericParameterTypes(), contains(GenericType.extends_(fromClass(String.class))));
assertThat(collectionField.asString(), equalTo("java.util.List<? extends java.lang.String>"));
}
@Test
public void retrievesGenericTypeOfListFieldWithSuperWildcard() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(WithSuperWildcardsGenericsListField.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.collectionType, equalTo(fromClass(List.class)));
assertThat(collectionField.getGenericParameterTypes(), contains(GenericType.super_(fromClass(String.class))));
assertThat(collectionField.asString(), equalTo("java.util.List<? super java.lang.String>"));
}
@Test
public void retrievesGenericTypeOfListFieldWithWildcard() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(WithWildcardGenericsListField.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.collectionType, equalTo(fromClass(List.class)));
assertThat(collectionField.getGenericParameterTypes(), contains(wildcard()));
assertThat(collectionField.asString(), equalTo("java.util.List<?>"));
}
@Test
public void retrievesGenericTypeOfMapField() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(WithGenericMapField.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.collectionType, equalTo(fromClass(Map.class)));
assertThat(collectionField.getGenericParameterTypes(), contains(GenericType.exact(fromClass(String.class)),
GenericType.exact(fromClass(Date.class))));
assertThat(collectionField.asString(), equalTo("java.util.Map<java.lang.String, java.util.Date>"));
}
@Test
public void retrievesGenericTypeOfNestedListField() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(WithNestedListField.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.collectionType, equalTo(fromClass(List.class)));
assertThat(collectionField.getGenericParameterTypes(), contains(exact(fromClass(Reference.class)), exact(fromClass(Date.class))));
assertThat(collectionField.asString(), equalTo("java.util.List<java.lang.ref.Reference<java.util.Date>>"));
}
@Test
public void recognisesPrimitiveArrayAsGenericTypeOfCollectionField() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(CollectionFields
.CollectionWithByteArrayGenericType.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.getGenericParameterTypes(), contains(exact(fromClass(byte[].class))));
}
/**
* FIXME it passes because in both cases method {@link org.mutabilitydetector.locations.Dotted#dotted(String)}
* removes '[L' from signature. However we have generic type = java.lang.String instead [LjavaLangString
*/
@Test
@Ignore
public void recognisesObjectArrayAsGenericTypeOfCollectionField() throws Exception {
String[] descAndSignature = descAndSignatureOfSingleFieldIn(CollectionFields
.CollectionWithStringArrayGenericType.class);
CollectionField collectionField = CollectionField.from(descAndSignature[0], descAndSignature[1]);
assertThat(collectionField.getGenericParameterTypes(), contains(exact(fromClass(String[].class))));
}
private static class WithGenericListField {
public List<String> listOfString;
}
private static class WithRawListField {
@SuppressWarnings("rawtypes")
public List listOfString;
}
private static class WithGenericMapField {
public Map<String, Date> stringToDateMap;
}
private static class WithNestedListField {
public List<Reference<Date>> stringToDateMap;
}
private static class WithExtendsWildcardsGenericsListField {
public List<? extends String> listOfString;
}
private static class WithSuperWildcardsGenericsListField {
public List<? super String> listOfString;
}
private static class WithWildcardGenericsListField {
public List<?> listOfString;
}
private String[] descAndSignatureOfSingleFieldIn(Class<?> class1) throws IOException {
final String[] fieldDescSignature = new String[2];
ClassReader classReader = new ClassReader(class1.getName());
classReader.accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
fieldDescSignature[0] = desc;
fieldDescSignature[1] = signature;
return super.visitField(access, name, desc, signature, value);
};
}, 0);
return fieldDescSignature;
}
}