1 #ifndef VALIDATORTEST_H
2 #define VALIDATORTEST_H
3 
4 #include <QTest>
5 #include <QObject>
6 #include <QHostInfo>
7 #include <QUuid>
8 #include <QJsonArray>
9 #include <QJsonObject>
10 #include <QJsonDocument>
11 #include <QCryptographicHash>
12 #include <QUrlQuery>
13 #include <QStringList>
14 #include <QRegularExpression>
15 #include <QLocale>
16 #include <QTimeZone>
17 #include <limits>
18 
19 #include "headers.h"
20 #include "coverageobject.h"
21 
22 #include <Cutelyst/application.h>
23 #include <Cutelyst/controller.h>
24 #include <Cutelyst/headers.h>
25 #include <Cutelyst/upload.h>
26 #include <Cutelyst/Plugins/Utils/Validator/Validator>
27 #include <Cutelyst/Plugins/Utils/Validator/Validators>
28 #include <Cutelyst/Plugins/Utils/Validator/validatorresult.h>
29 
30 using namespace Cutelyst;
31 
32 class TestValidator : public CoverageObject
33 {
34     Q_OBJECT
35 public:
TestValidator(QObject * parent=nullptr)36     explicit TestValidator(QObject *parent = nullptr) :
37         CoverageObject(parent)
38     {
39     }
40 
~TestValidator()41     ~TestValidator()
42     {
43     }
44 
45 private Q_SLOTS:
46     void initTestCase();
47 
48     void testController_data();
testController()49     void testController() {
50         doTest();
51     }
52 
53     void cleanupTestCase();
54 
55 private:
56     TestEngine *m_engine;
57 
58     TestEngine* getEngine();
59 
60     void doTest();
61 };
62 
63 
64 class ValidatorTest : public Controller
65 {
66     Q_OBJECT
67 public:
ValidatorTest(QObject * parent)68     explicit ValidatorTest(QObject *parent) : Controller(parent) {}
69 
70     // ***** Endpoint for checking Validator::BodyParamsOnly
71     C_ATTR(bodyParamsOnly, :Local :AutoArgs)
bodyParamsOnly(Context * c)72     void bodyParamsOnly(Context *c) {
73         Validator v({new ValidatorRequired(QStringLiteral("req_field"), m_validatorMessages)});
74         checkResponse(c, v.validate(c, Validator::BodyParamsOnly));
75     }
76 
77     // ***** Endpoint for checking Validator::QueryParamsOnly
78     C_ATTR(queryParamsOnly, :Local :AutoArgs)
queryParamsOnly(Context * c)79     void queryParamsOnly(Context *c) {
80         Validator v({new ValidatorRequired(QStringLiteral("req_field"), m_validatorMessages)});
81         checkResponse(c, v.validate(c, Validator::QueryParamsOnly));
82     }
83 
84     // ***** Endpoint for ValidatorAccepted ******
85     C_ATTR(accepted, :Local :AutoArgs)
accepted(Context * c)86     void accepted(Context *c) {
87         Validator v({new ValidatorAccepted(QStringLiteral("accepted_field"), m_validatorMessages)});
88         checkResponse(c, v.validate(c));
89     }
90 
91     // ***** Endpoint for ValidatorAfter with QDate ******
92     C_ATTR(afterDate, :Local :AutoArgs)
afterDate(Context * c)93     void afterDate(Context *c) {
94         Validator v({new ValidatorAfter(QStringLiteral("after_field"), QDate::currentDate(), QString(), nullptr, m_validatorMessages)});
95         checkResponse(c, v.validate(c));
96     }
97 
98     // ***** Endpoint for ValidatorAfter with QTime ******
99     C_ATTR(afterTime, :Local :AutoArgs)
afterTime(Context * c)100     void afterTime(Context *c) {
101         Validator v({new ValidatorAfter(QStringLiteral("after_field"), QTime(12, 0), QString(), nullptr, m_validatorMessages)});
102         checkResponse(c, v.validate(c));
103     }
104 
105     // ***** Endpoint for ValidatorAfter with QDateTime ******
106     C_ATTR(afterDateTime, :Local :AutoArgs)
afterDateTime(Context * c)107     void afterDateTime(Context *c) {
108         Validator v({new ValidatorAfter(QStringLiteral("after_field"), QDateTime::currentDateTime(), QString(), nullptr, m_validatorMessages)});
109         checkResponse(c, v.validate(c));
110     }
111 
112     // ***** Endpoint for ValidatorAfter with custom format ******
113     C_ATTR(afterFormat, :Local :AutoArgs)
afterFormat(Context * c)114     void afterFormat(Context *c) {
115         Validator v({new ValidatorAfter(QStringLiteral("after_field"), QDateTime::currentDateTime(), QString(), "yyyy d MM HH:mm", m_validatorMessages)});
116         checkResponse(c, v.validate(c));
117     }
118 
119     // ***** Endpoint for ValidatorAfter with invalid validation data ******
120     C_ATTR(afterInvalidValidationData, :Local :AutoArgs)
afterInvalidValidationData(Context * c)121     void afterInvalidValidationData(Context *c) {
122         Validator v({new ValidatorAfter(QStringLiteral("after_field"), QDate(), QString(), nullptr, m_validatorMessages)});
123         checkResponse(c, v.validate(c));
124     }
125 
126     // ***** Endpoint for ValidatorAfter with invalid validation data 2 ******
127     C_ATTR(afterInvalidValidationData2, :Local :AutoArgs)
afterInvalidValidationData2(Context * c)128     void afterInvalidValidationData2(Context *c) {
129         Validator v({new ValidatorAfter(QStringLiteral("after_field"), QStringLiteral("schiet"), QString(), nullptr, m_validatorMessages)});
130         checkResponse(c, v.validate(c));
131     }
132 
133     // ***** Endpoint for ValidatorAfter with time zone *****
134     C_ATTR(afterValidWithTimeZone, :Local :AutoArgs)
afterValidWithTimeZone(Context * c)135     void afterValidWithTimeZone(Context *c) {
136         Validator v({new ValidatorAfter(QStringLiteral("after_field"), QDateTime(QDate(2018, 1, 15), QTime(12,0), QTimeZone(QByteArrayLiteral("Indian/Christmas"))), QStringLiteral("Europe/Berlin"), nullptr, m_validatorMessages)});
137         checkResponse(c, v.validate(c));
138     }
139 
140     // ***** Endpoint for ValidatorAfter with time zone in iput field *****
141     C_ATTR(afterValidWithTimeZoneField, :Local :AutoArgs)
afterValidWithTimeZoneField(Context * c)142     void afterValidWithTimeZoneField(Context *c) {
143         Validator v({new ValidatorAfter(QStringLiteral("after_field"),
144                      QDateTime(QDate(2018,1,15), QTime(12,0), QTimeZone(QByteArrayLiteral("Indian/Christmas"))),
145                      QStringLiteral("tz_field"),
146                      nullptr,
147                      m_validatorMessages)});
148         checkResponse(c, v.validate(c));
149     }
150 
151     // ***** Endpoint for ValidatorAlpha ******
152     C_ATTR(alpha, :Local :AutoArgs)
alpha(Context * c)153     void alpha(Context *c) {
154         Validator v({new ValidatorAlpha(QStringLiteral("alpha_field"), false, m_validatorMessages)});
155         checkResponse(c, v.validate(c));
156     }
157 
158     // **** Endpoint for ValidatorAlpha only ASCII *****
159     C_ATTR(alphaAscii, :Local :AutoArgs)
alphaAscii(Context * c)160     void alphaAscii(Context *c) {
161         Validator v({new ValidatorAlpha(QStringLiteral("alpha_field"), true, m_validatorMessages)});
162         checkResponse(c, v.validate(c));
163     }
164 
165     // ***** Endpoint for ValidatorAlphaDash ******
166     C_ATTR(alphaDash, :Local :AutoArgs)
alphaDash(Context * c)167     void alphaDash(Context *c) {
168         Validator v({new ValidatorAlphaDash(QStringLiteral("alphadash_field"), false, m_validatorMessages)});
169         checkResponse(c, v.validate(c));
170     }
171 
172     // ***** Endpoint for ValidatorAlphaDash only ASCII ******
173     C_ATTR(alphaDashAscii, :Local :AutoArgs)
alphaDashAscii(Context * c)174     void alphaDashAscii(Context *c) {
175         Validator v({new ValidatorAlphaDash(QStringLiteral("alphadash_field"), true, m_validatorMessages)});
176         checkResponse(c, v.validate(c));
177     }
178 
179     // ***** Endpoint for ValidatorAlphaNum ******
180     C_ATTR(alphaNum, :Local :AutoArgs)
alphaNum(Context * c)181     void alphaNum(Context *c) {
182         Validator v({new ValidatorAlphaNum(QStringLiteral("alphanum_field"), false, m_validatorMessages)});
183         checkResponse(c, v.validate(c));
184     }
185 
186     // ***** Endpoint for ValidatorAlphaNum only ASCII ******
187     C_ATTR(alphaNumAscii, :Local :AutoArgs)
alphaNumAscii(Context * c)188     void alphaNumAscii(Context *c) {
189         Validator v({new ValidatorAlphaNum(QStringLiteral("alphanum_field"), true, m_validatorMessages)});
190         checkResponse(c, v.validate(c));
191     }
192 
193     // ***** Endpoint for ValidatorBefore with QDate ******
194     C_ATTR(beforeDate, :Local :AutoArgs)
beforeDate(Context * c)195     void beforeDate(Context *c) {
196         Validator v({new ValidatorBefore(QStringLiteral("before_field"), QDate::currentDate(), QString(), nullptr, m_validatorMessages)});
197         checkResponse(c, v.validate(c));
198     }
199 
200     // ***** Endpoint for ValidatorBefore with QTime ******
201     C_ATTR(beforeTime, :Local :AutoArgs)
beforeTime(Context * c)202     void beforeTime(Context *c) {
203         Validator v({new ValidatorBefore(QStringLiteral("before_field"), QTime(12, 0), QString(), nullptr, m_validatorMessages)});
204         checkResponse(c, v.validate(c));
205     }
206 
207     // ***** Endpoint for ValidatorBefore with QDateTime ******
208     C_ATTR(beforeDateTime, :Local :AutoArgs)
beforeDateTime(Context * c)209     void beforeDateTime(Context *c) {
210         Validator v({new ValidatorBefore(QStringLiteral("before_field"), QDateTime::currentDateTime(), QString(), nullptr, m_validatorMessages)});
211         checkResponse(c, v.validate(c));
212     }
213 
214     // ***** Endpoint for ValidatorBefore with custom format ******
215     C_ATTR(beforeFormat, :Local :AutoArgs)
beforeFormat(Context * c)216     void beforeFormat(Context *c) {
217         Validator v({new ValidatorBefore(QStringLiteral("before_field"), QDateTime::currentDateTime(), QString(), "yyyy d MM HH:mm", m_validatorMessages)});
218         checkResponse(c, v.validate(c));
219     }
220 
221     // ***** Endpoint for ValidatorBefore with invalid validation data ******
222     C_ATTR(beforeInvalidValidationData, :Local :AutoArgs)
beforeInvalidValidationData(Context * c)223     void beforeInvalidValidationData(Context *c) {
224         Validator v({new ValidatorBefore(QStringLiteral("before_field"), QDate(), QString(), nullptr, m_validatorMessages)});
225         checkResponse(c, v.validate(c));
226     }
227 
228     // ***** Endpoint for ValidatorBefore with invalid validation data 2 ******
229     C_ATTR(beforeInvalidValidationData2, :Local :AutoArgs)
beforeInvalidValidationData2(Context * c)230     void beforeInvalidValidationData2(Context *c) {
231         Validator v({new ValidatorBefore(QStringLiteral("before_field"), QStringLiteral("schiet"), QString(), nullptr, m_validatorMessages)});
232         checkResponse(c, v.validate(c));
233     }
234 
235     // ***** Endpoint for ValidatorBefore with time zone *****
236     C_ATTR(beforeValidWithTimeZone, :Local :AutoArgs)
beforeValidWithTimeZone(Context * c)237     void beforeValidWithTimeZone(Context *c) {
238         Validator v({new ValidatorBefore(QStringLiteral("after_field"), QDateTime(QDate(2018, 1, 15), QTime(12,0), QTimeZone(QByteArrayLiteral("America/Tijuana"))), QStringLiteral("Europe/Berlin"), nullptr, m_validatorMessages)});
239         checkResponse(c, v.validate(c));
240     }
241 
242     // ***** Endpoint for ValidatorBefore with time zone in iput field *****
243     C_ATTR(beforeValidWithTimeZoneField, :Local :AutoArgs)
beforeValidWithTimeZoneField(Context * c)244     void beforeValidWithTimeZoneField(Context *c) {
245         Validator v({new ValidatorBefore(QStringLiteral("after_field"),
246                      QDateTime(QDate(2018,1,15), QTime(12,0), QTimeZone(QByteArrayLiteral("America/Tijuana"))),
247                      QStringLiteral("tz_field"),
248                      nullptr,
249                      m_validatorMessages)});
250         checkResponse(c, v.validate(c));
251     }
252 
253     // ***** Endpoint for ValidatorBetween with int ******
254     C_ATTR(betweenInt, :Local :AutoArgs)
betweenInt(Context * c)255     void betweenInt(Context *c) {
256         Validator v({new ValidatorBetween(QStringLiteral("between_field"), QMetaType::Int, -10, 10, m_validatorMessages)});
257         checkResponse(c, v.validate(c));
258     }
259 
260     // ***** Endpoint for ValidatorBetween with uint ******
261     C_ATTR(betweenUint, :Local :AutoArgs)
betweenUint(Context * c)262     void betweenUint(Context *c) {
263         Validator v({new ValidatorBetween(QStringLiteral("between_field"), QMetaType::UInt, 10, 20, m_validatorMessages)});
264         checkResponse(c, v.validate(c));
265     }
266 
267     // ***** Endpoint for ValidatorBetween with float ******
268     C_ATTR(betweenFloat, :Local :AutoArgs)
betweenFloat(Context * c)269     void betweenFloat(Context *c) {
270         Validator v({new ValidatorBetween(QStringLiteral("between_field"), QMetaType::Float, -10.0, 10.0, m_validatorMessages)});
271         checkResponse(c, v.validate(c));
272     }
273 
274     // ***** Endpoint for ValidatorBetween with string ******
275     C_ATTR(betweenString, :Local :AutoArgs)
betweenString(Context * c)276     void betweenString(Context *c) {
277         Validator v({new ValidatorBetween(QStringLiteral("between_field"), QMetaType::QString, 5, 10, m_validatorMessages)});
278         checkResponse(c, v.validate(c));
279     }
280 
281     // ***** Endpoint for ValidatorBoolean ******
282     C_ATTR(boolean, :Local :AutoArgs)
boolean(Context * c)283     void boolean(Context *c) {
284         Validator v({new ValidatorBoolean(QStringLiteral("boolean_field"), m_validatorMessages)});
285         checkResponse(c, v.validate(c));
286     }
287 
288     // ***** Endpoint for ValidatorCharNotAllowed ******
289     C_ATTR(charNotAllowed, :Local :AutoArgs)
charNotAllowed(Context * c)290     void charNotAllowed(Context *c) {
291         Validator v({new ValidatorCharNotAllowed(QStringLiteral("char_not_allowed_field"), QStringLiteral("#%*."), m_validatorMessages)});
292         checkResponse(c, v.validate(c));
293     }
294 
295     // ***** Endpoint for ValidatorConfirmed ******
296     C_ATTR(confirmed, :Local :AutoArgs)
confirmed(Context * c)297     void confirmed(Context *c) {
298         Validator v({new ValidatorConfirmed(QStringLiteral("pass"), m_validatorMessages)});
299         checkResponse(c, v.validate(c));
300     }
301 
302     // ***** Endpoint for ValidatorDate with standard formats ******
303     C_ATTR(date, :Local :AutoArgs)
date(Context * c)304     void date(Context *c) {
305         Validator v({new ValidatorDate(QStringLiteral("field"), nullptr, m_validatorMessages)});
306         checkResponse(c, v.validate(c));
307     }
308 
309     // ***** Endpoint for ValidatorDate with custom format ******
310     C_ATTR(dateFormat, :Local :AutoArgs)
dateFormat(Context * c)311     void dateFormat(Context *c) {
312         Validator v({new ValidatorDate(QStringLiteral("field"), "yyyy d MM", m_validatorMessages)});
313         checkResponse(c, v.validate(c));
314     }
315 
316     // ***** Endpoint for ValidatorDateTime with standard formats ******
317     C_ATTR(dateTime, :Local :AutoArgs)
dateTime(Context * c)318     void dateTime(Context *c) {
319         Validator v({new ValidatorDateTime(QStringLiteral("field"), QString(), nullptr, m_validatorMessages)});
320         checkResponse(c, v.validate(c));
321     }
322 
323     // ***** Endpoint for ValidatorDateTime with custom format ******
324     C_ATTR(dateTimeFormat, :Local :AutoArgs)
dateTimeFormat(Context * c)325     void dateTimeFormat(Context *c) {
326         Validator v({new ValidatorDateTime(QStringLiteral("field"), QString(), "yyyy d MM mm:HH", m_validatorMessages)});
327         checkResponse(c, v.validate(c));
328     }
329 
330     // ***** Endpoint for ValidatorDifferent ******
331     C_ATTR(different, :Local :AutoArgs)
different(Context * c)332     void different(Context *c) {
333         Validator v({new ValidatorDifferent(QStringLiteral("field"), QStringLiteral("other"), nullptr, m_validatorMessages)});
334         checkResponse(c, v.validate(c));
335     }
336 
337     // ***** Endpoint for ValidatorDigits without exact length ******
338     C_ATTR(digits, :Local :AutoArgs)
digits(Context * c)339     void digits(Context *c) {
340         Validator v({new ValidatorDigits(QStringLiteral("field"), -1, m_validatorMessages)});
341         checkResponse(c, v.validate(c));
342     }
343 
344     // ***** Endpoint for ValidatorDigits with exact length ******
345     C_ATTR(digitsLength, :Local :AutoArgs)
digitsLength(Context * c)346     void digitsLength(Context *c) {
347         Validator v({new ValidatorDigits(QStringLiteral("field"), 10, m_validatorMessages)});
348         checkResponse(c, v.validate(c));
349     }
350 
351     // ***** Endpoint for ValidatorDigitsBetween ******
352     C_ATTR(digitsBetween, :Local :AutoArgs)
digitsBetween(Context * c)353     void digitsBetween(Context *c) {
354         Validator v({new ValidatorDigitsBetween(QStringLiteral("field"), 5, 10, m_validatorMessages)});
355         checkResponse(c, v.validate(c));
356     }
357 
358     // ***** Endpoint for ValidatorDomain without DNS check *****
359     C_ATTR(domain, :Local :AutoArgs)
domain(Context * c)360     void domain(Context *c) {
361         Validator v({new ValidatorDomain(QStringLiteral("field"), false, m_validatorMessages)});
362         checkResponse(c, v.validate(c));
363     }
364 
365     // ***** Endpoint for ValidatorDomain with DNS check *****
366     C_ATTR(domainDns, :Local :AutoArgs)
domainDns(Context * c)367     void domainDns(Context *c) {
368         Validator v({new ValidatorDomain(QStringLiteral("field"), true, m_validatorMessages)});
369         checkResponse(c, v.validate(c));
370     }
371 
372     // ***** Endpoint for ValidatorEmail valid ****
373     C_ATTR(emailValid, :Local :AutoArgs)
emailValid(Context * c)374     void emailValid(Context *c) {
375         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::Valid, ValidatorEmail::NoOption, m_validatorMessages)});
376         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
377     }
378 
379     // ***** Endpoint for ValidatorEmail valid emails completely valid *****
380     C_ATTR(emailDnsWarnValid, :Local :AutoArgs)
emailDnsWarnValid(Context * c)381     void emailDnsWarnValid(Context *c) {
382         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::Valid, ValidatorEmail::CheckDNS, m_validatorMessages)});
383         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
384     }
385 
386     // ***** Endpoint for ValidatorEmail RFC5321 conformant emails valid *****
387     C_ATTR(emailRfc5321Valid, :Local :AutoArgs)
emailRfc5321Valid(Context * c)388     void emailRfc5321Valid(Context *c) {
389         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::RFC5321, ValidatorEmail::NoOption, m_validatorMessages)});
390         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
391     }
392 
393     // ***** Endpoint for ValidatorEmail RFC5321 conformant emails invalid *****
394     C_ATTR(emailRfc5321Invalid, :Local :AutoArgs)
emailRfc5321Invalid(Context * c)395     void emailRfc5321Invalid(Context *c) {
396         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::DNSWarn, ValidatorEmail::NoOption, m_validatorMessages)});
397         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
398     }
399 
400     // ***** Endpoint for ValidatorEmail CFWS conformant emails valid *****
401     C_ATTR(emailCfwsValid, :Local :AutoArgs)
emailCfwsValid(Context * c)402     void emailCfwsValid(Context *c) {
403         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::CFWS, ValidatorEmail::NoOption, m_validatorMessages)});
404         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
405     }
406 
407     // ***** Endpoint for ValidatorEmail CFWS conformant emails invalid *****
408     C_ATTR(emailCfwsInvalid, :Local :AutoArgs)
emailCfwsInvalid(Context * c)409     void emailCfwsInvalid(Context *c) {
410         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::RFC5321, ValidatorEmail::NoOption, m_validatorMessages)});
411         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
412     }
413 
414     // ***** Endpoint for ValidatorEmail Deprecated emails valid *****
415     C_ATTR(emailDeprecatedValid, :Local :AutoArgs)
emailDeprecatedValid(Context * c)416     void emailDeprecatedValid(Context *c) {
417         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::Deprecated, ValidatorEmail::NoOption, m_validatorMessages)});
418         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
419     }
420 
421     // ***** Endpoint for ValidatorEmail CFWS conformant emails invalid *****
422     C_ATTR(emailDeprecatedInvalid, :Local :AutoArgs)
emailDeprecatedInvalid(Context * c)423     void emailDeprecatedInvalid(Context *c) {
424         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::CFWS, ValidatorEmail::NoOption, m_validatorMessages)});
425         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
426     }
427 
428     // ***** Endpoint for ValidatorEmail RFC5322 emails valid *****
429     C_ATTR(emailRfc5322Valid, :Local :AutoArgs)
emailRfc5322Valid(Context * c)430     void emailRfc5322Valid(Context *c) {
431         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::RFC5322, ValidatorEmail::NoOption, m_validatorMessages)});
432         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
433     }
434 
435     // ***** Endpoint for ValidatorEmail RFC5322 conformant emails invalid *****
436     C_ATTR(emailRfc5322Invalid, :Local :AutoArgs)
emailRfc5322Invalid(Context * c)437     void emailRfc5322Invalid(Context *c) {
438         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::Deprecated, ValidatorEmail::NoOption, m_validatorMessages)});
439         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
440     }
441 
442     // ***** Endpoint for ValidatorEmail with errors *****
443     C_ATTR(emailErrors, :Local :AutoArgs)
emailErrors(Context * c)444     void emailErrors(Context *c) {
445         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::RFC5322, ValidatorEmail::NoOption, m_validatorMessages)});
446         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
447     }
448 
449     // ***** Endpoint for ValidatorEmail with allowed IDNs
450     C_ATTR(emailIdnAllowed, :Local :AutoArgs)
emailIdnAllowed(Context * c)451     void emailIdnAllowed(Context *c) {
452         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::Valid, ValidatorEmail::AllowIDN, m_validatorMessages)});
453         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
454     }
455 
456     // ***** Endpoint for ValidatorEmail with allowed UTF8 local part
457     C_ATTR(emailUtf8Local, :Local :AutoArgs)
emailUtf8Local(Context * c)458     void emailUtf8Local(Context *c) {
459         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::Valid, ValidatorEmail::UTF8Local, m_validatorMessages)});
460         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
461     }
462 
463     // ***** Endpoint for ValidatorEmail with allowed UTF8 local part and IDN
464     C_ATTR(emailUtf8, :Local :AutoArgs)
emailUtf8(Context * c)465     void emailUtf8(Context *c) {
466         Validator v({new ValidatorEmail(QStringLiteral("field"), ValidatorEmail::Valid, ValidatorEmail::AllowUTF8, m_validatorMessages)});
467         checkResponse(c, v.validate(c, Validator::NoTrimming|Validator::BodyParamsOnly));
468     }
469 
470     // ***** Endpoint for ValidatorFileSize ******
471     C_ATTR(fileSize, :Local :AutoArgs)
fileSize(Context * c)472     void fileSize(Context *c) {
473         ValidatorFileSize::Option option = ValidatorFileSize::NoOption;
474         const QString opt = c->req()->bodyParameter(QStringLiteral("option"));
475         if (opt == QLatin1String("OnlyBinary")) {
476             option = ValidatorFileSize::OnlyBinary;
477         } else if (opt == QLatin1String("OnlyDecimal")) {
478             option = ValidatorFileSize::OnlyDecimal;
479         } else if (opt == QLatin1String("ForceBinary")) {
480             option = ValidatorFileSize::ForceBinary;
481         } else if (opt == QLatin1String("ForceDecimal")) {
482             option = ValidatorFileSize::ForceDecimal;
483         }
484         const double min = c->req()->bodyParameter(QStringLiteral("min"), QStringLiteral("-1.0")).toDouble();
485         const double max = c->req()->bodyParameter(QStringLiteral("max"), QStringLiteral("-1.0")).toDouble();
486         c->setLocale(QLocale(c->req()->bodyParameter(QStringLiteral("locale"), QStringLiteral("C"))));
487         Validator v({new ValidatorFileSize(QStringLiteral("field"), option, min, max, m_validatorMessages)});
488         checkResponse(c, v.validate(c, Validator::NoTrimming));
489     }
490 
491     // ***** Endpoint for ValidatorFileSize with return value check *****
492     C_ATTR(fileSizeValue, :Local :AutoArgs)
fileSizeValue(Context * c)493     void fileSizeValue(Context *c) {
494         c->setLocale(QLocale::c());
495         Validator v({new ValidatorFileSize(QStringLiteral("field"))});
496         const ValidatorResult r = v.validate(c);
497         if (r) {
498             QString sizeString;
499             const QVariant rv = r.value(QStringLiteral("field"));
500             if (rv.type() == QVariant::Double) {
501                 sizeString = QString::number(rv.toDouble(), 'f', 2);
502             } else {
503                 sizeString = QString::number(rv.toULongLong());
504             }
505             c->response()->setBody(sizeString.toUtf8());
506         } else {
507             c->response()->setBody(r.errorStrings().constFirst());
508         }
509     }
510 
511     // ***** Endpoint for ValidatorFilled ******
512     C_ATTR(filled, :Local :AutoArgs)
filled(Context * c)513     void filled(Context *c) {
514         Validator v({new ValidatorFilled(QStringLiteral("field"), m_validatorMessages)});
515         checkResponse(c, v.validate(c));
516     }
517 
518     // ***** Endpoint for ValidatorIn ******
519     C_ATTR(in, :Local :AutoArgs)
in(Context * c)520     void in(Context *c) {
521         Validator v({new ValidatorIn(QStringLiteral("field"), QStringList({QStringLiteral("eins"), QStringLiteral("zwei"), QStringLiteral("drei")}), Qt::CaseSensitive, m_validatorMessages)});
522         checkResponse(c, v.validate(c));
523     }
524 
525     // ***** Endpoint for ValidatorInteger ******
526     C_ATTR(integer, :Local :AutoArgs)
integer(Context * c)527     void integer(Context *c) {
528         Validator v({new ValidatorInteger(QStringLiteral("field"), QMetaType::Int, m_validatorMessages)});
529         checkResponse(c, v.validate(c));
530     }
531 
532     // ***** Endpoint for ValidatorIp ******
533     C_ATTR(ip, :Local :AutoArgs)
ip(Context * c)534     void ip(Context *c) {
535         ValidatorIp::Constraints constraints = ValidatorIp::NoConstraint;
536         if (!c->request()->bodyParameter(QStringLiteral("constraints")).isEmpty()) {
537             QStringList cons = c->request()->bodyParameter(QStringLiteral("constraints")).split(QStringLiteral(","));
538             if (cons.contains(QStringLiteral("IPv4Only"))) {
539                 constraints |= ValidatorIp::IPv4Only;
540             }
541 
542             if (cons.contains(QStringLiteral("IPv6Only"))) {
543                 constraints |= ValidatorIp::IPv6Only;
544             }
545 
546             if (cons.contains(QStringLiteral("NoPrivateRange"))) {
547                 constraints |= ValidatorIp::NoPrivateRange;
548             }
549 
550             if (cons.contains(QStringLiteral("NoReservedRange"))) {
551                 constraints |= ValidatorIp::NoReservedRange;
552             }
553 
554             if (cons.contains(QStringLiteral("NoMultiCast"))) {
555                 constraints |= ValidatorIp::NoMultiCast;
556             }
557         }
558         Validator v({new ValidatorIp(QStringLiteral("field"), constraints, m_validatorMessages)});
559         checkResponse(c, v.validate(c));
560     }
561 
562 
563     // ***** Endpoint for ValidatorJson ******
564     C_ATTR(json, :Local :AutoArgs)
json(Context * c)565     void json(Context *c) {
566         Validator v({new ValidatorJson(QStringLiteral("field"), m_validatorMessages)});
567         checkResponse(c, v.validate(c));
568     }
569 
570 
571     // ***** Endpoint for ValidatorMax ******
572     C_ATTR(max, :Local :AutoArgs)
max(Context * c)573     void max(Context *c) {
574         QMetaType::Type type = QMetaType::UnknownType;
575 
576         if (!c->request()->bodyParameter(QStringLiteral("type")).isEmpty()) {
577             const QString t = c->request()->bodyParameter(QStringLiteral("type"));
578             if (t == QLatin1String("sint")) {
579                 type = QMetaType::Int;
580             } else if (t == QLatin1String("uint")) {
581                 type = QMetaType::UInt;
582             } else if (t == QLatin1String("float")) {
583                 type = QMetaType::Float;
584             } else if (t == QLatin1String("string")) {
585                 type = QMetaType::QString;
586             }
587         }
588         Validator v({new ValidatorMax(QStringLiteral("field"), type, 10, m_validatorMessages)});
589         checkResponse(c, v.validate(c));
590     }
591 
592     // ***** Endpoint for ValidatorMin ******
593     C_ATTR(min, :Local :AutoArgs)
min(Context * c)594     void min(Context *c) {
595         c->setStash(QStringLiteral("compval"), 10);
596         QMetaType::Type type = QMetaType::UnknownType;
597 
598         if (!c->request()->bodyParameter(QStringLiteral("type")).isEmpty()) {
599             const QString t = c->request()->bodyParameter(QStringLiteral("type"));
600             if (t == QLatin1String("sint")) {
601                 type = QMetaType::Int;
602             } else if (t == QLatin1String("uint")) {
603                 type = QMetaType::UInt;
604             } else if (t == QLatin1String("float")) {
605                 type = QMetaType::Float;
606             } else if (t == QLatin1String("string")) {
607                 type = QMetaType::QString;
608             }
609         }
610         Validator v({new ValidatorMin(QStringLiteral("field"), type, QStringLiteral("compval"), m_validatorMessages)});
611         checkResponse(c, v.validate(c));
612     }
613 
614     // ***** Endpoint for ValidatorNotIn ******
615     C_ATTR(notIn, :Local :AutoArgs)
notIn(Context * c)616     void notIn(Context *c) {
617         Validator v({new ValidatorNotIn(QStringLiteral("field"), QStringList({QStringLiteral("eins"),QStringLiteral("zwei"),QStringLiteral("drei"),QStringLiteral("vier")}), Qt::CaseSensitive, m_validatorMessages)});
618         checkResponse(c, v.validate(c));
619     }
620 
621 
622     // ***** Endpoint for ValidatorNumeric ******
623     C_ATTR(numeric, :Local :AutoArgs)
numeric(Context * c)624     void numeric(Context *c) {
625         Validator v({new ValidatorNumeric(QStringLiteral("field"), m_validatorMessages)});
626         checkResponse(c, v.validate(c));
627     }
628 
629 
630     // ***** Endpoint for ValidatorPresent ******
631     C_ATTR(present, :Local :AutoArgs)
present(Context * c)632     void present(Context *c) {
633         Validator v({new ValidatorPresent(QStringLiteral("field"), m_validatorMessages)});
634         checkResponse(c, v.validate(c));
635     }
636 
637     // ***** Endpoint for ValidatorPwQuality *****
638 #ifdef CUTELYST_VALIDATOR_WITH_PWQUALITY
639     C_ATTR(pwQuality, :Local :AutoArgs)
pwQuality(Context * c)640     void pwQuality(Context *c) {
641         static const QVariantMap options({
642                                              {QStringLiteral("difok"), 1},
643                                              {QStringLiteral("minlen"), 8},
644                                              {QStringLiteral("dcredit"), 0},
645                                              {QStringLiteral("ucredit"), 0},
646                                              {QStringLiteral("ocredit"), 0},
647                                              {QStringLiteral("lcredit"), 0},
648                                              {QStringLiteral("minclass"), 0},
649                                              {QStringLiteral("maxrepeat"), 0},
650                                              {QStringLiteral("maxclassrepeat"), 0},
651                                              {QStringLiteral("maxsequence"), 0},
652                                              {QStringLiteral("gecoscheck"), 0},
653                                              {QStringLiteral("dictcheck"), 1},
654                                              {QStringLiteral("usercheck"), 0}
655                                   });
656         static Validator v({new ValidatorPwQuality(QStringLiteral("field"), 50, options, QString(), QString(), m_validatorMessages)});
657         checkResponse(c, v.validate(c));
658     }
659 #endif
660 
661     // ***** Endpoint for ValidatorRegularExpression ******
662     C_ATTR(regex, :Local :AutoArgs)
regex(Context * c)663     void regex(Context *c) {
664         Validator v({new ValidatorRegularExpression(QStringLiteral("field"), QRegularExpression(QStringLiteral("^(\\d\\d)/(\\d\\d)/(\\d\\d\\d\\d)$")), m_validatorMessages)});
665         checkResponse(c, v.validate(c));
666     }
667 
668     // ***** Endpoint for ValidatorRequired ******
669     C_ATTR(required, :Local :AutoArgs)
required(Context * c)670     void required(Context *c) {
671         Validator v({new ValidatorRequired(QStringLiteral("field"), m_validatorMessages)});
672         checkResponse(c, v.validate(c));
673     }
674 
675     // ***** Endpoint for ValidatorRequiredIf ******
676     C_ATTR(requiredIf, :Local :AutoArgs)
requiredIf(Context * c)677     void requiredIf(Context *c) {
678         Validator v({new ValidatorRequiredIf(QStringLiteral("field"), QStringLiteral("field2"), QStringList({QStringLiteral("eins"), QStringLiteral("zwei")}), m_validatorMessages)});
679         checkResponse(c, v.validate(c));
680     }
681 
682     // ***** Endpoint for ValidatorRequiredIfStash with stash match *****
683     C_ATTR(requiredIfStashMatch, :Local :AutoArgs)
requiredIfStashMatch(Context * c)684     void requiredIfStashMatch(Context *c) {
685         c->setStash(QStringLiteral("stashkey"), QStringLiteral("eins"));
686         Validator v({new ValidatorRequiredIfStash(QStringLiteral("field"), QStringLiteral("stashkey"), QVariantList({QStringLiteral("eins"), QStringLiteral("zwei")}), m_validatorMessages)});
687         checkResponse(c, v.validate(c));
688     }
689 
690     // ***** Endpoint for ValidatorRequiredIfStash with stash not match *****
691     C_ATTR(requiredIfStashNotMatch, :Local :AutoArgs)
requiredIfStashNotMatch(Context * c)692     void requiredIfStashNotMatch(Context *c) {
693         c->setStash(QStringLiteral("stashkey"), QStringLiteral("drei"));
694         Validator v({new ValidatorRequiredIfStash(QStringLiteral("field"), QStringLiteral("stashkey"), QVariantList({QStringLiteral("eins"), QStringLiteral("zwei")}), m_validatorMessages)});
695         checkResponse(c, v.validate(c));
696     }
697 
698     // ***** Endpoint for ValidatorRequiredUnless ******
699     C_ATTR(requiredUnless, :Local :AutoArgs)
requiredUnless(Context * c)700     void requiredUnless(Context *c) {
701         Validator v({new ValidatorRequiredUnless(QStringLiteral("field"), QStringLiteral("field2"), QStringList({QStringLiteral("eins"), QStringLiteral("zwei")}), m_validatorMessages)});
702         checkResponse(c, v.validate(c));
703     }
704 
705     // ***** Endpoint for ValidatorRequiredUnlessStash with stash match *****
706     C_ATTR(requiredUnlessStashMatch, :Local :AutoArgs)
requiredUnlessStashMatch(Context * c)707     void requiredUnlessStashMatch(Context *c) {
708         c->setStash(QStringLiteral("stashkey"), QStringLiteral("eins"));
709         Validator v({new ValidatorRequiredUnlessStash(QStringLiteral("field"), QStringLiteral("stashkey"), QVariantList({QStringLiteral("eins"), QStringLiteral("zwei")}), m_validatorMessages)});
710         checkResponse(c, v.validate(c));
711     }
712 
713     // ***** Endpoint for ValidatorRequiredUnlessStash with stash not match *****
714     C_ATTR(requiredUnlessStashNotMatch, :Local :AutoArgs)
requiredUnlessStashNotMatch(Context * c)715     void requiredUnlessStashNotMatch(Context *c) {
716         c->setStash(QStringLiteral("stashkey"), QStringLiteral("drei"));
717         Validator v({new ValidatorRequiredUnlessStash(QStringLiteral("field"), QStringLiteral("stashkey"), QVariantList({QStringLiteral("eins"), QStringLiteral("zwei")}), m_validatorMessages)});
718         checkResponse(c, v.validate(c));
719     }
720 
721     // ***** Endpoint for ValidatorRequiredWith ******
722     C_ATTR(requiredWith, :Local :AutoArgs)
requiredWith(Context * c)723     void requiredWith(Context *c) {
724         Validator v({new ValidatorRequiredWith(QStringLiteral("field"), QStringList({QStringLiteral("field2"), QStringLiteral("field3")}), m_validatorMessages)});
725         checkResponse(c, v.validate(c));
726     }
727 
728     // ***** Endpoint for ValidatorRequiredWithAll ******
729     C_ATTR(requiredWithAll, :Local :AutoArgs)
requiredWithAll(Context * c)730     void requiredWithAll(Context *c) {
731         Validator v({new ValidatorRequiredWithAll(QStringLiteral("field"), QStringList({QStringLiteral("field2"), QStringLiteral("field3"), QStringLiteral("field4")}), m_validatorMessages)});
732         checkResponse(c, v.validate(c));
733     }
734 
735     // ***** Endpoint for ValidatorRequiredWithout ******
736     C_ATTR(requiredWithout, :Local :AutoArgs)
requiredWithout(Context * c)737     void requiredWithout(Context *c) {
738         Validator v({new ValidatorRequiredWithout(QStringLiteral("field"), QStringList({QStringLiteral("field2"), QStringLiteral("field3")}), m_validatorMessages)});
739         checkResponse(c, v.validate(c));
740     }
741 
742     // ***** Endpoint for ValidatorRequiredWithoutAll ******
743     C_ATTR(requiredWithoutAll, :Local :AutoArgs)
requiredWithoutAll(Context * c)744     void requiredWithoutAll(Context *c) {
745         Validator v({new ValidatorRequiredWithoutAll(QStringLiteral("field"), QStringList({QStringLiteral("field2"), QStringLiteral("field3")}), m_validatorMessages)});
746         checkResponse(c, v.validate(c));
747     }
748 
749     // ***** Endpoint for ValidatorSame ******
750     C_ATTR(same, :Local :AutoArgs)
same(Context * c)751     void same(Context *c) {
752         Validator v({new ValidatorSame(QStringLiteral("field"), QStringLiteral("other"), nullptr, m_validatorMessages)});
753         checkResponse(c, v.validate(c));
754     }
755 
756     // ***** Endpoint for ValidatorSize ******
757     C_ATTR(size, :Local :AutoArgs)
size(Context * c)758     void size(Context *c) {
759         QMetaType::Type type = QMetaType::UnknownType;
760 
761         if (!c->request()->bodyParameter(QStringLiteral("type")).isEmpty()) {
762             const QString t = c->request()->bodyParameter(QStringLiteral("type"));
763             if (t == QLatin1String("sint")) {
764                 type = QMetaType::Int;
765             } else if (t == QLatin1String("uint")) {
766                 type = QMetaType::UInt;
767             } else if (t == QLatin1String("float")) {
768                 type = QMetaType::Float;
769             } else if (t == QLatin1String("string")) {
770                 type = QMetaType::QString;
771             }
772         }
773         Validator v({new ValidatorSize(QStringLiteral("field"), type, 10, m_validatorMessages)});
774         checkResponse(c, v.validate(c));
775     }
776 
777     // ***** Endpoint for ValidatorTime
778     C_ATTR(time, :Local :AutoArgs)
time(Context * c)779     void time(Context *c) {
780         Validator v({new ValidatorTime(QStringLiteral("field"), nullptr, m_validatorMessages)});
781         checkResponse(c, v.validate(c));
782     }
783 
784     // ***** Endpoint for ValidatorTime with custom format ******
785     C_ATTR(timeFormat, :Local :AutoArgs)
timeFormat(Context * c)786     void timeFormat(Context *c) {
787         Validator v({new ValidatorTime(QStringLiteral("field"), "m:hh", m_validatorMessages)});
788         checkResponse(c, v.validate(c));
789     }
790 
791     // ***** Endpoint for ValidatorUrl
792     C_ATTR(url, :Local :AutoArgs)
url(Context * c)793     void url(Context *c) {
794         ValidatorUrl::Constraints constraints = ValidatorUrl::NoConstraint;
795         QStringList schemes;
796         QString scheme = c->request()->bodyParameter(QStringLiteral("schemes"));
797         if (!scheme.isEmpty()) {
798             schemes = scheme.split(QStringLiteral(","));
799         }
800 
801         if (!c->request()->bodyParameter(QStringLiteral("constraints")).isEmpty()) {
802             const QStringList cons = c->request()->bodyParameter(QStringLiteral("constraints")).split(QStringLiteral(","));
803             if (cons.contains(QStringLiteral("StrictParsing"))) {
804                 constraints |= ValidatorUrl::StrictParsing;
805             }
806 
807             if (cons.contains(QStringLiteral("NoRelative"))) {
808                 constraints |= ValidatorUrl::NoRelative;
809             }
810 
811             if (cons.contains(QStringLiteral("NoLocalFile"))) {
812                 constraints |= ValidatorUrl::NoLocalFile;
813             }
814 
815             if (cons.contains(QStringLiteral("WebsiteOnly"))) {
816                 constraints |= ValidatorUrl::WebsiteOnly;
817             }
818         }
819 
820         Validator v({new ValidatorUrl(QStringLiteral("field"), constraints, schemes, m_validatorMessages)});
821         checkResponse(c, v.validate(c));
822     }
823 
824 private:
825     ValidatorMessages m_validatorMessages = ValidatorMessages(nullptr, "invalid", "parsingerror", "validationdataerror");
826 
checkResponse(Context * c,const ValidatorResult & r)827     void checkResponse(Context *c, const ValidatorResult &r) {
828         if (r) {
829             c->response()->setBody(QByteArrayLiteral("valid"));
830         } else {
831             c->response()->setBody(r.errorStrings().constFirst());
832         }
833     }
834 };
835 
836 
initTestCase()837 void TestValidator::initTestCase()
838 {
839     m_engine = getEngine();
840     QVERIFY(m_engine);
841 }
842 
843 
getEngine()844 TestEngine* TestValidator::getEngine()
845 {
846     qputenv("RECURSION", QByteArrayLiteral("100"));
847     auto app = new TestApplication;
848     auto engine = new TestEngine(app, QVariantMap());
849     new ValidatorTest(app);
850     if (!engine->init()) {
851         return nullptr;
852     }
853     return engine;
854 }
855 
856 
cleanupTestCase()857 void TestValidator::cleanupTestCase()
858 {
859     delete m_engine;
860 }
861 
862 
doTest()863 void TestValidator::doTest()
864 {
865     QFETCH(QString, url);
866     QFETCH(Headers, headers);
867     QFETCH(QByteArray, body);
868     QFETCH(QByteArray, output);
869 
870     QUrl urlAux(QLatin1String("validator/test") + url);
871 
872     QVariantMap result = m_engine->createRequest(QStringLiteral("POST"),
873                                                  urlAux.path(),
874                                                  urlAux.query(QUrl::FullyEncoded).toLatin1(),
875                                                  headers,
876                                                  &body);
877 
878     QCOMPARE(result.value(QStringLiteral("body")).toByteArray(), output);
879 }
880 
881 
testController_data()882 void TestValidator::testController_data()
883 {
884     QTest::addColumn<QString>("url");
885     QTest::addColumn<Headers>("headers");
886     QTest::addColumn<QByteArray>("body");
887     QTest::addColumn<QByteArray>("output");
888 
889     const QByteArray valid = QByteArrayLiteral("valid");
890     const QByteArray invalid = QByteArrayLiteral("invalid");
891     const QByteArray parsingError = QByteArrayLiteral("parsingerror");
892     const QByteArray validationDataError = QByteArrayLiteral("validationdataerror");
893 
894     Headers headers;
895     headers.setContentType(QStringLiteral("application/x-www-form-urlencoded"));
896     QUrlQuery query;
897 
898     const QList<Qt::DateFormat> dateFormats({Qt::ISODate, Qt::RFC2822Date, Qt::TextDate});
899 
900     // **** Start testing if the correct paramters are extracted according to the validator flags
901 
902     QTest::newRow("body-params-only-valid") << QStringLiteral("/bodyParamsOnly") << headers << QByteArrayLiteral("req_field=hallo") << valid;
903 
904     QTest::newRow("body-params-only-invalid") << QStringLiteral("/bodyParamsOnly?req_field=hallo") << headers << QByteArray() << invalid;
905 
906     QTest::newRow("query-params-only-valid") << QStringLiteral("/queryParamsOnly?req_field=hallo") << headers << QByteArray() << valid;
907 
908     QTest::newRow("query-params-only-invalid") << QStringLiteral("/queryParamsOnly") << headers << QByteArrayLiteral("req_field=hallo") << invalid;
909 
910     // **** Start testing ValidatorAccepted *****
911 
912     int count = 0;
913     for (const QString &val : {QStringLiteral("yes"), QStringLiteral("on"), QStringLiteral("1"), QStringLiteral("true")}) {
914         QTest::newRow(QString(QStringLiteral("accepted-valid0%1").arg(count)).toUtf8().constData())
915                 << QStringLiteral("/accepted?accepted_field=") + val << headers << QByteArray() << valid;
916         count++;
917     }
918 
919     QTest::newRow("accepted-invalid") << QStringLiteral("/accepted?accepted_field=asdf") << headers << QByteArray() << invalid;
920 
921     QTest::newRow("accepted-empty") << QStringLiteral("/accepted?accepted_field=") << headers << QByteArray() << invalid;
922 
923     QTest::newRow("accepted-missing") << QStringLiteral("/accepted") << headers << QByteArray() << invalid;
924 
925 
926     // **** Start testing ValidatorAfter *****
927 
928     count = 0;
929     for (Qt::DateFormat df : dateFormats) {
930         query.clear();
931         query.addQueryItem(QStringLiteral("after_field"), QDate::currentDate().addDays(2).toString(df));
932         QTest::newRow(QString(QStringLiteral("after-date-valid0%1").arg(count)).toUtf8().constData())
933                 << QStringLiteral("/afterDate?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << valid;
934 
935 
936         query.clear();
937         query.addQueryItem(QStringLiteral("after_field"), QDate(1999, 9, 9).toString(df));
938         QTest::newRow(QString(QStringLiteral("after-date-invalid0%1").arg(count)).toUtf8().constData())
939                 << QStringLiteral("/afterDate?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << invalid;
940 
941         count++;
942     }
943 
944     QTest::newRow("after-date-parsingerror") << QStringLiteral("/afterDate?after_field=lökjasdfjh") << headers << QByteArray() << parsingError;
945 
946     count = 0;
947     for (Qt::DateFormat df : dateFormats) {
948         query.clear();
949         query.addQueryItem(QStringLiteral("after_field"), QTime(13, 0).toString(df));
950         QTest::newRow(QString(QStringLiteral("after-time-valid0%1").arg(count)).toUtf8().constData())
951                 << QStringLiteral("/afterTime?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << valid;
952 
953 
954         query.clear();
955         query.addQueryItem(QStringLiteral("after_field"), QTime(11, 0).toString(df));
956         QTest::newRow(QString(QStringLiteral("after-time-invalid0%1").arg(count)).toUtf8().constData())
957                 << QStringLiteral("/afterTime?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << invalid;
958 
959         count++;
960     }
961 
962     QTest::newRow("after-time-parsingerror") << QStringLiteral("/afterTime?after_field=kjnagiuh") << headers << QByteArray() << parsingError;
963 
964 
965     count = 0;
966     for (Qt::DateFormat df : dateFormats) {
967         query.clear();
968         query.addQueryItem(QStringLiteral("after_field"), QDateTime::currentDateTime().addDays(2).toString(df));
969         QTest::newRow(QString(QStringLiteral("after-datetime-valid0%1").arg(count)).toUtf8().constData())
970                 << QStringLiteral("/afterDateTime?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << valid;
971 
972 
973         query.clear();
974         query.addQueryItem(QStringLiteral("after_field"), QDateTime(QDate(1999, 9, 9), QTime(19, 19)).toString(df));
975         QTest::newRow(QString(QStringLiteral("after-datetime-invalid0%1").arg(count)).toUtf8().constData())
976                 << QStringLiteral("/afterDateTime?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << invalid;
977 
978         count++;
979     }
980 
981     QTest::newRow("after-datetime-parsingerror")
982             << QStringLiteral("/afterDateTime?after_field=aio,aü")
983             << headers << QByteArray() << parsingError;
984 
985     QTest::newRow("after-invalidvalidationdata00")
986             << QStringLiteral("/afterInvalidValidationData?after_field=") + QDate::currentDate().addDays(2).toString(Qt::ISODate)
987             << headers << QByteArray() << validationDataError;
988 
989     QTest::newRow("after-invalidvalidationdata01")
990             << QStringLiteral("/afterInvalidValidationData2?after_field=") + QDate::currentDate().addDays(2).toString(Qt::ISODate)
991             << headers << QByteArray() << validationDataError;
992 
993     QTest::newRow("after-format-valid")
994             << QStringLiteral("/afterFormat?after_field=") + QDateTime::currentDateTime().addDays(2).toString(QStringLiteral("yyyy d MM HH:mm"))
995             << headers << QByteArray() << valid;
996 
997     QTest::newRow("after-format-invalid")
998             << QStringLiteral("/afterFormat?after_field=") + QDateTime(QDate(1999, 9, 9), QTime(19, 19)).toString(QStringLiteral("yyyy d MM HH:mm"))
999             << headers << QByteArray() << invalid;
1000 
1001     QTest::newRow("after-format-parsingerror")
1002             << QStringLiteral("/afterFormat?after_field=23590uj09")
1003             << headers << QByteArray() << parsingError;
1004 
1005     QTest::newRow("after-timezone-valid")
1006             << QStringLiteral("/afterValidWithTimeZone?after_field=") + QDateTime(QDate(2018, 1, 15), QTime(13,0)).toString(Qt::ISODate)
1007             << headers << QByteArray() << valid;
1008 
1009     QTest::newRow("after-timezone-fromfield-valid")
1010             << QStringLiteral("/afterValidWithTimeZoneField?after_field=") + QDateTime(QDate(2018, 1, 15), QTime(13,0)).toString(Qt::ISODate) + QLatin1String("&tz_field=Europe/Berlin")
1011             << headers << QByteArray() << valid;
1012 
1013     // **** Start testing ValidatorAlpha *****
1014 
1015     QTest::newRow("alpha-valid") << QStringLiteral("/alpha?alpha_field=adsfä") << headers << QByteArray() << valid;
1016 
1017     QTest::newRow("alpha-invalid") << QStringLiteral("/alpha?alpha_field=ad_sf 2ä!") << headers << QByteArray() << invalid;
1018 
1019     QTest::newRow("alpha-empty") << QStringLiteral("/alpha?alpha_field=") << headers << QByteArray() << valid;
1020 
1021     QTest::newRow("alpha-missing") << QStringLiteral("/alpha") << headers << QByteArray() << valid;
1022 
1023     QTest::newRow("alpha-ascii-valid") << QStringLiteral("/alphaAscii?alpha_field=basdf") << headers << QByteArray() << valid;
1024 
1025     QTest::newRow("alpha-ascii-invalid") << QStringLiteral("/alphaAscii?alpha_field=asdfös") << headers << QByteArray() << invalid;
1026 
1027 
1028 
1029     // **** Start testing ValidatorAlphaDash *****
1030 
1031     QTest::newRow("alphadash-valid") << QStringLiteral("/alphaDash?alphadash_field=ads2-fä_3") << headers << QByteArray() << valid;
1032 
1033     QTest::newRow("alphadash-invalid") << QStringLiteral("/alphaDash?alphadash_field=ad sf_2ä!") << headers << QByteArray() << invalid;
1034 
1035     QTest::newRow("alphadash-empty") << QStringLiteral("/alphaDash?alphadash_field=") << headers << QByteArray() << valid;
1036 
1037     QTest::newRow("alphadash-missing") << QStringLiteral("/alphaDash") << headers << QByteArray() << valid;
1038 
1039     QTest::newRow("alphadash-ascii-valid") << QStringLiteral("/alphaDashAscii?alphadash_field=s342-4d_3") << headers << QByteArray() << valid;
1040 
1041     QTest::newRow("alphadash-ascii-invalid") << QStringLiteral("/alphaDashAscii?alphadash_field=s342 4ä_3") << headers << QByteArray() << invalid;
1042 
1043 
1044 
1045     // **** Start testing ValidatorAlphaNum *****
1046 
1047     QTest::newRow("alphanum-valid") << QStringLiteral("/alphaNum?alphanum_field=ads2fä3") << headers << QByteArray() << valid;
1048 
1049     QTest::newRow("alphanum-invalid") << QStringLiteral("/alphaNum?alphanum_field=ad sf_2ä!") << headers << QByteArray() << invalid;
1050 
1051     QTest::newRow("alphanum-empty") << QStringLiteral("/alphaNum?alphanum_field=") << headers << QByteArray() << valid;
1052 
1053     QTest::newRow("alphanum-missing") << QStringLiteral("/alphaNum") << headers << QByteArray() << valid;
1054 
1055     QTest::newRow("alphanum-ascii-valid") << QStringLiteral("/alphaNumAscii?alphanum_field=ba34sdf") << headers << QByteArray() << valid;
1056 
1057     QTest::newRow("alphanum-ascii-invalid") << QStringLiteral("/alphaNumAscii?alphanum_field=as3dfös") << headers << QByteArray() << invalid;
1058 
1059 
1060 
1061 
1062     // **** Start testing ValidatorBefore *****
1063 
1064     count = 0;
1065     for (Qt::DateFormat df : dateFormats) {
1066         query.clear();
1067         query.addQueryItem(QStringLiteral("before_field"), QDate(1999, 9, 9).toString(df));
1068         QTest::newRow(QString(QStringLiteral("before-date-valid0%1").arg(count)).toUtf8().constData())
1069                 << QStringLiteral("/beforeDate?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << valid;
1070 
1071 
1072         query.clear();
1073         query.addQueryItem(QStringLiteral("before_field"), QDate::currentDate().addDays(2).toString(df));
1074         QTest::newRow(QString(QStringLiteral("before-date-invalid0%1").arg(count)).toUtf8().constData())
1075                 << QStringLiteral("/beforeDate?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << invalid;
1076 
1077         count++;
1078     }
1079 
1080     QTest::newRow("before-date-parsingerror") << QStringLiteral("/beforeDate?before_field=lökjasdfjh") << headers << QByteArray() << parsingError;
1081 
1082     count = 0;
1083     for (Qt::DateFormat df : dateFormats) {
1084         query.clear();
1085         query.addQueryItem(QStringLiteral("before_field"), QTime(11, 0).toString(df));
1086         QTest::newRow(QString(QStringLiteral("before-time-valid0%1").arg(count)).toUtf8().constData())
1087                 << QStringLiteral("/beforeTime?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << valid;
1088 
1089 
1090         query.clear();
1091         query.addQueryItem(QStringLiteral("before_field"), QTime(13, 0).toString(df));
1092         QTest::newRow(QString(QStringLiteral("before-time-invalid0%1").arg(count)).toUtf8().constData())
1093                 << QStringLiteral("/beforeTime?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << invalid;
1094 
1095         count++;
1096     }
1097 
1098     QTest::newRow("before-time-parsingerror") << QStringLiteral("/beforeTime?before_field=kjnagiuh") << headers << QByteArray() << parsingError;
1099 
1100 
1101     count = 0;
1102     for (Qt::DateFormat df : dateFormats) {
1103         query.clear();
1104         query.addQueryItem(QStringLiteral("before_field"), QDateTime(QDate(1999, 9, 9), QTime(19, 19)).toString(df));
1105         QTest::newRow(QString(QStringLiteral("before-datetime-valid0%1").arg(count)).toUtf8().constData())
1106                 << QStringLiteral("/beforeDateTime?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << valid;
1107 
1108 
1109         query.clear();
1110         query.addQueryItem(QStringLiteral("before_field"), QDateTime::currentDateTime().addDays(2).toString(df));
1111         QTest::newRow(QString(QStringLiteral("before-datetime-invalid0%1").arg(count)).toUtf8().constData())
1112                 << QStringLiteral("/beforeDateTime?") + query.toString(QUrl::FullyEncoded) << headers << QByteArray() << invalid;
1113 
1114         count++;
1115     }
1116 
1117     QTest::newRow("before-datetime-parsingerror")
1118             << QStringLiteral("/beforeDateTime?before_field=aio,aü")
1119             << headers << QByteArray() << parsingError;
1120 
1121 
1122     QTest::newRow("before-invalidvalidationdata00")
1123             << QStringLiteral("/beforeInvalidValidationData?before_field=") + QDate(1999, 9, 9).toString(Qt::ISODate)
1124             << headers << QByteArray() << validationDataError;
1125 
1126     QTest::newRow("before-invalidvalidationdata01")
1127             << QStringLiteral("/beforeInvalidValidationData2?before_field=") + QDate(1999, 9, 9).toString(Qt::ISODate)
1128             << headers << QByteArray() << validationDataError;
1129 
1130     QTest::newRow("before-format-valid")
1131             << QStringLiteral("/beforeFormat?before_field=") + QDateTime(QDate(1999, 9, 9), QTime(19, 19)).toString(QStringLiteral("yyyy d MM HH:mm"))
1132             << headers << QByteArray() << valid;
1133 
1134     QTest::newRow("before-format-invalid")
1135             << QStringLiteral("/beforeFormat?before_field=") + QDateTime::currentDateTime().addDays(2).toString(QStringLiteral("yyyy d MM HH:mm"))
1136             << headers << QByteArray() << invalid;
1137 
1138     QTest::newRow("before-format-parsingerror")
1139             << QStringLiteral("/beforeFormat?before_field=23590uj09")
1140             << headers << QByteArray() << parsingError;
1141 
1142     QTest::newRow("before-timezone-valid")
1143             << QStringLiteral("/beforeValidWithTimeZone?after_field=") + QDateTime(QDate(2018, 1, 15), QTime(11,0)).toString(Qt::ISODate)
1144             << headers << QByteArray() << valid;
1145 
1146     QTest::newRow("before-timezone-fromfield-valid")
1147             << QStringLiteral("/beforeValidWithTimeZoneField?after_field=") + QDateTime(QDate(2018, 1, 15), QTime(11,0)).toString(Qt::ISODate) + QLatin1String("&tz_field=Europe/Berlin")
1148             << headers << QByteArray() << valid;
1149 
1150 
1151 
1152 
1153     // **** Start testing ValidatorBetween *****
1154 
1155     QTest::newRow("between-int-valid") << QStringLiteral("/betweenInt?between_field=0") << headers << QByteArray() << valid;
1156 
1157     QTest::newRow("between-int-invalid-lower") << QStringLiteral("/betweenInt?between_field=-15") << headers << QByteArray() << invalid;
1158 
1159     QTest::newRow("between-int-invalid-greater") << QStringLiteral("/betweenInt?between_field=15") << headers << QByteArray() << invalid;
1160 
1161     QTest::newRow("between-int-empty") << QStringLiteral("/betweenInt?between_field=") << headers << QByteArray() << valid;
1162 
1163     QTest::newRow("between-uint-valid") << QStringLiteral("/betweenUint?between_field=15") << headers << QByteArray() << valid;
1164 
1165     QTest::newRow("between-uint-invalid-lower") << QStringLiteral("/betweenUint?between_field=5") << headers << QByteArray() << invalid;
1166 
1167     QTest::newRow("between-uint-invalid-greater") << QStringLiteral("/betweenUint?between_field=25") << headers << QByteArray() << invalid;
1168 
1169     QTest::newRow("between-uint-empty") << QStringLiteral("/betweenUint?between_field=") << headers << QByteArray() << valid;
1170 
1171     QTest::newRow("between-float-valid") << QStringLiteral("/betweenFloat?between_field=0.0") << headers << QByteArray() << valid;
1172 
1173     QTest::newRow("between-float-invalid-lower") << QStringLiteral("/betweenFloat?between_field=-15.2") << headers << QByteArray() << invalid;
1174 
1175     QTest::newRow("between-float-invalid-greater") << QStringLiteral("/betweenFloat?between_field=15.2") << headers << QByteArray() << invalid;
1176 
1177     QTest::newRow("between-float-empty") << QStringLiteral("/betweenFloat?between_field=") << headers << QByteArray() << valid;
1178 
1179     QTest::newRow("between-string-valid") << QStringLiteral("/betweenString?between_field=abcdefg") << headers << QByteArray() << valid;
1180 
1181     QTest::newRow("between-string-invalid-lower") << QStringLiteral("/betweenString?between_field=abc") << headers << QByteArray() << invalid;
1182 
1183     QTest::newRow("between-string-invalid-greater") << QStringLiteral("/betweenString?between_field=abcdefghijklmn") << headers << QByteArray() << invalid;
1184 
1185     QTest::newRow("between-string-empty") << QStringLiteral("/betweenString?between_field=") << headers << QByteArray() << valid;
1186 
1187 
1188 
1189     // **** Start testing ValidatorBoolean *****
1190 
1191     for (const QString &bv : {QStringLiteral("1"), QStringLiteral("0"), QStringLiteral("true"), QStringLiteral("false"), QStringLiteral("on"), QStringLiteral("off")}) {
1192         QTest::newRow(QString(QStringLiteral("boolean-valid-%1").arg(bv)).toUtf8().constData())
1193                 << QStringLiteral("/boolean?boolean_field=") + bv << headers << QByteArray() << valid;
1194     }
1195 
1196     for (const QString &bv : {QStringLiteral("2"), QStringLiteral("-45"), QStringLiteral("wahr"), QStringLiteral("unwahr"), QStringLiteral("ja")}) {
1197         QTest::newRow(QString(QStringLiteral("boolean-invalid-%1").arg(bv)).toUtf8().constData())
1198                 << QStringLiteral("/boolean?boolean_field=") + bv << headers << QByteArray() << invalid;
1199     }
1200 
1201     QTest::newRow("boolean-empty") << QStringLiteral("/boolean?boolean_field=") << headers << QByteArray() << valid;
1202 
1203 
1204     // **** Start testing ValidatorCharNotAllowed *****
1205 
1206     QTest::newRow("charnotallowed-empty") << QStringLiteral("/charNotAllowed?char_not_allowed_field=") << headers << QByteArray() << valid;
1207 
1208     QTest::newRow("charnotallowed-valid") << QStringLiteral("/charNotAllowed?char_not_allowed_field=holladiewaldfee") << headers << QByteArray() << valid;
1209 
1210     QTest::newRow("charnotallowed-invalid") << QStringLiteral("/charNotAllowed?char_not_allowed_field=holla.die.waldfee") << headers << QByteArray() << invalid;
1211 
1212 
1213 
1214     // **** Start testing ValidatorConfirmed *****
1215 
1216     QTest::newRow("confirmed-valid") << QStringLiteral("/confirmed?pass=abcdefg&pass_confirmation=abcdefg") << headers << QByteArray() << valid;
1217 
1218     QTest::newRow("confirmed-invalid") << QStringLiteral("/confirmed?pass=abcdefg&pass_confirmation=hijklmn") << headers << QByteArray() << invalid;
1219 
1220     QTest::newRow("confirmed-empty") << QStringLiteral("/confirmed?pass&pass_confirmation=abcdefg") << headers << QByteArray() << valid;
1221 
1222     QTest::newRow("confirmed-missing-confirmation") << QStringLiteral("/confirmed?pass=abcdefg") << headers << QByteArray() << invalid;
1223 
1224 
1225 
1226     // **** Start testing ValidatorDate *****
1227 
1228     count = 0;
1229     for (Qt::DateFormat df : dateFormats) {
1230         QTest::newRow(QString(QStringLiteral("date-valid0%1").arg(count)).toUtf8().constData())
1231                 << QStringLiteral("/date?field=") + QDate::currentDate().toString(df) << headers << QByteArray() << valid;
1232         count++;
1233     }
1234 
1235     QTest::newRow("date-invalid") << QStringLiteral("/date?field=123456789") << headers << QByteArray() << invalid;
1236 
1237     QTest::newRow("date-empty") << QStringLiteral("/date?field=") << headers << QByteArray() << valid;
1238 
1239     QTest::newRow("date-format-valid") << QStringLiteral("/dateFormat?field=") + QDate::currentDate().toString(QStringLiteral("yyyy d MM")) << headers << QByteArray() << valid;
1240 
1241     QTest::newRow("date-format-invalid") << QStringLiteral("/dateFormat?field=") + QDate::currentDate().toString(QStringLiteral("MM yyyy d")) << headers << QByteArray() << invalid;
1242 
1243 
1244 
1245 
1246     // **** Start testing ValidatorDateTime *****
1247 
1248     count = 0;
1249     for (Qt::DateFormat df : dateFormats) {
1250         QTest::newRow(QString(QStringLiteral("datetime-valid0%1").arg(count)).toUtf8().constData())
1251                 << QStringLiteral("/dateTime?field=") + QDateTime::currentDateTime().toString(df) << headers << QByteArray() << valid;
1252         count++;
1253     }
1254 
1255     QTest::newRow("datetime-invalid") << QStringLiteral("/dateTime?field=123456789") << headers << QByteArray() << invalid;
1256 
1257     QTest::newRow("datetime-empty") << QStringLiteral("/dateTime?field=") << headers << QByteArray() << valid;
1258 
1259     QTest::newRow("datetime-format-valid") << QStringLiteral("/dateTimeFormat?field=") + QDateTime::currentDateTime().toString(QStringLiteral("yyyy d MM mm:HH")) << headers << QByteArray() << valid;
1260 
1261     QTest::newRow("datetime-format-invalid") << QStringLiteral("/dateTimeFormat?field=") + QDateTime::currentDateTime().toString(QStringLiteral("MM mm yyyy HH d")) << headers << QByteArray() << invalid;
1262 
1263 
1264 
1265 
1266 
1267     // **** Start testing ValidatorDifferent *****
1268 
1269     QTest::newRow("different-valid") << QStringLiteral("/different?field=abcdefg&other=hijklmno") << headers << QByteArray() << valid;
1270 
1271     QTest::newRow("different-invalid") << QStringLiteral("/different?field=abcdefg&other=abcdefg") << headers << QByteArray() << invalid;
1272 
1273     QTest::newRow("different-empty") << QStringLiteral("/different?field=&other=hijklmno") << headers << QByteArray() << valid;
1274 
1275     QTest::newRow("different-other-missing") << QStringLiteral("/different?field=abcdefg") << headers << QByteArray() << valid;
1276 
1277 
1278 
1279 
1280     // **** Start testing ValidatorDigits *****
1281 
1282     QTest::newRow("digits-valid") << QStringLiteral("/digits?field=0123456") << headers << QByteArray() << valid;
1283 
1284     QTest::newRow("digits-invalid") << QStringLiteral("/digits?field=01234asdf56") << headers << QByteArray() << invalid;
1285 
1286     QTest::newRow("digits-empty") << QStringLiteral("/digits?field=") << headers << QByteArray() << valid;
1287 
1288     QTest::newRow("digits-length-valid") << QStringLiteral("/digitsLength?field=0123456789") << headers << QByteArray() << valid;
1289 
1290     QTest::newRow("digits-length-invalid") << QStringLiteral("/digitsLength?field=012345") << headers << QByteArray() << invalid;
1291 
1292 
1293 
1294     // **** Start testing ValidatorDigitsBetween *****
1295 
1296     QTest::newRow("digitsbetween-valid") << QStringLiteral("/digitsBetween?field=0123456") << headers << QByteArray() << valid;
1297 
1298     QTest::newRow("digitsbetween-invalid") << QStringLiteral("/digitsBetween?field=01234ad56") << headers << QByteArray() << invalid;
1299 
1300     QTest::newRow("digitsbetween-empty") << QStringLiteral("/digitsBetween?field=") << headers << QByteArray() << valid;
1301 
1302     QTest::newRow("digitsbetween-invalid-lower") << QStringLiteral("/digitsBetween?field=0123") << headers << QByteArray() << invalid;
1303 
1304     QTest::newRow("digitsbetween-invalid-greater") << QStringLiteral("/digitsBetween?field=0123456789123") << headers << QByteArray() << invalid;
1305 
1306 
1307     // **** Start testing ValidatorDomain *****
1308 
1309     QByteArray domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("huessenbergnetz.de"));
1310     QTest::newRow("domain-valid01") << QStringLiteral("/domain") << headers << domainBody << valid;
1311 
1312     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("a.de"));
1313     QTest::newRow("domain-valid02") << QStringLiteral("/domain") << headers << domainBody << valid;
1314 
1315     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("a1.de"));
1316     QTest::newRow("domain-valid03") << QStringLiteral("/domain") << headers << domainBody << valid;
1317 
1318     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("example.com."));
1319     QTest::newRow("domain-valid04") << QStringLiteral("/domain") << headers << domainBody << valid;
1320 
1321     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("test-1.example.com."));
1322     QTest::newRow("domain-valid05") << QStringLiteral("/domain") << headers << domainBody << valid;
1323 
1324     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com")); // label with max length of 63 chars
1325     QTest::newRow("domain-valid06") << QStringLiteral("/domain") << headers << domainBody << valid;
1326 
1327     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcde.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com")); // total length of 253 chars
1328     QTest::newRow("domain-valid07") << QStringLiteral("/domain") << headers << domainBody << valid;
1329 
1330     // disabled on MSVC because that shit still has problems with utf8 in 2018...
1331 #ifndef _MSC_VER
1332     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("hüssenbergnetz.de"));
1333     QTest::newRow("domain-valid08") << QStringLiteral("/domain") << headers << domainBody << valid;
1334 
1335     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("موقع.وزارة-الاتصالات.مصر"));
1336     QTest::newRow("domain-valid09") << QStringLiteral("/domain") << headers << domainBody << valid;
1337 #endif
1338 
1339     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("example.com1")); // digit in non puny code TLD
1340     QTest::newRow("domain-invalid01") << QStringLiteral("/domain") << headers << domainBody << invalid;
1341 
1342     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("example.c")); // one char tld
1343     QTest::newRow("domain-invalid02") << QStringLiteral("/domain") << headers << domainBody << invalid;
1344 
1345     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("example.3com")); // starts with digit
1346     QTest::newRow("domain-invalid03") << QStringLiteral("/domain") << headers << domainBody << invalid;
1347 
1348     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("example.co3m")); // contains digit
1349     QTest::newRow("domain-invalid04") << QStringLiteral("/domain") << headers << domainBody << invalid;
1350 
1351     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl.com")); // label too long, 64 chars
1352     QTest::newRow("domain-invalid05") << QStringLiteral("/domain") << headers << domainBody << invalid;
1353 
1354     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.com")); // too long, 254 chars
1355     QTest::newRow("domain-invalid06") << QStringLiteral("/domain") << headers << domainBody << invalid;
1356 
1357     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("example.co-m")); // contains dash in tld
1358     QTest::newRow("domain-invalid07") << QStringLiteral("/domain") << headers << domainBody << invalid;
1359 
1360     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("-example.com")); // contains dash at label start
1361     QTest::newRow("domain-invalid08") << QStringLiteral("/domain") << headers << domainBody << invalid;
1362 
1363     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("3example.com")); // contains digit at label start
1364     QTest::newRow("domain-invalid09") << QStringLiteral("/domain") << headers << domainBody << invalid;
1365 
1366     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("example-.com")); // contains dash at label end
1367     QTest::newRow("domain-invalid10") << QStringLiteral("/domain") << headers << domainBody << invalid;
1368 
1369     // disabled on MSVC because that shit still has problems with utf8 in 2018...
1370 #ifndef _MSC_VER
1371     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("موقع.وزارة-الاتصالات.مصر1"));
1372     QTest::newRow("domain-invalid11") << QStringLiteral("/domain") << headers << domainBody << invalid;
1373 
1374     domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("موقع.وزارة-الاتصالات.مصر-"));
1375     QTest::newRow("domain-invalid12") << QStringLiteral("/domain") << headers << domainBody << invalid;
1376 #endif
1377 
1378     if (qEnvironmentVariableIsSet("CUTELYST_VALIDATORS_TEST_NETWORK")) {
1379         domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("example.com"));
1380         QTest::newRow("domain-dns-valid") << QStringLiteral("/domainDns") << headers << domainBody << valid;
1381 
1382         domainBody = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("test.example.com"));
1383         QTest::newRow("domain-dns-invalid") << QStringLiteral("/domainDns") << headers << domainBody << invalid;
1384     }
1385 
1386 
1387     // **** Start testing ValidatorEmail *****
1388 
1389     const QList<QString> validEmails({
1390                                          QStringLiteral("test@huessenbergnetz.de"),
1391                                          // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests.xml
1392                                          QStringLiteral("test@iana.org"),
1393                                          QStringLiteral("test@nominet.org.uk"),
1394                                          QStringLiteral("test@about.museum"),
1395                                          QStringLiteral("a@iana.org"),
1396                                          QStringLiteral("test.test@iana.org"),
1397                                          QStringLiteral("!#$%&`*+/=?^`{|}~@iana.org"),
1398                                          QStringLiteral("123@iana.org"),
1399                                          QStringLiteral("test@123.com"),
1400                                          QStringLiteral("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@iana.org"),
1401                                          QStringLiteral("test@mason-dixon.com"),
1402                                          QStringLiteral("test@c--n.com"),
1403                                          QStringLiteral("test@xn--hxajbheg2az3al.xn--jxalpdlp"),
1404                                          QStringLiteral("xn--test@iana.org"),
1405                                          // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests-original.xml
1406                                          QStringLiteral("first.last@iana.org"),
1407                                          QStringLiteral("1234567890123456789012345678901234567890123456789012345678901234@iana.org"),
1408                                          QStringLiteral("first.last@3com.com"),
1409                                          QStringLiteral("user+mailbox@iana.org"),
1410                                          QStringLiteral("customer/department=shipping@iana.org"),
1411                                          QStringLiteral("$A12345@iana.org"),
1412                                          QStringLiteral("!def!xyz%abc@iana.org"),
1413                                          QStringLiteral("_somename@iana.org"),
1414                                          QStringLiteral("dclo@us.ibm.com"),
1415                                          QStringLiteral("peter.piper@iana.org"),
1416                                          QStringLiteral("TEST@iana.org"),
1417                                          QStringLiteral("1234567890@iana.org"),
1418                                          QStringLiteral("test+test@iana.org"),
1419                                          QStringLiteral("test-test@iana.org"),
1420                                          QStringLiteral("t*est@iana.org"),
1421                                          QStringLiteral("+1~1+@iana.org"),
1422                                          QStringLiteral("{_test_}@iana.org"),
1423                                          QStringLiteral("test.test@iana.org"),
1424                                          QStringLiteral("customer/department@iana.org"),
1425                                          QStringLiteral("Yosemite.Sam@iana.org"),
1426                                          QStringLiteral("~@iana.org"),
1427                                          QStringLiteral("Ima.Fool@iana.org"),
1428                                          QStringLiteral("name.lastname@domain.com"),
1429                                          QStringLiteral("a@bar.com"),
1430                                          QStringLiteral("a-b@bar.com"),
1431                                          QStringLiteral("valid@about.museum"),
1432                                          QStringLiteral("user%uucp!path@berkeley.edu"),
1433                                          QStringLiteral("cdburgess+!#$%&'*-/=?+_{}|~test@gmail.com")
1434                                      });
1435 
1436     const QList<QString> dnsWarnEmails({
1437                                            QStringLiteral("test@example.com"), // no mx record
1438                                            // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests.xml
1439                                            QStringLiteral("test@e.com"), // no record
1440                                            QStringLiteral("test@iana.a"), // no record
1441                                            QStringLiteral("test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.com"), // no record
1442                                            QStringLiteral("test@iana.co-uk"), // no record
1443                                            QStringLiteral("a@a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v"), // no record
1444                                            QStringLiteral("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi"),
1445                                            // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests-original.xml
1446                                            QStringLiteral("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x2"), // no record
1447                                            QStringLiteral("1234567890123456789012345678901234567890123456789012345678901@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.123456789012345678901234567890123456789012345678901234567890123.iana.org"), // no record
1448                                            QStringLiteral("first.last@x23456789012345678901234567890123456789012345678901234567890123.iana.org"), // no record
1449                                            QStringLiteral("first.last@123.iana.org"), // no record
1450                                            QStringLiteral("test@123.123.123.x123"), // no record
1451                                            QStringLiteral("test@example.iana.org"), // no record
1452                                            QStringLiteral("test@example.example.iana.org"), // no record
1453                                            QStringLiteral("+@b.c"), // no record
1454                                            QStringLiteral("+@b.com"), // no record
1455                                            QStringLiteral("a@b.co-foo.uk"), // no record
1456                                            QStringLiteral("shaitan@my-domain.thisisminekthx"), // no record
1457                                            QStringLiteral("test@xn--example.com") // no record
1458                                        });
1459 
1460     const QList<QString> rfc5321Emails({
1461                                            // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests-original.xml
1462                                            QStringLiteral("\"first\\\"last\"@iana.org"), // quoted string
1463                                            QStringLiteral("\"first@last\"@iana.org"), // quoted string
1464                                            QStringLiteral("\"first\\\\last\"@iana.org"), // quoted string
1465                                            QStringLiteral("first.last@[12.34.56.78]"), // address literal
1466                                            QStringLiteral("first.last@[IPv6:::12.34.56.78]"), // address literal
1467                                            QStringLiteral("first.last@[IPv6:1111:2222:3333::4444:12.34.56.78]"), // address literal
1468                                            QStringLiteral("first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.56.78]"), // address literal
1469                                            QStringLiteral("first.last@[IPv6:::1111:2222:3333:4444:5555:6666]"), // address literal
1470                                            QStringLiteral("first.last@[IPv6:1111:2222:3333::4444:5555:6666]"), // address literal
1471                                            QStringLiteral("first.last@[IPv6:1111:2222:3333:4444:5555:6666::]"), // address literal
1472                                            QStringLiteral("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]"), // address literal
1473                                            QStringLiteral("\"first\\last\"@iana.org"), // quoted string
1474                                            QStringLiteral("\"\"@iana.org"), // quoted string
1475                                            QStringLiteral("first.last@[IPv6:1111:2222:3333::4444:5555:12.34.56.78]"), // ipv6 deprecated
1476                                            QStringLiteral("first.last@example.123"), // tld numeric
1477                                            QStringLiteral("first.last@com"), // tld
1478                                            QStringLiteral("\"Abc\\@def\"@iana.org"), // quoted string
1479                                            QStringLiteral("\"Fred\\ Bloggs\"@iana.org"), // quoted string
1480                                            QStringLiteral("\"Joe.\\\\Blow\"@iana.org"), // quoted string
1481                                            QStringLiteral("\"Abc@def\"@iana.org"), // quoted string
1482                                            QStringLiteral("\"Fred Bloggs\"@iana.org"), // quoted string
1483                                            QStringLiteral("\"Doug \\\"Ace\\\" L.\"@iana.org"), // quoted string
1484                                            QStringLiteral("\"[[ test ]]\"@iana.org"), // quoted string
1485                                            QStringLiteral("\"test.test\"@iana.org"), // quoted string
1486                                            QStringLiteral("\"test@test\"@iana.org"), // quoted string
1487                                            QStringLiteral("test@123.123.123.123"), // tld numeric
1488                                            QStringLiteral("test@[123.123.123.123]"), // address literal
1489                                            QStringLiteral("\"test\\test\"@iana.org"), // quoted string
1490                                            QStringLiteral("test@example"), // tld
1491                                            QStringLiteral("\"test\\\\blah\"@iana.org"), //quoted string
1492                                            QStringLiteral("\"test\\blah\"@iana.org"), // quoted string
1493                                            QStringLiteral("\"test\\\"blah\"@iana.org"), // quoted string
1494                                            QStringLiteral("\"Austin@Powers\"@iana.org"), // quoted string
1495                                            QStringLiteral("\"Ima.Fool\"@iana.org"), // quoted string
1496                                            QStringLiteral("\"Ima Fool\"@iana.org"), // quoted string
1497                                            QStringLiteral("\"first.middle.last\"@iana.org"), // quoted string
1498                                            QStringLiteral("\"first..last\"@iana.org"), // quoted string
1499                                            QStringLiteral("\"first\\\\\\\"last\"@iana.org"), // quoted string
1500                                            QStringLiteral("a@b"), // tld
1501                                            QStringLiteral("aaa@[123.123.123.123]"), // address literal
1502                                            QStringLiteral("a@bar"), // tld
1503                                            QStringLiteral("\"hello my name is\"@stutter.com"), // quoted string
1504                                            QStringLiteral("\"Test \\\"Fail\\\" Ing\"@iana.org"), // quoted string
1505                                            QStringLiteral("foobar@192.168.0.1"), // tld numeric
1506                                            QStringLiteral("\"Joe\\\\Blow\"@iana.org"), // quoted string
1507                                            QStringLiteral("\"first(last)\"@iana.org"), // quoted string
1508                                            QStringLiteral("first.last@[IPv6:::a2:a3:a4:b1:b2:b3:b4]"), // ipv6 deprecated
1509                                            QStringLiteral("first.last@[IPv6:a1:a2:a3:a4:b1:b2:b3::]"), // ipv6 deprecated
1510                                            QStringLiteral("first.last@[IPv6:::]"), // address literal
1511                                            QStringLiteral("first.last@[IPv6:::b4]"), // address literal
1512                                            QStringLiteral("first.last@[IPv6:::b3:b4]"), // address literal
1513                                            QStringLiteral("first.last@[IPv6:a1::b4]"), // address literal
1514                                            QStringLiteral("first.last@[IPv6:a1::]"), // address literal
1515                                            QStringLiteral("first.last@[IPv6:a1:a2::]"), // address literal
1516                                            QStringLiteral("first.last@[IPv6:0123:4567:89ab:cdef::]"), // address literal
1517                                            QStringLiteral("first.last@[IPv6:0123:4567:89ab:CDEF::]"), // address literal
1518                                            QStringLiteral("first.last@[IPv6:::a3:a4:b1:ffff:11.22.33.44]"), // address literal
1519                                            QStringLiteral("first.last@[IPv6:::a2:a3:a4:b1:ffff:11.22.33.44]"), // ipv6 deprecated
1520                                            QStringLiteral("first.last@[IPv6:a1:a2:a3:a4::11.22.33.44]"), // address literal
1521                                            QStringLiteral("first.last@[IPv6:a1:a2:a3:a4:b1::11.22.33.44]"), // ipv6 deprecated
1522                                            QStringLiteral("first.last@[IPv6:a1::11.22.33.44]"), // address literal
1523                                            QStringLiteral("first.last@[IPv6:a1:a2::11.22.33.44]"), // address literal
1524                                            QStringLiteral("first.last@[IPv6:0123:4567:89ab:cdef::11.22.33.44]"), // address literal
1525                                            QStringLiteral("first.last@[IPv6:0123:4567:89ab:CDEF::11.22.33.44]"), // address literal
1526                                            QStringLiteral("first.last@[IPv6:a1::b2:11.22.33.44]"), // address literal
1527                                            // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests.xml
1528                                            QStringLiteral("test@iana.123"), // tld numeric
1529                                            QStringLiteral("test@255.255.255.255"), // tld numeric
1530                                            QStringLiteral("\"test\"@iana.org"), // quoted string
1531                                            QStringLiteral("\"\"@iana.org"), // quoted string
1532                                            QStringLiteral("\"\\a\"@iana.org"), // quoted string
1533                                            QStringLiteral("\"\\\"\"@iana.org"), // quoted string
1534                                            QStringLiteral("\"\\\\\"@iana.org"), // quoted string
1535                                            QStringLiteral("\"test\\ test\"@iana.org"), // quoted string
1536                                            QStringLiteral("test@[255.255.255.255]"), // address literal
1537                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]"), // address literal
1538                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666::8888]"), // ipv6 deprecated
1539                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555::8888]"), // address literal
1540                                            QStringLiteral("test@[IPv6:::3333:4444:5555:6666:7777:8888]"), // address literal
1541                                            QStringLiteral("test@[IPv6:::]"), // address literal
1542                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666:255.255.255.255]"), // address literal
1543                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444::255.255.255.255]"), // address literal
1544                                            QStringLiteral("test@org") // tld
1545                                        });
1546 
1547     const QList<QString> cfwsEmails({
1548                                         // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests.xml
1549                                         QStringLiteral("\r\n test@iana.org"), // folding white space
1550                                         QStringLiteral("(comment)test@iana.org"), // comment
1551                                         QStringLiteral("(comment(comment))test@iana.org"), // coment
1552                                         QStringLiteral("(comment)abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@iana.org"), // comment
1553                                         QStringLiteral("(comment)test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghik.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstuvwxyzabcdefghijk.abcdefghijklmnopqrstu"), // comment
1554                                         QStringLiteral(" \r\n test@iana.org"), // folding white space
1555                                         QStringLiteral("test@iana.org\r\n "), // folding white space
1556                                         QStringLiteral("test@iana.org \r\n "), // folding white space
1557                                         QStringLiteral(" test@iana.org"), // folding white space
1558                                         QStringLiteral("test@iana.org "), // folding white space
1559                                         // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests-original.xml
1560                                         QStringLiteral("\"test\r\n blah\"@iana.org"), // folding white space
1561                                         QStringLiteral("first.last@iana(1234567890123456789012345678901234567890123456789012345678901234567890).org") // comment
1562                                     });
1563 
1564     const QList<QString> deprecatedEmails({
1565                                               // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests.xml
1566                                               QStringLiteral("\"test\".\"test\"@iana.org"), // local part
1567                                               QStringLiteral("\"test\".test@iana.org"), // local part
1568 //                                              QStringLiteral("\"test\\\0\"@iana.org"), // quoted pair
1569                                               QStringLiteral(" test @iana.org"), // folding white space near at
1570                                               QStringLiteral("test@ iana .com"), // folding white space near at
1571                                               QStringLiteral("test . test@iana.org"), // folding white space
1572                                               QStringLiteral("\r\n \r\n test@iana.org"), // folding white space
1573                                               QStringLiteral("test@(comment)iana.org"), // comment near at
1574                                               QStringLiteral("test@(comment)[255.255.255.255]"), // comment near at
1575                                               QStringLiteral("test@(comment)abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.com"), // comment near at
1576 //                                              QStringLiteral("\"\"@iana.org"), // quoted string with deprecated char - currently also not working on upstream
1577 //                                              QStringLiteral("\"\\\"@iana.org"), // quoted string with deprecated char
1578 //                                              QStringLiteral("()test@iana.org"), // comment string with deprecated char - currently also not working on upstream
1579                                               QStringLiteral("\"\\\n\"@iana.org"), // quoted pair with deprecated char
1580                                               QStringLiteral("\"\a\"@iana.org"), // quoted string with deprecated char
1581                                               QStringLiteral("\"\\\a\"@iana.org"), // quoted pair with deprecated char
1582                                               QStringLiteral("(\a)test@iana.org"), // comment with deprecated char
1583                                               QStringLiteral("test@iana.org\r\n \r\n "), // obsolete folding white space
1584                                               QStringLiteral("test.(comment)test@iana.org"), // deprecated comment position
1585                                               // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests-original.xml
1586                                               QStringLiteral("test.\"test\"@iana.org"), // local part
1587                                               QStringLiteral("\"test\\\rblah\"@iana.org"), // quoted pair with deprecated char
1588                                               QStringLiteral("\"first\".\"last\"@iana.org"), // local part
1589                                               QStringLiteral("\"first\".middle.\"last\"@iana.org"), // local part
1590                                               QStringLiteral("\"first\".last@iana.org"), // local part
1591                                               QStringLiteral("first.\"last\"@iana.org"), // local part
1592                                               QStringLiteral("\"first\".\"middle\".\"last\"@iana.org"), // local part
1593                                               QStringLiteral("\"first.middle\".\"last\"@iana.org"), // local part
1594                                               QStringLiteral("first.\"mid\\dle\".\"last\"@iana.org"), // local part
1595                                               QStringLiteral("Test.\r\n Folding.\r\n Whitespace@iana.org"), // folding white space
1596                                               QStringLiteral("first.\"\".last@iana.org"), // local part
1597                                               QStringLiteral("(foo)cal(bar)@(baz)iamcal.com(quux)"), // comment near at
1598                                               QStringLiteral("cal@iamcal(woo).(yay)com"), // comment position
1599                                               QStringLiteral("\"foo\"(yay)@(hoopla)[1.2.3.4]"), // comment near at
1600                                               QStringLiteral("cal(woo(yay)hoopla)@iamcal.com"), // comment near at
1601                                               QStringLiteral("cal(foo\\@bar)@iamcal.com"), // comment near at
1602                                               QStringLiteral("cal(foo\\)bar)@iamcal.com"), // comment near at
1603                                               QStringLiteral("first().last@iana.org"), // local part
1604                                               QStringLiteral("first.(\r\n middle\r\n )last@iana.org"), // deprecated comment
1605                                               QStringLiteral("first(Welcome to\r\n the (\"wonderful\" (!)) world\r\n of email)@iana.org"), // comment near at
1606                                               QStringLiteral("pete(his account)@silly.test(his host)"), // comment near at
1607                                               QStringLiteral("c@(Chris's host.)public.example"), // comment near at
1608                                               QStringLiteral("jdoe@machine(comment). example"), // folding white space
1609                                               QStringLiteral("1234 @ local(blah) .machine .example"), // white space near at
1610                                               QStringLiteral("first(abc.def).last@iana.org"), // local part
1611                                               QStringLiteral("first(a\"bc.def).last@iana.org"), // local part
1612                                               QStringLiteral("first.(\")middle.last(\")@iana.org"), // local part
1613                                               QStringLiteral("first(abc\\(def)@iana.org"), // comment near at
1614                                               QStringLiteral("a(a(b(c)d(e(f))g)h(i)j)@iana.org"),
1615                                               QStringLiteral("HM2Kinsists@(that comments are allowed)this.is.ok"), // comment near at
1616                                               QStringLiteral(" \r\n (\r\n x \r\n ) \r\n first\r\n ( \r\n x\r\n ) \r\n .\r\n ( \r\n x) \r\n last \r\n ( x \r\n ) \r\n @iana.org"), // folding white space near at
1617                                               QStringLiteral("first.last @iana.org"), // folding white space near at
1618                                               QStringLiteral("test. \r\n \r\n obs@syntax.com") // folding white space
1619 //                                              QStringLiteral("\"Unicode NULL \\\0\"@char.com") // quoted pair contains deprecated char
1620                                           });
1621 
1622     const QList<QString> rfc5322Emails({
1623                                            // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests.xml
1624                                            QStringLiteral("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklmn@iana.org"), // local too long
1625                                            QStringLiteral("test@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm.com"), // label too long
1626                                            QStringLiteral("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghiklm@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij"), // too long
1627                                            QStringLiteral("a@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg.hij"), // too long
1628                                            QStringLiteral("a@abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghikl.abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefg.hijk"), // too long
1629                                            QStringLiteral("\"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghj\"@iana.org"), // local too long
1630                                            QStringLiteral("\"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefg\\h\"@iana.org"), // local too long
1631                                            QStringLiteral("test@[255.255.255]"), // invalid domain literal
1632                                            QStringLiteral("test@[255.255.255.255.255]"), // invalid domain litearl
1633                                            QStringLiteral("test@[255.255.255.256]"), // invalid domain literal
1634                                            QStringLiteral("test@[1111:2222:3333:4444:5555:6666:7777:8888]"), // invalid domain literal
1635                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666:7777]"), // ipv6 group count
1636                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]"), // ipv6 group count
1637                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666:7777:888G]"), // ipv6 bad char
1638                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666::7777:8888]"), // ipv6 max groups
1639                                            QStringLiteral("test@[IPv6::3333:4444:5555:6666:7777:8888]"), // ipv6 colon start
1640                                            QStringLiteral("test@[IPv6:1111::4444:5555::8888]"), // ipv6 2x2x colon
1641                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:255.255.255.255]"), // ipv6 group count
1642                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666:7777:255.255.255.255]"), // ipv6 group count
1643                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:5555:6666::255.255.255.255]"), // ipv6 max groups
1644                                            QStringLiteral("test@[IPv6:1111:2222:3333:4444:::255.255.255.255]"), // ipv6 2x2x colon
1645                                            QStringLiteral("test@[IPv6::255.255.255.255]"), // ipv6 colon start
1646                                            QStringLiteral("test@[RFC-5322-domain-literal]"), // invalid domain literal
1647                                            QStringLiteral("test@[RFC-5322-\\\a-domain-literal]"), // invalid domain literal containing obsolete chars
1648                                            QStringLiteral("test@[RFC-5322-\\\t-domain-literal]"), // invalid domain literal containing obsolete chars
1649                                            QStringLiteral("test@[RFC-5322-\\]-domain-literal]"), // invalid domain literal containing obsolete chars
1650                                            QStringLiteral("test@[RFC 5322 domain literal]"), // invalid domain literal
1651                                            QStringLiteral("test@[RFC-5322-domain-literal] (comment)"), // invalid domain literal
1652                                            QStringLiteral("test@[IPv6:1::2:]"), // ipv6 colon end
1653                                            QStringLiteral("test@iana/icann.org"), // domain invalid for DNS
1654                                            // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests-original.xml
1655                                            QStringLiteral("123456789012345678901234567890123456789012345678901234567890@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345.iana.org"), // too long
1656                                            QStringLiteral("12345678901234567890123456789012345678901234567890123456789012345@iana.org"), // local too long
1657                                            QStringLiteral("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456"), // domain too long
1658                                            QStringLiteral("first.last@[.12.34.56.78]"), // invalid domain literal
1659                                            QStringLiteral("first.last@[12.34.56.789]"), // invalid domain literal
1660                                            QStringLiteral("first.last@[::12.34.56.78]"), // invalid domain literal
1661                                            QStringLiteral("first.last@[IPv5:::12.34.56.78]"), // invalid domain literal
1662                                            QStringLiteral("first.last@[IPv6:1111:2222:3333:4444:5555:12.34.56.78]"), // ipv6 group count
1663                                            QStringLiteral("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:12.34.56.78]"), // ipv6 group count
1664                                            QStringLiteral("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777]"), // ipv6 group count
1665                                            QStringLiteral("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]"), // ipv6 group count
1666                                            QStringLiteral("first.last@[IPv6:1111:2222::3333::4444:5555:6666]"), // ipv6 2x2x colon
1667                                            QStringLiteral("first.last@[IPv6:1111:2222:333x::4444:5555]"), // ipv6 bad char
1668                                            QStringLiteral("first.last@[IPv6:1111:2222:33333::4444:5555]"), // ipv6 bad char
1669                                            QStringLiteral("first.last@x234567890123456789012345678901234567890123456789012345678901234.iana.org"), // label too long
1670                                            QStringLiteral("test@123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890.com"), // domain too long
1671                                            QStringLiteral("foo@[\\1.2.3.4]"), // invalid domain literal containing obsolete chars
1672                                            QStringLiteral("first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.567.89]"), // ipv6 bad char
1673                                            QStringLiteral("aaa@[123.123.123.333]"), // invalid domain literal
1674                                            QStringLiteral("first.last@[IPv6::]"), // ipv6 colon start
1675                                            QStringLiteral("first.last@[IPv6::::]"), // ipv6 2x2x colon
1676                                            QStringLiteral("first.last@[IPv6::b4]"), // ipv6 colon start
1677                                            QStringLiteral("first.last@[IPv6::::b4]"), // ipv6 2x2x colon
1678                                            QStringLiteral("first.last@[IPv6::b3:b4]"), // ipv6 colon start
1679                                            QStringLiteral("first.last@[IPv6::::b3:b4]"), // ipv6 2x2x colon
1680                                            QStringLiteral("first.last@[IPv6:a1:::b4]"), // ipv6 2x2x colon
1681                                            QStringLiteral("first.last@[IPv6:a1:]"), // ipv6 colon end
1682                                            QStringLiteral("first.last@[IPv6:a1:::]"), // ipv6 2x2x colon
1683                                            QStringLiteral("first.last@[IPv6:a1:a2:]"), // ipv6 colon end
1684                                            QStringLiteral("first.last@[IPv6:a1:a2:::]"), // ipv6 2x2x colon
1685                                            QStringLiteral("first.last@[IPv6::11.22.33.44]"), // ipv6 colon start
1686                                            QStringLiteral("first.last@[IPv6::::11.22.33.44]"), // ipv6 2x2x colon
1687                                            QStringLiteral("first.last@[IPv6:a1:11.22.33.44]"), // ipv6 group count
1688                                            QStringLiteral("first.last@[IPv6:a1:::11.22.33.44]"), // ipv6 2x2x colon
1689                                            QStringLiteral("first.last@[IPv6:a1:a2:::11.22.33.44]"), // ipv6 2x2x colon
1690                                            QStringLiteral("first.last@[IPv6:0123:4567:89ab:cdef::11.22.33.xx]"), // ipv6 bad char
1691                                            QStringLiteral("first.last@[IPv6:0123:4567:89ab:CDEFF::11.22.33.44]"), // ipv6 bad char
1692                                            QStringLiteral("first.last@[IPv6:a1::a4:b1::b4:11.22.33.44]"), // ipv6 2x2x colon
1693                                            QStringLiteral("first.last@[IPv6:a1::11.22.33]"), // ipv6 bad char
1694                                            QStringLiteral("first.last@[IPv6:a1::11.22.33.44.55]"), // ipv6 bad char
1695                                            QStringLiteral("first.last@[IPv6:a1::b211.22.33.44]"), // ipv6 bad char
1696                                            QStringLiteral("first.last@[IPv6:a1::b2::11.22.33.44]"), // ipv6 2x2x colon
1697                                            QStringLiteral("first.last@[IPv6:a1::b3:]"), // ipv6 colon end
1698                                            QStringLiteral("first.last@[IPv6::a2::b4]"), // ipv6 colon start
1699                                            QStringLiteral("first.last@[IPv6:a1:a2:a3:a4:b1:b2:b3:]"), // ipv6 colon end
1700                                            QStringLiteral("first.last@[IPv6::a2:a3:a4:b1:b2:b3:b4]"), // ipv6 colon end
1701                                            QStringLiteral("first.last@[IPv6:a1:a2:a3:a4::b1:b2:b3:b4]") // ipv6 max groups
1702                                        });
1703 
1704     QList<QString> errorEmails({
1705                                    // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests.xml
1706                                    QStringLiteral(" "), // no domain
1707                                    QStringLiteral("test"), // no domain
1708                                    QStringLiteral("@"), // no local part
1709                                    QStringLiteral("test@"), // no domain
1710                                    QStringLiteral("@io"), // no local part
1711                                    QStringLiteral("@iana.org"), // no local part
1712                                    QStringLiteral(".test@iana.org"), // dot start
1713                                    QStringLiteral("test.@iana.org"), // dot end
1714                                    QStringLiteral("test..iana.org"), // consecutive dots
1715                                    QStringLiteral("test_exa-mple.com"), // no domain
1716                                    QStringLiteral("test\\@test@iana.org"), // expecting atext
1717                                    QStringLiteral("test@-iana.org"), // domain hypen start
1718                                    QStringLiteral("test@iana-.com"), // domain hypen end
1719                                    QStringLiteral("test@.iana.org"), // dot start
1720                                    QStringLiteral("test@iana.org."), // dot end
1721                                    QStringLiteral("test@iana..com"), // consecutive dots
1722                                    QStringLiteral("\"\"\"@iana.org"), // expecting atext
1723                                    QStringLiteral("\"\\\"@iana.org"), // unclosed quoted string
1724                                    QStringLiteral("test\"@iana.org"), // expecting atext
1725                                    QStringLiteral("\"test@iana.org"), // unclosed quoted string
1726                                    QStringLiteral("\"test\"test@iana.org"), // atext after quoted string
1727                                    QStringLiteral("test\"text\"@iana.org"), // expecting atext
1728                                    QStringLiteral("\"test\"\"test\"@iana.org"), // expecting atext
1729 //                                   QStringLiteral("\"test\0\"@iana.org"), // expecting qtext
1730                                    QStringLiteral("test@a[255.255.255.255]"), // expecting atext
1731                                    QStringLiteral("((comment)test@iana.org"), // unclosed comment
1732                                    QStringLiteral("test(comment)test@iana.org"), // atext after comment
1733                                    QStringLiteral("test@iana.org\n"), // expecting atext
1734                                    QStringLiteral("test@iana.org-"), // domain hypehn end
1735                                    QStringLiteral("\"test@iana.org"), // unclosed quoted string
1736                                    QStringLiteral("(test@iana.org"), // unclosed comment
1737                                    QStringLiteral("test@(iana.org"), // unclosed comment
1738                                    QStringLiteral("test@[1.2.3.4"), // unclosed domain literal
1739                                    QStringLiteral("\"test\\\"@iana.org"), // unclosed quoted string
1740                                    QStringLiteral("(comment\\)test@iana.org"), // unclosed comment
1741                                    QStringLiteral("test@iana.org(comment\\)"), // unclosed comment
1742                                    QStringLiteral("test@iana.org(comment\\"), // backslash end
1743                                    QStringLiteral("test@[RFC-5322]-domain-literal]"), // atext after domain literal
1744                                    QStringLiteral("test@[RFC-5322-[domain-literal]"), // expecting dtext
1745                                    QStringLiteral("test@[RFC-5322-domain-literal\\]"), // unclosed domain literal
1746                                    QStringLiteral("test@[RFC-5322-domain-literal\\"), // backslash end
1747                                    QStringLiteral("@iana.org"), // expecting atext
1748                                    QStringLiteral("test@.org"), // expecting atext
1749                                    QStringLiteral("test@iana.org\r"), // no lf after cr
1750                                    QStringLiteral("\rtest@iana.org"), // no lf after cr
1751                                    QStringLiteral("\"\rtest\"@iana.org"), // no lf after cr
1752                                    QStringLiteral("(\r)test@iana.org"), // no lf after cr
1753                                    QStringLiteral("test@iana.org(\r)"), // no lf after cr
1754                                    QStringLiteral("\ntest@iana.org"), // expecting atext
1755                                    QStringLiteral("\"\n\"@iana.org"), // expecting qtext
1756                                    QStringLiteral("(\n)test@iana.org"), // expecting ctext
1757                                    QStringLiteral("\a@iana.org"), // expecting atext
1758                                    QStringLiteral("test@\a.org"), // expecting atext
1759                                    QStringLiteral("\r\ntest@iana.org"), // folding white space ends with CRLF
1760                                    QStringLiteral("\r\n \r\ntest@iana.org"), // folding white space ends with CRLF
1761                                    QStringLiteral(" \r\ntest@iana.org"), // folding white space ends with CRLF
1762                                    QStringLiteral(" \r\n \r\ntest@iana.org"), // folding white space ends with CRLF
1763                                    QStringLiteral(" \r\n\r\ntest@iana.org"), // Folding White Space contains consecutive CRLF sequences
1764                                    QStringLiteral(" \r\n\r\n test@iana.org"), // Folding White Space contains consecutive CRLF sequences
1765                                    QStringLiteral("test@iana.org\r\n"), // Folding White Space ends with a CRLF sequence
1766                                    QStringLiteral("test@iana.org\r\n \r\n"), // Folding White Space ends with a CRLF sequence
1767                                    QStringLiteral("test@iana.org \r\n"), // Folding White Space ends with a CRLF sequence
1768                                    QStringLiteral("test@iana.org \r\n \r\n"), // Folding White Space ends with a CRLF sequence
1769                                    QStringLiteral("test@iana.org \r\n\r\n"), // Folding White Space contains consecutive CRLF sequences
1770                                    QStringLiteral("test@iana.org \r\n\r\n "), // Folding White Space contains consecutive CRLF sequences
1771                                    QStringLiteral("\"test\\©\"@iana.org"), // expecting quoted pair
1772                                    // addresses are taken from https://github.com/dominicsayers/isemail/blob/master/test/tests-original.xml
1773                                    QStringLiteral("first.last@sub.do,com"), // expecting atext
1774                                    QStringLiteral("first\\@last@iana.org"), // expecting atext
1775                                    QStringLiteral("first.last"), // no domain
1776                                    QStringLiteral(".first.last@iana.org"), // dot start
1777                                    QStringLiteral("first.last.@iana.org"), // dot end
1778                                    QStringLiteral("first..last@iana.org"), // consecutive dots
1779                                    QStringLiteral("\"first\"last\"@iana.org"), // atext after quoted string
1780                                    QStringLiteral("\"\"\"@iana.org"), // expecting atext
1781                                    QStringLiteral("\"\\\"@iana.org"), // unclosed quoted string
1782                                    QStringLiteral("first\\\\@last@iana.org"), // expecting atext
1783                                    QStringLiteral("first.last@"), // no domain
1784                                    QStringLiteral("first.last@-xample.com"), // domain hyphen start
1785                                    QStringLiteral("first.last@exampl-.com"), // domain hyphen end
1786                                    QStringLiteral("abc\\@def@iana.org"), // expecting atext
1787                                    QStringLiteral("abc\\\\@iana.org"), // expecting atext
1788                                    QStringLiteral("Doug\\ \\\"Ace\\\"\\ Lovell@iana.org"), // expecting atext
1789                                    QStringLiteral("abc@def@iana.org"), // expecting atext
1790                                    QStringLiteral("abc\\\\@def@iana.org"), // expecting atext
1791                                    QStringLiteral("abc\\@iana.org"), // expecting atext
1792                                    QStringLiteral("@iana.org"), // no local part
1793                                    QStringLiteral("doug@"), // no domain
1794                                    QStringLiteral("\"qu@iana.org"), // unclosed quoted string
1795                                    QStringLiteral("ote\"@iana.org"), // expecting atext
1796                                    QStringLiteral(".dot@iana.org"), // dot start
1797                                    QStringLiteral("dot.@iana.org"), // dot end
1798                                    QStringLiteral("two..dot@iana.org"), // consecutive dots
1799                                    QStringLiteral("\"Doug \"Ace\" L.\"@iana.org"), // atext after quoted string
1800                                    QStringLiteral("Doug\\ \\\"Ace\\\"\\ L\\.@iana.org"), // expecting atext
1801                                    QStringLiteral("hello world@iana.org"), // atext after folding white space
1802                                    QStringLiteral("gatsby@f.sc.ot.t.f.i.tzg.era.l.d."), // dot end
1803                                    QStringLiteral("test.iana.org"), // no domain
1804                                    QStringLiteral("test.@iana.org"), // dot end
1805                                    QStringLiteral("test..test@iana.org"), // consecutive dots
1806                                    QStringLiteral(".test@iana.org"), // dot start
1807                                    QStringLiteral("test@test@iana.org"), // expecting atext
1808                                    QStringLiteral("test@@iana.org"), // expecting atext
1809                                    QStringLiteral("-- test --@iana.org"), // atext after folding white space
1810                                    QStringLiteral("[test]@iana.org"), // expecting atext
1811                                    QStringLiteral("\"test\"test\"@iana.org"), // atext after quoted string
1812                                    QStringLiteral("()[]\\;:,><@iana.org"), // expecting atext
1813                                    QStringLiteral("test@."), // dot start
1814                                    QStringLiteral("test@example."), // dot end
1815                                    QStringLiteral("test@.org"), // dot start
1816                                    QStringLiteral("test@[123.123.123.123"), // unclosed domain literal
1817                                    QStringLiteral("test@123.123.123.123]"), // expecting atext
1818                                    QStringLiteral("NotAnEmail"), // no domain
1819                                    QStringLiteral("@NotAnEmail"), // no local part
1820                                    QStringLiteral("\"test\rblah\"@iana.org"), // cr no lf
1821                                    QStringLiteral("\"test\"blah\"@iana.org"), // atext after quoted string
1822                                    QStringLiteral(".wooly@iana.org"), // dot start
1823                                    QStringLiteral("wo..oly@iana.org"), // consecutive dots
1824                                    QStringLiteral("pootietang.@iana.org"), // dot end
1825                                    QStringLiteral(".@iana.org"), // dot start
1826                                    QStringLiteral("Ima Fool@iana.org"), // atext after white space
1827                                    QStringLiteral("phil.h\\@\\@ck@haacked.com"), // expecting atext
1828                                    QStringLiteral("\"first\\\\\"last\"@iana.org"), // atext after quoted string
1829                                    QStringLiteral("first\\last@iana.org"), // expecting atext
1830                                    QStringLiteral("Abc\\@def@iana.org"), // expecting atext
1831                                    QStringLiteral("Fred\\ Bloggs@iana.org"), // expectin atext
1832                                    QStringLiteral("Joe.\\\\Blow@iana.org"), // expecting atext
1833                                    QStringLiteral("\"test\\\r\n blah\"@iana.org"), // expecting qtext
1834                                    QStringLiteral("{^c\\@**Dog^}@cartoon.com"), // expecting atext
1835                                    QStringLiteral("cal(foo(bar)@iamcal.com"), // unclosed comment
1836                                    QStringLiteral("cal(foo)bar)@iamcal.com"), // atext after comment
1837                                    QStringLiteral("cal(foo\\)@iamcal.com"), // unclosed comment
1838                                    QStringLiteral("first(12345678901234567890123456789012345678901234567890)last@(1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890)iana.org"), // atext after comment
1839                                    QStringLiteral("first(middle)last@iana.org"), // atext after comment
1840                                    QStringLiteral("first(abc(\"def\".ghi).mno)middle(abc(\"def\".ghi).mno).last@(abc(\"def\".ghi).mno)example(abc(\"def\".ghi).mno).(abc(\"def\".ghi).mno)com(abc(\"def\".ghi).mno)"), // atext after comment
1841                                    QStringLiteral("a(a(b(c)d(e(f))g)(h(i)j)@iana.org"), // unclosed comment
1842                                    QStringLiteral(".@"), // dot start
1843                                    QStringLiteral("@bar.com"), // no local part
1844                                    QStringLiteral("@@bar.com"), // no local part
1845                                    QStringLiteral("aaa.com"), // no domain
1846                                    QStringLiteral("aaa@.com"), // dot start
1847                                    QStringLiteral("aaa@.123"), // dot start
1848                                    QStringLiteral("aaa@[123.123.123.123]a"), // atext after domain literal
1849                                    QStringLiteral("a@bar.com."), // dot end
1850                                    QStringLiteral("a@-b.com"), // domain hyphen start
1851                                    QStringLiteral("a@b-.com"), // domain hypen end
1852                                    QStringLiteral("-@..com"), // dot start
1853                                    QStringLiteral("-@a..com"), // consecutive dots
1854                                    QStringLiteral("invalid@about.museum-"), // domain hyphen end
1855                                    QStringLiteral("test@...........com"), // dot start
1856                                    QStringLiteral("Invalid \\\n Folding \\\n Whitespace@iana.org"), // atext after white space
1857                                    QStringLiteral("test.\r\n\r\n obs@syntax.com"), // Folding White Space contains consecutive CRLF sequences
1858 //                                   QStringLiteral("\"Unicode NULL \0\"@char.com"), // expecting qtext
1859 //                                   QStringLiteral("Unicode NULL \\0@char.com"), // atext after cfws
1860                                    QStringLiteral("test@example.com\n") // expecting atext
1861                                });
1862 
1863     count = 0;
1864     for (const QString &email : validEmails) {
1865         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1866         QTest::newRow(QString(QStringLiteral("email-valid-valid-%1").arg(count)).toUtf8().constData())
1867                 << QStringLiteral("/emailValid") << headers << body << valid;
1868         count++;
1869     }
1870 
1871     count = 0;
1872     for (const QString &email : {QStringLiteral("test@hüssenbergnetz.de"), QStringLiteral("täst@huessenbergnetz.de"), QStringLiteral("täst@hüssenbergnetz.de")}) {
1873         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1874         QTest::newRow(QString(QStringLiteral("email-valid-invalid-%1").arg(count)).toUtf8().constData())
1875                 << QStringLiteral("/emailValid") << headers << body << invalid;
1876         count++;
1877     }
1878 
1879     if (qEnvironmentVariableIsSet("CUTELYST_VALIDATORS_TEST_NETWORK")) {
1880         QTest::newRow("email-valid-dns") << QStringLiteral("/emailDnsWarnValid") << headers << QByteArrayLiteral("field=test@huessenbergnetz.de") << valid;
1881         count = 0;
1882         for (const QString &email : dnsWarnEmails) {
1883             const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1884             QTest::newRow(QString(QStringLiteral("email-dnswarn-valid-%1").arg(count)).toUtf8().constData())
1885                     << QStringLiteral("/emailDnsWarnValid") << headers << body << invalid;
1886             count++;
1887         }
1888     }
1889 
1890     count = 0;
1891     for (const QString &email : rfc5321Emails) {
1892         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1893         QTest::newRow(QString(QStringLiteral("email-rfc5321-valid-%1").arg(count)).toUtf8().constData())
1894                 << QStringLiteral("/emailRfc5321Valid") << headers << body << valid;
1895         count++;
1896     }
1897 
1898     count = 0;
1899     for (const QString &email : rfc5321Emails) {
1900         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1901         QTest::newRow(QString(QStringLiteral("email-rfc5321-invalid-%1").arg(count)).toUtf8().constData())
1902                 << QStringLiteral("/emailRfc5321Invalid") << headers << body << invalid;
1903         count++;
1904     }
1905 
1906     count = 0;
1907     for (const QString &email : cfwsEmails) {
1908         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1909         QTest::newRow(QString(QStringLiteral("email-cfws-valid-%1").arg(count)).toUtf8().constData())
1910                 << QStringLiteral("/emailCfwsValid") << headers << body << valid;
1911         count++;
1912     }
1913 
1914     count = 0;
1915     for (const QString &email : deprecatedEmails) {
1916         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1917         QTest::newRow(QString(QStringLiteral("email-deprecated-valid-%1").arg(count)).toUtf8().constData())
1918                 << QStringLiteral("/emailDeprecatedValid") << headers << body << valid;
1919         count++;
1920     }
1921 
1922     count = 0;
1923     for (const QString &email : deprecatedEmails) {
1924         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1925         QTest::newRow(QString(QStringLiteral("email-deprecated-invalid-%1").arg(count)).toUtf8().constData())
1926                 << QStringLiteral("/emailDeprecatedInvalid") << headers << body << invalid;
1927         count++;
1928     }
1929 
1930     count = 0;
1931     for (const QString &email : rfc5322Emails) {
1932         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1933         QTest::newRow(QString(QStringLiteral("email-rfc5322-valid-%1").arg(count)).toUtf8().constData())
1934                 << QStringLiteral("/emailRfc5322Valid") << headers << body << valid;
1935         count++;
1936     }
1937 
1938     count = 0;
1939     for (const QString &email : rfc5322Emails) {
1940         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1941         QTest::newRow(QString(QStringLiteral("email-rfc5322-invalid-%1").arg(count)).toUtf8().constData())
1942                 << QStringLiteral("/emailRfc5322Invalid") << headers << body << invalid;
1943         count++;
1944     }
1945 
1946     count = 0;
1947     for (const QString &email : errorEmails) {
1948         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1949         QTest::newRow(QString(QStringLiteral("email-errors-invalid-%1").arg(count)).toUtf8().constData())
1950                 << QStringLiteral("/emailErrors") << headers << body << invalid;
1951         count++;
1952     }
1953 
1954     {
1955         QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("test@hüssenbergnetz.de"));
1956         QTest::newRow("email-idnallowed-valid") << QStringLiteral("/emailIdnAllowed") << headers << body << valid;
1957 
1958         body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("täst@hüssenbergnetz.de"));
1959         QTest::newRow("email-idnallowed-invalid") << QStringLiteral("/emailIdnAllowed") << headers << body << invalid;
1960 
1961         body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("täst@huessenbergnetz.de"));
1962         QTest::newRow("email-utf8localallowed-valid") << QStringLiteral("/emailUtf8Local") << headers << body << valid;
1963 
1964         body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("täst@hüssenbergnetz.de"));
1965         QTest::newRow("email-utf8localallowed-invalid") << QStringLiteral("/emailUtf8Local") << headers << body << invalid;
1966 
1967         body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(QStringLiteral("täst@hüssenbergnetz.de"));
1968         QTest::newRow("email-utf8allowed-valid-0") << QStringLiteral("/emailUtf8") << headers << body << valid;
1969     }
1970 
1971     count = 1;
1972     for (const QString &email : validEmails) {
1973         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1974         QTest::newRow(QString(QStringLiteral("email-utf8allowed-valid-%1").arg(count)).toUtf8().constData())
1975                 << QStringLiteral("/emailUtf8") << headers << body << valid;
1976         count++;
1977     }
1978 
1979     QList<QString> utf8InvalidEmails;
1980     utf8InvalidEmails.append(rfc5321Emails);
1981     utf8InvalidEmails.append(cfwsEmails);
1982     utf8InvalidEmails.append(deprecatedEmails);
1983     utf8InvalidEmails.append(rfc5322Emails);
1984     utf8InvalidEmails.append(errorEmails);
1985 
1986     count = 0;
1987     for (const QString &email : utf8InvalidEmails) {
1988         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(email);
1989         QTest::newRow(QString(QStringLiteral("email-utf8allowed-invalid-%1").arg(count)).toUtf8().constData())
1990                 << QStringLiteral("/emailUtf8") << headers << body << invalid;
1991         count++;
1992     }
1993 
1994     QTest::newRow("email-empty") << QStringLiteral("/emailValid") << headers << QByteArrayLiteral("field=") << valid;
1995 
1996 
1997     // **** Start testing ValidatorFileSize *****
1998 
1999     count = 0;
2000     for (const QString &size : {
2001          QStringLiteral("1M"),
2002          QStringLiteral("M1"),
2003          QStringLiteral("1 G"),
2004          QStringLiteral("G 1"),
2005          QStringLiteral("1.5 G"),
2006          QStringLiteral("G 1.5"),
2007          QStringLiteral("2.345 TiB"),
2008          QStringLiteral("TiB2.345"),
2009          QStringLiteral("5B"),
2010          QStringLiteral("B5"),
2011          QStringLiteral("5 B"),
2012          QStringLiteral("B 5"),
2013          QStringLiteral(" 2.0 Gi"),
2014          QStringLiteral(" Gi 2.0"),
2015          QStringLiteral("2.0 Gi "),
2016          QStringLiteral("Gi 2.0 "),
2017          QStringLiteral(" 2.0 Gi "),
2018          QStringLiteral(" Gi 2.0 "),
2019          QStringLiteral(" 2.0    Gi "),
2020          QStringLiteral(" Gi    2.0 "),
2021          QStringLiteral("3.67YB"),
2022          QStringLiteral("YB3.67"),
2023          QStringLiteral("1"),
2024          QStringLiteral("1024"),
2025          QStringLiteral(".5MB"),
2026          QStringLiteral("MB.5")}) {
2027         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(size);
2028         QTest::newRow(QString(QStringLiteral("filesize-valid-%1").arg(count)).toUtf8().constData())
2029                 << QStringLiteral("/fileSize") << headers << body << valid;
2030         count++;
2031     }
2032 
2033     count = 0;
2034     for (const QString &size : {
2035          QStringLiteral("1QiB"),
2036          QStringLiteral("QiB1"),
2037          QStringLiteral(" 1QiB"),
2038          QStringLiteral(" QiB1"),
2039          QStringLiteral("1QiB "),
2040          QStringLiteral("QiB1 "),
2041          QStringLiteral("1 QiB"),
2042          QStringLiteral("Q iB1"),
2043          QStringLiteral("1   QiB"),
2044          QStringLiteral("Q   iB1"),
2045          QStringLiteral("1..4 G"),
2046          QStringLiteral("G 1..4"),
2047          QStringLiteral("1iB"),
2048          QStringLiteral("iB1"),
2049          QStringLiteral("1Byte"),
2050          QStringLiteral("Byte1"),
2051          QStringLiteral("1024iK"),
2052          QStringLiteral("iK 2048")}) {
2053         const QByteArray body = QByteArrayLiteral("field=") + QUrl::toPercentEncoding(size);
2054         QTest::newRow(QString(QStringLiteral("filesize-invalid-%1").arg(count)).toUtf8().constData())
2055                 << QStringLiteral("/fileSize") << headers << body << invalid;
2056         count++;
2057     }
2058 
2059     query.clear();
2060     query.addQueryItem(QStringLiteral("field"), QStringLiteral("1,5M"));
2061     query.addQueryItem(QStringLiteral("locale"), QStringLiteral("de"));
2062     QTest::newRow("filesize-locale-de-valid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2063 
2064     query.clear();
2065     query.addQueryItem(QStringLiteral("field"), QStringLiteral("1.5M"));
2066     query.addQueryItem(QStringLiteral("locale"), QStringLiteral("de"));
2067     QTest::newRow("filesize-locale-de-invalid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2068 
2069     // disabled on MSVC because that shit still has problems with utf8 in 2018...
2070 #ifndef _MSC_VER
2071     query.clear();
2072     query.addQueryItem(QStringLiteral("field"), QStringLiteral("1٫5M"));
2073     query.addQueryItem(QStringLiteral("locale"), QStringLiteral("ar"));
2074     QTest::newRow("filesize-locale-ar-valid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2075 #endif
2076 
2077     query.clear();
2078     query.addQueryItem(QStringLiteral("field"), QStringLiteral("1.5M"));
2079     query.addQueryItem(QStringLiteral("locale"), QStringLiteral("ar"));
2080     QTest::newRow("filesize-locale-ar-invalid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2081 
2082     query.clear();
2083     query.addQueryItem(QStringLiteral("field"), QStringLiteral("1.5TiB"));
2084     query.addQueryItem(QStringLiteral("option"), QStringLiteral("OnlyBinary"));
2085     QTest::newRow("filesize-onlybinary-valid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2086 
2087     query.clear();
2088     query.addQueryItem(QStringLiteral("field"), QStringLiteral("1.5TB"));
2089     query.addQueryItem(QStringLiteral("option"), QStringLiteral("OnlyBinary"));
2090     QTest::newRow("filesize-onlybinary-invalid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2091 
2092     query.clear();
2093     query.addQueryItem(QStringLiteral("field"), QStringLiteral("1.5TB"));
2094     query.addQueryItem(QStringLiteral("option"), QStringLiteral("OnlyDecimal"));
2095     QTest::newRow("filesize-onlydecimyl-valid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2096 
2097     query.clear();
2098     query.addQueryItem(QStringLiteral("field"), QStringLiteral("1.5TiB"));
2099     query.addQueryItem(QStringLiteral("option"), QStringLiteral("OnlyDecimal"));
2100     QTest::newRow("filesize-onlydecimyl-invalid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2101 
2102     query.clear();
2103     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2K"));
2104     query.addQueryItem(QStringLiteral("min"), QStringLiteral("1000"));
2105     QTest::newRow("filesize-min-valid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2106 
2107     query.clear();
2108     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2K"));
2109     query.addQueryItem(QStringLiteral("min"), QStringLiteral("2048"));
2110     QTest::newRow("filesize-min-invalid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2111 
2112     query.clear();
2113     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2KiB"));
2114     query.addQueryItem(QStringLiteral("max"), QStringLiteral("2048"));
2115     QTest::newRow("filesize-max-valid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2116 
2117     query.clear();
2118     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2KiB"));
2119     query.addQueryItem(QStringLiteral("max"), QStringLiteral("2047"));
2120     QTest::newRow("filesize-max-invalid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2121 
2122     query.clear();
2123     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2KiB"));
2124     query.addQueryItem(QStringLiteral("min"), QStringLiteral("2048"));
2125     query.addQueryItem(QStringLiteral("max"), QStringLiteral("2048"));
2126     QTest::newRow("filesize-min-max-valid") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2127 
2128     query.clear();
2129     query.addQueryItem(QStringLiteral("field"), QStringLiteral("0.5KiB"));
2130     query.addQueryItem(QStringLiteral("min"), QStringLiteral("1024"));
2131     query.addQueryItem(QStringLiteral("max"), QStringLiteral("2048"));
2132     QTest::newRow("filesize-min-max-invalid-1") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2133 
2134     query.clear();
2135     query.addQueryItem(QStringLiteral("field"), QStringLiteral("3.5KiB"));
2136     query.addQueryItem(QStringLiteral("min"), QStringLiteral("1024"));
2137     query.addQueryItem(QStringLiteral("max"), QStringLiteral("2048"));
2138     QTest::newRow("filesize-min-max-invalid-2") << QStringLiteral("/fileSize") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2139 
2140 
2141     // **** Start testing ValidatorFileSize with return values
2142 
2143     const QMap<QString, QString> fileSizes({
2144                                                {QStringLiteral("1"), QStringLiteral("1")},
2145                                                {QStringLiteral("1B"), QStringLiteral("1")},
2146                                                {QStringLiteral("1K"), QStringLiteral("1000")},
2147                                                {QStringLiteral("1KiB"), QStringLiteral("1024")},
2148                                                {QStringLiteral("3.45K"), QStringLiteral("3450")},
2149                                                {QStringLiteral("3.45KiB"), QStringLiteral("3533")},
2150                                                {QStringLiteral("3456MB"), QStringLiteral("3456000000")},
2151                                                {QStringLiteral("3456MiB"), QStringLiteral("3623878656")},
2152                                                {QStringLiteral("4.321GB"), QStringLiteral("4321000000")},
2153                                                {QStringLiteral("4.321GiB"), QStringLiteral("4639638422")},
2154                                                {QStringLiteral("45.7890TB"), QStringLiteral("45789000000000")},
2155                                                {QStringLiteral("45.7890TiB"), QStringLiteral("50345537924235")},
2156                                                {QStringLiteral("123.456789PB"), QStringLiteral("123456789000000000")},
2157                                                {QStringLiteral("123.456789PiB"), QStringLiteral("138999987234189488")},
2158                                                {QStringLiteral("1.23EB"), QStringLiteral("1230000000000000000")},
2159                                                {QStringLiteral("1.23EiB"), QStringLiteral("1418093450666421760")},
2160                                                {QStringLiteral("2ZB"), QStringLiteral("2000000000000000000000.00")},
2161                                                {QStringLiteral("2ZiB"), QStringLiteral("2361183241434822606848.00")}
2162                                            });
2163 
2164     count = 0;
2165     auto fileSizesIt = fileSizes.constBegin();
2166     while (fileSizesIt != fileSizes.constEnd()) {
2167         query.clear();
2168         query.addQueryItem(QStringLiteral("field"), fileSizesIt.key());
2169         QTest::newRow(QString(QStringLiteral("filesize-return-value-%1").arg(count)).toUtf8().constData())
2170                 << QStringLiteral("/fileSizeValue") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << fileSizesIt.value().toUtf8();
2171         ++fileSizesIt;
2172         count++;
2173     }
2174 
2175     // **** Start testing ValidatorFilled *****
2176 
2177     query.clear();
2178     query.addQueryItem(QStringLiteral("field"), QStringLiteral("toll"));
2179     QTest::newRow("filled-valid") << QStringLiteral("/filled") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2180 
2181     QTest::newRow("filled-missing") << QStringLiteral("/filled") << headers << QByteArray() << valid;
2182 
2183     query.clear();
2184     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2185     QTest::newRow("filled-invalid") << QStringLiteral("/filled") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2186 
2187 
2188 
2189     // **** Start testing ValidatorIn *****
2190 
2191     query.clear();
2192     query.addQueryItem(QStringLiteral("field"), QStringLiteral("zwei"));
2193     QTest::newRow("in-valid") << QStringLiteral("/in") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2194 
2195     query.clear();
2196     query.addQueryItem(QStringLiteral("field"), QStringLiteral("vier"));
2197     QTest::newRow("in-invalid") << QStringLiteral("/in") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2198 
2199     query.clear();
2200     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2201     QTest::newRow("in-empty") << QStringLiteral("/in") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2202 
2203     QTest::newRow("in-missing") << QStringLiteral("/in") << headers << QByteArray() << valid;
2204 
2205 
2206 
2207     // **** Start testing ValidatorInteger *****
2208 
2209     query.clear();
2210     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2345"));
2211     QTest::newRow("integer-valid01") << QStringLiteral("/integer") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2212 
2213     query.clear();
2214     query.addQueryItem(QStringLiteral("field"), QStringLiteral("-2345"));
2215     QTest::newRow("integer-valid02") << QStringLiteral("/integer") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2216 
2217     query.clear();
2218     query.addQueryItem(QStringLiteral("field"), QString::number(std::numeric_limits<int>::max()));
2219     QTest::newRow("integer-valid03") << QStringLiteral("/integer") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2220 
2221     query.clear();
2222     query.addQueryItem(QStringLiteral("field"), QStringLiteral("-23a45 f"));
2223     QTest::newRow("integer-invalid01") << QStringLiteral("/integer") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2224 
2225     query.clear();
2226     query.addQueryItem(QStringLiteral("field"), QStringLiteral("a-23f45"));
2227     QTest::newRow("integer-invalid02") << QStringLiteral("/integer") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2228 
2229     query.clear();
2230     query.addQueryItem(QStringLiteral("field"), QString::number(std::numeric_limits<qlonglong>::max()));
2231     QTest::newRow("integer-invalid03") << QStringLiteral("/integer") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2232 
2233     query.clear();
2234     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2235     QTest::newRow("integer-empty") << QStringLiteral("/integer") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2236 
2237     QTest::newRow("integer-missing") << QStringLiteral("/integer") << headers << QByteArray() << valid;
2238 
2239 
2240 
2241 
2242     // **** Start testing ValidatorIp *****
2243 
2244     query.clear();
2245     query.addQueryItem(QStringLiteral("field"), QStringLiteral("192.0.43.8"));
2246     QTest::newRow("ip-v4-valid") << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2247 
2248     const QList<QString> invalidIpv4({
2249                                          QStringLiteral("192.0.s.34"),
2250                                          QStringLiteral("192.0.43."),
2251                                          QStringLiteral("192.0.43"),
2252                                          QStringLiteral("300.167.168.5"),
2253                                          QStringLiteral("192.168.178.-5")
2254                                      });
2255     count = 0;
2256     for (const QString &ipv4 : invalidIpv4) {
2257         query.clear();
2258         query.addQueryItem(QStringLiteral("field"), ipv4);
2259         QTest::newRow(QString(QStringLiteral("ip-v4-invalid0%1").arg(count)).toUtf8().constData())
2260                 << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2261         count++;
2262     }
2263 
2264     const QList<QString> validIpv6({
2265                                        QStringLiteral("::"),
2266                                        QStringLiteral("::123"),
2267                                        QStringLiteral("::123:456"),
2268                                        QStringLiteral("::123:456:789:abc:def:6666"),
2269                                        QStringLiteral("::123:456:789:abc:def:6666:7"),
2270                                        QStringLiteral("123::456"),
2271                                        QStringLiteral("123::456:789"),
2272                                        QStringLiteral("123::456:789:abc"),
2273                                        QStringLiteral("123::456:789:abc:def"),
2274                                        QStringLiteral("123::456:789:abc:def:6"),
2275                                        QStringLiteral("123:456::789:abc:def:6666"),
2276                                        QStringLiteral("2001:0db8:85a3:08d3:1319:8a2e:0370:7344"),
2277                                        QStringLiteral("2001:0db8:0000:08d3:0000:8a2e:0070:7344"),
2278                                        QStringLiteral("2001:db8:0:8d3:0:8a2e:70:7344"),
2279                                        QStringLiteral("2001:0db8:0:0:0:0:1428:57ab"),
2280                                        QStringLiteral("2001:db8::1428:57ab"),
2281                                        QStringLiteral("2001:0db8:0:0:8d3:0:0:0"),
2282                                        QStringLiteral("2001:db8:0:0:8d3::"),
2283                                        QStringLiteral("2001:db8::8d3:0:0:0"),
2284                                        QStringLiteral("::ffff:127.0.0.1"),
2285                                        QStringLiteral("::ffff:7f00:1")
2286                                    });
2287 
2288     count = 0;
2289     for (const QString &ipv6 : validIpv6) {
2290         query.clear();
2291         query.addQueryItem(QStringLiteral("field"), ipv6);
2292         QTest::newRow(QString(QStringLiteral("ip-v6-valid0%1").arg(count)).toUtf8().constData())
2293                 << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2294         count++;
2295     }
2296 
2297     const QList<QString> invalidIpv6({
2298                                          QStringLiteral("2001:db8::8d3::"),
2299                                          QStringLiteral("2001:0db8:85a3:08d3:1319:8a2e:0370:7344:1234"),
2300                                          QStringLiteral(":::08d3:1319:8a2e:0370:7344"),
2301                                          QStringLiteral("2001:0db8:85a3:08d3:1319:8a2k:0370:7344"),
2302                                          QStringLiteral("127.0.0.1:1319:8a2k:0370:7344"),
2303                                          QStringLiteral("2001::0db8:85a3:08d3::1319:8a2k:0370:7344"),
2304                                          QStringLiteral("2001::0DB8:85A3:08D3::1319:8a2k:0370:7344"),
2305                                          QStringLiteral(":::")
2306                                      });
2307     count = 0;
2308     for (const QString &ipv6 : invalidIpv6) {
2309         query.clear();
2310         query.addQueryItem(QStringLiteral("field"), ipv6);
2311         QTest::newRow(QString(QStringLiteral("ip-v6-invalid0%1").arg(count)).toUtf8().constData())
2312                 << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2313         count++;
2314     }
2315 
2316 
2317     query.clear();
2318     query.addQueryItem(QStringLiteral("field"), QStringLiteral("192.0.43.8"));
2319     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("IPv4Only"));
2320     QTest::newRow("ip-ipv4only-valid") << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2321 
2322     query.clear();
2323     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2a02:810d:22c0:1c8c:5900:83dc:83b6:9ed8"));
2324     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("IPv4Only"));
2325     QTest::newRow("ip-ipv4only-invalid") << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2326 
2327     query.clear();
2328     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2a02:810d:22c0:1c8c:5900:83dc:83b6:9ed8"));
2329     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("IPv6Only"));
2330     QTest::newRow("ip-ipv6only-valid") << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2331 
2332     query.clear();
2333     query.addQueryItem(QStringLiteral("field"), QStringLiteral("192.0.43.8"));
2334     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("IPv6Only"));
2335     QTest::newRow("ip-ipv6only-invalid") << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2336 
2337 
2338     query.clear();
2339     query.addQueryItem(QStringLiteral("field"), QStringLiteral("192.0.43.8"));
2340     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoPrivateRange"));
2341     QTest::newRow("ip-noprivate-valid00")  << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2342 
2343     query.clear();
2344     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2a02:810d:22c0:1c8c:5900:83dc:83b6:9ed8"));
2345     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoPrivateRange"));
2346     QTest::newRow("ip-noprivate-valid01")  << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2347 
2348     const QList<QString> invalidIpNoPrivate({
2349                                                 QStringLiteral("10.1.2.3"),
2350                                                 QStringLiteral("172.21.158.56"),
2351                                                 QStringLiteral("192.168.178.100"),
2352                                                 QStringLiteral("169.254.254.254"),
2353                                                 QStringLiteral("fe80::5652:697b:2531:a7ed"),
2354                                                 QStringLiteral("fd00:26:5bf0:abd2:15ff:1adb:e8c4:8453")
2355                                             });
2356     count = 0;
2357     for (const QString &ip : invalidIpNoPrivate) {
2358         query.clear();
2359         query.addQueryItem(QStringLiteral("field"), ip);
2360         query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoPrivateRange"));
2361         QTest::newRow(qUtf8Printable(QStringLiteral("ip-noprivate-invalid0%1").arg(count)))
2362                 << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2363         count++;
2364     }
2365 
2366 
2367     query.clear();
2368     query.addQueryItem(QStringLiteral("field"), QStringLiteral("192.0.43.8"));
2369     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoReservedRange"));
2370     QTest::newRow("ip-noreserved-valid00")  << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2371 
2372     query.clear();
2373     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2a02:810d:22c0:1c8c:5900:83dc:83b6:9ed8"));
2374     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoReservedRange"));
2375     QTest::newRow("ip-noreserved-valid01")  << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2376 
2377     const QList<QString> invalidIpNoReserved({
2378                                                  QStringLiteral("0.1.2.3"),
2379                                                  QStringLiteral("127.0.0.1"),
2380                                                  QStringLiteral("100.88.5.89"),
2381                                                  QStringLiteral("192.0.0.56"),
2382                                                  QStringLiteral("192.0.2.165"),
2383                                                  QStringLiteral("192.88.99.67"),
2384                                                  QStringLiteral("198.18.5.85"),
2385                                                  QStringLiteral("198.51.100.33"),
2386                                                  QStringLiteral("203.0.113.97"),
2387                                                  QStringLiteral("250.240.230.230"),
2388                                                  QStringLiteral("255.255.255.255"),
2389                                                  QStringLiteral("::"),
2390                                                  QStringLiteral("::1"),
2391                                                  QStringLiteral("0000:0000:0000:0000:0000:ffff:1234:abcd"),
2392                                                  QStringLiteral("0100:0000:0000:0000:1234:5678:9abc:def0"),
2393                                                  QStringLiteral("64:ff9b::95.4.66.32"),
2394                                                  QStringLiteral("2001:0000:1234:5678:90ab:cdef:1234:5678"),
2395                                                  QStringLiteral("2001:0010:0000:9876:abcd:5432:0000:a5b4"),
2396                                                  QStringLiteral("2001:0020:0000:9876:abcd:5432:0000:a5b4"),
2397                                                  QStringLiteral("2001:0db8:5b8e:6b5c:cdab:8546:abde:abdf"),
2398                                                  QStringLiteral("2002:fd4b:5b8e:6b5c:cdab:8546:abde:abdf")
2399                                              });
2400     count = 0;
2401     for (const QString &ip : invalidIpNoReserved) {
2402         query.clear();
2403         query.addQueryItem(QStringLiteral("field"), ip);
2404         query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoReservedRange"));
2405         QTest::newRow(qUtf8Printable(QStringLiteral("ip-noreserved-invalid0%1").arg(count)))
2406                 << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2407         count++;
2408     }
2409 
2410     query.clear();
2411     query.addQueryItem(QStringLiteral("field"), QStringLiteral("192.0.43.8"));
2412     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoMultiCast"));
2413     QTest::newRow("ip-nomulticast-valid00")  << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2414 
2415     query.clear();
2416     query.addQueryItem(QStringLiteral("field"), QStringLiteral("2a02:810d:22c0:1c8c:5900:83dc:83b6:9ed8"));
2417     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoMultiCast"));
2418     QTest::newRow("ip-nomulticast-valid01")  << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2419 
2420     query.clear();
2421     query.addQueryItem(QStringLiteral("field"), QStringLiteral("229.0.43.8"));
2422     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoMultiCast"));
2423     QTest::newRow("ip-nomulticast-invalid00")  << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2424 
2425     query.clear();
2426     query.addQueryItem(QStringLiteral("field"), QStringLiteral("ff02:810d:22c0:1c8c:5900:83dc:83b6:9ed8"));
2427     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoMultiCast"));
2428     QTest::newRow("ip-nomulticast-invalid01")  << QStringLiteral("/ip") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2429 
2430 
2431 
2432 
2433     // **** Start testing ValidatorJson *****
2434 
2435     query.clear();
2436     query.addQueryItem(QStringLiteral("field"), QStringLiteral("{\"Herausgeber\":\"Xema\",\"Nummer\":\"1234-5678-9012-3456\",\"Deckung\":2e%2B6,\"Waehrung\":\"EURO\",\"Inhaber\":{\"Name\":\"Mustermann\",\"Vorname\":\"Max\",\"maennlich\":true,\"Hobbys\":[\"Reiten\",\"Golfen\",\"Lesen\"],\"Alter\":42,\"Kinder\":[],\"Partner\":null}}"));
2437     QTest::newRow("json-valid") << QStringLiteral("/json") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2438 
2439     query.clear();
2440     query.addQueryItem(QStringLiteral("field"), QStringLiteral("{\"Herausgeber\":\"Xema\",\"Nummer\":\"1234-5678-9012-3456\",\"Deckung\":2e 6,\"Waehrung\":\"EURO\",\"Inhaber\":{\"Name\":\"Mustermann\",\"Vorname\":\"Max\",\"maennlich\":true,\"Hobbys\":[\"Reiten\",\"Golfen\",\"Lesen\"],\"Alter\":42,\"Kinder\":[],\"Partner\":null}}"));
2441     QTest::newRow("json-invalid") << QStringLiteral("/json") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2442 
2443 
2444 
2445     // **** Start testing ValidatorMax *****
2446 
2447     query.clear();
2448     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2449     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2450     QTest::newRow("max-sint-empty") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2451 
2452     query.clear();
2453     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2454     query.addQueryItem(QStringLiteral("field"), QStringLiteral("-5"));
2455     QTest::newRow("max-sint-valid") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2456 
2457     query.clear();
2458     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2459     query.addQueryItem(QStringLiteral("field"), QStringLiteral("15"));
2460     QTest::newRow("max-sint-invalid") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2461 
2462     query.clear();
2463     query.addQueryItem(QStringLiteral("type"), QStringLiteral("uint"));
2464     query.addQueryItem(QStringLiteral("field"), QStringLiteral("5"));
2465     QTest::newRow("max-uint-valid") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2466 
2467     query.clear();
2468     query.addQueryItem(QStringLiteral("type"), QStringLiteral("uint"));
2469     query.addQueryItem(QStringLiteral("field"), QStringLiteral("15"));
2470     QTest::newRow("max-uint-invalid") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2471 
2472     query.clear();
2473     query.addQueryItem(QStringLiteral("type"), QStringLiteral("float"));
2474     query.addQueryItem(QStringLiteral("field"), QStringLiteral("-5.234652435"));
2475     QTest::newRow("max-uint-valid") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2476 
2477     query.clear();
2478     query.addQueryItem(QStringLiteral("type"), QStringLiteral("float"));
2479     query.addQueryItem(QStringLiteral("field"), QStringLiteral("15.912037"));
2480     QTest::newRow("max-uint-invalid") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2481 
2482     query.clear();
2483     query.addQueryItem(QStringLiteral("type"), QStringLiteral("string"));
2484     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdefghij"));
2485     QTest::newRow("max-uint-valid") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2486 
2487     query.clear();
2488     query.addQueryItem(QStringLiteral("type"), QStringLiteral("string"));
2489     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdefghijlmnop"));
2490     QTest::newRow("max-uint-invalid") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2491 
2492     query.clear();
2493     query.addQueryItem(QStringLiteral("type"), QStringLiteral("strsdf"));
2494     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdefghijlmnop"));
2495     QTest::newRow("max-validationdataerror") << QStringLiteral("/max") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << validationDataError;
2496 
2497 
2498 
2499 
2500 
2501     // **** Start testing ValidatorMin *****
2502 
2503     query.clear();
2504     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2505     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2506     QTest::newRow("min-sint-empty") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2507 
2508     query.clear();
2509     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2510     query.addQueryItem(QStringLiteral("field"), QStringLiteral("15"));
2511     QTest::newRow("min-sint-valid") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2512 
2513     query.clear();
2514     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2515     query.addQueryItem(QStringLiteral("field"), QStringLiteral("-5"));
2516     QTest::newRow("min-sint-invalid") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2517 
2518     query.clear();
2519     query.addQueryItem(QStringLiteral("type"), QStringLiteral("uint"));
2520     query.addQueryItem(QStringLiteral("field"), QStringLiteral("15"));
2521     QTest::newRow("min-uint-valid") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2522 
2523     query.clear();
2524     query.addQueryItem(QStringLiteral("type"), QStringLiteral("uint"));
2525     query.addQueryItem(QStringLiteral("field"), QStringLiteral("5"));
2526     QTest::newRow("min-uint-invalid") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2527 
2528     query.clear();
2529     query.addQueryItem(QStringLiteral("type"), QStringLiteral("float"));
2530     query.addQueryItem(QStringLiteral("field"), QStringLiteral("15.912037"));
2531     QTest::newRow("min-float-valid") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2532 
2533     query.clear();
2534     query.addQueryItem(QStringLiteral("type"), QStringLiteral("float"));
2535     query.addQueryItem(QStringLiteral("field"), QStringLiteral("-5.234652435"));
2536     QTest::newRow("min-float-invalid") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2537 
2538     query.clear();
2539     query.addQueryItem(QStringLiteral("type"), QStringLiteral("string"));
2540     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdefghijklmnop"));
2541     QTest::newRow("min-string-valid") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2542 
2543     query.clear();
2544     query.addQueryItem(QStringLiteral("type"), QStringLiteral("string"));
2545     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdef"));
2546     QTest::newRow("min-string-invalid") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2547 
2548     query.clear();
2549     query.addQueryItem(QStringLiteral("type"), QStringLiteral("strsdf"));
2550     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdefghijlmnop"));
2551     QTest::newRow("min-validationdataerror") << QStringLiteral("/min") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << validationDataError;
2552 
2553 
2554 
2555 
2556     // **** Start testing ValidatorNotIn *****
2557 
2558     query.clear();
2559     query.addQueryItem(QStringLiteral("field"), QStringLiteral("fünf"));
2560     QTest::newRow("notin-valid") << QStringLiteral("/notIn") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2561 
2562     query.clear();
2563     query.addQueryItem(QStringLiteral("field"), QStringLiteral("vier"));
2564     QTest::newRow("notin-invalid") << QStringLiteral("/notIn") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2565 
2566 
2567     // **** Start testing ValidatorNumeric *****
2568 
2569     const QList<QString> validNumerics({QStringLiteral("23"), QStringLiteral("-3465"), QStringLiteral("23.45"), QStringLiteral("-3456.32453245"), QStringLiteral("23.345345e15"), QStringLiteral("-1.23e4")});
2570 
2571     count = 0;
2572     for (const QString &num : validNumerics) {
2573         query.clear();
2574         query.addQueryItem(QStringLiteral("field"), num);
2575         QTest::newRow(qUtf8Printable(QStringLiteral("numeric-valid0%1").arg(count)))
2576                 << QStringLiteral("/numeric") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2577         count++;
2578     }
2579 
2580     const QList<QString> invalidNumerics({QStringLiteral("2s3"), QStringLiteral("-a3465"), QStringLiteral("23:45"), QStringLiteral("-3456:32453245"), QStringLiteral("23.345345c15"), QStringLiteral("-1.23D4")});
2581 
2582     count = 0;
2583     for (const QString &num : invalidNumerics) {
2584         query.clear();
2585         query.addQueryItem(QStringLiteral("field"), num);
2586         QTest::newRow(qUtf8Printable(QStringLiteral("numeric-invalid0%1").arg(count)))
2587                 << QStringLiteral("/numeric") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2588         count++;
2589     }
2590 
2591     query.clear();
2592     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2593     QTest::newRow("numeric-empty") << QStringLiteral("/numeric") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2594 
2595 
2596     // **** Start testing ValidatorPresent *****
2597 
2598     query.clear();
2599     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2600     QTest::newRow("present-valid") << QStringLiteral("/present") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2601 
2602     query.clear();
2603     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdfasdf"));
2604     QTest::newRow("present-invalid") << QStringLiteral("/present") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2605 
2606 
2607     // **** Start testing ValidatorPwQuality
2608 #ifdef CUTELYST_VALIDATOR_WITH_PWQUALITY
2609     const QList<QString> invalidPws({
2610                                         QStringLiteral("ovkaCPa"), // too short, lower than 8
2611                                         QStringLiteral("password"), // dictionary
2612                                         QStringLiteral("aceg1234") // score too low
2613                                     });
2614     count = 0;
2615     for (const QString &pw : invalidPws) {
2616         query.clear();
2617         query.addQueryItem(QStringLiteral("field"), pw);
2618         QTest::newRow(qUtf8Printable(QStringLiteral("pwquality-invalid0%1").arg(count)))
2619                 << QStringLiteral("/pwQuality") << headers << query.toString(QUrl::FullyEncoded).toUtf8() << invalid;
2620         count++;
2621     }
2622 
2623     query.clear();
2624     query.addQueryItem(QStringLiteral("field"), QStringLiteral("niK3sd2eHAm@M0vZ!8sd$uJv?4AYlDaP6"));
2625     QTest::newRow("pwquality-valid") << QStringLiteral("/pwQuality") << headers << query.toString(QUrl::FullyEncoded).toUtf8() << valid;
2626 #endif
2627 
2628 
2629     // **** Start testing ValidatorRegex *****
2630 
2631     query.clear();
2632     query.addQueryItem(QStringLiteral("field"), QStringLiteral("08/12/1985"));
2633     QTest::newRow("regex-valid") << QStringLiteral("/regex") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2634 
2635     query.clear();
2636     query.addQueryItem(QStringLiteral("field"), QStringLiteral("8/2/85"));
2637     QTest::newRow("regex-invalid") << QStringLiteral("/regex") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2638 
2639     query.clear();
2640     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2641     QTest::newRow("regex-empty") << QStringLiteral("/regex") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2642 
2643 
2644     // **** Start testing ValidatorRequired *****
2645 
2646     query.clear();
2647     query.addQueryItem(QStringLiteral("field"), QStringLiteral("08/12/1985"));
2648     QTest::newRow("required-valid") << QStringLiteral("/required") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2649 
2650     query.clear();
2651     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2652     QTest::newRow("required-empty") << QStringLiteral("/required") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2653 
2654     query.clear();
2655     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("08/12/1985"));
2656     QTest::newRow("required-missing") << QStringLiteral("/required") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2657 
2658 
2659 
2660 
2661     // **** Start testing ValidatorRequiredIf *****
2662 
2663     query.clear();
2664     query.addQueryItem(QStringLiteral("field"), QStringLiteral("asdfasdf"));
2665     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("eins"));
2666     QTest::newRow("requiredif-valid00") << QStringLiteral("/requiredIf") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2667 
2668     query.clear();
2669     query.addQueryItem(QStringLiteral("field"), QStringLiteral("adfasdf"));
2670     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("vier"));
2671     QTest::newRow("requiredif-valid01") << QStringLiteral("/requiredIf") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2672 
2673     query.clear();
2674     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2675     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("vier"));
2676     QTest::newRow("requiredif-valid02") << QStringLiteral("/requiredIf") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2677 
2678     query.clear();
2679     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("vier"));
2680     QTest::newRow("requiredif-valid03") << QStringLiteral("/requiredIf") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2681 
2682     query.clear();
2683     query.addQueryItem(QStringLiteral("field3"), QStringLiteral("eins"));
2684     QTest::newRow("requiredif-valid04") << QStringLiteral("/requiredIf") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2685 
2686     query.clear();
2687     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2688     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("eins"));
2689     QTest::newRow("requiredif-invalid00") << QStringLiteral("/requiredIf") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2690 
2691     query.clear();
2692     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("eins"));
2693     QTest::newRow("requiredif-invalid01") << QStringLiteral("/requiredIf") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2694 
2695 
2696 
2697     // **** Start testing ValidatorRequiredIfStash *****
2698 
2699     query.clear();
2700     query.addQueryItem(QStringLiteral("field"), QStringLiteral("adsf"));
2701     QTest::newRow("requiredifstash-valid01") << QStringLiteral("/requiredIfStashMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2702 
2703     query.clear();
2704     query.addQueryItem(QStringLiteral("field"), QStringLiteral("adsf"));
2705     QTest::newRow("requiredifstash-valid02") << QStringLiteral("/requiredIfStashNotMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2706 
2707     query.clear();
2708     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("adsf"));
2709     QTest::newRow("requiredifstash-invalid03") << QStringLiteral("/requiredIfStashNotMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2710 
2711     query.clear();
2712     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("adsf"));
2713     QTest::newRow("requiredifstash-invalid") << QStringLiteral("/requiredIfStashMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2714 
2715     // **** Start testing ValidatorRequiredUnless *****
2716 
2717     query.clear();
2718     query.addQueryItem(QStringLiteral("field"), QStringLiteral("asdfasdf"));
2719     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("eins"));
2720     QTest::newRow("requiredunless-valid00") << QStringLiteral("/requiredUnless") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2721 
2722     query.clear();
2723     query.addQueryItem(QStringLiteral("field"), QStringLiteral("asdfasdf"));
2724     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("vier"));
2725     QTest::newRow("requiredunless-valid01") << QStringLiteral("/requiredUnless") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2726 
2727     query.clear();
2728     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2729     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("eins"));
2730     QTest::newRow("requiredunless-valid02") << QStringLiteral("/requiredUnless") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2731 
2732     query.clear();
2733     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("zwei"));
2734     QTest::newRow("requiredunless-valid03") << QStringLiteral("/requiredUnless") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2735 
2736     query.clear();
2737     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2738     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("vier"));
2739     QTest::newRow("requiredunless-invalid00") << QStringLiteral("/requiredUnless") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2740 
2741     query.clear();
2742     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("vier"));
2743     QTest::newRow("requiredunless-invalid01") << QStringLiteral("/requiredUnless") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2744 
2745 
2746     // **** Start testing ValidatorRequiredUnlessStash *****
2747 
2748     query.clear();
2749     query.addQueryItem(QStringLiteral("field"), QStringLiteral("asdf"));
2750     QTest::newRow("requiredunlessstash-valid00") << QStringLiteral("/requiredUnlessStashMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2751 
2752     query.clear();
2753     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdf"));
2754     QTest::newRow("requiredunlessstash-valid01") << QStringLiteral("/requiredUnlessStashMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2755 
2756     query.clear();
2757     query.addQueryItem(QStringLiteral("field"), QStringLiteral("asdf"));
2758     QTest::newRow("requiredunlessstash-valid02") << QStringLiteral("/requiredUnlessStashNotMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2759 
2760     query.clear();
2761     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdf"));
2762     QTest::newRow("requiredunlessstash-invalid00") << QStringLiteral("/requiredUnlessStashNotMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2763 
2764     query.clear();
2765     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("%20"));
2766     QTest::newRow("requiredunlessstash-invalid01") << QStringLiteral("/requiredUnlessStashNotMatch") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2767 
2768 
2769     // **** Start testing ValidatorRequiredWith *****
2770 
2771     query.clear();
2772     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2773     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("wlklasdf"));
2774     QTest::newRow("requiredwith-valid00") << QStringLiteral("/requiredWith") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2775 
2776     query.clear();
2777     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2778     query.addQueryItem(QStringLiteral("field3"), QStringLiteral("wlklasdf"));
2779     QTest::newRow("requiredwith-valid01") << QStringLiteral("/requiredWith") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2780 
2781     query.clear();
2782     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2783     query.addQueryItem(QStringLiteral("field3"), QStringLiteral("wlklasdf"));
2784     QTest::newRow("requiredwith-valid02") << QStringLiteral("/requiredWith") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2785 
2786     query.clear();
2787     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2788     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("wlklasdf"));
2789     QTest::newRow("requiredwith-invalid00") << QStringLiteral("/requiredWith") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2790 
2791     query.clear();
2792     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("wlklasdf"));
2793     QTest::newRow("requiredwith-invalid01") << QStringLiteral("/requiredWith") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2794 
2795 
2796 
2797     // **** Start testing ValidatorRequiredWithAll *****
2798 
2799     query.clear();
2800     query.addQueryItem(QStringLiteral("field"), QStringLiteral("asdfdasf"));
2801     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdfdasf"));
2802     query.addQueryItem(QStringLiteral("field3"), QStringLiteral("asdfdasf"));
2803     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("asdfdasf"));
2804     QTest::newRow("requiredwithall-valid00") << QStringLiteral("/requiredWithAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2805 
2806     query.clear();
2807     query.addQueryItem(QStringLiteral("field"), QStringLiteral("asdfdasf"));
2808     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdfdasf"));
2809     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("asdfdasf"));
2810     QTest::newRow("requiredwithall-valid01") << QStringLiteral("/requiredWithAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2811 
2812     query.clear();
2813     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2814     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdfdasf"));
2815     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("asdfdasf"));
2816     QTest::newRow("requiredwithall-valid02") << QStringLiteral("/requiredWithAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2817 
2818     query.clear();
2819     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdfdasf"));
2820     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("asdfdasf"));
2821     QTest::newRow("requiredwithall-valid03") << QStringLiteral("/requiredWithAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2822 
2823     query.clear();
2824     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2825     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdfdasf"));
2826     query.addQueryItem(QStringLiteral("field3"), QStringLiteral("asdfdasf"));
2827     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("asdfdasf"));
2828     QTest::newRow("requiredwithall-invalid00") << QStringLiteral("/requiredWithAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2829 
2830     query.clear();
2831     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdfdasf"));
2832     query.addQueryItem(QStringLiteral("field3"), QStringLiteral("asdfdasf"));
2833     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("asdfdasf"));
2834     QTest::newRow("requiredwithall-invalid01") << QStringLiteral("/requiredWithAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2835 
2836 
2837 
2838     // **** Start testing ValidatorRequiredWithout *****
2839 
2840     query.clear();
2841     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2842     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("wlklasdf"));
2843     QTest::newRow("requiredwithout-valid00") << QStringLiteral("/requiredWithout") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2844 
2845     query.clear();
2846     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2847     QTest::newRow("requiredwithout-valid01") << QStringLiteral("/requiredWithout") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2848 
2849     query.clear();
2850     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2851     QTest::newRow("requiredwithout-invalid00") << QStringLiteral("/requiredWithout") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2852 
2853     query.clear();
2854     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("asdfasdf"));
2855     QTest::newRow("requiredwithout-invalid01") << QStringLiteral("/requiredWithout") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2856 
2857     query.clear();
2858     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("asdfasdf"));
2859     QTest::newRow("requiredwithout-invalid02") << QStringLiteral("/requiredWithout") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2860 
2861 
2862     // **** Start testing ValidatorRequiredWithoutAll *****
2863 
2864     query.clear();
2865     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2866     query.addQueryItem(QStringLiteral("field2"), QStringLiteral("wlklasdf"));
2867     QTest::newRow("requiredwithoutall-valid00") << QStringLiteral("/requiredWithoutAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2868 
2869     query.clear();
2870     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2871     QTest::newRow("requiredwithoutall-valid01") << QStringLiteral("/requiredWithoutAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2872 
2873     query.clear();
2874     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2875     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("wlklasdf"));
2876     QTest::newRow("requiredwithoutall-valid02") << QStringLiteral("/requiredWithoutAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2877 
2878     query.clear();
2879     QTest::newRow("requiredwithoutall-invalid00") << QStringLiteral("/requiredWithoutAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2880 
2881     query.clear();
2882     query.addQueryItem(QStringLiteral("field4"), QStringLiteral("wlklasdf"));
2883     QTest::newRow("requiredwithoutall-invalid01") << QStringLiteral("/requiredWithoutAll") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2884 
2885 
2886     // **** Start testing ValidatorSame *****
2887     query.clear();
2888     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2889     query.addQueryItem(QStringLiteral("other"), QStringLiteral("wlklasdf"));
2890     QTest::newRow("same-valid") << QStringLiteral("/same") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2891 
2892     query.clear();
2893     query.addQueryItem(QStringLiteral("field"), QStringLiteral("wlklasdf"));
2894     query.addQueryItem(QStringLiteral("other"), QStringLiteral("wlkla"));
2895     QTest::newRow("same-invalid") << QStringLiteral("/same") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2896 
2897     query.clear();
2898     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2899     query.addQueryItem(QStringLiteral("other"), QStringLiteral("wlkla"));
2900     QTest::newRow("same-empty") << QStringLiteral("/same") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2901 
2902 
2903     // **** Start testing ValidatorSize *****
2904 
2905     query.clear();
2906     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2907     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2908     QTest::newRow("size-sint-empty") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2909 
2910     query.clear();
2911     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2912     query.addQueryItem(QStringLiteral("field"), QStringLiteral("10"));
2913     QTest::newRow("size-sint-valid") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2914 
2915     query.clear();
2916     query.addQueryItem(QStringLiteral("type"), QStringLiteral("sint"));
2917     query.addQueryItem(QStringLiteral("field"), QStringLiteral("-5"));
2918     QTest::newRow("size-sint-invalid") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2919 
2920     query.clear();
2921     query.addQueryItem(QStringLiteral("type"), QStringLiteral("uint"));
2922     query.addQueryItem(QStringLiteral("field"), QStringLiteral("10"));
2923     QTest::newRow("size-uint-valid") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2924 
2925     query.clear();
2926     query.addQueryItem(QStringLiteral("type"), QStringLiteral("uint"));
2927     query.addQueryItem(QStringLiteral("field"), QStringLiteral("5"));
2928     QTest::newRow("size-uint-invalid") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2929 
2930     query.clear();
2931     query.addQueryItem(QStringLiteral("type"), QStringLiteral("float"));
2932     query.addQueryItem(QStringLiteral("field"), QStringLiteral("10.0"));
2933     QTest::newRow("size-float-valid") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2934 
2935     query.clear();
2936     query.addQueryItem(QStringLiteral("type"), QStringLiteral("float"));
2937     query.addQueryItem(QStringLiteral("field"), QStringLiteral("-5.234652435"));
2938     QTest::newRow("size-flost-invalid") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2939 
2940     query.clear();
2941     query.addQueryItem(QStringLiteral("type"), QStringLiteral("string"));
2942     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdefghij"));
2943     QTest::newRow("size-string-valid") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2944 
2945     query.clear();
2946     query.addQueryItem(QStringLiteral("type"), QStringLiteral("string"));
2947     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdef"));
2948     QTest::newRow("size-string-invalid") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
2949 
2950     query.clear();
2951     query.addQueryItem(QStringLiteral("type"), QStringLiteral("strsdf"));
2952     query.addQueryItem(QStringLiteral("field"), QStringLiteral("abcdefghijlmnop"));
2953     QTest::newRow("size-validationdataerror") << QStringLiteral("/size") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << validationDataError;
2954 
2955 
2956 
2957     // **** Start testing ValidatorTime *****
2958 
2959     count = 0;
2960     for (Qt::DateFormat df : dateFormats) {
2961         QTest::newRow(QString(QStringLiteral("time-valid0%1").arg(count)).toUtf8().constData())
2962                 << QStringLiteral("/time?field=") + QTime::currentTime().toString(df) << headers << QByteArray() << valid;
2963         count++;
2964     }
2965 
2966     QTest::newRow("time-invalid") << QStringLiteral("/time?field=123456789") << headers << QByteArray() << invalid;
2967 
2968     QTest::newRow("time-empty") << QStringLiteral("/time?field=%20") << headers << QByteArray() << valid;
2969 
2970     QTest::newRow("time-format-valid") << QStringLiteral("/timeFormat?field=") + QTime::currentTime().toString(QStringLiteral("m:hh")) << headers << QByteArray() << valid;
2971 
2972     QTest::newRow("time-format-invalid") << QStringLiteral("/timeFormat?field=") + QTime::currentTime().toString(QStringLiteral("m:AP")) << headers << QByteArray() << invalid;
2973 
2974 
2975 
2976     // **** Start testing ValidatorUrl*****
2977 
2978     query.clear();
2979     query.addQueryItem(QStringLiteral("field"), QStringLiteral("http://www.example.org"));
2980     QTest::newRow("url-valid00") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2981 
2982     query.clear();
2983     query.addQueryItem(QStringLiteral("field"), QStringLiteral("/home/user"));
2984     QTest::newRow("url-valid01") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2985 
2986     query.clear();
2987     query.addQueryItem(QStringLiteral("field"), QStringLiteral("user"));
2988     QTest::newRow("url-valid02") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2989 
2990     query.clear();
2991     query.addQueryItem(QStringLiteral("field"), QStringLiteral("file:///home/user/test.txt"));
2992     QTest::newRow("url-valid03") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2993 
2994     query.clear();
2995     query.addQueryItem(QStringLiteral("field"), QStringLiteral("%20"));
2996     QTest::newRow("url-empty") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
2997 
2998     query.clear();
2999     query.addQueryItem(QStringLiteral("field"), QStringLiteral("http://www.example.org"));
3000     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoRelative"));
3001     QTest::newRow("url-norelative-valid") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
3002 
3003     query.clear();
3004     query.addQueryItem(QStringLiteral("field"), QStringLiteral("/home/user"));
3005     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoRelative"));
3006     QTest::newRow("url-norelative-invalid") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
3007 
3008     query.clear();
3009     query.addQueryItem(QStringLiteral("field"), QStringLiteral("http://www.example.org"));
3010     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoLocalFile"));
3011     QTest::newRow("url-nolocalfile-valid00") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
3012 
3013     query.clear();
3014     query.addQueryItem(QStringLiteral("field"), QStringLiteral("/home/user/test.txt"));
3015     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoLocalFile"));
3016     QTest::newRow("url-nolocalfile-valid01") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
3017 
3018     query.clear();
3019     query.addQueryItem(QStringLiteral("field"), QStringLiteral("file:///home/user/test.txt"));
3020     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("NoLocalFile"));
3021     QTest::newRow("url-nolocalfile-invalid") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
3022 
3023     query.clear();
3024     query.addQueryItem(QStringLiteral("field"), QStringLiteral("http://www.example.org"));
3025     query.addQueryItem(QStringLiteral("schemes"), QStringLiteral("HTTP,https"));
3026     QTest::newRow("url-scheme-valid") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
3027 
3028     query.clear();
3029     query.addQueryItem(QStringLiteral("field"), QStringLiteral("ftp://www.example.org"));
3030     query.addQueryItem(QStringLiteral("schemes"), QStringLiteral("HTTP,https"));
3031     QTest::newRow("url-scheme-invalid") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
3032 
3033 
3034     query.clear();
3035     query.addQueryItem(QStringLiteral("field"), QStringLiteral("http://www.example.org"));
3036     query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("WebsiteOnly"));
3037     QTest::newRow("url-websiteonly-valid") << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << valid;
3038 
3039     const QStringList invalidWebsiteUrls({QStringLiteral("ftp://www.example.org"), QStringLiteral("file:///home/user/test.txt"), QStringLiteral("/home/user")});
3040     count = 0;
3041     for (const QString &invalidWebsite : invalidWebsiteUrls) {
3042         query.clear();
3043         query.addQueryItem(QStringLiteral("field"), invalidWebsite);
3044         query.addQueryItem(QStringLiteral("constraints"), QStringLiteral("WebsiteOnly"));
3045         QTest::newRow(qUtf8Printable(QStringLiteral("url-websiteonly-invalid0%1").arg(count)))
3046                 << QStringLiteral("/url") << headers << query.toString(QUrl::FullyEncoded).toLatin1() << invalid;
3047         count++;
3048     }
3049 
3050 
3051 }
3052 
3053 QTEST_MAIN(TestValidator)
3054 
3055 #include "testvalidator.moc"
3056 
3057 #endif //VALIDATORTEST_H
3058