001: /*
002: * @(#)CCCreatorUtil.java
003: *
004: * Copyright (C) 2003 Matt Albrecht
005: * groboclown@users.sourceforge.net
006: * http://groboutils.sourceforge.net
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a
009: * copy of this software and associated documentation files (the "Software"),
010: * to deal in the Software without restriction, including without limitation
011: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
012: * and/or sell copies of the Software, and to permit persons to whom the
013: * Software is furnished to do so, subject to the following conditions:
014: *
015: * The above copyright notice and this permission notice shall be included in
016: * all copies or substantial portions of the Software.
017: *
018: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
021: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
023: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
024: * DEALINGS IN THE SOFTWARE.
025: */
026:
027: package net.sourceforge.groboutils.codecoverage.v2;
028:
029: import java.io.File;
030: import java.io.IOException;
031:
032: import junit.framework.Assert;
033: import net.sourceforge.groboutils.autodoc.v1.AutoDoc;
034: import net.sourceforge.groboutils.codecoverage.v2.compiler.CompilerCreatorUtil;
035: import net.sourceforge.groboutils.codecoverage.v2.compiler.ModifiedClass;
036: import net.sourceforge.groboutils.codecoverage.v2.compiler.ModifiedMethod;
037: import net.sourceforge.groboutils.codecoverage.v2.compiler.ParseCoverageLogger;
038: import net.sourceforge.groboutils.codecoverage.v2.datastore.AnalysisModuleSet;
039: import net.sourceforge.groboutils.codecoverage.v2.datastore.ClassRecord;
040: import net.sourceforge.groboutils.codecoverage.v2.datastore.DatastoreCreatorUtil;
041: import net.sourceforge.groboutils.codecoverage.v2.datastore.DirMetaDataReader;
042: import net.sourceforge.groboutils.codecoverage.v2.datastore.DirMetaDataWriter;
043: import net.sourceforge.groboutils.codecoverage.v2.datastore.IClassMetaDataWriter;
044: import net.sourceforge.groboutils.codecoverage.v2.datastore.IMetaDataReader;
045: import net.sourceforge.groboutils.codecoverage.v2.datastore.IMetaDataWriter;
046: import net.sourceforge.groboutils.codecoverage.v2.logger.DirectoryChannelLogReader;
047: import net.sourceforge.groboutils.codecoverage.v2.logger.DirectoryChannelLogger;
048: import net.sourceforge.groboutils.codecoverage.v2.module.BranchCountMeasure;
049: import net.sourceforge.groboutils.codecoverage.v2.module.BytecodeCountMeasure;
050: import net.sourceforge.groboutils.codecoverage.v2.module.DefaultAnalysisMetaData;
051: import net.sourceforge.groboutils.codecoverage.v2.module.LineCountMeasure;
052: import net.sourceforge.groboutils.codecoverage.v2.report.AnalysisModuleData;
053:
054: import org.apache.bcel.classfile.JavaClass;
055: import org.apache.bcel.classfile.Method;
056: import org.apache.bcel.generic.MethodGen;
057:
058: /**
059: * Helper for creating code coverage test objects.
060: *
061: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
062: * @version $Date: 2004/04/15 05:48:27 $
063: * @since January 23, 2003
064: */
065: public class CCCreatorUtil {
066: private static final Class THIS_CLASS = CCCreatorUtil.class;
067: private static final AutoDoc DOC = new AutoDoc(THIS_CLASS);
068:
069: public static AnalysisModuleSet createAnalysisModuleSet(int count) {
070: return createAnalysisModuleSet(createAnalysisModules(count));
071: }
072:
073: public static AnalysisModuleSet createAnalysisModuleSet(
074: IAnalysisModule[] amL) {
075: Assert.assertNotNull(amL);
076: AnalysisModuleSet ams = new AnalysisModuleSet(amL);
077: return ams;
078: }
079:
080: public static IAnalysisModule[] createAnalysisModules(int count) {
081: IAnalysisModule amL[] = new IAnalysisModule[count];
082: for (int i = 0; i < count; ++i) {
083: amL[i] = createIAnalysisModule(0);
084: }
085: ;
086: return amL;
087: }
088:
089: private static int moduleIndex = 0;
090:
091: public static IAnalysisModule createIAnalysisModule(int type) {
092: IAnalysisModule am;
093: switch (type) {
094: case 0:
095: am = createIAnalysisModule("n" + (moduleIndex++), "u",
096: "text/plain");
097: break;
098: case 1:
099: am = createIAnalysisModule("a", "b", "text/html");
100: break;
101: case 2:
102: am = new LineCountMeasure();
103: break;
104: case 3:
105: am = new BytecodeCountMeasure();
106: break;
107: case 4:
108: am = new BranchCountMeasure();
109: break;
110: default:
111: am = null;
112: }
113: return am;
114: }
115:
116: public static IAnalysisModule createIAnalysisModule(String n,
117: String u, String m) {
118: IAnalysisModule am = DatastoreCreatorUtil.createAnalysisModule(
119: n, u, m);
120: return am;
121: }
122:
123: public static ClassRecord createClassRecord(Class c,
124: ModifiedMethod mm, AnalysisModuleSet ams) {
125: Assert.assertNotNull("Null method.", mm);
126: Assert.assertNotNull("Null class.", c);
127: ClassRecord cr = new ClassRecord(c.getName(), 0, "Source.java",
128: new String[] { mm.getMethodName() }, ams);
129: return cr;
130: }
131:
132: public static ModifiedClass createModifiedClass(Class c)
133: throws IOException {
134: Assert.assertNotNull(c);
135: String filename = BytecodeLoaderUtil.getClassFilename(c);
136: ModifiedClass mc = new ModifiedClass(filename,
137: BytecodeLoaderUtil.loadBytecode(filename));
138: return mc;
139: }
140:
141: public static ModifiedClass createModifiedClass(
142: ParseCoverageLogger pcl, Class c) throws IOException {
143: Assert.assertNotNull(c);
144: String filename = BytecodeLoaderUtil.getClassFilename(c);
145: ModifiedClass mc = createModifiedClass(pcl, filename,
146: BytecodeLoaderUtil.loadBytecode(filename));
147: return mc;
148: }
149:
150: public static ModifiedClass createModifiedClass(
151: ParseCoverageLogger pcl, String classFilename,
152: byte[] bytecode) throws IOException {
153: Assert.assertNotNull(bytecode);
154: ModifiedClass mc = new ModifiedClass(pcl, classFilename,
155: bytecode);
156: return mc;
157: }
158:
159: public static ModifiedMethod getMainModifiedMethod(ModifiedClass mc) {
160: ModifiedMethod mm[] = mc.getMethods();
161: for (int i = 0; i < mm.length; ++i) {
162: if ("main([Ljava/lang/String;)V".equals(mm[i]
163: .getMethodName())) {
164: return mm[i];
165: }
166: }
167: Assert.fail("Class " + mc.getClassName()
168: + " does not have a main method.");
169: // needs a return
170: throw new IllegalStateException("Unreachable statement.");
171: }
172:
173: public static ModifiedMethod createModifiedMethod(JavaClass jc,
174: int methodIndex, Method m, MethodGen mg) {
175: return CompilerCreatorUtil.createModifiedMethod(jc,
176: methodIndex, m, mg);
177: }
178:
179: public static ModifiedMethod createModifiedMethod(Class c,
180: int methodIndex) throws IOException {
181: JavaClass jc = BCELCreatorUtil.createJavaClass(c);
182: Method m = BCELCreatorUtil.getMethod(jc, methodIndex);
183: MethodGen mg = BCELCreatorUtil.createMethodGen(jc, methodIndex);
184: ModifiedMethod mm = createModifiedMethod(jc, methodIndex, m, mg);
185: return mm;
186: }
187:
188: public static IMethodCode createIMethodCode(Class c,
189: int methodIndex, AnalysisModuleSet ams, int measureIndex)
190: throws IOException {
191: ModifiedMethod mm = createModifiedMethod(c, methodIndex);
192: return createIMethodCode(c, mm, ams, measureIndex);
193: }
194:
195: public static IMethodCode createIMethodCode(Class c,
196: ModifiedMethod mm, AnalysisModuleSet ams, int measureIndex) {
197: IMethodCode mc = CompilerCreatorUtil
198: .createIMethodCode((short) measureIndex, mm,
199: createClassRecord(c, mm, ams));
200: return mc;
201: }
202:
203: public static IAnalysisMetaData createIAnalysisMetaData(String c,
204: String nc, byte w) {
205: DefaultAnalysisMetaData damd = new DefaultAnalysisMetaData(c,
206: nc, w);
207: return damd;
208: }
209:
210: public static AnalysisModuleData createAnalysisModuleData(
211: IAnalysisModule module, IMetaDataReader mdr,
212: IChannelLogReader clr) throws IOException {
213: AnalysisModuleData amd = new AnalysisModuleData(module, mdr,
214: clr);
215: return amd;
216: }
217:
218: public synchronized static File createNewDirectory() {
219: File f = null;
220: while (f == null || f.exists()) {
221: f = new File(".", Long.toString(System.currentTimeMillis()));
222: }
223: f.mkdirs();
224: Assert.assertTrue("Did not generate a directory.", f
225: .isDirectory());
226: return f;
227: }
228:
229: public static class SimpleClassLogData {
230: public String classSig;
231: public int methods[];
232: public int marks[];
233:
234: public SimpleClassLogData(String cs, int me[], int ma[]) {
235: this .classSig = cs;
236: this .methods = me;
237: this .marks = ma;
238: validate();
239: }
240:
241: public void validate() {
242: Assert.assertNotNull(this .classSig);
243: Assert.assertNotNull(this .methods);
244: Assert.assertNotNull(this .marks);
245: Assert.assertEquals(this .methods.length, this .marks.length);
246: }
247: }
248:
249: public static void populateLogger(IChannelLogger cl,
250: SimpleClassLogData inputData[]) {
251: Assert.assertNotNull(cl);
252: Assert.assertNotNull(inputData);
253: for (int i = 0; i < inputData.length; ++i) {
254: inputData[i].validate();
255: DOC.getLog().info(
256: "Logging class " + inputData[i].classSig + ".");
257: for (int j = 0; j < inputData[i].methods.length; ++j) {
258: DOC.getLog().debug(
259: "-- mark " + inputData[i].methods[j] + "-"
260: + inputData[i].marks[j] + ".");
261: cl.cover(inputData[i].classSig,
262: (short) inputData[i].methods[j],
263: (short) inputData[i].marks[j]);
264: }
265: }
266: }
267:
268: /**
269: * Creates a DirChannelLogReader suitable for testing. You need to
270: * pass in an array of channel datas (classes above) to create the
271: * base data.
272: */
273: public static DirectoryChannelLogReader createDirectoryChannelLogReader(
274: File basedir, SimpleClassLogData inputData[], int channel) {
275: short sc = (short) channel;
276: File channelDir = new File(basedir, Short.toString(sc));
277: DirectoryChannelLogger dcl = new DirectoryChannelLogger(
278: channelDir);
279: DOC.getLog().info(
280: "Putting log data into dir '" + channelDir + "'.");
281: populateLogger(dcl, inputData);
282: DirectoryChannelLogReader dclr = new DirectoryChannelLogReader(
283: basedir, sc);
284: return dclr;
285: }
286:
287: public static void populateMetaData(IMetaDataWriter mdw,
288: Class set[], IAnalysisModule modules[]) throws IOException {
289: Assert.assertNotNull(mdw);
290: Assert.assertNotNull(set);
291: Assert.assertNotNull(modules);
292: AnalysisModuleSet ams = createAnalysisModuleSet(modules);
293: for (int i = 0; i < modules.length; ++i) {
294: IClassMetaDataWriter cmdw = mdw.getClassWriter(modules[i]);
295: try {
296: for (int j = 0; j < set.length; ++j) {
297: ModifiedClass mc = createModifiedClass(set[j]);
298: cmdw.writeClassRecord(mc.createClassRecord(ams));
299: }
300: } finally {
301: cmdw.close();
302: }
303: }
304: }
305:
306: public static DirMetaDataReader createDirMetaDataReader(
307: File basedir, Class populateSet[],
308: IAnalysisModule modules[]) throws IOException {
309: IMetaDataWriter mdw = new DirMetaDataWriter(basedir);
310: try {
311: populateMetaData(mdw, populateSet, modules);
312: } finally {
313: mdw.close();
314: }
315:
316: DirMetaDataReader dmdr = new DirMetaDataReader(basedir);
317: return dmdr;
318: }
319: }
|