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 test suite 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 <qdebug.h> |
31 | #include <QtTest/QtTest> |
32 | |
33 | #include <qglobal.h> |
34 | #ifdef Q_OS_WIN |
35 | #include <qt_windows.h> |
36 | #endif |
37 | |
38 | class tst_QGetPutEnv : public QObject |
39 | { |
40 | Q_OBJECT |
41 | private slots: |
42 | void getSetCheck(); |
43 | void encoding(); |
44 | void intValue_data(); |
45 | void intValue(); |
46 | }; |
47 | |
48 | void tst_QGetPutEnv::getSetCheck() |
49 | { |
50 | const char varName[] = "should_not_exist" ; |
51 | |
52 | bool ok; |
53 | |
54 | QVERIFY(!qEnvironmentVariableIsSet(varName)); |
55 | QVERIFY(qEnvironmentVariableIsEmpty(varName)); |
56 | ok = true; |
57 | QCOMPARE(qEnvironmentVariableIntValue(varName), 0); |
58 | QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0); |
59 | QVERIFY(!ok); |
60 | QByteArray result = qgetenv(varName); |
61 | QVERIFY(result.isNull()); |
62 | QString sresult = qEnvironmentVariable(varName); |
63 | QVERIFY(sresult.isNull()); |
64 | sresult = qEnvironmentVariable(varName, defaultValue: "hello" ); |
65 | QCOMPARE(sresult, QString("hello" )); |
66 | |
67 | #ifndef Q_OS_WIN |
68 | QVERIFY(qputenv(varName, "" )); // deletes varName instead of making it empty, on Windows |
69 | |
70 | QVERIFY(qEnvironmentVariableIsSet(varName)); |
71 | QVERIFY(qEnvironmentVariableIsEmpty(varName)); |
72 | ok = true; |
73 | QCOMPARE(qEnvironmentVariableIntValue(varName), 0); |
74 | QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0); |
75 | QVERIFY(!ok); |
76 | |
77 | result = qgetenv(varName); |
78 | QVERIFY(!result.isNull()); |
79 | QCOMPARE(result, QByteArray()); |
80 | sresult = qEnvironmentVariable(varName); |
81 | QVERIFY(!sresult.isNull()); |
82 | QCOMPARE(sresult, QString()); |
83 | sresult = qEnvironmentVariable(varName, defaultValue: "hello" ); |
84 | QVERIFY(!sresult.isNull()); |
85 | QCOMPARE(sresult, QString()); |
86 | #endif |
87 | |
88 | QVERIFY(qputenv(varName, QByteArray("supervalue" ))); |
89 | |
90 | QVERIFY(qEnvironmentVariableIsSet(varName)); |
91 | QVERIFY(!qEnvironmentVariableIsEmpty(varName)); |
92 | ok = true; |
93 | QCOMPARE(qEnvironmentVariableIntValue(varName), 0); |
94 | QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0); |
95 | QVERIFY(!ok); |
96 | result = qgetenv(varName); |
97 | QCOMPARE(result, QByteArrayLiteral("supervalue" )); |
98 | sresult = qEnvironmentVariable(varName); |
99 | QCOMPARE(sresult, QString("supervalue" )); |
100 | sresult = qEnvironmentVariable(varName, defaultValue: "hello" ); |
101 | QCOMPARE(sresult, QString("supervalue" )); |
102 | |
103 | qputenv(varName,value: QByteArray()); |
104 | |
105 | // Now test qunsetenv |
106 | QVERIFY(qunsetenv(varName)); |
107 | QVERIFY(!qEnvironmentVariableIsSet(varName)); // note: might fail on some systems! |
108 | QVERIFY(qEnvironmentVariableIsEmpty(varName)); |
109 | ok = true; |
110 | QCOMPARE(qEnvironmentVariableIntValue(varName), 0); |
111 | QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0); |
112 | QVERIFY(!ok); |
113 | |
114 | result = qgetenv(varName); |
115 | QVERIFY(result.isNull()); |
116 | sresult = qEnvironmentVariable(varName); |
117 | QVERIFY(sresult.isNull()); |
118 | sresult = qEnvironmentVariable(varName, defaultValue: "hello" ); |
119 | QCOMPARE(sresult, QString("hello" )); |
120 | } |
121 | |
122 | void tst_QGetPutEnv::encoding() |
123 | { |
124 | // The test string is: |
125 | // U+0061 LATIN SMALL LETTER A |
126 | // U+00E1 LATIN SMALL LETTER A WITH ACUTE |
127 | // U+03B1 GREEK SMALL LETTER ALPHA |
128 | // U+0430 CYRILLIC SMALL LETTER A |
129 | // This has letters in three different scripts, so no locale besides |
130 | // UTF-8 is able handle them all. |
131 | // The LATIN SMALL LETTER A WITH ACUTE is NFC for NFD: |
132 | // U+0061 U+0301 LATIN SMALL LETTER A + COMBINING ACUTE ACCENT |
133 | |
134 | const char varName[] = "should_not_exist" ; |
135 | static const wchar_t rawvalue[] = { 'a', 0x00E1, 0x03B1, 0x0430, 0 }; |
136 | QString value = QString::fromWCharArray(string: rawvalue); |
137 | |
138 | #if defined(Q_OS_WINRT) |
139 | QSKIP("Test cannot be run on this platform" ); |
140 | #elif defined(Q_OS_WIN) |
141 | const wchar_t wvarName[] = L"should_not_exist" ; |
142 | _wputenv_s(wvarName, rawvalue); |
143 | #else |
144 | // confirm the locale is UTF-8 |
145 | if (value.toLocal8Bit() != "a\xc3\xa1\xce\xb1\xd0\xb0" ) |
146 | QSKIP("Locale is not UTF-8, cannot test" ); |
147 | |
148 | qputenv(varName, value: QFile::encodeName(fileName: value)); |
149 | #endif |
150 | |
151 | QVERIFY(qEnvironmentVariableIsSet(varName)); |
152 | QCOMPARE(qEnvironmentVariable(varName), value); |
153 | } |
154 | |
155 | void tst_QGetPutEnv::intValue_data() |
156 | { |
157 | QTest::addColumn<QByteArray>(name: "value" ); |
158 | QTest::addColumn<int>(name: "expected" ); |
159 | QTest::addColumn<bool>(name: "ok" ); |
160 | |
161 | // some repetition from what is tested in getSetCheck() |
162 | QTest::newRow(dataTag: "empty" ) << QByteArray() << 0 << false; |
163 | QTest::newRow(dataTag: "spaces-heading" ) << QByteArray(" \n\r\t1" ) << 1 << true; |
164 | QTest::newRow(dataTag: "spaces-trailing" ) << QByteArray("1 \n\r\t" ) << 1 << true; |
165 | QTest::newRow(dataTag: "junk-heading" ) << QByteArray("x1" ) << 0 << false; |
166 | QTest::newRow(dataTag: "junk-trailing" ) << QByteArray("1x" ) << 0 << false; |
167 | |
168 | #define ROW(x, i, b) \ |
169 | QTest::newRow(#x) << QByteArray(#x) << (i) << (b) |
170 | ROW(auto, 0, false); |
171 | ROW(1auto, 0, false); |
172 | ROW(0, 0, true); |
173 | ROW(+0, 0, true); |
174 | ROW(1, 1, true); |
175 | ROW(+1, 1, true); |
176 | ROW(09, 0, false); |
177 | ROW(010, 8, true); |
178 | ROW(0x10, 16, true); |
179 | ROW(0x, 0, false); |
180 | ROW(0xg, 0, false); |
181 | ROW(0x1g, 0, false); |
182 | ROW(000000000000000000000000000000000000000000000000001, 0, false); |
183 | ROW(+000000000000000000000000000000000000000000000000001, 0, false); |
184 | ROW(000000000000000000000000000000000000000000000000001g, 0, false); |
185 | ROW(-0, 0, true); |
186 | ROW(-1, -1, true); |
187 | ROW(-010, -8, true); |
188 | ROW(-000000000000000000000000000000000000000000000000001, 0, false); |
189 | ROW(2147483648, 0, false); |
190 | // ROW(0xffffffff, -1, true); // could be expected, but not how QByteArray::toInt() works |
191 | ROW(0xffffffff, 0, false); |
192 | const int bases[] = {10, 8, 16}; |
193 | for (size_t i = 0; i < sizeof bases / sizeof *bases; ++i) { |
194 | QTest::addRow(format: "INT_MAX, base %d" , bases[i]) |
195 | << QByteArray::number(INT_MAX) << INT_MAX << true; |
196 | QTest::addRow(format: "INT_MAX+1, base %d" , bases[i]) |
197 | << QByteArray::number(qlonglong(INT_MAX) + 1) << 0 << false; |
198 | QTest::addRow(format: "INT_MIN, base %d" , bases[i]) |
199 | << QByteArray::number(INT_MIN) << INT_MIN << true; |
200 | QTest::addRow(format: "INT_MIN-1, base %d" , bases[i]) |
201 | << QByteArray::number(qlonglong(INT_MIN) - 1) << 0 << false; |
202 | }; |
203 | } |
204 | |
205 | void tst_QGetPutEnv::intValue() |
206 | { |
207 | const int maxlen = (sizeof(int) * CHAR_BIT + 2) / 3; |
208 | const char varName[] = "should_not_exist" ; |
209 | |
210 | QFETCH(QByteArray, value); |
211 | QFETCH(int, expected); |
212 | QFETCH(bool, ok); |
213 | |
214 | bool actualOk = !ok; |
215 | |
216 | // Self-test: confirm that it was like the docs said it should be |
217 | if (value.length() < maxlen) { |
218 | QCOMPARE(value.toInt(&actualOk, 0), expected); |
219 | QCOMPARE(actualOk, ok); |
220 | } |
221 | |
222 | actualOk = !ok; |
223 | QVERIFY(qputenv(varName, value)); |
224 | QCOMPARE(qEnvironmentVariableIntValue(varName), expected); |
225 | QCOMPARE(qEnvironmentVariableIntValue(varName, &actualOk), expected); |
226 | QCOMPARE(actualOk, ok); |
227 | } |
228 | |
229 | QTEST_MAIN(tst_QGetPutEnv) |
230 | #include "tst_qgetputenv.moc" |
231 | |