~ubuntu-branches/ubuntu/trusty/cobertura/trusty

« back to all changes in this revision

Viewing changes to test/net/sourceforge/cobertura/ant/FunctionalConditionCoverageTest.java

  • Committer: Bazaar Package Importer
  • Author(s): Yulia Novozhilova
  • Date: 2009-06-24 13:56:29 UTC
  • Revision ID: james.westby@ubuntu.com-20090624135629-hgvo8631yye7ofj3
Tags: upstream-1.9
ImportĀ upstreamĀ versionĀ 1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Cobertura - http://cobertura.sourceforge.net/
 
3
 *
 
4
 * Copyright (C) 2006 John Lewis
 
5
 * Copyright (C) 2006 Mark Doliner
 
6
 * 
 
7
 * Note: This file is dual licensed under the GPL and the Apache
 
8
 * Source License 1.1 (so that it can be used from both the main
 
9
 * Cobertura classes and the ant tasks).
 
10
 *
 
11
 * Cobertura is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published
 
13
 * by the Free Software Foundation; either version 2 of the License,
 
14
 * or (at your option) any later version.
 
15
 *
 
16
 * Cobertura is distributed in the hope that it will be useful, but
 
17
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
19
 * General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with Cobertura; if not, write to the Free Software
 
23
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
24
 * USA
 
25
 */
 
26
 
 
27
package net.sourceforge.cobertura.ant;
 
28
 
 
29
import java.io.File;
 
30
import java.io.FilenameFilter;
 
31
import java.io.IOException;
 
32
import java.util.ArrayList;
 
33
import java.util.Arrays;
 
34
import java.util.HashMap;
 
35
import java.util.Iterator;
 
36
import java.util.List;
 
37
import java.util.Map;
 
38
 
 
39
import junit.framework.TestCase;
 
40
import net.sourceforge.cobertura.reporting.JUnitXMLHelper;
 
41
 
 
42
import org.apache.tools.ant.Project;
 
43
import org.apache.tools.ant.taskdefs.Java;
 
44
import org.apache.tools.ant.types.Path;
 
45
import org.apache.tools.ant.types.Path.PathElement;
 
46
import org.jdom.Attribute;
 
47
import org.jdom.DataConversionException;
 
48
import org.jdom.Document;
 
49
import org.jdom.Element;
 
50
import org.jdom.JDOMException;
 
51
import org.jdom.xpath.XPath;
 
52
 
 
53
import test.condition.ConditionCalls;
 
54
 
 
55
/**
 
56
 * These tests generally exec ant to run a test.xml file.  A different target is used for
 
57
 * each test.  The text.xml file sets up a test, instruments, runs junit, and generates a
 
58
 * coverage xml report.  Then the xml report is parsed and checked.
 
59
 * 
 
60
 * @author jwlewi
 
61
 */
 
62
public class FunctionalConditionCoverageTest extends TestCase
 
