/* * Copyright (C) 2015 Red Hat, Inc. and/or its affiliates. * * 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.jboss.errai.reflections; import static java.util.Arrays.asList; import static org.jboss.errai.reflections.TestModel.*; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import com.google.common.base.Predicate; import com.google.common.collect.Lists; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.jboss.errai.reflections.scanners.ConvertersScanner; import org.jboss.errai.reflections.scanners.FieldAnnotationsScanner; import org.jboss.errai.reflections.scanners.MethodAnnotationsScanner; import org.jboss.errai.reflections.scanners.ResourcesScanner; import org.jboss.errai.reflections.scanners.SubTypesScanner; import org.jboss.errai.reflections.scanners.TypeAnnotationsScanner; import org.jboss.errai.reflections.util.ClasspathHelper; import org.jboss.errai.reflections.util.ConfigurationBuilder; import org.jboss.errai.reflections.util.FilterBuilder; import org.jboss.errai.reflections.vfs.Vfs; import org.junit.BeforeClass; import org.junit.Test; import java.io.File; import java.io.IOException; import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.Collection; import java.util.Set; import java.util.regex.Pattern; /** * */ public class ReflectionsTest { static Reflections reflections; //todo add tests for annotations on constructors //todo add tests for package annotations @BeforeClass public static void init() { Predicate<String> filter = new FilterBuilder().include("org.jboss.errai.reflections.TestModel\\$.*"); reflections = new Reflections(new ConfigurationBuilder() .filterInputsBy(filter) .setScanners( new SubTypesScanner().filterResultsBy(filter), new TypeAnnotationsScanner().filterResultsBy(filter), new FieldAnnotationsScanner().filterResultsBy(filter), new MethodAnnotationsScanner().filterResultsBy(filter), new ConvertersScanner().filterResultsBy(filter)) .setUrls(asList(ClasspathHelper.forClass(TestModel.class)))); reflections.scan(); } @Test public void testAll() { testSubTypesOf(); testTypesAnnotatedWith(); testMethodsAnnotatedWith(); testFieldsAnnotatedWith(); testConverters(); } @Test public void testSubTypesOf() { assertThat(reflections.getSubTypesOf(I1.class), are(I2.class, C1.class, C2.class, C3.class, C5.class)); assertThat(reflections.getSubTypesOf(I2.class), are(C1.class, C2.class, C3.class, C5.class)); } @Test public void testTypesAnnotatedWith() { //@Inherited assertThat("when honoring @Inherited, meta-annotation should only effect annotated super classes and it's sub types", reflections.getTypesAnnotatedWith(MAI1.class), are(AI1.class)); assertThat("when honoring @Inherited, meta-annotation should only effect annotated super classes and it's sub types", reflections.getTypesAnnotatedWith(AI2.class), are(I2.class)); assertThat("when honoring @Inherited, meta-annotation should only effect annotated super classes and it's sub types", reflections.getTypesAnnotatedWith(AC1.class), are(C1.class, C2.class, C3.class, C5.class)); assertThat("when not honoring @Inherited, meta annotation effects all subtypes, including annotations interfaces and classes", reflections.getTypesAnnotatedWith(AI1.class, false), are(I1.class, I2.class, C1.class, C2.class, C3.class, C5.class)); assertThat("when not honoring @Inherited, meta annotation effects all subtypes, including annotations interfaces and classes", reflections.getTypesAnnotatedWith(AI2.class, false), are(I2.class, C1.class, C2.class, C3.class, C5.class)); assertThat(reflections.getTypesAnnotatedWith(AM1.class), isEmpty); //annotation member value matching AC2 ac2 = new AC2() { public String value() { return "ugh?!"; } public Class<? extends Annotation> annotationType() { return AC2.class; } }; assertThat("when honoring @Inherited, meta-annotation should only effect annotated super classes and it's sub types", reflections.getTypesAnnotatedWith(ac2), are(C3.class, I3.class)); assertThat("when not honoring @Inherited, meta annotation effects all subtypes, including annotations interfaces and classes", reflections.getTypesAnnotatedWith(ac2, false), are(C3.class, C5.class, I3.class, C6.class)); } @Test public void testMethodsAnnotatedWith() { try { assertThat(reflections.getMethodsAnnotatedWith(AM1.class), are(C4.class.getDeclaredMethod("m1"), C4.class.getDeclaredMethod("m1", int.class, String[].class), C4.class.getDeclaredMethod("m1", int[][].class, String[][].class), C4.class.getDeclaredMethod("m3"))); AM1 am1 = new AM1() { public String value() { return "1"; } public Class<? extends Annotation> annotationType() { return AM1.class; } }; assertThat(reflections.getMethodsAnnotatedWith(am1), are(C4.class.getDeclaredMethod("m1"), C4.class.getDeclaredMethod("m1", int.class, String[].class), C4.class.getDeclaredMethod("m1", int[][].class, String[][].class))); } catch (NoSuchMethodException e) { fail(); } } @Test public void testFieldsAnnotatedWith() { try { assertThat(reflections.getFieldsAnnotatedWith(AF1.class), are(C4.class.getDeclaredField("f1"), C4.class.getDeclaredField("f2") )); assertThat(reflections.getFieldsAnnotatedWith(new AF1() { public String value() { return "2"; } public Class<? extends Annotation> annotationType() { return AF1.class; } }), are(C4.class.getDeclaredField("f2"))); } catch (NoSuchFieldException e) { fail(); } } @Test public void testConverters() { try { assertThat(reflections.getConverters(C2.class, C3.class), are(C4.class.getDeclaredMethod("c2toC3", C2.class))); } catch (NoSuchMethodException e) { fail(); } } @Test public void collect() { String path = getUserDir() + "/target/test-classes" + "/META-INF/reflections/testModel-reflections.xml"; try { Predicate<String> filter = new FilterBuilder().include("org.jboss.errai.reflections.TestModel\\$.*"); Reflections testModelReflections = new Reflections(new ConfigurationBuilder() .filterInputsBy(filter) .setScanners( new SubTypesScanner().filterResultsBy(filter), new TypeAnnotationsScanner().filterResultsBy(filter)) .setUrls(asList(ClasspathHelper.forClass(TestModel.class)))); testModelReflections.scan(); testModelReflections.save(path); reflections = Reflections.collect(); reflections.scan(); testAll(); } finally { new File(path).delete(); } } @Test public void collectInputStream() { String path = getUserDir() + "/target/test-classes" + "/META-INF/reflections/testModel-reflections.xml"; try { Predicate<String> filter = new FilterBuilder().include("org.jboss.errai.reflections.TestModel\\$.*"); Reflections testModelReflections = new Reflections(new ConfigurationBuilder() .filterInputsBy(filter) .setScanners(new SubTypesScanner().filterResultsBy(filter), new TypeAnnotationsScanner().filterResultsBy(filter)) .setUrls(asList(ClasspathHelper.forClass(TestModel.class)))); testModelReflections.scan(); testModelReflections.save(path); final Iterable<Vfs.File> xmls = Vfs.findFiles(Arrays.asList(ClasspathHelper.forClass(ReflectionsTest.class)), new Predicate<Vfs.File>() { public boolean apply(Vfs.File input) { return input.getName().endsWith(".xml"); } }); reflections = new Reflections(new ConfigurationBuilder()); for (Vfs.File xml : xmls) { try { reflections.collect(xml.openInputStream()); reflections.scan(); } catch (IOException e) { throw new RuntimeException("", e); } } testAll(); } finally { new File(path).delete(); } } // @Test @Ignore // public void jsonCollect() { // Predicate<String> filter = new FilterBuilder().include("org.jboss.errai.reflections.TestModel\\$.*"); // Reflections testModelReflections = new Reflections(new ConfigurationBuilder() // .filterInputsBy(filter) // .setScanners( // new SubTypesScanner().filterResultsBy(filter), // new TypeAnnotationsScanner().filterResultsBy(filter)) // .setUrls(asList(ClasspathHelper.forClass(TestModel.class)))); // // testModelReflections.scan(); // // String path = getUserDir() + "/target/test-classes" + "/META-INF/reflections/testModel-reflections.json"; // // final JsonSerializer serializer = new JsonSerializer(); // testModelReflections.save(path, serializer); // // reflections = new Reflections(new ConfigurationBuilder()).collect("META-INF/reflections", // new FilterBuilder().include(".*-reflections.json"), // serializer); // // reflections.scan(); // // // reflections.collect("META-INF/reflections", // new FilterBuilder().include(".*-reflections.xml").exclude("testModel-reflections.xml"), // new XmlSerializer()); // // // testAll(); // } public static String getUserDir() { File file = new File(System.getProperty("user.dir")); //a hack to fix user.dir issue(?) in surfire if (Lists.newArrayList(file.list()).contains("reflections")) { file = new File(file, "reflections"); } return file.getAbsolutePath(); } @Test public void testResourcesScanner() { Predicate<String> filter = new FilterBuilder().include(".*\\.xml"); Reflections reflections = new Reflections(new ConfigurationBuilder() .filterInputsBy(filter) .setScanners(new ResourcesScanner()) .setUrls(asList(ClasspathHelper.forClass(TestModel.class)))); reflections.scan(); Set<String> resolved = reflections.getResources(Pattern.compile(".*resource1-reflections\\.xml")); assertThat(resolved, are("META-INF/reflections/resource1-reflections.xml")); Set<String> resources = reflections.getStore().get(ResourcesScanner.class).keySet(); assertThat(resources, are( "resource1-reflections.xml", "resource2-reflections.xml")); } // private final BaseMatcher<Set<Class<?>>> isEmpty = new BaseMatcher<Set<Class<?>>>() { public boolean matches(Object o) { return ((Collection<?>) o).isEmpty(); } public void describeTo(Description description) { description.appendText("empty collection"); } }; public <T> Matcher<Set<? super T>> are(final T... ts) { final Collection<?> c1 = Arrays.asList(ts); return new BaseMatcher<Set<? super T>>() { public boolean matches(Object o) { Collection<?> c2 = (Collection<?>) o; return c1.containsAll(c2) && c2.containsAll(c1); } public void describeTo(Description description) { description.appendText("elements: "); description.appendValueList("(", ",", ")", ts); } }; } }