Skip to content

Commit a91894d

Browse files
authored
Merge pull request #87 from TestMyQt/qmake
Add qmake support
2 parents abc1818 + 4634d54 commit a91894d

File tree

159 files changed

+3809
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

159 files changed

+3809
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,6 @@ __pycache__/
5050
/tmc-langs-java/src/main/resources/tmc-junit-runner.jar
5151
/tmc-langs-java/src/test/resources/exit_zero/build/
5252

53+
# Qt Creator user files
54+
*.pro.user*
55+

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,15 @@ before_install:
2121
- curl -L https://static.rust-lang.org/rustup.sh | sh -s -- --channel=stable --yes --prefix=$PWD --disable-sudo
2222
- sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9
2323
- echo "deb https://cloud.r-project.org/bin/linux/ubuntu trusty/" | sudo tee -a /etc/apt/sources.list
24+
- sudo add-apt-repository --yes ppa:beineri/opt-qt591-trusty
2425
- sudo apt-get update -qq
2526
- sudo apt-get install r-base -y
27+
- sudo apt-get install qt59base
2628
- sudo chmod 277 /usr/local/lib/R/site-library
2729
- Rscript -e 'install.packages(c("devtools","testthat"),repos="http://cran.us.r-project.org")'
2830
- Rscript -e 'devtools::install_github("RTMC/tmc-r-tester/tmcRtestrunner")'
2931
- export PATH=$PATH:$PWD/bin
32+
- source /opt/qt59/bin/qt59-env.sh
3033
- export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/lib
3134
- mkdir -p $HOME/bin && ln -s $(which python3.4) $HOME/bin/python3 && export PATH="$HOME/bin:$PATH"
3235
- mvn install -Dmaven.test.skip=true

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@
233233
<module>tmc-langs-python3</module>
234234
<module>tmc-langs-notests</module>
235235
<!--module>tmc-langs-rust</module-->
236+
<module>tmc-langs-qmake</module>
236237
<!-- TODO: add plugins and support libraries here -->
237238

238239
<module>tmc-langs-util</module>

