| /******************************************************************************* |
| * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Marc R. Hoffmann - initial API and implementation |
| * |
| *******************************************************************************/ |
| package org.jacoco.core.test.validation; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.objectweb.asm.Opcodes.ACC_PUBLIC; |
| import static org.objectweb.asm.Opcodes.ACC_SUPER; |
| import static org.objectweb.asm.Opcodes.ALOAD; |
| import static org.objectweb.asm.Opcodes.INVOKESPECIAL; |
| import static org.objectweb.asm.Opcodes.RETURN; |
| import static org.objectweb.asm.Opcodes.V1_1; |
| import static org.objectweb.asm.Opcodes.V1_2; |
| import static org.objectweb.asm.Opcodes.V1_3; |
| import static org.objectweb.asm.Opcodes.V1_4; |
| import static org.objectweb.asm.Opcodes.V1_5; |
| import static org.objectweb.asm.Opcodes.V1_6; |
| import static org.objectweb.asm.Opcodes.V1_7; |
| import static org.objectweb.asm.Opcodes.V1_8; |
| |
| import java.io.IOException; |
| |
| import org.jacoco.core.instr.Instrumenter; |
| import org.jacoco.core.internal.Java9Support; |
| import org.jacoco.core.internal.instr.InstrSupport; |
| import org.jacoco.core.runtime.IRuntime; |
| import org.jacoco.core.runtime.SystemPropertiesRuntime; |
| import org.junit.Test; |
| import org.objectweb.asm.ClassReader; |
| import org.objectweb.asm.ClassVisitor; |
| import org.objectweb.asm.ClassWriter; |
| import org.objectweb.asm.MethodVisitor; |
| |
| /** |
| * Test class inserted stackmap frames for different class file versions. |
| */ |
| public class ClassFileVersionsTest { |
| |
| @Test |
| public void test_1_1() throws IOException { |
| testVersion(V1_1, false); |
| } |
| |
| @Test |
| public void test_1_2() throws IOException { |
| testVersion(V1_2, false); |
| } |
| |
| @Test |
| public void test_1_3() throws IOException { |
| testVersion(V1_3, false); |
| } |
| |
| @Test |
| public void test_1_4() throws IOException { |
| testVersion(V1_4, false); |
| } |
| |
| @Test |
| public void test_1_5() throws IOException { |
| testVersion(V1_5, false); |
| } |
| |
| @Test |
| public void test_1_6() throws IOException { |
| testVersion(V1_6, true); |
| } |
| |
| @Test |
| public void test_1_7() throws IOException { |
| testVersion(V1_7, true); |
| } |
| |
| @Test |
| public void test_1_8() throws IOException { |
| testVersion(V1_8, true); |
| } |
| |
| @Test |
| public void test_1_9() throws IOException { |
| testVersion(Java9Support.V1_9, true); |
| } |
| |
| private void testVersion(int version, boolean frames) throws IOException { |
| final byte[] original = createClass(version); |
| |
| IRuntime runtime = new SystemPropertiesRuntime(); |
| Instrumenter instrumenter = new Instrumenter(runtime); |
| byte[] instrumented = instrumenter.instrument(original, "TestTarget"); |
| |
| assertFrames(instrumented, frames); |
| } |
| |
| private void assertFrames(byte[] source, boolean expected) { |
| final boolean[] hasFrames = new boolean[] { false }; |
| new ClassReader(Java9Support.downgradeIfRequired(source)).accept( |
| new ClassVisitor(InstrSupport.ASM_API_VERSION) { |
| |
| @Override |
| public MethodVisitor visitMethod(int access, String name, |
| String desc, String signature, String[] exceptions) { |
| return new MethodVisitor(InstrSupport.ASM_API_VERSION) { |
| |
| @Override |
| public void visitFrame(int type, int nLocal, |
| Object[] local, int nStack, Object[] stack) { |
| hasFrames[0] = true; |
| } |
| |
| }; |
| } |
| |
| }, 0); |
| assertEquals(Boolean.valueOf(expected), Boolean.valueOf(hasFrames[0])); |
| } |
| |
| private byte[] createClass(int version) { |
| |
| ClassWriter cw = new ClassWriter(0); |
| MethodVisitor mv; |
| |
| cw.visit(version, ACC_PUBLIC + ACC_SUPER, "org/jacoco/test/Sample", |
| null, "java/lang/Object", null); |
| |
| mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); |
| mv.visitCode(); |
| mv.visitVarInsn(ALOAD, 0); |
| mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", |
| false); |
| mv.visitInsn(RETURN); |
| mv.visitMaxs(1, 1); |
| mv.visitEnd(); |
| |
| cw.visitEnd(); |
| |
| return cw.toByteArray(); |
| } |
| |
| } |