1/******************************************************************************* 2 * Copyright (c) 2009, 2015 Mountainminds GmbH & Co. KG and Contributors 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * Marc R. Hoffmann - initial API and implementation 10 * 11 *******************************************************************************/ 12package org.jacoco.core.test.validation; 13 14import static org.junit.Assert.assertEquals; 15import static org.objectweb.asm.Opcodes.ACC_PUBLIC; 16import static org.objectweb.asm.Opcodes.ACC_SUPER; 17import static org.objectweb.asm.Opcodes.ALOAD; 18import static org.objectweb.asm.Opcodes.INVOKESPECIAL; 19import static org.objectweb.asm.Opcodes.RETURN; 20import static org.objectweb.asm.Opcodes.V1_1; 21import static org.objectweb.asm.Opcodes.V1_2; 22import static org.objectweb.asm.Opcodes.V1_3; 23import static org.objectweb.asm.Opcodes.V1_4; 24import static org.objectweb.asm.Opcodes.V1_5; 25import static org.objectweb.asm.Opcodes.V1_6; 26import static org.objectweb.asm.Opcodes.V1_7; 27import static org.objectweb.asm.Opcodes.V1_8; 28 29import java.io.IOException; 30 31import org.jacoco.core.JaCoCo; 32import org.jacoco.core.instr.Instrumenter; 33import org.jacoco.core.runtime.IRuntime; 34import org.jacoco.core.runtime.SystemPropertiesRuntime; 35import org.junit.Test; 36import org.objectweb.asm.ClassReader; 37import org.objectweb.asm.ClassVisitor; 38import org.objectweb.asm.ClassWriter; 39import org.objectweb.asm.MethodVisitor; 40 41/** 42 * Test class inserted stackmap frames for different class file versions. 43 */ 44public class ClassFileVersionsTest { 45 46 @Test 47 public void test_1_1() throws IOException { 48 testVersion(V1_1, false); 49 } 50 51 @Test 52 public void test_1_2() throws IOException { 53 testVersion(V1_2, false); 54 } 55 56 @Test 57 public void test_1_3() throws IOException { 58 testVersion(V1_3, false); 59 } 60 61 @Test 62 public void test_1_4() throws IOException { 63 testVersion(V1_4, false); 64 } 65 66 @Test 67 public void test_1_5() throws IOException { 68 testVersion(V1_5, false); 69 } 70 71 @Test 72 public void test_1_6() throws IOException { 73 testVersion(V1_6, true); 74 } 75 76 @Test 77 public void test_1_7() throws IOException { 78 testVersion(V1_7, true); 79 } 80 81 @Test 82 public void test_1_8() throws IOException { 83 testVersion(V1_8, true); 84 } 85 86 private void testVersion(int version, boolean frames) throws IOException { 87 final byte[] original = createClass(version); 88 89 IRuntime runtime = new SystemPropertiesRuntime(); 90 Instrumenter instrumenter = new Instrumenter(runtime); 91 byte[] instrumented = instrumenter.instrument(original, "TestTarget"); 92 93 assertFrames(instrumented, frames); 94 } 95 96 private void assertFrames(byte[] source, boolean expected) { 97 final boolean[] hasFrames = new boolean[] { false }; 98 new ClassReader(source).accept( 99 new ClassVisitor(JaCoCo.ASM_API_VERSION) { 100 101 @Override 102 public MethodVisitor visitMethod(int access, String name, 103 String desc, String signature, String[] exceptions) { 104 return new MethodVisitor(JaCoCo.ASM_API_VERSION) { 105 106 @Override 107 public void visitFrame(int type, int nLocal, 108 Object[] local, int nStack, Object[] stack) { 109 hasFrames[0] = true; 110 } 111 112 }; 113 } 114 115 }, 0); 116 assertEquals(Boolean.valueOf(expected), Boolean.valueOf(hasFrames[0])); 117 } 118 119 private byte[] createClass(int version) { 120 121 ClassWriter cw = new ClassWriter(0); 122 MethodVisitor mv; 123 124 cw.visit(version, ACC_PUBLIC + ACC_SUPER, "org/jacoco/test/Sample", 125 null, "java/lang/Object", null); 126 127 mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 128 mv.visitCode(); 129 mv.visitVarInsn(ALOAD, 0); 130 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", 131 false); 132 mv.visitInsn(RETURN); 133 mv.visitMaxs(1, 1); 134 mv.visitEnd(); 135 136 cw.visitEnd(); 137 138 return cw.toByteArray(); 139 } 140 141} 142