63
{
 
64
 
 
65
        private final static File BASEDIR = new File((System.getProperty("basedir") != null) ? System
 
66
                        .getProperty("basedir") : ".", "examples/functionalconditiontest");
 
67
 
 
68
        private final static String CONDITION_MISSING_TRUE = "50%";
 
69
        private final static String CONDITION_MISSING_FALSE = "50%";
 
70
        
 
71
        private final static Map testInfoMap = new HashMap();
 
72
        
 
73
        static
 
74
        {
 
75
                ConditionTestInfo[] expectedConditions;
 
76
                TestInfo info;
 
77
                
 
78
                /*
 
79
                 * Load expected information into testInfoMap for each method.
 
80
                 */
 
81
                expectedConditions = new ConditionTestInfo[1];
 
82
                expectedConditions[0] = new ConditionTestInfo("0", "jump", CONDITION_MISSING_FALSE);
 
83
 
 
84
                info = new TestInfo(ConditionCalls.CALL_CONDITION_LINE_NUMBER, "50% (1/2)", expectedConditions);
 
85
                info.setIgnoreLineNumber(ConditionCalls.CALL_IGNORE_LINE_NUMBER);
 
86
 
 
87
                testInfoMap.put("call", info);
 
88
                
 
89
                expectedConditions = new ConditionTestInfo[1];
 
90
                expectedConditions[0] = new ConditionTestInfo("0", "switch", "33%");
 
91
                
 
92
                info = new TestInfo(ConditionCalls.LOOKUP_SWITCH_LINE_NUMBER, "33% (1/3)", expectedConditions);
 
93
 
 
94
                testInfoMap.put("callLookupSwitch", info);
 
95
                
 
96
                expectedConditions = new ConditionTestInfo[1];
 
97
                expectedConditions[0] = new ConditionTestInfo("0", "switch", "10%");
 
98
 
 
99
                info = new TestInfo(ConditionCalls.TABLE_SWITCH_LINE_NUMBER, "10% (1/10)", expectedConditions);
 
100
 
 
101
                testInfoMap.put("callTableSwitch", info);
 
102
                
 
103
                expectedConditions = new ConditionTestInfo[3];
 
104
                expectedConditions[0] = new ConditionTestInfo("0", "jump", CONDITION_MISSING_TRUE);
 
105
                expectedConditions[1] = new ConditionTestInfo("1", "jump", "0%");
 
106
                expectedConditions[2] = new ConditionTestInfo("2", "jump", CONDITION_MISSING_FALSE);
 
107
 
 
108
                info = new TestInfo(ConditionCalls.MULTI_CONDITION_LINE_NUMBER, "33% (2/6)", expectedConditions);
 
109
 
 
110
                testInfoMap.put("callMultiCondition", info);
 
111
                
 
112
                expectedConditions = new ConditionTestInfo[3];
 
113
                expectedConditions[0] = new ConditionTestInfo("0", "jump", CONDITION_MISSING_FALSE);
 
114
                expectedConditions[1] = new ConditionTestInfo("1", "jump", CONDITION_MISSING_FALSE);
 
115
                expectedConditions[2] = new ConditionTestInfo("2", "jump", "0%");
 
116
 
 
117
                info = new TestInfo(ConditionCalls.MULTI_CONDITION2_LINE_NUMBER, "33% (2/6)", expectedConditions);
 
118
 
 
119
                testInfoMap.put("callMultiCondition2", info);
 
120
        };
 
121
        
 
122
        private static class TestInfo
 
123
        {
 
124
                int conditionNumber;
 
125
                String expectedLineConditionCoverage;
 
126
                ConditionTestInfo[] expectedConditions;
 
127
                Integer ignoreLineNumber;
 
128
 
 
129
                TestInfo(int conditionNumber, String expectedLineConditionCoverage, ConditionTestInfo[] expectedConditions)
 
130
                {
 
131
                        this.conditionNumber = conditionNumber;
 
132
                        this.expectedLineConditionCoverage = expectedLineConditionCoverage;
 
133
                        this.expectedConditions = expectedConditions;
 
134
                }
 
135
 
 
136
                public void setIgnoreLineNumber(int number) {
 
137
                        ignoreLineNumber = new Integer(number);
 
138
                }
 
139
        }
 
140
        private static class ConditionTestInfo
 
141
        {
 
142
                String number;
 
143
                String type;
 
144
                String coverage;
 
145
                
 
146
                ConditionTestInfo(String number, String type, String coverage)
 
147
                {
 
148
                        this.number = number;
 
149
                        this.type = type;
 
150
                        this.coverage = coverage;
 
151
                }
 
152
        }
 
153
 
 
154
        public static void testConditionCoverage() throws Exception
 
155
        {
 
156
                runTestAntScript("condition-coverage", "test-condition-coverage");
 
157
                verify("condition-coverage");
 
158
        }
 
159
 
 
160
        private static void verify(String testName) throws Exception
 
161
        {
 
162
                verifyXml(testName);
 
163
                verifyHtml(testName);
 
164
        }
 
165
 
 
166
        private static void verifyXml(String testName) throws Exception
 
167
        {
 
168
                // Get a list of all classes listed in the XML report
 
169
                List classesList = getClassElements();
 
170
                assertTrue("Test " + testName + ": Did not find any classes listed in the XML report.",
 
171
                                classesList.size() > 0);
 
172
 
 
173
                boolean conditionCallsClassFound = false;
 
174
                for (Iterator iter = classesList.iterator(); iter.hasNext();)
 
175
                {
 
176
                        Element classElement = (Element)iter.next();
 
177
                        String className = classElement.getAttributeValue("name");
 
178
                        if (className.equals("test.condition.ConditionCalls"))
 
179
                        {
 
180
                                conditionCallsClassFound = true;
 
181
                        }
 
182
                        else
 
183
                                fail("Test "
 
184
                                                + testName
 
185
                                                + ": Found a class with the name '"
 
186
                                                + className
 
187
                                                + "' in the XML report, but was only expecting 'test.condition.ConditionCalls'.");
 
188
                        verifyClass(testName, classElement);
 
189
                }
 
190
                assertTrue("Test " + testName + ": Did not find class 'test.condition.ConditionCalls' in the XML report.",
 
191
                                conditionCallsClassFound);
 
192
        }
 
193
 
 
194
        /**
 
195
         * Use XPath to get all <class> elements in the
 
196
         * cobertura.xml file under the given directory.
 
197
         * @return A list of JDOM Elements.
 
198
         */
 
199
        private static List getClassElements() throws IOException, JDOMException
 
200
        {
 
201
                File xmlFile = new File(BASEDIR, "reports/cobertura-xml/coverage.xml");
 
202
                Document document = JUnitXMLHelper.readXmlFile(xmlFile, true);
 
203
                XPath xpath = XPath.newInstance("/coverage/packages/package/classes/class");
 
204
                List classesList = xpath.selectNodes(document);
 
205
                return classesList;
 
206
        }
 
207
 
 
208
        /**
 
209
         * Verify that the class's condition information is correct.
 
210
         */
 
211
        private static void verifyClass(String testName, Element classElement)
 
212
        {
 
213
                // Get a list of methods
 
214
                Element methodsElement = classElement.getChild("methods");
 
215
                List methodList = methodsElement.getChildren("method");
 
216
                assertTrue("Test " + testName + ": Did not find any methods listed in the class "
 
217
                                + classElement.getAttributeValue("name"), methodList.size() > 0);
 
218
                List methodsFound = new ArrayList();
 
219
                for (Iterator iter = methodList.iterator(); iter.hasNext();)
 
220
                {
 
221
                        Element methodElement = (Element)iter.next();
 
222
                        String methodName = methodElement.getAttributeValue("name");
 
223
                        TestInfo info = (TestInfo) testInfoMap.get(methodName);
 
224
                        if (info != null)
 
225
                        {
 
226
                                if (methodsFound.contains(methodName))
 
227
                                {
 
228
                                        fail("Test " + testName
 
229
                                                        + ": Found more than one instance of the method " + methodName + " in the class "
 
230
                                                        + classElement.getAttributeValue("name"));
 
231
                                }
 
232
                                methodsFound.add(methodName);
 
233
                                
 
234
                                verifyMethod(info, testName, classElement, methodElement);
 
235
                        }
 
236
                        else if (methodName.equals("<clinit>") || 
 
237
                                        methodName.equals("<init>") || 
 
238
                                        methodName.startsWith("util") ||
 
239
                                        methodName.equals("class$"))
 
240
                        {
 
241
                                // These methods are ok--ignore them.
 
242
                        }
 
243
                        else
 
244
                        {
 
245
                                fail("Test " + testName + ": Found method " + methodName + " in the class "
 
246
                                                + classElement.getAttributeValue("name")
 
247
                                                + ", but was only expecting either 'call' or 'dontCall'.");
 
248
                        }
 
249
                }
 
250
                /*
 
251
                 * now make sure all methods in testInfoMap were found and verified
 
252
                 */
 
253
                for (Iterator iter = testInfoMap.keySet().iterator(); iter.hasNext();) {
 
254
                        String methodName = (String) iter.next();
 
255
                        assertTrue("Test " + testName + ": Did not find method " + methodName + " in the class "
 
256
                                        + classElement.getAttributeValue("name"), methodsFound.contains(methodName));
 
257
                }
 
258
        }
 
259
 
 
260
        private static void verifyMethod(TestInfo info, String testName, Element classElement, Element methodElement) {
 
261
                Element linesElement = methodElement.getChild("lines");
 
262
                List lineList = linesElement.getChildren("line");
 
263
                String methodName = methodElement.getAttributeValue("name");
 
264
                assertTrue("Test " + testName + ", class " + classElement.getAttributeValue("name")
 
265
                                + ": Did not find any lines in the method "
 
266
                                + methodName, lineList.size() > 0);
 
267
 
 
268
                boolean foundCondition = false;
 
269
                for (Iterator iter = lineList.iterator(); iter.hasNext();)
 
270
                {
 
271
                        Element lineElement = (Element)iter.next();
 
272
                        int number;
 
273
                        try {
 
274
                                number = lineElement.getAttribute("number").getIntValue();
 
275
                                if ((info.ignoreLineNumber != null) && (info.ignoreLineNumber.intValue() == number))
 
276
                                {
 
277
                                        fail("Expected line " + info.ignoreLineNumber + " to be ignored.");
 
278
                                }
 
279
                        } catch (DataConversionException e) {
 
280
                                throw new RuntimeException(e.toString());
 
281
                        }
 
282
                        if (number == info.conditionNumber) {
 
283
                                foundCondition = true;
 
284
                                verifyLineConditionInfo(lineElement, info.conditionNumber, 
 
285
                                                info.expectedLineConditionCoverage, info.expectedConditions);
 
286
                        }
 
287
                }
 
288
                assertTrue("Expected condition element for line " + info.conditionNumber + " of " + methodName, foundCondition);
 
289
        }
 
290
 
 
291
        private static void verifyLineConditionInfo(Element lineElement, int conditionLineNumber, 
 
292
                        String expectedLineConditionCoverage, ConditionTestInfo[] expectedConditions)
 
293
        {
 
294
                String errorMessage = "Line " + conditionLineNumber;
 
295
                boolean branch = false;
 
296
                try {
 
297
                        branch = lineElement.getAttribute("branch").getBooleanValue();
 
298
                } catch (DataConversionException e) {
 
299
                        fail(errorMessage + " has missing or wrong branch attribute");
 
300
                }
 
301
                assertTrue(errorMessage + "Branch attribute should be true", branch);
 
302
                
 
303
                String lineCoverageStr = getRequiredAttribute(lineElement, "condition-coverage", errorMessage).getValue();
 
304
                assertEquals(errorMessage + " has incorrect condition-coverage", expectedLineConditionCoverage, lineCoverageStr);
 
305
                
 
306
                List conditionList = lineElement.getChildren("conditions");
 
307
                assertTrue(errorMessage + " should have one and only one conditions element.", conditionList.size() == 1);
 
308
                conditionList = ((Element) conditionList.get(0)).getChildren("condition");
 
309
                
 
310
                assertEquals(errorMessage + " has incorrect number of condition elements.", expectedConditions.length, conditionList.size());
 
311
                
 
312
                errorMessage = "Condition for " + conditionLineNumber;
 
313
 
 
314
                int i = 0;
 
315
                for (Iterator iter = conditionList.iterator(); iter.hasNext(); i++) {
 
316
                        Element element = (Element) iter.next();
 
317
                        verifyCondition(element, errorMessage, expectedConditions[i]);
 
318
                }
 
319
        }
 
320
        
 
321
        private static void verifyCondition(Element conditionElement, String errorMessage, ConditionTestInfo info)
 
322
        {
 
323
                String numberStr = getRequiredAttribute(conditionElement, "number", errorMessage).getValue();
 
324
                assertEquals(errorMessage + " has incorrect number", info.number, numberStr);
 
325
                String typeStr = getRequiredAttribute(conditionElement, "type", errorMessage).getValue();
 
326
                assertEquals(errorMessage + " has incorrect type", info.type, typeStr);
 
327
                String coverageStr = getRequiredAttribute(conditionElement, "coverage", errorMessage).getValue();
 
328
                assertEquals(errorMessage + " has incorrect coverage", info.coverage, coverageStr);
 
329
        }
 
330
        
 
331
        private static Attribute getRequiredAttribute(Element element, String attribute, String errorMessage) {
 
332
                Attribute attr = element.getAttribute(attribute);
 
333
                assertNotNull(errorMessage + " has missing " + attribute + " attribute.", attr);
 
334
                return attr;
 
335
        }
 
336
 
 
337
        private static void verifyHtml(String testName) throws Exception
 
338
        {
 
339
                File htmlReportDir = new File(BASEDIR, "reports/cobertura-html");
 
340
 
 
341
                // Get all files from report directory
 
342
                String htmlFiles[] = htmlReportDir.list(new FilenameFilter()
 
343
                {
 
344
 
 
345
                        public boolean accept(File dir, String name)
 
346
                        {
 
347
                                return name.endsWith(".html");
 
348
                        }
 
349
                });
 
350
                Arrays.sort(htmlFiles);
 
351
 
 
352
                assertTrue(htmlFiles.length >= 5);
 
353
 
 
354
                // Assert that all required files are there
 
355
                String[] requiredFiles = { "index.html", "help.html", "frame-packages.html",
 
356
                                "frame-summary.html", "frame-sourcefiles.html" };
 
357
 
 
358
                for (int i = 0; i < requiredFiles.length; i++)
 
359
                {
 
360
                        if (!containsFile(htmlFiles, requiredFiles[i]))
 
361
                        {
 
362
                                fail("Test " + testName + ": File " + requiredFiles[i]
 
363
                                                + " not found among report files");
 
364
                        }
 
365
                }
 
366
 
 
367
                // Validate selected files
 
368
                String previousPrefix = "NONE";
 
369
                for (int i = 0; i < htmlFiles.length; i++)
 
370
                {
 
371
                        // Validate file if has prefix different than previous one, or is required file
 
372
                        if (containsFile(requiredFiles, htmlFiles[i])
 
373
                                        || !htmlFiles[i].startsWith(previousPrefix))
 
374
                        {
 
375
                                JUnitXMLHelper.readXmlFile(new File(htmlReportDir, htmlFiles[i]), true);
 
376
                        }
 
377
                        if (htmlFiles[i].length() > 7)
 
378
                        {
 
379
                                previousPrefix = htmlFiles[i].substring(0, 7);
 
380
                        }
 
381
                        else
 
382
                        {
 
383
                                previousPrefix = htmlFiles[i];
 
384
                        }
 
385
                }
 
386
        }
 
387
 
 
388
        private static boolean containsFile(String[] files, String fileName)
 
389
        {
 
390
                for (int i = 0; i < files.length; i++)
 
391
                {
 
392
                        if (files[i].equals(fileName))
 
393
                                return true;
 
394
                }
 
395
                return false;
 
396
        }
 
397
 
 
398
        /**
 
399
         * Use the ant 'java' task to run the test.xml
 
400
         * file and the specified target.
 
401
         */
 
402
        private static void runTestAntScript(String testName, String target) throws IOException
 
403
        {
 
404
                Java task = new Java();
 
405
                task.setTaskName("java");
 
406
                task.setProject(new Project());
 
407
                task.init();
 
408
 
 
409
                // Call ant launcher.  Requires ant-lancher.jar.
 
410
                task.setClassname("org.apache.tools.ant.launch.Launcher");
 
411
                task.setFork(true);
 
412
 
 
413
                AntUtil.transferCoberturaDataFileProperty(task);
 
414
 
 
415
                task.createArg().setValue("-f");
 
416
                task.createArg().setValue(BASEDIR + "/build.xml");
 
417
                task.createArg().setValue(target);
 
418
 
 
419
                task.setFailonerror(true);
 
420
 
 
421
                // Set output to go to a temp file
 
422
                File outputFile = Util.createTemporaryTextFile("cobertura-test");
 
423
                task.setOutput(outputFile);
 
424
 
 
425
                // Set the classpath to the same classpath as this JVM
 
426
                Path classpath = task.createClasspath();
 
427
                PathElement pathElement = classpath.createPathElement();
 
428
                pathElement.setPath(System.getProperty("java.class.path"));
 
429
 
 
430
                try
 
431
                {
 
432
                        task.execute();
 
433
                }
 
434
                finally
 
435
                {
 
436
                        if (outputFile.exists())
 
437
                        {
 
438
                                // Put the contents of the output file in the exception
 
439
                                System.out.println("\n\n\nOutput from Ant for " + testName
 
440
                                                + " test:\n----------------------------------------\n"
 
441
                                                + Util.getText(outputFile) + "----------------------------------------");
 
442
                                outputFile.delete();
 
443
                        }
 
444
                }
 
445
        }
 
446
 
 
447
}