1 /*
2     SPDX-FileCopyrightText: 2011 Andriy Rysin <rysin@kde.org>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include <QtTest>
8 
9 #include "../xkb_rules.h"
10 
11 #include <qdom.h>
12 #include <qxml.h>
13 
14 static const Rules::ExtrasFlag readExtras = Rules::NO_EXTRAS;
15 
16 class RulesTest : public QObject
17 {
18     Q_OBJECT
19 
20     Rules *rules;
21 
22 private Q_SLOTS:
initTestCase()23     void initTestCase()
24     {
25         rules = Rules::readRules(readExtras);
26     }
27 
cleanupTestCase()28     void cleanupTestCase()
29     {
30         delete rules;
31     }
32 
testRules()33     void testRules()
34     {
35         QVERIFY(rules != nullptr);
36         QVERIFY(rules->modelInfos.size() > 0);
37         QVERIFY(rules->layoutInfos.size() > 0);
38         QVERIFY(rules->optionGroupInfos.size() > 0);
39     }
40 
testModel()41     void testModel()
42     {
43         foreach (const ModelInfo *modelInfo, rules->modelInfos) {
44             QVERIFY(modelInfo != nullptr);
45             QVERIFY(modelInfo->name.length() > 0);
46             QVERIFY(modelInfo->description.length() > 0);
47             //        	QVERIFY( ! modelInfo->vendor.isEmpty() );
48         }
49     }
50 
testLayouts()51     void testLayouts()
52     {
53         foreach (const LayoutInfo *layoutInfo, rules->layoutInfos) {
54             QVERIFY(layoutInfo != nullptr);
55             QVERIFY(!layoutInfo->name.isEmpty());
56             //        	const char* desc = layoutInfo->name.toUtf8() ;
57             //        	qDebug() << layoutInfo->name;
58             QVERIFY(!layoutInfo->description.isEmpty());
59 
60             foreach (const VariantInfo *variantInfo, layoutInfo->variantInfos) {
61                 QVERIFY(variantInfo != nullptr);
62                 QVERIFY(!variantInfo->name.isEmpty());
63                 QVERIFY(!variantInfo->description.isEmpty());
64             }
65             foreach (const QString &language, layoutInfo->languages) {
66                 QVERIFY(!language.isEmpty());
67             }
68         }
69     }
70 
testOptionGroups()71     void testOptionGroups()
72     {
73         foreach (const OptionGroupInfo *optionGroupInfo, rules->optionGroupInfos) {
74             QVERIFY(optionGroupInfo != nullptr);
75             QVERIFY(!optionGroupInfo->name.isEmpty());
76             QVERIFY(!optionGroupInfo->description.isEmpty());
77             // optionGroupInfo->exclusive
78 
79             foreach (const OptionInfo *optionInfo, optionGroupInfo->optionInfos) {
80                 QVERIFY(optionInfo != nullptr);
81                 QVERIFY(!optionInfo->name.isEmpty());
82                 QVERIFY(!optionInfo->description.isEmpty());
83             }
84         }
85     }
86 
testExtras()87     void testExtras()
88     {
89         Rules *rulesWithExtras = Rules::readRules(Rules::READ_EXTRAS);
90         QVERIFY2(rulesWithExtras->layoutInfos.size() > rules->layoutInfos.size(), "Rules with extras should have more layouts");
91 
92         foreach (const LayoutInfo *layoutInfo, rules->layoutInfos) {
93             QVERIFY(!layoutInfo->fromExtras);
94         }
95 
96         bool foundFromExtras = false, foundNonExtras = false;
97         foreach (const LayoutInfo *layoutInfo, rulesWithExtras->layoutInfos) {
98             if (layoutInfo->fromExtras)
99                 foundFromExtras = true;
100             if (!layoutInfo->fromExtras)
101                 foundNonExtras = true;
102             layoutInfo->languages.size(); // make sure we can access all merged objects
103             layoutInfo->variantInfos.size(); // make sure we can access all merged objects
104         }
105         QVERIFY(foundNonExtras);
106         QVERIFY(foundFromExtras);
107     }
108 
testWriteNewXml()109     void testWriteNewXml()
110     {
111         QDomDocument doc(QStringLiteral("xkbConfigRegistry"));
112         QDomElement root = doc.createElement(QStringLiteral("xkbConfigRegistry"));
113         root.setAttribute(QStringLiteral("version"), QStringLiteral("2.0"));
114         doc.appendChild(root);
115 
116         QDomElement modelList = doc.createElement(QStringLiteral("modelList"));
117         root.appendChild(modelList);
118         foreach (const ModelInfo *modelInfo, rules->modelInfos) {
119             QDomElement model = doc.createElement(QStringLiteral("model"));
120             model.setAttribute(QStringLiteral("name"), modelInfo->name);
121             model.setAttribute(QStringLiteral("description"), modelInfo->description);
122             model.setAttribute(QStringLiteral("vendor"), modelInfo->vendor);
123             modelList.appendChild(model);
124         }
125 
126         QDomElement layoutList = doc.createElement(QStringLiteral("layoutList"));
127         foreach (const LayoutInfo *layoutInfo, rules->layoutInfos) {
128             QDomElement layout = doc.createElement(QStringLiteral("layout"));
129             layout.setAttribute(QStringLiteral("name"), layoutInfo->name);
130             layout.setAttribute(QStringLiteral("description"), layoutInfo->description);
131 
132             QDomElement langList = doc.createElement(QStringLiteral("languageList"));
133             foreach (const QString &lang, layoutInfo->languages) {
134                 QDomElement langNode = doc.createElement(QStringLiteral("lang"));
135                 langNode.setAttribute(QStringLiteral("iso639Id"), lang);
136                 langList.appendChild(langNode);
137             }
138             if (langList.hasChildNodes()) {
139                 layout.appendChild(langList);
140             }
141 
142             QDomElement variantList = doc.createElement(QStringLiteral("variantList"));
143             foreach (const VariantInfo *variantInfo, layoutInfo->variantInfos) {
144                 QDomElement variant = doc.createElement(QStringLiteral("variant"));
145                 variant.setAttribute(QStringLiteral("name"), variantInfo->name);
146                 variant.setAttribute(QStringLiteral("description"), variantInfo->description);
147 
148                 QDomElement langList = doc.createElement(QStringLiteral("languageList"));
149                 foreach (const QString &lang, variantInfo->languages) {
150                     QDomElement langNode = doc.createElement(QStringLiteral("lang"));
151                     langNode.setAttribute(QStringLiteral("iso639Id"), lang);
152                     langList.appendChild(langNode);
153                 }
154                 if (langList.hasChildNodes()) {
155                     variant.appendChild(langList);
156                 }
157 
158                 variantList.appendChild(variant);
159             }
160             if (variantList.hasChildNodes()) {
161                 layout.appendChild(variantList);
162             }
163 
164             layoutList.appendChild(layout);
165         }
166         root.appendChild(layoutList);
167 
168         QDomElement optionGroupList = doc.createElement(QStringLiteral("optionList"));
169         foreach (const OptionGroupInfo *optionGroupInfo, rules->optionGroupInfos) {
170             QDomElement optionGroup = doc.createElement(QStringLiteral("optionGroup"));
171             optionGroup.setAttribute(QStringLiteral("name"), optionGroupInfo->name);
172             optionGroup.setAttribute(QStringLiteral("description"), optionGroupInfo->description);
173             optionGroup.setAttribute(QStringLiteral("exclusive"), optionGroupInfo->exclusive);
174 
175             foreach (const OptionInfo *optionGroupInfo, optionGroupInfo->optionInfos) {
176                 QDomElement option = doc.createElement(QStringLiteral("option"));
177                 option.setAttribute(QStringLiteral("name"), optionGroupInfo->name);
178                 option.setAttribute(QStringLiteral("description"), optionGroupInfo->description);
179                 optionGroup.appendChild(option);
180             }
181 
182             optionGroupList.appendChild(optionGroup);
183         }
184         root.appendChild(optionGroupList);
185 
186         QFile file(QStringLiteral("base2.xml"));
187         if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
188             qWarning() << "Failed to open layout memory xml file for writing" << file.fileName();
189             QFAIL("failed");
190         }
191 
192         QTextStream out(&file);
193         out << doc.toString();
194     }
195 
testRulesVersion()196     void testRulesVersion()
197     {
198         QVERIFY(!rules->version.isEmpty());
199 
200         Rules *rules10 = new Rules();
201         Rules::readRules(rules10, QStringLiteral("config/base.xml"), false);
202         QCOMPARE(rules10->version, QString("1.0"));
203         delete rules10;
204 
205         Rules *rules11 = new Rules();
206         Rules::readRules(rules11, QStringLiteral("config/base.1.1.xml"), false);
207         QCOMPARE(rules11->version, QString("1.1"));
208 
209         foreach (const LayoutInfo *layoutInfo, rules11->layoutInfos) {
210             QVERIFY(layoutInfo != nullptr);
211             QVERIFY(!layoutInfo->name.isEmpty());
212             QVERIFY(!layoutInfo->description.isEmpty());
213 
214             foreach (const VariantInfo *variantInfo, layoutInfo->variantInfos) {
215                 QVERIFY(variantInfo != nullptr);
216                 QVERIFY(!variantInfo->name.isEmpty());
217                 QVERIFY(!variantInfo->description.isEmpty());
218             }
219         }
220 
221         delete rules11;
222     }
223 
loadRulesBenchmark()224     void loadRulesBenchmark()
225     {
226         QBENCHMARK {
227             Rules *rules = Rules::readRules(readExtras);
228             delete rules;
229         }
230     }
231 };
232 
233 // need kde libs for config-workspace.h used in xkb_rules.cpp
234 QTEST_MAIN(RulesTest)
235 
236 #include "xkb_rules_test.moc"
237