tmc-langs-qmake/pom.xml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>fi.helsinki.cs.tmc</groupId>
6+
<artifactId>tmc-langs</artifactId>
7+
<version>0.7.7-SNAPSHOT</version>
8+
</parent>
9+
10+
<properties>
11+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12+
<tmc.basedir>../target</tmc.basedir>
13+
</properties>
14+
15+
<artifactId>tmc-langs-qmake</artifactId>
16+
<packaging>jar</packaging>
17+
18+
<!-- Deploy to maven.testmycode.net/nexus -->
19+
<distributionManagement>
20+
<repository>
21+
<id>tmc</id>
22+
<name>TMC releases</name>
23+
<url>http://maven.testmycode.net/nexus/content/repositories/releases</url>
24+
</repository>
25+
<snapshotRepository>
26+
<id>tmc-snapshots</id>
27+
<name>TMC snapshots</name>
28+
<url>http://maven.testmycode.net/nexus/content/repositories/snapshots</url>
29+
</snapshotRepository>
30+
</distributionManagement>
31+
32+
<dependencies>
33+
<dependency>
34+
<groupId>fi.helsinki.cs.tmc</groupId>
35+
<artifactId>tmc-langs-framework</artifactId>
36+
<version>${project.version}</version>
37+
<type>jar</type>
38+
</dependency>
39+
</dependencies>
40+
<build>
41+
<plugins>
42+
<plugin>
43+
<groupId>org.apache.maven.plugins</groupId>
44+
<artifactId>maven-surefire-plugin</artifactId>
45+
<version>2.18.1</version>
46+
<configuration>
47+
<excludes>
48+
<exclude>**/make-project/**/*</exclude>
49+
<exclude>**/eRror/**/*</exclude>
50+
</excludes>
51+
</configuration>
52+
</plugin>
53+
<plugin>
54+
<groupId>org.apache.maven.plugins</groupId>
55+
<artifactId>maven-jar-plugin</artifactId>
56+
<version>2.6</version>
57+
<configuration>
58+
<outputDirectory>${tmc.basedir}</outputDirectory>
59+
<archive>
60+
<manifest>
61+
<addClasspath>true</addClasspath>
62+
<classpathPrefix>lib/</classpathPrefix>
63+
</manifest>
64+
</archive>
65+
</configuration>
66+
</plugin>
67+
</plugins>
68+
</build>
69+
</project>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package fi.helsinki.cs.tmc.langs.qmake;
2+
3+
import fi.helsinki.cs.tmc.langs.domain.TestResult;
4+
5+
import com.google.common.collect.ImmutableList;
6+
7+
import java.util.List;
8+
9+
public final class QTestCase {
10+
11+
private String name;
12+
private boolean passed;
13+
private String message;
14+
private List<String> points;
15+
16+
/**
17+
* Create a test case for QT tests.
18+
*
19+
* @param name Name of the test
20+
* @param passed Passed status
21+
* @param message for failed assertion
22+
* @param points for test case
23+
*/
24+
public QTestCase(String name, boolean passed, String message, List<String> points) {
25+
this.name = name;
26+
this.passed = passed;
27+
this.message = message;
28+
this.points = points;
29+
}
30+
31+
/**
32+
* Get the test result of this test case.
33+
*/
34+
public TestResult getTestResult() {
35+
String msg = message;
36+
37+
ImmutableList<String> trace = ImmutableList.of();
38+
ImmutableList<String> points = ImmutableList.of();
39+
if (this.points != null) {
40+
points = ImmutableList.copyOf(this.points);
41+
}
42+
43+
return new TestResult(name, passed, points, msg, trace);
44+
}
45+
46+
public String getName() {
47+
return name;
48+
}
49+
50+
public boolean getResult() {
51+
return passed;
52+
}
53+
54+
public String getMessage() {
55+
return message;
56+
}
57+
58+
public List<String> getPoints() {
59+
return points;
60+
}
61+
62+
}
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
package fi.helsinki.cs.tmc.langs.qmake;
2+
3+
import fi.helsinki.cs.tmc.langs.domain.RunResult;
4+
import fi.helsinki.cs.tmc.langs.domain.RunResult.Status;
5+
import fi.helsinki.cs.tmc.langs.domain.TestResult;
6+
7+
import com.google.common.collect.ImmutableList;
8+
import com.google.common.collect.ImmutableMap;
9+
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
13+
import org.w3c.dom.Document;
14+
import org.w3c.dom.Element;
15+
import org.w3c.dom.NodeList;
16+
17+
import org.xml.sax.InputSource;
18+
import org.xml.sax.SAXException;
19+
20+
import java.io.FileInputStream;
21+
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.io.InputStreamReader;
24+
import java.io.Reader;
25+
import java.nio.file.Path;
26+
import java.util.ArrayList;
27+
import java.util.List;
28+
29+
import javax.xml.parsers.DocumentBuilder;
30+
import javax.xml.parsers.DocumentBuilderFactory;
31+
import javax.xml.parsers.ParserConfigurationException;
32+
33+
public final class QTestResultParser {
34+
35+
private static final String DOC_NULL_ERROR_MESSAGE = "Failed to parse test results";
36+
private static final String SAX_PARSER_ERROR = "SAX parser error occured";
37+
private static final String PARSING_DONE_MESSAGE = "Qt test cases parsed.";
38+
39+
private static final Logger log = LoggerFactory.getLogger(QTestResultParser.class);
40+
41+
private List<TestResult> tests;
42+
43+
public QTestResultParser() {
44+
}
45+
46+
public void loadTests(Path testResult) {
47+
this.tests = parseTestCases(testResult);
48+
}
49+
50+
private List<TestResult> parseTestCases(Path testOutput) {
51+
Document doc;
52+
try {
53+
doc = prepareDocument(testOutput);
54+
} catch (ParserConfigurationException | IOException e) {
55+
log.error("Unexpected exception, could not parse Qt testcases.", e);
56+
return new ArrayList<>();
57+
}
58+
59+
NodeList nodeList = doc.getElementsByTagName("TestFunction");
60+
List<TestResult> cases = createQtTestResults(nodeList);
61+
62+
log.info(PARSING_DONE_MESSAGE);
63+
64+
return cases;
65+
}
66+
67+
private Document prepareDocument(Path testOutput)
68+
throws ParserConfigurationException, IOException {
69+
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
70+
DocumentBuilder documentBuilder = dbFactory.newDocumentBuilder();
71+
documentBuilder.setErrorHandler(null); // Silence logging
72+
dbFactory.setValidating(false);
73+
74+
InputStream inputStream = new FileInputStream(testOutput.toFile());
75+
Reader reader = new InputStreamReader(inputStream, "UTF-8");
76+
InputSource is = new InputSource(reader);
77+
is.setEncoding("UTF-8");
78+
79+
Document doc = null;
80+
try {
81+
doc = documentBuilder.parse(is);
82+
} catch (SAXException ex) {
83+
log.info(SAX_PARSER_ERROR, ex);
84+
}
85+
86+
if (doc == null) {
87+
log.info(DOC_NULL_ERROR_MESSAGE);
88+
throw new IllegalStateException(DOC_NULL_ERROR_MESSAGE);
89+
}
90+
91+
doc.getDocumentElement().normalize();
92+
93+
return doc;
94+
}
95+
96+
/**
97+
* Parses Qt testlib XML output, as generated with -o filename.xml,xml.
98+
* <p>
99+
* Points are mapped to test cases with Message node type 'qinfo'. These
100+
* messages contain: prefix "TMC:" test case name: "test_function_name"
101+
* points separated by period: ".1"
102+
*
103+
* With failing testcase assertions, there will be an Incident node with
104+
* type "fail" and Description node with the failed assertion message.
105+
*
106+
* When the testcase assertion(s) has passed, there will be an Incident node
107+
* with type "pass" and no Description node.
108+
* </p>
109+
* <TestFunction name="test_function_name">
110+
* <Message type="qinfo" file="" line="0">
111+
* <Description><![CDATA[TMC:test_function_name.1]]></Description>
112+
* </Message>
113+
* <Incident type="fail" file="test_source.cpp" line="420">
114+
* <Description>
115+
* <![CDATA['!strcmp(hello_msg(), "Helo, world!" )' returned FALSE. ()]]>
116+
* </Description>
117+
* </Incident>
118+
* <Duration msecs="0.135260"/>
119+
* </TestFunction>
120+
*
121+
*/
122+
private List<TestResult> createQtTestResults(NodeList nodeList) {
123+
List<TestResult> cases = new ArrayList<>();
124+
125+
for (int i = 0; i < nodeList.getLength(); i++) {
126+
Element testcase = (Element) nodeList.item(i);
127+
List<String> points = parsePoints(testcase);
128+
129+
if (points.isEmpty()) {
130+
// No points == not a TMC testcase
131+
continue;
132+
}
133+
134+
Element incident = (Element) testcase.getElementsByTagName("Incident").item(0);
135+
136+
String id = testcase.getAttribute("name");
137+
boolean passed = incident.getAttribute("type").equals("pass");
138+
String msg = "";
139+
140+
// Get the assertion error if testcase failed
141+
if (!passed) {
142+
Element desc = (Element) incident.getElementsByTagName("Description").item(0);
143+
msg = desc.getTextContent();
144+
}
145+
146+
ImmutableList<String> trace = ImmutableList.of();
147+
cases.add(new TestResult(id, passed, ImmutableList.copyOf(points), msg, trace));
148+
}
149+
150+
return cases;
151+
}
152+
153+
/**
154+
* <p>
155+
* Parse potential points from testcase.
156+
* </p>
157+
*/
158+
private List<String> parsePoints(Element testcase) {
159+
List<String> points = new ArrayList<>();
160+
NodeList messages = testcase.getElementsByTagName("Message");
161+
for (int i = 0; i < messages.getLength(); i++) {
162+
// Convert node to element, messages.item(i) returns a node
163+
Element message = (Element) messages.item(i);
164+
Element desc = (Element) message.getElementsByTagName("Description").item(0);
165+
String text = desc.getTextContent();
166+
if (text.matches("^(TMC:.*)")) {
167+
String result = text.substring(text.indexOf(".") + 1);
168+
points.add(result);
169+
}
170+
}
171+
172+
return points;
173+
}
174+
175+
public List<TestResult> getTestResults() {
176+
return this.tests;
177+
}
178+
179+
private Status getResultStatus() {
180+
for (TestResult result : getTestResults()) {
181+
if (!result.isSuccessful()) {
182+
return Status.TESTS_FAILED;
183+
}
184+
}
185+
186+
return Status.PASSED;
187+
}
188+
189+
/**
190+
* Returns the run result of this file.
191+
*
192+
* @return Runresults
193+
*/
194+
public RunResult result() {
195+
return new RunResult(
196+
getResultStatus(),
197+
ImmutableList.copyOf(getTestResults()),
198+
new ImmutableMap.Builder<String, byte[]>().build());
199+
}
200+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
package fi.helsinki.cs.tmc.langs.qmake;
3+
4+
5+
public class QmakeBuildException extends RuntimeException {
6+
7+
QmakeBuildException(java.lang.Exception exception) {
8+
System.err.println(exception);
9+
}
10+
11+
}

0 commit comments

Comments
 (0)