1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package test.net.sourceforge.pmd.testframework;
5   
6   import java.util.ArrayList;
7   import java.util.List;
8   
9   import net.sourceforge.pmd.Rule;
10  
11  import org.junit.Test;
12  import org.junit.internal.runners.InitializationError;
13  import org.junit.internal.runners.JUnit4ClassRunner;
14  import org.junit.runner.Description;
15  import org.junit.runner.RunWith;
16  import org.junit.runner.notification.Failure;
17  import org.junit.runner.notification.RunNotifier;
18  
19  /**
20   * Standard methods for (simple) testcases.
21   */
22  @RunWith(SimpleAggregatorTst.CustomXmlTestClassMethodsRunner.class)
23  /**
24   * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
25   */
26  public abstract class SimpleAggregatorTst extends RuleTst {
27      /**
28       * Run a set of tests defined in an XML test-data file for a rule. The file
29       * should be ./xml/RuleName.xml relative to the test-class. The format is
30       * defined in test-data.xsd.
31       */
32      public void runTests(Rule rule) {
33          runTests(extractTestsFromXml(rule));
34      }
35  
36      /**
37       * Run a set of tests defined in a XML test-data file. The file should be
38       * ./xml/[testsFileName].xml relative to the test-class. The format is
39       * defined in test-data.xsd.
40       */
41      public void runTests(Rule rule, String testsFileName) {
42          runTests(extractTestsFromXml(rule, testsFileName));
43      }
44  
45      /**
46       * Run a set of tests of a certain sourceType.
47       */
48      public void runTests(TestDescriptor[] tests) {
49          for (int i = 0; i < tests.length; i++) {
50              runTest(tests[i]);
51          }
52      }
53  
54      private List<Rule> rules = new ArrayList<Rule>();
55  
56      /**
57       * Add new XML tests associated with the rule to the test suite. This should
58       * be called from the setup method.
59       */
60      protected void addRule(String ruleSet, String ruleName) {
61          rules.add(findRule(ruleSet, ruleName));
62      }
63  
64      /**
65       * Run a set of tests for all rules added in the setup method.
66       */
67      @Test
68      public void testAll() {
69          boolean regressionTest = TestDescriptor.inRegressionTestMode();
70          ArrayList<Failure> l = new ArrayList<Failure>();
71          for (Rule r : rules) {
72              TestDescriptor[] tests = extractTestsFromXml(r);
73              for (TestDescriptor test: tests) {
74                  try {
75                      if (!regressionTest || test.isRegressionTest()) {
76                          runTest(test);
77                      }
78                  } catch (Throwable t) {
79                      Failure f = CustomXmlTestClassMethodsRunner.createFailure(r, t);
80                      l.add(f);
81                  }
82              }
83          }
84          for(Failure f: l) {
85              CustomXmlTestClassMethodsRunner.addFailure(f);
86          }
87      }
88  
89      public static class CustomXmlTestClassMethodsRunner extends JUnit4ClassRunner {
90          public CustomXmlTestClassMethodsRunner(Class<?> klass) throws InitializationError {
91              super(klass);
92          }
93  
94          public static Failure createFailure(Rule rule, Throwable targetException) {
95              return new Failure(Description.createTestDescription(
96                      SimpleAggregatorTst.class, "xml." + rule.getRuleSetName() + '.' + rule.getName()),
97                      targetException);
98          }
99  
100         public static void addFailure(Failure failure) {
101             synchronized(CustomXmlTestClassMethodsRunner.class) {
102                 NOTIFIER.fireTestFailure(failure);
103             }
104         }
105 
106         @Override
107         public void run(RunNotifier n) {
108             synchronized(CustomXmlTestClassMethodsRunner.class) {
109                 // synchronized so that access to NOTIFIER is safe: only
110                 // one runner at a time is active
111                 NOTIFIER = n;
112                 super.run(n);
113             }
114         }
115 
116         private static RunNotifier NOTIFIER;
117     }
118 
119 }