1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtTest module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #include "qtestxunitstreamer.h" |
43 | #include "qtestelement.h" |
44 | |
45 | #include "QtTest/private/qtestlog_p.h" |
46 | #include "QtTest/private/qtestresult_p.h" |
47 | #include "QtTest/private/qxmltestlogger_p.h" |
48 | |
49 | QT_BEGIN_NAMESPACE |
50 | |
51 | QTestXunitStreamer::QTestXunitStreamer() |
52 | :QTestBasicStreamer() |
53 | {} |
54 | |
55 | QTestXunitStreamer::~QTestXunitStreamer() |
56 | {} |
57 | |
58 | void QTestXunitStreamer::indentForElement(const QTestElement* element, char* buf, int size) |
59 | { |
60 | if (size == 0) return; |
61 | |
62 | buf[0] = 0; |
63 | |
64 | if (!element) return; |
65 | |
66 | char* endbuf = buf + size; |
67 | element = element->parentElement(); |
68 | while (element && buf+2 < endbuf) { |
69 | *(buf++) = ' '; |
70 | *(buf++) = ' '; |
71 | *buf = 0; |
72 | element = element->parentElement(); |
73 | } |
74 | } |
75 | |
76 | void QTestXunitStreamer::formatStart(const QTestElement *element, QTestCharBuffer *formatted) const |
77 | { |
78 | if(!element || !formatted ) |
79 | return; |
80 | |
81 | char indent[20]; |
82 | indentForElement(element, indent, sizeof(indent)); |
83 | |
84 | // Errors are written as CDATA within system-err, comments elsewhere |
85 | if (element->elementType() == QTest::LET_Error) { |
86 | if (element->parentElement()->elementType() == QTest::LET_SystemError) { |
87 | QTest::qt_asprintf(formatted, "<![CDATA[" ); |
88 | } else { |
89 | QTest::qt_asprintf(formatted, "%s<!--" , indent); |
90 | } |
91 | return; |
92 | } |
93 | |
94 | QTest::qt_asprintf(formatted, "%s<%s" , indent, element->elementName()); |
95 | } |
96 | |
97 | void QTestXunitStreamer::formatEnd(const QTestElement *element, QTestCharBuffer *formatted) const |
98 | { |
99 | if (!element || !formatted ) |
100 | return; |
101 | |
102 | if (!element->childElements()){ |
103 | formatted->data()[0] = '\0'; |
104 | return; |
105 | } |
106 | |
107 | char indent[20]; |
108 | indentForElement(element, indent, sizeof(indent)); |
109 | |
110 | QTest::qt_asprintf(formatted, "%s</%s>\n" , indent, element->elementName()); |
111 | } |
112 | |
113 | void QTestXunitStreamer::formatAttributes(const QTestElement* element, const QTestElementAttribute *attribute, QTestCharBuffer *formatted) const |
114 | { |
115 | if(!attribute || !formatted ) |
116 | return; |
117 | |
118 | QTest::AttributeIndex attrindex = attribute->index(); |
119 | |
120 | // For errors within system-err, we only want to output `message' |
121 | if (element && element->elementType() == QTest::LET_Error |
122 | && element->parentElement()->elementType() == QTest::LET_SystemError) { |
123 | |
124 | if (attrindex != QTest::AI_Description) return; |
125 | |
126 | QXmlTestLogger::xmlCdata(formatted, attribute->value()); |
127 | return; |
128 | } |
129 | |
130 | char const* key = 0; |
131 | if (attrindex == QTest::AI_Description) |
132 | key = "message" ; |
133 | else if (attrindex != QTest::AI_File && attrindex != QTest::AI_Line) |
134 | key = attribute->name(); |
135 | |
136 | if (key) { |
137 | QTestCharBuffer quotedValue; |
138 | QXmlTestLogger::xmlQuote("edValue, attribute->value()); |
139 | QTest::qt_asprintf(formatted, " %s=\"%s\"" , key, quotedValue.constData()); |
140 | } else { |
141 | formatted->data()[0] = '\0'; |
142 | } |
143 | } |
144 | |
145 | void QTestXunitStreamer::formatAfterAttributes(const QTestElement *element, QTestCharBuffer *formatted) const |
146 | { |
147 | if(!element || !formatted ) |
148 | return; |
149 | |
150 | // Errors are written as CDATA within system-err, comments elsewhere |
151 | if (element->elementType() == QTest::LET_Error) { |
152 | if (element->parentElement()->elementType() == QTest::LET_SystemError) { |
153 | QTest::qt_asprintf(formatted, "]]>\n" ); |
154 | } else { |
155 | QTest::qt_asprintf(formatted, " -->\n" ); |
156 | } |
157 | return; |
158 | } |
159 | |
160 | if(!element->childElements()) |
161 | QTest::qt_asprintf(formatted, "/>\n" ); |
162 | else |
163 | QTest::qt_asprintf(formatted, ">\n" ); |
164 | } |
165 | |
166 | void QTestXunitStreamer::output(QTestElement *element) const |
167 | { |
168 | outputString("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" ); |
169 | QTestBasicStreamer::output(element); |
170 | } |
171 | |
172 | void QTestXunitStreamer::outputElements(QTestElement *element, bool) const |
173 | { |
174 | QTestCharBuffer buf; |
175 | bool hasChildren; |
176 | /* |
177 | Elements are in reverse order of occurrence, so start from the end and work |
178 | our way backwards. |
179 | */ |
180 | while (element && element->nextElement()) { |
181 | element = element->nextElement(); |
182 | } |
183 | while (element) { |
184 | hasChildren = element->childElements(); |
185 | |
186 | if(element->elementType() != QTest::LET_Benchmark){ |
187 | formatStart(element, &buf); |
188 | outputString(buf.data()); |
189 | |
190 | formatBeforeAttributes(element, &buf); |
191 | outputString(buf.data()); |
192 | |
193 | outputElementAttributes(element, element->attributes()); |
194 | |
195 | formatAfterAttributes(element, &buf); |
196 | outputString(buf.data()); |
197 | |
198 | if(hasChildren) |
199 | outputElements(element->childElements(), true); |
200 | |
201 | formatEnd(element, &buf); |
202 | outputString(buf.data()); |
203 | } |
204 | element = element->previousElement(); |
205 | } |
206 | } |
207 | |
208 | QT_END_NAMESPACE |
209 | |
210 | |