diff options
author | Marc R. Hoffmann <hoffmann@mountainminds.com> | 2013-06-01 12:19:09 +0200 |
---|---|---|
committer | Marc R. Hoffmann <hoffmann@mountainminds.com> | 2013-06-01 12:19:09 +0200 |
commit | e048201f115d862e1b99e78249ef9e720212c201 (patch) | |
tree | e127902553a8c7b40e8c1a847b619ffcfba1482b | |
parent | 73a2235e02b93b114b2dee69b05ab07ae5a0693a (diff) | |
download | jacoco-e048201f115d862e1b99e78249ef9e720212c201.tar.gz |
Issue error when analyzing instrumented classes (GitHub #108)
6 files changed, 100 insertions, 25 deletions
diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java new file mode 100644 index 00000000..c60901c2 --- /dev/null +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/analysis/ClassAnalyzerTest.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2009, 2013 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.internal.analysis; + +import org.jacoco.core.internal.instr.InstrSupport; +import org.junit.Before; +import org.junit.Test; +import org.objectweb.asm.Opcodes; + +/** + * Unit tests for {@link ClassAnalyzer}. + */ +public class ClassAnalyzerTest { + + private ClassAnalyzer analyzer; + + @Before + public void setup() { + analyzer = new ClassAnalyzer(0x0000, null, new StringPool()); + analyzer.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "Foo", null, + "java/lang/Object", null); + } + + @Test(expected = IllegalStateException.class) + public void testAnalyzeInstrumentedClass1() { + analyzer.visitField(InstrSupport.DATAFIELD_ACC, + InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC, null, + null); + } + + @Test(expected = IllegalStateException.class) + public void testAnalyzeInstrumentedClass2() { + analyzer.visitMethod(InstrSupport.INITMETHOD_ACC, + InstrSupport.INITMETHOD_NAME, InstrSupport.INITMETHOD_DESC, + null, null); + } + +} diff --git a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java index f10fe6fb..1d8004a4 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/internal/instr/InstrSupportTest.java @@ -34,6 +34,21 @@ public class InstrSupportTest { } @Test + public void testAssertNotIntrumentedPositive() { + InstrSupport.assertNotInstrumented("run", "Foo"); + } + + @Test(expected = IllegalStateException.class) + public void testAssertNotIntrumentedField() { + InstrSupport.assertNotInstrumented("$jacocoData", "Foo"); + } + + @Test(expected = IllegalStateException.class) + public void testAssertNotIntrumentedMethod() { + InstrSupport.assertNotInstrumented("$jacocoInit", "Foo"); + } + + @Test public void testPushIntM2147483648() { InstrSupport.push(trace, -2147483648); assertInstruction("LDC -2147483648"); diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java index ee8f05a2..9fa52889 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/ClassAnalyzer.java @@ -14,6 +14,8 @@ package org.jacoco.core.internal.analysis; import org.jacoco.core.analysis.IMethodCoverage; import org.jacoco.core.internal.flow.ClassProbesVisitor; import org.jacoco.core.internal.flow.MethodProbesVisitor; +import org.jacoco.core.internal.instr.InstrSupport; +import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Opcodes; /** @@ -72,6 +74,8 @@ public class ClassAnalyzer extends ClassProbesVisitor { public MethodProbesVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { + InstrSupport.assertNotInstrumented(name, coverage.getName()); + // TODO: Use filter hook if ((access & Opcodes.ACC_SYNTHETIC) != 0) { return null; @@ -92,6 +96,13 @@ public class ClassAnalyzer extends ClassProbesVisitor { } @Override + public FieldVisitor visitField(final int access, final String name, + final String desc, final String signature, final Object value) { + InstrSupport.assertNotInstrumented(name, coverage.getName()); + return super.visitField(access, name, desc, signature, value); + } + + @Override public void visitTotalProbeCount(final int count) { // nothing to do } diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java index 796a004a..d9fb76ea 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/ClassInstrumenter.java @@ -11,8 +11,6 @@ *******************************************************************************/ package org.jacoco.core.internal.instr; -import static java.lang.String.format; - import org.jacoco.core.internal.flow.ClassProbesVisitor; import org.jacoco.core.internal.flow.MethodProbesVisitor; import org.jacoco.core.runtime.IExecutionDataAccessorGenerator; @@ -78,7 +76,7 @@ public class ClassInstrumenter extends ClassProbesVisitor { @Override public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) { - assertNotInstrumented(name, InstrSupport.DATAFIELD_NAME); + InstrSupport.assertNotInstrumented(name, className); return super.visitField(access, name, desc, signature, value); } @@ -86,7 +84,7 @@ public class ClassInstrumenter extends ClassProbesVisitor { public MethodProbesVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { - assertNotInstrumented(name, InstrSupport.INITMETHOD_NAME); + InstrSupport.assertNotInstrumented(name, className); final MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); @@ -119,27 +117,6 @@ public class ClassInstrumenter extends ClassProbesVisitor { super.visitEnd(); } - /** - * Ensures that the given member does not correspond to a internal member - * created by the instrumentation process. This would mean that the class - * has been instrumented twice. - * - * @param member - * name of the member to check - * @param instrMember - * name of a instrumentation member - * @throws IllegalStateException - * thrown if the member has the same name than the - * instrumentation member - */ - private void assertNotInstrumented(final String member, - final String instrMember) throws IllegalStateException { - if (member.equals(instrMember)) { - throw new IllegalStateException(format( - "Class %s is already instrumented.", className)); - } - } - // === probe array strategies === private class ClassTypeStrategy implements IProbeArrayStrategy { diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java index 8bb46026..8c74a4b8 100644 --- a/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java +++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java @@ -11,6 +11,8 @@ *******************************************************************************/ package org.jacoco.core.internal.instr; +import static java.lang.String.format; + import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; @@ -61,6 +63,27 @@ public final class InstrSupport { | Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; /** + * Ensures that the given member does not correspond to a internal member + * created by the instrumentation process. This would mean that the class is + * already instrumented. + * + * @param member + * name of the member to check + * @param owner + * name of the class owning the member + * @throws IllegalStateException + * thrown if the member has the same name than the + * instrumentation member + */ + public static void assertNotInstrumented(final String member, + final String owner) throws IllegalStateException { + if (member.equals(DATAFIELD_NAME) || member.equals(INITMETHOD_NAME)) { + throw new IllegalStateException(format( + "Class %s is already instrumented.", owner)); + } + } + + /** * Generates the instruction to push the given int value on the stack. * Implementation taken from * {@link org.objectweb.asm.commons.GeneratorAdapter#push(int)}. diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index a002b95e..306c6716 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -38,6 +38,8 @@ <ul> <li>More context information when exceptions occur during analysis or instrumentation (GitHub #104).</li> + <li>If analysis is performed on offline instrumented classes - which is an + build configuration error - an exception is now thrown (GitHub #108).</li> </ul> |