From 4d3839eb99d720393e1386d63fa04c83367bb076 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 10 Dec 2009 11:29:22 +0100 Subject: Ensure that QProcessEnvironment::operator== doesn't crash Also add an extensive autotest suite for QProcessEnvironment Task-number: QTBUG-6701 Reviewed-by: Markus Goetz --- src/corelib/io/qprocess.cpp | 3 +- tests/auto/auto.pro | 1 + .../qprocessenvironment/qprocessenvironment.pro | 5 + .../tst_qprocessenvironment.cpp | 265 +++++++++++++++++++++ 4 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 tests/auto/qprocessenvironment/qprocessenvironment.pro create mode 100644 tests/auto/qprocessenvironment/tst_qprocessenvironment.cpp diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 37161bc..c78af3c 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -275,7 +275,7 @@ QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &o */ bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const { - return d->hash == other.d->hash; + return d == other.d || (d && other.d && d->hash == other.d->hash); } /*! @@ -334,6 +334,7 @@ bool QProcessEnvironment::contains(const QString &name) const */ void QProcessEnvironment::insert(const QString &name, const QString &value) { + // d detaches from null d->hash.insert(prepareName(name), prepareValue(value)); } diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 92d29ae..5041812 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -256,6 +256,7 @@ SUBDIRS += \ qprinter \ qprinterinfo \ qprocess \ + qprocessenvironment \ qprogressbar \ qprogressdialog \ qpropertyanimation \ diff --git a/tests/auto/qprocessenvironment/qprocessenvironment.pro b/tests/auto/qprocessenvironment/qprocessenvironment.pro new file mode 100644 index 0000000..398facc --- /dev/null +++ b/tests/auto/qprocessenvironment/qprocessenvironment.pro @@ -0,0 +1,5 @@ +load(qttest_p4) + +QT = core + +SOURCES += tst_qprocessenvironment.cpp diff --git a/tests/auto/qprocessenvironment/tst_qprocessenvironment.cpp b/tests/auto/qprocessenvironment/tst_qprocessenvironment.cpp new file mode 100644 index 0000000..1cde33c --- /dev/null +++ b/tests/auto/qprocessenvironment/tst_qprocessenvironment.cpp @@ -0,0 +1,265 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +// Note: +// in cross-platform tests, ALWAYS use UPPERCASE variable names +// That's because on Windows, the variables are uppercased + +class tst_QProcessEnvironment: public QObject +{ + Q_OBJECT +private slots: + void operator_eq(); + void clearAndIsEmpty(); + void insert(); + void emptyNull(); + void toStringList(); + + void caseSensitivity(); + void systemEnvironment(); + void putenv(); +}; + +void tst_QProcessEnvironment::operator_eq() +{ + QProcessEnvironment e1; + QVERIFY(e1 == e1); + e1.clear(); + QVERIFY(e1 == e1); + + e1 = QProcessEnvironment(); + QProcessEnvironment e2; + QVERIFY(e1 == e2); + + e1.clear(); + QVERIFY(e1 != e2); + + e2.clear(); + + QVERIFY(e1 == e2); +} + +void tst_QProcessEnvironment::clearAndIsEmpty() +{ + QProcessEnvironment e; + e.insert("FOO", "bar"); + QVERIFY(!e.isEmpty()); + e.clear(); + QVERIFY(e.isEmpty()); +} + +void tst_QProcessEnvironment::insert() +{ + QProcessEnvironment e; + e.insert("FOO", "bar"); + QVERIFY(!e.isEmpty()); + QVERIFY(e.contains("FOO")); + QCOMPARE(e.value("FOO"), QString("bar")); + + e.remove("FOO"); + QVERIFY(!e.contains("FOO")); + QVERIFY(e.value("FOO").isNull()); + + e.clear(); + QVERIFY(!e.contains("FOO")); +} + +void tst_QProcessEnvironment::emptyNull() +{ + QProcessEnvironment e; + + e.insert("FOO", ""); + QVERIFY(e.contains("FOO")); + QVERIFY(e.value("FOO").isEmpty()); + QVERIFY(!e.value("FOO").isNull()); + + e.insert("FOO", QString()); + QVERIFY(e.contains("FOO")); + QVERIFY(e.value("FOO").isEmpty()); + // don't test if it's NULL, since we shall not make a guarantee + + e.remove("FOO"); + QVERIFY(!e.contains("FOO")); +} + +void tst_QProcessEnvironment::toStringList() +{ + QProcessEnvironment e; + QVERIFY(e.isEmpty()); + QVERIFY(e.toStringList().isEmpty()); + + e.insert("FOO", "bar"); + QStringList result = e.toStringList(); + QVERIFY(!result.isEmpty()); + QCOMPARE(result.length(), 1); + QCOMPARE(result.at(0), QString("FOO=bar")); + + e.clear(); + e.insert("BAZ", ""); + result = e.toStringList(); + QCOMPARE(result.at(0), QString("BAZ=")); + + e.insert("FOO", "bar"); + e.insert("A", "bc"); + e.insert("HELLO", "World"); + result = e.toStringList(); + QCOMPARE(result.length(), 4); + + // order is not specified, so use contains() + QVERIFY(result.contains("FOO=bar")); + QVERIFY(result.contains("BAZ=")); + QVERIFY(result.contains("A=bc")); + QVERIFY(result.contains("HELLO=World")); +} + +void tst_QProcessEnvironment::caseSensitivity() +{ + QProcessEnvironment e; + e.insert("foo", "bar"); + +#ifdef Q_OS_WIN + // on Windows, it's uppercased + QVERIFY(e.contains("foo")); + QVERIFY(e.contains("FOO")); + QVERIFY(e.contains("FoO")); + + QCOMPARE(e.value("foo"), QString("bar")); + QCOMPARE(e.value("FOO"), QString("bar")); + QCOMPARE(e.value("FoO"), QString("bar")); + + QStringList list = e.toStringList(); + QCOMPARE(list.at(0), QString("FOO=bar")); +#else + // otherwise, it's case sensitive + QVERIFY(e.contains("foo")); + QVERIFY(!e.contains("FOO")); + + e.insert("FOO", "baz"); + QVERIFY(e.contains("FOO")); + QCOMPARE(e.value("FOO"), QString("baz")); + QCOMPARE(e.value("foo"), QString("bar")); + + QStringList list = e.toStringList(); + QVERIFY(list.contains("foo=bar")); + QVERIFY(list.contains("FOO=baz")); +#endif +} + +void tst_QProcessEnvironment::systemEnvironment() +{ + static const char envname[] = "THIS_ENVIRONMENT_VARIABLE_HOPEFULLY_DOESNT_EXIST"; + QByteArray path = qgetenv("PATH"); + QByteArray nonexistant = qgetenv(envname); + QProcessEnvironment system = QProcessEnvironment::systemEnvironment(); + + QVERIFY(nonexistant.isNull()); + +#ifdef Q_WS_WINCE + // Windows CE has no environment + QVERIFY(path.isEmpty()); + QVERIFY(!system.contains("PATH")); + QVERIFY(system.isEmpty()); +#else + // all other system have environments + if (path.isEmpty()) + QFAIL("Could not find the PATH environment variable -- please correct the test environment"); + + QVERIFY(system.contains("PATH")); + QCOMPARE(system.value("PATH"), QString::fromLocal8Bit(path)); + + QVERIFY(!system.contains(envname)); + +# ifdef Q_OS_WIN + // check case-insensitive too + QVERIFY(system.contains("path")); + QCOMPARE(system.value("path"), QString::fromLocal8Bit(path)); + + QVERIFY(!system.contains(QString(envname).toLower())); +# endif +#endif +} + +void tst_QProcessEnvironment::putenv() +{ +#ifdef Q_WS_WINCE + QSKIP("Windows CE has no environment", SkipAll); +#else + static const char envname[] = "WE_RE_SETTING_THIS_ENVIRONMENT_VARIABLE"; + static bool testRan = false; + + if (testRan) + QFAIL("You cannot run this test more than once, since we modify the environment"); + testRan = true; + + QByteArray valBefore = qgetenv(envname); + if (!valBefore.isNull()) + QFAIL("The environment variable we set in the environment is already set! -- please correct the test environment"); + QProcessEnvironment eBefore = QProcessEnvironment::systemEnvironment(); + + qputenv(envname, "Hello, World"); + QByteArray valAfter = qgetenv(envname); + if (valAfter != "Hello, World") + QSKIP("Could not test: qputenv did not do its job", SkipAll); + + QProcessEnvironment eAfter = QProcessEnvironment::systemEnvironment(); + + QVERIFY(!eBefore.contains(envname)); + QVERIFY(eAfter.contains(envname)); + QCOMPARE(eAfter.value(envname), QString("Hello, World")); + +# ifdef Q_OS_WIN + // check case-insensitive too + QString lower = envname; + lower = lower.toLower(); + QVERIFY(!eBefore.contains(lower)); + QVERIFY(eAfter.contains(lower)); + QCOMPARE(eAfter.value(lower), QString("Hello, World")); +# endif +#endif +} + +QTEST_MAIN(tst_QProcessEnvironment) + +#include "tst_qprocessenvironment.moc" -- cgit v0.12