export html action: do not traverse tree for excluded elements
[idea/community.git] / platform / testFramework / src / com / intellij / testFramework / InspectionTestUtil.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.testFramework;
17
18 import com.intellij.analysis.AnalysisScope;
19 import com.intellij.codeInsight.daemon.HighlightDisplayKey;
20 import com.intellij.codeInspection.ex.GlobalInspectionContextImpl;
21 import com.intellij.codeInspection.ex.InspectionToolWrapper;
22 import com.intellij.codeInspection.ui.InspectionToolPresentation;
23 import com.intellij.openapi.util.Comparing;
24 import com.intellij.openapi.util.JDOMUtil;
25 import com.intellij.testFramework.fixtures.impl.GlobalInspectionContextForTests;
26 import com.intellij.util.ui.UIUtil;
27 import org.jdom.Document;
28 import org.jdom.Element;
29 import org.jetbrains.annotations.NotNull;
30 import org.junit.Assert;
31
32 import java.io.CharArrayReader;
33 import java.io.File;
34 import java.io.StreamTokenizer;
35 import java.util.ArrayList;
36 import java.util.List;
37
38 public class InspectionTestUtil {
39   private InspectionTestUtil() {
40   }
41
42   protected static void compareWithExpected(Document expectedDoc, Document doc, boolean checkRange) throws Exception {
43     List<Element> expectedProblems = new ArrayList<Element>(expectedDoc.getRootElement().getChildren("problem"));
44     List<Element> reportedProblems = new ArrayList<Element>(doc.getRootElement().getChildren("problem"));
45
46     Element[] expectedArray = expectedProblems.toArray(new Element[expectedProblems.size()]);
47     boolean failed = false;
48
49 expected:
50     for (Element expectedProblem : expectedArray) {
51       Element[] reportedArrayed = reportedProblems.toArray(new Element[reportedProblems.size()]);
52       for (Element reportedProblem : reportedArrayed) {
53         if (compareProblemWithExpected(reportedProblem, expectedProblem, checkRange)) {
54           expectedProblems.remove(expectedProblem);
55           reportedProblems.remove(reportedProblem);
56           continue expected;
57         }
58       }
59
60       Document missing = new Document(expectedProblem.clone());
61       System.out.println("The following haven't been reported as expected: " + new String(JDOMUtil.printDocument(missing, "\n")));
62       failed = true;
63     }
64
65     for (Element reportedProblem : reportedProblems) {
66       Document extra = new Document(reportedProblem.clone());
67       System.out.println("The following has been unexpectedly reported: " + new String(JDOMUtil.printDocument(extra, "\n")));
68       failed = true;
69     }
70
71     Assert.assertFalse(failed);
72   }
73
74   static boolean compareProblemWithExpected(Element reportedProblem, Element expectedProblem, boolean checkRange) throws Exception {
75     if (!compareFiles(reportedProblem, expectedProblem)) return false;
76     if (!compareLines(reportedProblem, expectedProblem)) return false;
77     if (!compareDescriptions(reportedProblem, expectedProblem)) return false;
78     if (checkRange && !compareTextRange(reportedProblem, expectedProblem)) return false;
79     return true;
80   }
81
82   static boolean compareTextRange(final Element reportedProblem, final Element expectedProblem) {
83     Element reportedTextRange = reportedProblem.getChild("entry_point");
84     if (reportedTextRange == null) return false;
85     Element expectedTextRange = expectedProblem.getChild("entry_point");
86     return Comparing.equal(reportedTextRange.getAttributeValue("TYPE"), expectedTextRange.getAttributeValue("TYPE")) &&
87            Comparing.equal(reportedTextRange.getAttributeValue("FQNAME"), expectedTextRange.getAttributeValue("FQNAME"));
88   }
89
90   static boolean compareDescriptions(Element reportedProblem, Element expectedProblem) throws Exception {
91     String expectedDescription = expectedProblem.getChildText("description");
92     String reportedDescription = reportedProblem.getChildText("description");
93     if (expectedDescription.equals(reportedDescription)) return true;
94
95     StreamTokenizer tokenizer = new StreamTokenizer(new CharArrayReader(expectedDescription.toCharArray()));
96     tokenizer.quoteChar('\'');
97
98     int idx = 0;
99     while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
100       String word;
101       if (tokenizer.sval != null) {
102         word = tokenizer.sval;
103       } else if (tokenizer.ttype == StreamTokenizer.TT_NUMBER) {
104         word = Double.toString(tokenizer.nval);
105       }
106       else {
107         continue;
108       }
109
110       idx = reportedDescription.indexOf(word, idx);
111       if (idx == -1) return false;
112       idx += word.length();
113     }
114
115     return true;
116   }
117
118   static boolean compareLines(Element reportedProblem, Element expectedProblem) {
119     return Comparing.equal(reportedProblem.getChildText("line"), expectedProblem.getChildText("line"));
120   }
121
122   static boolean compareFiles(Element reportedProblem, Element expectedProblem) {
123     String reportedFileName = reportedProblem.getChildText("file");
124     if (reportedFileName == null) {
125       return true;
126     }
127     File reportedFile = new File(reportedFileName);
128
129     return Comparing.equal(reportedFile.getName(), expectedProblem.getChildText("file"));
130   }
131
132   public static void compareToolResults(@NotNull GlobalInspectionContextImpl context,
133                                         @NotNull InspectionToolWrapper toolWrapper,
134                                         boolean checkRange,
135                                         String testDir) {
136     final Element root = new Element("problems");
137     final Document doc = new Document(root);
138     InspectionToolPresentation presentation = context.getPresentation(toolWrapper);
139
140     presentation.updateContent();  //e.g. dead code need check for reachables
141     presentation.exportResults(root, x -> false, x -> false);
142
143     File file = new File(testDir + "/expected.xml");
144     try {
145       compareWithExpected(JDOMUtil.loadDocument(file), doc, checkRange);
146     }
147     catch (Exception e) {
148       throw new RuntimeException(e);
149     }
150   }
151
152   public static void runTool(@NotNull InspectionToolWrapper toolWrapper,
153                              @NotNull final AnalysisScope scope,
154                              @NotNull final GlobalInspectionContextForTests globalContext) {
155     final String shortName = toolWrapper.getShortName();
156     final HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
157     if (key == null){
158       HighlightDisplayKey.register(shortName);
159     }
160
161     globalContext.doInspections(scope);
162     do {
163       UIUtil.dispatchAllInvocationEvents();
164     }
165     while (!globalContext.isFinished());
166   }
167 }