/** * Copyright 2011-2017 Asakusa Framework Team. * * 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.asakusafw.operator.method; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.util.ElementFilter; import org.junit.Test; import com.asakusafw.operator.Callback; import com.asakusafw.operator.CompileEnvironment; import com.asakusafw.operator.OperatorCompilerTestRoot; import com.asakusafw.operator.OperatorDriver; import com.asakusafw.operator.description.ClassDescription; import com.asakusafw.operator.model.OperatorClass; import com.asakusafw.operator.model.OperatorDescription; import com.asakusafw.operator.model.OperatorElement; /** * Test for {@link OperatorMethodAnalyzer}. */ public class OperatorMethodAnalyzerTest extends OperatorCompilerTestRoot { /** * simple. */ @Test public void simple() { compile(new Action("com.example.Simple") { @Override protected void perform(OperatorClass target) { assertThat(target, is(notNullValue())); assertThat(target.getElements().size(), is(1)); assertThat(find(target, "method"), is(notNullValue())); } }); } /** * must be class. */ @Test public void violate_class() { violate("com.example.ViolateClass"); } /** * must be top-level. */ @Test public void violate_top_level() { violate("com.example.ViolateTopLevel"); } /** * must be public. */ @Test public void violate_public() { violate("com.example.ViolatePublic"); } /** * must be abstract. */ @Test public void violate_abstract() { violate("com.example.ViolateAbstract"); } /** * must be abstract. */ @Test public void violate_no_final() { violate("com.example.ViolateNoFinal"); } /** * must be no type parameters. */ @Test public void violate_no_type_parameters() { violate("com.example.ViolateNoTypeParameters"); } /** * should be no extends. */ @Test public void violate_no_extends() { violate("com.example.ViolateNoExtends"); } /** * should be no implements. */ @Test public void violate_no_implements() { violate("com.example.ViolateNoImplements"); } /** * must have a public empty constructor. */ @Test public void violate_empty_constructor() { violate("com.example.ViolateEmptyConstructor"); } /** * must have no other public methods. */ @Test public void violate_no_public_method() { violate("com.example.ViolateNoPublicMethod"); } /** * constructor must be empty. */ @Test public void violate_ctor_public() { violate("com.example.ctor.ViolatePublic"); } /** * constructor must not have type parameters. */ @Test public void violate_ctor_no_type_parameters() { violate("com.example.ctor.ViolateNoTypeParameters"); } /** * constructor must not have exceptions. */ @Test public void violate_ctor_no_exceptions() { violate("com.example.ctor.ViolateNoExceptions"); } /** * must have up to one operator annotation. */ @Test public void violate_method_one_annotation() { violate("com.example.method.ViolateOneAnnotation"); } /** * method must be public. */ @Test public void violate_method_public() { violate("com.example.method.ViolatePublic"); } /** * method must no be static. */ @Test public void violate_method_not_static() { violate("com.example.method.ViolateNotStatic"); } /** * method must have unique id. */ @Test public void violate_method_unique_id() { violate("com.example.method.ViolateUniqueId"); } OperatorElement find(OperatorClass target, String name) { for (OperatorElement element : target.getElements()) { if (element.getDeclaration().getSimpleName().contentEquals(name)) { return element; } } return null; } private void compile(Action action) { add(action.className); add("com.example.Mock"); add("com.example.Conflict"); start(action); assertThat(action.performed, is(true)); } private void violate(String className) { add(className); add("com.example.Mock"); add("com.example.Conflict"); Action action = new Action(className) { @Override protected void perform(OperatorClass target) { return; } }; error(action); assertThat(action.performed, is(true)); } private abstract static class Action extends Callback { final String className; boolean performed; Action(String className) { this.className = className; } @Override protected CompileEnvironment createCompileEnvironment(ProcessingEnvironment processingEnv) { return new CompileEnvironment( processingEnv, Arrays.asList( new MockDriver("com.example.Mock"), new MockDriver("com.example.Conflict")), Collections.emptyList()); } @Override protected void test() { TypeElement element = env.findTypeElement(new ClassDescription(className)); assertThat(className, element, is(notNullValue())); while (element.getEnclosingElement().getKind() != ElementKind.PACKAGE) { element = (TypeElement) element.getEnclosingElement(); } if (round.getRootElements().contains(element)) { this.performed = true; OperatorMethodAnalyzer analyzer = new OperatorMethodAnalyzer(env); for (TypeElement annotation : annotatios) { if (env.findDriver(annotation) == null) { continue; } for (ExecutableElement method : ElementFilter.methodsIn(round.getElementsAnnotatedWith(annotation))) { analyzer.register(annotation, method); } } Collection<OperatorClass> resolved = analyzer.resolve(); if (resolved.size() == 1) { OperatorClass first = resolved.iterator().next(); assertThat(first.getDeclaration(), is(element)); perform(first); } else { perform(null); } } } protected abstract void perform(OperatorClass target); } private static class MockDriver implements OperatorDriver { private final ClassDescription typeName; public MockDriver(String typeName) { this.typeName = new ClassDescription(typeName); } @Override public ClassDescription getAnnotationTypeName() { return typeName; } @Override public OperatorDescription analyze(Context context) { return null; } } }