1/******************************************************************************* 2 * Copyright (c) 2009, 2018 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; 28import static org.objectweb.asm.Opcodes.V9; 29 30import java.io.IOException; 31 32import org.jacoco.core.instr.Instrumenter; 33import org.jacoco.core.internal.instr.InstrSupport; 34import org.jacoco.core.runtime.IRuntime; 35import org.jacoco.core.runtime.SystemPropertiesRuntime; 36import org.junit.Test; 37import org.objectweb.asm.ClassReader; 38import org.objectweb.asm.ClassVisitor; 39import org.objectweb.asm.ClassWriter; 40import org.objectweb.asm.MethodVisitor; 41 42/** 43 * Test class inserted stackmap frames for different class file versions. 44 */ 45public class ClassFileVersionsTest { 46 47 @Test 48 public void test_1_1() throws IOException { 49 testVersion(V1_1, false); 50 } 51 52 @Test 53 public void test_1_2() throws IOException { 54 testVersion(V1_2, false); 55 } 56 57 @Test 58 public void test_1_3() throws IOException { 59 testVersion(V1_3, false); 60 } 61 62 @Test 63 public void test_1_4() throws IOException { 64 testVersion(V1_4, false); 65 } 66 67 @Test 68 public void test_1_5() throws IOException { 69 testVersion(V1_5, false); 70 } 71 72 @Test 73 public void test_1_6() throws IOException { 74 testVersion(V1_6, true); 75 } 76 77 @Test 78 public void test_1_7() throws IOException { 79 testVersion(V1_7, true); 80 } 81 82 @Test 83 public void test_1_8() throws IOException { 84 testVersion(V1_8, true); 85 } 86 87 @Test 88 public void test_1_9() throws IOException { 89 testVersion(V9, true); 90 } 91 92 private void testVersion(int version, boolean frames) throws IOException { 93 final byte[] original = createClass(version); 94 95 IRuntime runtime = new SystemPropertiesRuntime(); 96 Instrumenter instrumenter = new Instrumenter(runtime); 97 byte[] instrumented = instrumenter.instrument(original, "TestTarget"); 98 99 assertFrames(instrumented, frames); 100 } 101 102 private void assertFrames(byte[] source, boolean expected) { 103 final boolean[] hasFrames = new boolean[] { false }; 104 new ClassReader(source) 105 .accept(new ClassVisitor(InstrSupport.ASM_API_VERSION) { 106 107 @Override 108 public MethodVisitor visitMethod(int access, String name, 109 String desc, String signature, String[] exceptions) { 110 return new MethodVisitor(InstrSupport.ASM_API_VERSION) { 111 112 @Override 113 public void visitFrame(int type, int nLocal, 114 Object[] local, int nStack, Object[] stack) { 115 hasFrames[0] = true; 116 } 117 118 }; 119 } 120 121 }, 0); 122 assertEquals(Boolean.valueOf(expected), Boolean.valueOf(hasFrames[0])); 123 } 124 125 private byte[] createClass(int version) { 126 127 ClassWriter cw = new ClassWriter(0); 128 MethodVisitor mv; 129 130 cw.visit(version, ACC_PUBLIC + ACC_SUPER, "org/jacoco/test/Sample", 131 null, "java/lang/Object", null); 132 133 mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 134 mv.visitCode(); 135 mv.visitVarInsn(ALOAD, 0); 136 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", 137 false); 138 mv.visitInsn(RETURN); 139 mv.visitMaxs(1, 1); 140 mv.visitEnd(); 141 142 cw.visitEnd(); 143 144 return cw.toByteArray(); 145 } 146 147} 148