/* * Copyright (c) 2013-2017 Chris Newland. * Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD * Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki */ package org.adoptopenjdk.jitwatch.test; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_ADDRESS; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_COMPILE_ID; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_NEWLINE; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_TASK_QUEUED; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_NMETHOD; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_TASK; import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.TAG_TASK_DONE; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.adoptopenjdk.jitwatch.core.IJITListener; import org.adoptopenjdk.jitwatch.core.TagProcessor; import org.adoptopenjdk.jitwatch.loader.BytecodeLoader; import org.adoptopenjdk.jitwatch.model.AnnotationException; import org.adoptopenjdk.jitwatch.model.IMetaMember; import org.adoptopenjdk.jitwatch.model.IReadOnlyJITDataModel; import org.adoptopenjdk.jitwatch.model.JITDataModel; import org.adoptopenjdk.jitwatch.model.JITEvent; import org.adoptopenjdk.jitwatch.model.MemberSignatureParts; import org.adoptopenjdk.jitwatch.model.MetaClass; import org.adoptopenjdk.jitwatch.model.MetaPackage; import org.adoptopenjdk.jitwatch.model.Tag; import org.adoptopenjdk.jitwatch.model.Task; import org.adoptopenjdk.jitwatch.model.bytecode.BCAnnotationType; import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeAnnotationBuilder; import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeAnnotationList; import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeAnnotations; import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction; import org.adoptopenjdk.jitwatch.model.bytecode.LineAnnotation; import org.adoptopenjdk.jitwatch.parser.ILogParseErrorListener; import org.adoptopenjdk.jitwatch.util.ClassUtil; import org.adoptopenjdk.jitwatch.util.StringUtil; public class UnitTestUtil { public static Set<Tag> unhandledTags; public static MetaClass createMetaClassFor(JITDataModel model, String fqClassName) throws ClassNotFoundException { Class<?> clazz = Class.forName(fqClassName); return model.buildAndGetMetaClass(clazz); } public static HelperMetaMethod createTestMetaMember(String fqClassName, String methodName, Class<?>[] params, Class<?> returnType) { String packageName = StringUtil.getPackageName(fqClassName); String className = StringUtil.getUnqualifiedClassName(fqClassName); MetaPackage metaPackage = new MetaPackage(packageName); MetaClass metaClass = new MetaClass(metaPackage, className); HelperMetaMethod helper = null; try { helper = new HelperMetaMethod(methodName, metaClass, params, returnType); } catch (NoSuchMethodException | SecurityException e) { e.printStackTrace(); } return helper; } public static HelperMetaMethod createTestMetaMember(JITDataModel model, String fqClassName, String methodName, Class<?>[] params, Class<?> returnType) { String packageName = StringUtil.getPackageName(fqClassName); String className = StringUtil.getUnqualifiedClassName(fqClassName); MetaPackage metaPackage = new MetaPackage(packageName); MetaClass metaClass = model.getPackageManager().getMetaClass(fqClassName); if (metaClass == null) { metaClass = new MetaClass(metaPackage, className); model.getPackageManager().addMetaClass(metaClass); } HelperMetaMethod helper = null; try { helper = new HelperMetaMethod(methodName, metaClass, params, returnType); } catch (NoSuchMethodException | SecurityException e) { e.printStackTrace(); } return helper; } public static IMetaMember setUpTestMember(JITDataModel model, String fqClassName, String memberName, Class<?> returnType, Class<?>[] params, String nmethodAddress) throws ClassNotFoundException { MetaClass metaClass = model.getPackageManager().getMetaClass(fqClassName); if (metaClass == null) { metaClass = UnitTestUtil.createMetaClassFor(model, fqClassName); } List<String> paramList = new ArrayList<>(); for (Class<?> clazz : params) { paramList.add(clazz.getName()); } MemberSignatureParts msp = MemberSignatureParts.fromParts(fqClassName, memberName, returnType.getName(), paramList); IMetaMember createdMember = metaClass.getMemberForSignature(msp); Tag tagTaskQueued = new Tag(TAG_TASK_QUEUED, ATTR_COMPILE_ID + "='1'", true); createdMember.setTagTaskQueued(tagTaskQueued); Tag tagNMethod = new Tag(TAG_NMETHOD, ATTR_COMPILE_ID + "='1' " + ATTR_ADDRESS + "='" + nmethodAddress + "'", true); createdMember.setTagNMethod(tagNMethod); return createdMember; } public static IMetaMember createTestMetaMember() { return createTestMetaMember("java.lang.String", "length", new Class<?>[0], void.class); } public static Method getMethod(String fqClassName, String method, Class<?>[] paramTypes) { Method m = null; try { Class<?> clazz = ClassUtil.loadClassWithoutInitialising(fqClassName); m = clazz.getDeclaredMethod(method, paramTypes); } catch (Exception e) { e.printStackTrace(); } return m; } public static Constructor<?> getConstructor(String fqClassName, Class<?>[] paramTypes) { Constructor<?> c = null; try { Class<?> clazz = ClassUtil.loadClassWithoutInitialising(fqClassName); c = clazz.getDeclaredConstructor(paramTypes); } catch (Exception e) { e.printStackTrace(); } return c; } public static IJITListener getNoOpJITListener() { return new IJITListener() { @Override public void handleLogEntry(String entry) { } @Override public void handleErrorEntry(String entry) { } @Override public void handleReadStart() { } @Override public void handleReadComplete() { } @Override public void handleJITEvent(JITEvent event) { } }; } public static ILogParseErrorListener getNoOpParseErrorListener() { return new ILogParseErrorListener() { @Override public void handleError(String title, String body) { } }; } public static void processLogLines(IMetaMember member, String[] logLines) { TagProcessor tp = new TagProcessor(); Tag tag = null; for (String line : logLines) { line = line.trim(); line = StringUtil.replaceXMLEntities(line); tag = tp.processLine(line); if (tag != null) { switch (tag.getName()) { case TAG_TASK_QUEUED: member.setTagTaskQueued(tag); break; case TAG_NMETHOD: member.setTagNMethod(tag); break; case TAG_TASK: member.setTagTask((Task) tag); break; case TAG_TASK_DONE: member.setTagNMethod(tag); break; } } } } public static BytecodeAnnotations buildAnnotations(boolean verifyBytecode, boolean processInlineAnnotations, IReadOnlyJITDataModel model, IMetaMember member, String[] logLines, String[] bytecodeLines) { UnitTestUtil.processLogLines(member, logLines); StringBuilder bytecodeBuilder = new StringBuilder(); for (String bcLine : bytecodeLines) { bytecodeBuilder.append(bcLine.trim()).append(S_NEWLINE); } List<BytecodeInstruction> instructions = BytecodeLoader.parseInstructions(bytecodeBuilder.toString()); ((HelperMetaMethod) member).setInstructions(instructions); BytecodeAnnotations bcAnnotations = null; int compilationIndex = member.getSelectedCompilation().getIndex(); BytecodeAnnotationBuilder annotationBuilder = new BytecodeAnnotationBuilder(verifyBytecode, processInlineAnnotations); try { bcAnnotations = annotationBuilder.buildBytecodeAnnotations(member, compilationIndex, model); } catch (AnnotationException annoEx) { annoEx.printStackTrace(); fail(); } unhandledTags = annotationBuilder.getUnhandledTags(); return bcAnnotations; } public static void checkAnnotation(BytecodeAnnotationList result, int index, String annotation, BCAnnotationType type) { List<LineAnnotation> lines = result.getAnnotationsForBCI(index); assertNotNull(lines); boolean matchedAnnotation = false; boolean matchedType = false; for (LineAnnotation lineAnnotation : lines) { if (lineAnnotation.getAnnotation().contains(annotation)) { matchedAnnotation = true; if (lineAnnotation.getType() == type) { matchedType = true; } } } assertTrue("Did not match text: " + annotation, matchedAnnotation); assertTrue("Did not match type: " + type, matchedType); } }