001/* 002 * Cobertura - http://cobertura.sourceforge.net/ 003 * 004 * Copyright (C) 2011 Piotr Tabor 005 * 006 * Note: This file is dual licensed under the GPL and the Apache 007 * Source License (so that it can be used from both the main 008 * Cobertura classes and the ant tasks). 009 * 010 * Cobertura is free software; you can redistribute it and/or modify 011 * it under the terms of the GNU General Public License as published 012 * by the Free Software Foundation; either version 2 of the License, 013 * or (at your option) any later version. 014 * 015 * Cobertura is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of 017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 018 * General Public License for more details. 019 * 020 * You should have received a copy of the GNU General Public License 021 * along with Cobertura; if not, write to the Free Software 022 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 023 * USA 024 */ 025 026package net.sourceforge.cobertura.instrument.pass3; 027 028import net.sourceforge.cobertura.instrument.tp.ClassMap; 029 030import org.objectweb.asm.ClassVisitor; 031import org.objectweb.asm.MethodVisitor; 032 033/** 034 * Universal API for all methods that are responsible for generating any JASM code that have 035 * to be injected into real classes. 036 * 037 * The general idea is that injected code is responsible for incrementing counters. The realization of counters 038 * is implementation dependent. 039 * 040 * @author piotr.tabor@gmail.com 041 * 042 */ 043public interface CodeProvider { 044 /** 045 * Name of a field that have to be injected into instrumented class that is responsible for storing counters 046 */ 047 public static final String COBERTURA_COUNTERS_FIELD_NAME = "__cobertura_counters"; 048 049 /** 050 * Name of a method that will to be injected into instrumented class that is responsible for storing 051 * class-map (information on mapping of counter identifiers into lines, jumps and switch-touches). 052 */ 053 public static final String COBERTURA_CLASSMAP_METHOD_NAME = "__cobertura_classmap"; 054 055 /** 056 * Name of method that will initialize internal counters variable. 057 */ 058 public static final String COBERTURA_INIT_METHOD_NAME = "__cobertura_init"; 059 060 /** 061 * Name of a method that have to be injected into instrumented class that is responsible for reading 062 * value of given counter. 063 * 064 * Signature of this method is: int[] __cobertura_counter(int counterId); 065 */ 066 public static final String COBERTURA_GET_AND_RESET_COUNTERS_METHOD_NAME = "__cobertura_get_and_reset_counters"; 067 068 069 /** 070 * Generates fields injected into instrumented class by cobertura. 071 * 072 * @param cv - ClassVisitor that is listener of code-generation events 073 */ 074 public abstract void generateCountersField(ClassVisitor cv); 075 076 /** 077 * Injects code that increments counter given by parameter. 078 * 079 * @param nextMethodVisitor - {@link MethodVisitor} that is listener of code-generation events 080 * @param counterId - counterId of counter that have to be incremented 081 * @param className - internal name (asm) of class being instrumented 082 */ 083 public abstract void generateCodeThatIncrementsCoberturaCounter( 084 MethodVisitor nextMethodVisitor, Integer counterId, String className); 085 086 /** 087 * Injects code that increments counter given by internal variable. 088 * The id of the variable is identified by lastJumpIdVariableIndex. The variable is in most cases set (by {@link #generateCodeThatSetsJumpCounterIdVariable(MethodVisitor, int, int)} 089 * to some counterId and in the target label, the counter identified by the variable is incremented. 090 * long 091 * @param nextMethodVisitor - {@link MethodVisitor} that is listener of code-generation events 092 * @param lastJumpIdVariableIndex - id of the variable used to store counterId that have to be incremented 093 * @param className - internal name (asm) of class being instrumented 094 */ 095 public abstract void generateCodeThatIncrementsCoberturaCounterFromInternalVariable( 096 MethodVisitor nextMethodVisitor, int lastJumpIdVariableIndex, 097 String className); 098 099 /** 100 * Injects code that sets internal variable (identified by lastJumpIdVariableIndex) to given value. 101 * 102 * @param nextMethodVisitor - {@link MethodVisitor} that is listener of code-generation events 103 * @param new_value - value to set the variable to 104 * @param lastJumpIdVariableIndex - index of variable that have to be set 105 */ 106 public abstract void generateCodeThatSetsJumpCounterIdVariable( 107 MethodVisitor nextMethodVisitor, int new_value, 108 int lastJumpIdVariableIndex); 109 110 /** 111 * Injects code that sets internal variable (identified by lastJumpIdVariableIndex) to zero. 112 * 113 * @param nextMethodVisitor - {@link MethodVisitor} that is listener of code-generation events 114 * @param lastJumpIdVariableIndex - index of variable that have to be set 115 */ 116 public abstract void generateCodeThatZeroJumpCounterIdVariable( 117 MethodVisitor nextMethodVisitor, int lastJumpIdVariableIndex); 118 119 /** 120 * Injects code that behaves the same as such a code snippet: 121 * <pre> 122 * if (value('lastJumpIdVariableIndex')==neededJumpCounterIdVariableValue){ 123 * cobertura_counters.increment(counterIdToIncrement); 124 * } 125 * </pre> 126 * 127 * This snippet is used in switch case of switch statement. We have a label and we want to ensure that 128 * we are executing the label in effect of switch statement-jump, and not other JUMP or fall-throught. 129 */ 130 public abstract void generateCodeThatIncrementsCoberturaCounterIfVariableEqualsAndCleanVariable( 131 MethodVisitor nextMethodVisitor, 132 Integer neededJumpCounterIdVariableValue, 133 Integer counterIdToIncrement, int lastJumpIdVariableIndex, 134 String className); 135 136 /** 137 * The version of cobertura prior to 1.10 used *.ser file to store information of lines, jumps, switches and other 138 * constructions used in the class. It was difficult to user to transfer the files after instrumentation into 139 * 'production' directory. To avoid that we are now creating the class-map as a special injected method that is responsible 140 * for keeping such a informations. 141 * 142 * @param cv - listener used to inject the code 143 * @param classMap - structure that is keeping all collected information about the class. The information from the structure will be stored as 144 * method body. 145 */ 146 public void generateCoberturaClassMapMethod(ClassVisitor cv, ClassMap classMap); 147 148 /** 149 * Generate method {@value #COBERTURA_GET_AND_RESET_COUNTERS_METHOD_NAME} that is accessor to couters. 150 * Signature of this method is: static int __cobertura_counter(int counterId); 151 * 152 * @param cv - listener used to inject the code 153 */ 154 public abstract void generateCoberturaGetAndResetCountersMethod(ClassVisitor cv, String className); 155 156 public void generateCoberturaInitMethod(ClassVisitor cv, String className, int countersCnt); 157 158 public abstract void generateCallCoberturaInitMethod(MethodVisitor mv, 159 String className); 160}