| 1 | /**************************************************************************** |
| 2 | ** |
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. |
| 4 | ** Copyright (C) 2016 Intel Corporation. |
| 5 | ** Contact: https://www.qt.io/licensing/ |
| 6 | ** |
| 7 | ** This file is part of the FOO module of the Qt Toolkit. |
| 8 | ** |
| 9 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| 10 | ** Commercial License Usage |
| 11 | ** Licensees holding valid commercial Qt licenses may use this file in |
| 12 | ** accordance with the commercial license agreement provided with the |
| 13 | ** Software or, alternatively, in accordance with the terms contained in |
| 14 | ** a written agreement between you and The Qt Company. For licensing terms |
| 15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
| 16 | ** information use the contact form at https://www.qt.io/contact-us. |
| 17 | ** |
| 18 | ** GNU General Public License Usage |
| 19 | ** Alternatively, this file may be used under the terms of the GNU |
| 20 | ** General Public License version 3 as published by the Free Software |
| 21 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| 22 | ** included in the packaging of this file. Please review the following |
| 23 | ** information to ensure the GNU General Public License requirements will |
| 24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| 25 | ** |
| 26 | ** $QT_END_LICENSE$ |
| 27 | ** |
| 28 | ****************************************************************************/ |
| 29 | |
| 30 | #include <QtTest/QtTest> |
| 31 | #include <QtCore/QCoreApplication> |
| 32 | |
| 33 | #include <QtDBus/private/qdbusutil_p.h> |
| 34 | #include <QtDBus/private/qdbus_symbols_p.h> |
| 35 | |
| 36 | DEFINEFUNC(dbus_bool_t, dbus_signature_validate, (const char *signature, |
| 37 | DBusError *error), |
| 38 | (signature, error), return) |
| 39 | DEFINEFUNC(dbus_bool_t, dbus_signature_validate_single, (const char *signature, |
| 40 | DBusError *error), |
| 41 | (signature, error), return) |
| 42 | DEFINEFUNC(dbus_bool_t, dbus_type_is_basic, (int typecode), |
| 43 | (typecode), return) |
| 44 | DEFINEFUNC(dbus_bool_t, dbus_type_is_fixed, (int typecode), |
| 45 | (typecode), return) |
| 46 | |
| 47 | class tst_QDBusType : public QObject |
| 48 | { |
| 49 | Q_OBJECT |
| 50 | |
| 51 | private Q_SLOTS: |
| 52 | void isValidFixedType_data(); |
| 53 | void isValidFixedType(); |
| 54 | void isValidBasicType_data(); |
| 55 | void isValidBasicType(); |
| 56 | void isValidSingleSignature_data(); |
| 57 | void isValidSingleSignature(); |
| 58 | void isValidArray_data(); |
| 59 | void isValidArray(); |
| 60 | void isValidSignature_data(); |
| 61 | void isValidSignature(); |
| 62 | }; |
| 63 | |
| 64 | enum { Invalid = false, Valid = true }; |
| 65 | |
| 66 | static void addColumns() |
| 67 | { |
| 68 | // All tests use these two columns only |
| 69 | QTest::addColumn<QString>(name: "data" ); |
| 70 | QTest::addColumn<bool>(name: "result" ); |
| 71 | QTest::addColumn<bool>(name: "isValid" ); |
| 72 | } |
| 73 | |
| 74 | // ---- type adds --- |
| 75 | static void addFixedTypes() |
| 76 | { |
| 77 | QTest::newRow(dataTag: "bool" ) << DBUS_TYPE_BOOLEAN_AS_STRING << true << true; |
| 78 | QTest::newRow(dataTag: "byte" ) << DBUS_TYPE_BYTE_AS_STRING << true << true; |
| 79 | QTest::newRow(dataTag: "int16" ) << DBUS_TYPE_INT16_AS_STRING << true << true; |
| 80 | QTest::newRow(dataTag: "uint16" ) << DBUS_TYPE_UINT16_AS_STRING << true << true; |
| 81 | QTest::newRow(dataTag: "int32" ) << DBUS_TYPE_INT32_AS_STRING << true << true; |
| 82 | QTest::newRow(dataTag: "uint32" ) << DBUS_TYPE_UINT32_AS_STRING << true << true; |
| 83 | QTest::newRow(dataTag: "int64" ) << DBUS_TYPE_INT64_AS_STRING << true << true; |
| 84 | QTest::newRow(dataTag: "uint64" ) << DBUS_TYPE_UINT64_AS_STRING << true << true; |
| 85 | QTest::newRow(dataTag: "double" ) << DBUS_TYPE_DOUBLE_AS_STRING << true << true; |
| 86 | |
| 87 | #ifdef DBUS_TYPE_UNIX_FD_AS_STRING |
| 88 | # ifndef QT_LINKED_LIBDBUS |
| 89 | // We have got the macro from dbus_minimal_p.h, so we need to check if |
| 90 | // the library recognizes this as valid type first. |
| 91 | // The following function was added for Unix FD support, so if it is |
| 92 | // present, so is support for Unix FDs. |
| 93 | # if QT_CONFIG(library) |
| 94 | bool supportsUnixFds = qdbus_resolve_conditionally("dbus_connection_can_send_type" ); |
| 95 | # else |
| 96 | bool supportsUnixFds = false; |
| 97 | # endif |
| 98 | # else |
| 99 | bool supportsUnixFds = true; |
| 100 | # endif |
| 101 | if (supportsUnixFds) |
| 102 | QTest::newRow(dataTag: "unixfd" ) << DBUS_TYPE_UNIX_FD_AS_STRING << true << true; |
| 103 | #endif |
| 104 | } |
| 105 | |
| 106 | static void addInvalidSingleLetterTypes() |
| 107 | { |
| 108 | QChar nulString[] = { 0 }; |
| 109 | QTest::newRow(dataTag: "nul" ) << QString(nulString, 1) << false << false; |
| 110 | QTest::newRow(dataTag: "tilde" ) << "~" << false << false; |
| 111 | QTest::newRow(dataTag: "struct-begin" ) << "(" << false << false; |
| 112 | QTest::newRow(dataTag: "struct-end" ) << ")" << false << false; |
| 113 | QTest::newRow(dataTag: "dict-entry-begin" ) << "{" << false << false; |
| 114 | QTest::newRow(dataTag: "dict-entry-end" ) << "}" << false << false; |
| 115 | QTest::newRow(dataTag: "array-no-element" ) << "a" << false << false; |
| 116 | } |
| 117 | |
| 118 | static void addBasicTypes(bool basicsAreValid) |
| 119 | { |
| 120 | addFixedTypes(); |
| 121 | QTest::newRow(dataTag: "string" ) << DBUS_TYPE_STRING_AS_STRING << basicsAreValid << true; |
| 122 | QTest::newRow(dataTag: "object-path" ) << DBUS_TYPE_OBJECT_PATH_AS_STRING << basicsAreValid << true; |
| 123 | QTest::newRow(dataTag: "signature" ) << DBUS_TYPE_SIGNATURE_AS_STRING << basicsAreValid << true; |
| 124 | } |
| 125 | |
| 126 | static void addVariant(bool variantIsValid) |
| 127 | { |
| 128 | QTest::newRow(dataTag: "variant" ) << "v" << variantIsValid << true; |
| 129 | } |
| 130 | |
| 131 | static void addSingleSignatures() |
| 132 | { |
| 133 | addBasicTypes(basicsAreValid: Valid); |
| 134 | addVariant(variantIsValid: Valid); |
| 135 | QTest::newRow(dataTag: "struct-1" ) << "(y)" << true; |
| 136 | QTest::newRow(dataTag: "struct-2" ) << "(yy)" << true; |
| 137 | QTest::newRow(dataTag: "struct-3" ) << "(yyv)" << true; |
| 138 | |
| 139 | QTest::newRow(dataTag: "struct-nested-1" ) << "((y))" << true; |
| 140 | QTest::newRow(dataTag: "struct-nested-2" ) << "((yy))" << true; |
| 141 | QTest::newRow(dataTag: "struct-nested-3" ) << "(y(y))" << true; |
| 142 | QTest::newRow(dataTag: "struct-nested-4" ) << "((y)y)" << true; |
| 143 | QTest::newRow(dataTag: "struct-nested-5" ) << "(y(y)y)" << true; |
| 144 | QTest::newRow(dataTag: "struct-nested-6" ) << "((y)(y))" << true; |
| 145 | |
| 146 | QTest::newRow(dataTag: "array-1" ) << "as" << true; |
| 147 | QTest::newRow(dataTag: "struct-array-1" ) << "(as)" << true; |
| 148 | QTest::newRow(dataTag: "struct-array-2" ) << "(yas)" << true; |
| 149 | QTest::newRow(dataTag: "struct-array-3" ) << "(asy)" << true; |
| 150 | QTest::newRow(dataTag: "struct-array-4" ) << "(yasy)" << true; |
| 151 | |
| 152 | QTest::newRow(dataTag: "dict-1" ) << "a{sy}" << true; |
| 153 | QTest::newRow(dataTag: "dict-2" ) << "a{sv}" << true; |
| 154 | QTest::newRow(dataTag: "dict-struct-1" ) << "a{s(y)}" << true; |
| 155 | QTest::newRow(dataTag: "dict-struct-2" ) << "a{s(yyyy)}" << true; |
| 156 | QTest::newRow(dataTag: "dict-struct-array" ) << "a{s(ay)}" << true; |
| 157 | QTest::newRow(dataTag: "dict-array" ) << "a{sas}" << true; |
| 158 | QTest::newRow(dataTag: "dict-array-struct" ) << "a{sa(y)}" << true; |
| 159 | |
| 160 | addInvalidSingleLetterTypes(); |
| 161 | QTest::newRow(dataTag: "naked-dict-empty" ) << "{}" << false; |
| 162 | QTest::newRow(dataTag: "naked-dict-missing-value" ) << "{i}" << false; |
| 163 | |
| 164 | QTest::newRow(dataTag: "dict-empty" ) << "a{}" << false; |
| 165 | QTest::newRow(dataTag: "dict-missing-value" ) << "a{i}" << false; |
| 166 | QTest::newRow(dataTag: "dict-non-basic-key" ) << "a{vi}" << false; |
| 167 | QTest::newRow(dataTag: "dict-struct-key" ) << "a{(y)y}" << false; |
| 168 | QTest::newRow(dataTag: "dict-missing-close" ) << "a{sv" << false; |
| 169 | QTest::newRow(dataTag: "dict-mismatched-close" ) << "a{sv)" << false; |
| 170 | QTest::newRow(dataTag: "dict-missing-value-close" ) << "a{s" << false; |
| 171 | |
| 172 | QTest::newRow(dataTag: "empty-struct" ) << "()" << false; |
| 173 | QTest::newRow(dataTag: "struct-missing-close" ) << "(s" << false; |
| 174 | QTest::newRow(dataTag: "struct-nested-missing-close-1" ) << "((s)" << false; |
| 175 | QTest::newRow(dataTag: "struct-nested-missing-close-2" ) << "((s" << false; |
| 176 | |
| 177 | QTest::newRow(dataTag: "struct-ending-array-no-element" ) << "(a)" << false; |
| 178 | } |
| 179 | |
| 180 | static void addNakedDictEntry() |
| 181 | { |
| 182 | QTest::newRow(dataTag: "naked-dict-entry" ) << "{sv}" << false; |
| 183 | } |
| 184 | |
| 185 | // ---- tests ---- |
| 186 | |
| 187 | void tst_QDBusType::isValidFixedType_data() |
| 188 | { |
| 189 | addColumns(); |
| 190 | addFixedTypes(); |
| 191 | addBasicTypes(basicsAreValid: Invalid); |
| 192 | addVariant(variantIsValid: Invalid); |
| 193 | addInvalidSingleLetterTypes(); |
| 194 | } |
| 195 | |
| 196 | void tst_QDBusType::isValidFixedType() |
| 197 | { |
| 198 | QFETCH(QString, data); |
| 199 | QFETCH(bool, result); |
| 200 | QFETCH(bool, isValid); |
| 201 | QVERIFY2(data.length() == 1, "Test is malformed, this function must test only one-letter types" ); |
| 202 | QVERIFY(isValid || (!isValid && !result)); |
| 203 | |
| 204 | int type = data.at(i: 0).unicode(); |
| 205 | if (isValid) |
| 206 | QCOMPARE(bool(q_dbus_type_is_fixed(type)), result); |
| 207 | QCOMPARE(QDBusUtil::isValidFixedType(type), result); |
| 208 | } |
| 209 | |
| 210 | void tst_QDBusType::isValidBasicType_data() |
| 211 | { |
| 212 | addColumns(); |
| 213 | addBasicTypes(basicsAreValid: Valid); |
| 214 | addVariant(variantIsValid: Invalid); |
| 215 | addInvalidSingleLetterTypes(); |
| 216 | } |
| 217 | |
| 218 | void tst_QDBusType::isValidBasicType() |
| 219 | { |
| 220 | QFETCH(QString, data); |
| 221 | QFETCH(bool, result); |
| 222 | QFETCH(bool, isValid); |
| 223 | QVERIFY2(data.length() == 1, "Test is malformed, this function must test only one-letter types" ); |
| 224 | QVERIFY(isValid || (!isValid && !result)); |
| 225 | |
| 226 | int type = data.at(i: 0).unicode(); |
| 227 | if (isValid) |
| 228 | QCOMPARE(bool(q_dbus_type_is_basic(type)), result); |
| 229 | QCOMPARE(QDBusUtil::isValidBasicType(type), result); |
| 230 | } |
| 231 | |
| 232 | void tst_QDBusType::isValidSingleSignature_data() |
| 233 | { |
| 234 | addColumns(); |
| 235 | addSingleSignatures(); |
| 236 | addNakedDictEntry(); |
| 237 | } |
| 238 | |
| 239 | void tst_QDBusType::isValidSingleSignature() |
| 240 | { |
| 241 | QFETCH(QString, data); |
| 242 | QFETCH(bool, result); |
| 243 | |
| 244 | QCOMPARE(bool(q_dbus_signature_validate_single(data.toLatin1(), 0)), result); |
| 245 | QCOMPARE(QDBusUtil::isValidSingleSignature(data), result); |
| 246 | } |
| 247 | |
| 248 | void tst_QDBusType::isValidArray_data() |
| 249 | { |
| 250 | addColumns(); |
| 251 | addSingleSignatures(); |
| 252 | } |
| 253 | |
| 254 | void tst_QDBusType::isValidArray() |
| 255 | { |
| 256 | QFETCH(QString, data); |
| 257 | QFETCH(bool, result); |
| 258 | |
| 259 | data.prepend(c: QLatin1Char('a')); |
| 260 | QCOMPARE(bool(q_dbus_signature_validate_single(data.toLatin1(), 0)), result); |
| 261 | QCOMPARE(QDBusUtil::isValidSingleSignature(data), result); |
| 262 | |
| 263 | data.prepend(c: QLatin1Char('a')); |
| 264 | QCOMPARE(bool(q_dbus_signature_validate_single(data.toLatin1(), 0)), result); |
| 265 | QCOMPARE(QDBusUtil::isValidSingleSignature(data), result); |
| 266 | } |
| 267 | |
| 268 | void tst_QDBusType::isValidSignature_data() |
| 269 | { |
| 270 | isValidSingleSignature_data(); |
| 271 | } |
| 272 | |
| 273 | void tst_QDBusType::isValidSignature() |
| 274 | { |
| 275 | QFETCH(QString, data); |
| 276 | QFETCH(bool, result); |
| 277 | |
| 278 | data.append(s: data); |
| 279 | if (data.at(i: 0).unicode()) |
| 280 | QCOMPARE(bool(q_dbus_signature_validate(data.toLatin1(), 0)), result); |
| 281 | QCOMPARE(QDBusUtil::isValidSignature(data), result); |
| 282 | } |
| 283 | |
| 284 | QTEST_MAIN(tst_QDBusType) |
| 285 | |
| 286 | #include "tst_qdbustype.moc" |
| 287 | |