/* * Copyright (C) 2015 Sebastian Daschner, sebastian-daschner.com * * 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/LICENSE2.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.sebastian_daschner.jaxrs_analyzer.analysis.bytecode.reduction; import com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ContextClassReader; import com.sebastian_daschner.jaxrs_analyzer.analysis.classes.ProjectMethodClassVisitor; import com.sebastian_daschner.jaxrs_analyzer.analysis.utils.TestClassUtils; import com.sebastian_daschner.jaxrs_analyzer.model.JavaUtils; import com.sebastian_daschner.jaxrs_analyzer.model.instructions.Instruction; import com.sebastian_daschner.jaxrs_analyzer.model.results.MethodResult; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.objectweb.asm.ClassReader; import org.objectweb.asm.Type; import javax.ws.rs.NotFoundException; import java.io.IOException; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Stream; import static com.sebastian_daschner.jaxrs_analyzer.model.methods.MethodIdentifier.of; @RunWith(Parameterized.class) public class RelevantInstructionReducerTest { private final RelevantInstructionReducer classUnderTest; private final String testClass; private final List<Instruction> expectedInstructions; public RelevantInstructionReducerTest(final String testClass, final List<Instruction> expectedInstructions) { this.testClass = testClass; this.expectedInstructions = expectedInstructions; this.classUnderTest = new RelevantInstructionReducer(); } @Parameterized.Parameters public static Collection<Object[]> data() throws NotFoundException, IOException, ReflectiveOperationException { Collection<Object[]> data = new LinkedList<>(); final Set<String> testClasses = TestClassUtils.getClasses("com/sebastian_daschner/jaxrs_analyzer/analysis/bytecode/reduction/testclasses"); testClassLabel: for (final String testClass : testClasses) { final Object[] testData = new Object[2]; data.add(testData); testData[0] = testClass; final Class<?> loadedClass = JavaUtils.loadClassFromName(testClass); // take "instructions"-method with higher priority for (Method method : loadedClass.getDeclaredMethods()) { if ("instructions".equals(method.getName())) { testData[1] = loadedClass.getDeclaredMethod("instructions").invoke(null); continue testClassLabel; } } // "expected"#-methods testData[1] = new LinkedList<>(); Stream.of(loadedClass.getDeclaredMethods()) .filter(m -> m.getName().startsWith("expected")).sorted(Comparator.comparing(Method::getName)) .map(RelevantInstructionReducerTest::getInstructions) .forEach(((List<Instruction>) testData[1])::addAll); } return data; } @Test public void test() throws IOException { // round trip to find the correct test method final Method method = Stream.of(JavaUtils.loadClassFromName(testClass).getDeclaredMethods()).filter(m -> m.getName().equals("method")).findAny().orElseThrow(NoSuchElementException::new); final List<Instruction> visitedInstructions = classUnderTest.reduceInstructions(getInstructions(method)); Assert.assertEquals("failed for " + testClass, expectedInstructions, visitedInstructions); } private static List<Instruction> getInstructions(final Method method) { try { final String className = method.getDeclaringClass().getCanonicalName().replace('.', '/'); final MethodResult methodResult = new MethodResult(); final ProjectMethodClassVisitor visitor = new ProjectMethodClassVisitor(methodResult, of(className, method.getName(), Type.getMethodDescriptor(method), false)); new ContextClassReader(className).accept(visitor, ClassReader.EXPAND_FRAMES); return methodResult.getInstructions(); } catch (IOException e) { throw new RuntimeException(e); } } }