From 404598b61366e681100893052fdb394702d3bcbf Mon Sep 17 00:00:00 2001 From: David Faure Date: Sat, 24 Aug 2013 11:15:19 +0200 Subject: Long live QCommandLineParser! The QCommandLineParser class provides a means for handling the command line options. QCoreApplication provides the command-line arguments as a simple list of strings. QCommandLineParser provides the ability to define a set of options, parse the command-line arguments, and store which options have actually been used, as well as option values. Done-with: Laszlo Papp Change-Id: Ic7bebc10b3f8d8dd06ad0f4bb897c51d566e3b7c Reviewed-by: Thiago Macieira --- .../qcommandlineparser/qcommandlineparser.pro | 3 + .../testhelper/qcommandlineparser_test_helper.cpp | 93 ++++ .../testhelper/qcommandlineparser_test_helper.pro | 6 + .../qcommandlineparser/tst_qcommandlineparser.cpp | 531 +++++++++++++++++++++ .../qcommandlineparser/tst_qcommandlineparser.pro | 4 + tests/auto/corelib/tools/tools.pro | 1 + 6 files changed, 638 insertions(+) create mode 100644 tests/auto/corelib/tools/qcommandlineparser/qcommandlineparser.pro create mode 100644 tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp create mode 100644 tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.pro create mode 100644 tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp create mode 100644 tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.pro (limited to 'tests') diff --git a/tests/auto/corelib/tools/qcommandlineparser/qcommandlineparser.pro b/tests/auto/corelib/tools/qcommandlineparser/qcommandlineparser.pro new file mode 100644 index 0000000000..a9aedc4c0d --- /dev/null +++ b/tests/auto/corelib/tools/qcommandlineparser/qcommandlineparser.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS += tst_qcommandlineparser.pro testhelper/qcommandlineparser_test_helper.pro diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp new file mode 100644 index 0000000000..c7bd2a5dc9 --- /dev/null +++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2013 David Faure +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + app.setApplicationVersion("1.0"); + + QCommandLineParser parser; + parser.setApplicationDescription("Test helper"); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument("parsingMode", "The parsing mode to test."); + parser.addPositionalArgument("command", "The command to execute."); + parser.addOption(QCommandLineOption("load", "Load file from URL.", "url")); + parser.addOption(QCommandLineOption(QStringList() << "o" << "output", "Set output file.", "file")); + parser.addOption(QCommandLineOption("D", "Define macro.", "key=value")); + + // An option with a longer description, to test wrapping + QCommandLineOption noImplicitIncludesOption(QStringList() << QStringLiteral("n") << QStringLiteral("no-implicit-includes")); + noImplicitIncludesOption.setDescription(QStringLiteral("Disable automatic generation of implicit #include-directives.")); + parser.addOption(noImplicitIncludesOption); + + // This program supports different options depending on the "command" (first argument). + // Call parse() to find out the positional arguments. + parser.parse(QCoreApplication::arguments()); + + QStringList args = parser.positionalArguments(); + if (args.isEmpty()) + parser.showHelp(1); + parser.setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode(args.takeFirst().toInt())); + const QString command = args.isEmpty() ? QString() : args.first(); + if (command == "resize") { + parser.clearPositionalArguments(); + parser.addPositionalArgument("resize", "Resize the object to a new size.", "resize [resize_options]"); + parser.addOption(QCommandLineOption("size", "New size.", "size")); + parser.process(app); + const QString size = parser.value("size"); + printf("Resizing %s to %s and saving to %s\n", qPrintable(parser.value("load")), qPrintable(size), qPrintable(parser.value("o"))); + } else { + // Call process again, to handle unknown options this time. + parser.process(app); + } + + printf("Positional arguments: %s\n", qPrintable(parser.positionalArguments().join(","))); + + return 0; +} + diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.pro b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.pro new file mode 100644 index 0000000000..dce1ac0d37 --- /dev/null +++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.pro @@ -0,0 +1,6 @@ +CONFIG += console +CONFIG -= app_bundle +QT = core +DESTDIR = ./ + +SOURCES += qcommandlineparser_test_helper.cpp diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp new file mode 100644 index 0000000000..79ab212d47 --- /dev/null +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -0,0 +1,531 @@ +/**************************************************************************** +** +** Copyright (C) 2013 David Faure +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +Q_DECLARE_METATYPE(char**) + +class tst_QCommandLineParser : public QObject +{ + Q_OBJECT + +private slots: + void parsingModes_data(); + + // In-process tests + void testInvalidOptions(); + void testPositionalArguments(); + void testBooleanOption_data(); + void testBooleanOption(); + void testMultipleNames_data(); + void testMultipleNames(); + void testSingleValueOption_data(); + void testSingleValueOption(); + void testValueNotSet(); + void testMultipleValuesOption(); + void testUnknownOptionErrorHandling_data(); + void testUnknownOptionErrorHandling(); + void testDoubleDash_data(); + void testDoubleDash(); + void testProcessNotCalled(); + void testEmptyArgsList(); + void testMissingOptionValue(); + void testStdinArgument_data(); + void testStdinArgument(); + void testSingleDashWordOptionModes_data(); + void testSingleDashWordOptionModes(); + + // QProcess-based tests using qcommandlineparser_test_helper + void testVersionOption(); + void testHelpOption_data(); + void testHelpOption(); +}; + +static char *empty_argv[] = { const_cast("tst_qcommandlineparser") }; +static int empty_argc = 1; + +Q_DECLARE_METATYPE(QCommandLineParser::SingleDashWordOptionMode) + +void tst_QCommandLineParser::parsingModes_data() +{ + QTest::addColumn("parsingMode"); + + QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions; + QTest::newRow("implicitlylong") << QCommandLineParser::ParseAsLongOptions; +} + +void tst_QCommandLineParser::testInvalidOptions() +{ + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + QTest::ignoreMessage(QtWarningMsg, "Option names cannot start with a '-'"); + parser.addOption(QCommandLineOption(QStringLiteral("-v"), QStringLiteral("Displays version information."))); +} + +void tst_QCommandLineParser::testPositionalArguments() +{ + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "file.txt")); + QCOMPARE(parser.positionalArguments(), QStringList() << QStringLiteral("file.txt")); +} + +void tst_QCommandLineParser::testBooleanOption_data() +{ + QTest::addColumn("args"); + QTest::addColumn("expectedOptionNames"); + QTest::addColumn("expectedIsSet"); + + QTest::newRow("set") << (QStringList() << "tst_qcommandlineparser" << "-b") << (QStringList() << "b") << true; + QTest::newRow("unset") << (QStringList() << "tst_qcommandlineparser") << QStringList() << false; +} + +void tst_QCommandLineParser::testBooleanOption() +{ + QFETCH(QStringList, args); + QFETCH(QStringList, expectedOptionNames); + QFETCH(bool, expectedIsSet); + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + QVERIFY(parser.addOption(QCommandLineOption(QStringLiteral("b"), QStringLiteral("a boolean option")))); + QVERIFY(parser.parse(args)); + QCOMPARE(parser.optionNames(), expectedOptionNames); + QCOMPARE(parser.isSet("b"), expectedIsSet); + QCOMPARE(parser.values("b"), QStringList()); + QCOMPARE(parser.positionalArguments(), QStringList()); + // Should warn on typos + QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not defined: \"c\""); + QVERIFY(!parser.isSet("c")); +} + +void tst_QCommandLineParser::testMultipleNames_data() +{ + QTest::addColumn("args"); + QTest::addColumn("expectedOptionNames"); + + QTest::newRow("short") << (QStringList() << "tst_qcommandlineparser" << "-v") << (QStringList() << "v"); + QTest::newRow("long") << (QStringList() << "tst_qcommandlineparser" << "--version") << (QStringList() << "version"); + QTest::newRow("not_set") << (QStringList() << "tst_qcommandlineparser") << QStringList(); +} + +void tst_QCommandLineParser::testMultipleNames() +{ + QFETCH(QStringList, args); + QFETCH(QStringList, expectedOptionNames); + QCoreApplication app(empty_argc, empty_argv); + QCommandLineOption option(QStringList() << "v" << "version", QStringLiteral("Show version information")); + QCOMPARE(option.names(), QStringList() << "v" << "version"); + QCommandLineParser parser; + QVERIFY(parser.addOption(option)); + QVERIFY(parser.parse(args)); + QCOMPARE(parser.optionNames(), expectedOptionNames); + const bool expectedIsSet = !expectedOptionNames.isEmpty(); + QCOMPARE(parser.isSet("v"), expectedIsSet); + QCOMPARE(parser.isSet("version"), expectedIsSet); +} + +void tst_QCommandLineParser::testSingleValueOption_data() +{ + QTest::addColumn("args"); + QTest::addColumn("defaults"); + QTest::addColumn("expectedIsSet"); + + QTest::newRow("short") << (QStringList() << "tst" << "-s" << "oxygen") << QStringList() << true; + QTest::newRow("long") << (QStringList() << "tst" << "--style" << "oxygen") << QStringList() << true; + QTest::newRow("longequal") << (QStringList() << "tst" << "--style=oxygen") << QStringList() << true; + QTest::newRow("default") << (QStringList() << "tst") << (QStringList() << "oxygen") << false; +} + +void tst_QCommandLineParser::testSingleValueOption() +{ + QFETCH(QStringList, args); + QFETCH(QStringList, defaults); + QFETCH(bool, expectedIsSet); + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + QCommandLineOption option(QStringList() << "s" << "style", QStringLiteral("style name"), "styleName"); + option.setDefaultValues(defaults); + QVERIFY(parser.addOption(option)); + for (int mode = 0; mode < 2; ++mode) { + parser.setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode(mode)); + QVERIFY(parser.parse(args)); + QCOMPARE(parser.isSet("s"), expectedIsSet); + QCOMPARE(parser.isSet("style"), expectedIsSet); + QCOMPARE(parser.isSet(option), expectedIsSet); + QCOMPARE(parser.value("s"), QString("oxygen")); + QCOMPARE(parser.value("style"), QString("oxygen")); + QCOMPARE(parser.values("s"), QStringList() << "oxygen"); + QCOMPARE(parser.values("style"), QStringList() << "oxygen"); + QCOMPARE(parser.values(option), QStringList() << "oxygen"); + QCOMPARE(parser.positionalArguments(), QStringList()); + } + // Should warn on typos + QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not defined: \"c\""); + QVERIFY(parser.values("c").isEmpty()); +} + +void tst_QCommandLineParser::testValueNotSet() +{ + QCoreApplication app(empty_argc, empty_argv); + // Not set, no default value + QCommandLineParser parser; + QCommandLineOption option(QStringList() << "s" << "style", QStringLiteral("style name")); + option.setValueName("styleName"); + QVERIFY(parser.addOption(option)); + QVERIFY(parser.parse(QStringList() << "tst")); + QCOMPARE(parser.optionNames(), QStringList()); + QVERIFY(!parser.isSet("s")); + QVERIFY(!parser.isSet("style")); + QCOMPARE(parser.value("s"), QString()); + QCOMPARE(parser.value("style"), QString()); + QCOMPARE(parser.values("s"), QStringList()); + QCOMPARE(parser.values("style"), QStringList()); +} + +void tst_QCommandLineParser::testMultipleValuesOption() +{ + QCoreApplication app(empty_argc, empty_argv); + QCommandLineOption option(QStringLiteral("param"), QStringLiteral("Pass parameter to the backend.")); + option.setValueName("key=value"); + QCommandLineParser parser; + QVERIFY(parser.addOption(option)); + { + QVERIFY(parser.parse(QStringList() << "tst" << "--param" << "key1=value1")); + QVERIFY(parser.isSet("param")); + QCOMPARE(parser.values("param"), QStringList() << "key1=value1"); + QCOMPARE(parser.value("param"), QString("key1=value1")); + } + { + QVERIFY(parser.parse(QStringList() << "tst" << "--param" << "key1=value1" << "--param" << "key2=value2")); + QVERIFY(parser.isSet("param")); + QCOMPARE(parser.values("param"), QStringList() << "key1=value1" << "key2=value2"); + QCOMPARE(parser.value("param"), QString("key2=value2")); + } + + QString expected = + "Usage: tst_qcommandlineparser [options]\n" + "\n" + "Options:\n" + " --param Pass parameter to the backend.\n"; + + const QString exeName = QCoreApplication::instance()->arguments().first(); // e.g. debug\tst_qcommandlineparser.exe on Windows + expected.replace(QStringLiteral("tst_qcommandlineparser"), exeName); + QCOMPARE(parser.helpText(), expected); +} + +void tst_QCommandLineParser::testUnknownOptionErrorHandling_data() +{ + QTest::addColumn("parsingMode"); + QTest::addColumn("args"); + QTest::addColumn("expectedUnknownOptionNames"); + QTest::addColumn("expectedErrorText"); + + const QStringList args_hello = QStringList() << "tst_qcommandlineparser" << "--hello"; + const QString error_hello("Unknown option 'hello'."); + QTest::newRow("unknown_name_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_hello << QStringList("hello") << error_hello; + QTest::newRow("unknown_name_long") << QCommandLineParser::ParseAsLongOptions << args_hello << QStringList("hello") << error_hello; + + const QStringList args_value = QStringList() << "tst_qcommandlineparser" << "-b=1"; + QTest::newRow("bool_with_value_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_value << QStringList() << QString("Unexpected value after '-b'."); + QTest::newRow("bool_with_value_long") << QCommandLineParser::ParseAsLongOptions << args_value << QStringList() << QString("Unexpected value after '-b'."); + + const QStringList args_dash_long = QStringList() << "tst_qcommandlineparser" << "-bool"; + const QString error_bool("Unknown options: o, o, l."); + QTest::newRow("unknown_name_long_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_dash_long << (QStringList() << "o" << "o" << "l") << error_bool; +} + +void tst_QCommandLineParser::testUnknownOptionErrorHandling() +{ + QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); + QFETCH(QStringList, args); + QFETCH(QStringList, expectedUnknownOptionNames); + QFETCH(QString, expectedErrorText); + + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + parser.setSingleDashWordOptionMode(parsingMode); + QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "b" << "bool", QStringLiteral("a boolean option")))); + QCOMPARE(parser.parse(args), expectedErrorText.isEmpty()); + QCOMPARE(parser.unknownOptionNames(), expectedUnknownOptionNames); + QCOMPARE(parser.errorText(), expectedErrorText); +} + +void tst_QCommandLineParser::testDoubleDash_data() +{ + parsingModes_data(); +} + +void tst_QCommandLineParser::testDoubleDash() +{ + QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); + + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + parser.addOption(QCommandLineOption(QStringList() << "o" << "output", QStringLiteral("Output file"), QStringLiteral("filename"))); + parser.setSingleDashWordOptionMode(parsingMode); + QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "--output" << "foo")); + QCOMPARE(parser.value("output"), QString("foo")); + QCOMPARE(parser.positionalArguments(), QStringList()); + QCOMPARE(parser.unknownOptionNames(), QStringList()); + QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "--" << "--output" << "bar" << "-b" << "bleh")); + QCOMPARE(parser.value("output"), QString()); + QCOMPARE(parser.positionalArguments(), QStringList() << "--output" << "bar" << "-b" << "bleh"); + QCOMPARE(parser.unknownOptionNames(), QStringList()); +} + +void tst_QCommandLineParser::testProcessNotCalled() +{ + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + QVERIFY(parser.addOption(QCommandLineOption(QStringLiteral("b"), QStringLiteral("a boolean option")))); + QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: call process() or parse() before isSet"); + QVERIFY(!parser.isSet("b")); + QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: call process() or parse() before values"); + QCOMPARE(parser.values("b"), QStringList()); +} + +void tst_QCommandLineParser::testEmptyArgsList() +{ + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: argument list cannot be empty, it should contain at least the executable name"); + QVERIFY(!parser.parse(QStringList())); // invalid call, argv[0] is missing +} + +void tst_QCommandLineParser::testMissingOptionValue() +{ + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + parser.addOption(QCommandLineOption(QStringLiteral("option"), QStringLiteral("An option"), "value")); + QVERIFY(!parser.parse(QStringList() << "argv0" << "--option")); // the user forgot to pass a value for --option + QCOMPARE(parser.value("option"), QString()); + QCOMPARE(parser.errorText(), QString("Missing value after '--option'.")); +} + +void tst_QCommandLineParser::testStdinArgument_data() +{ + parsingModes_data(); +} + +void tst_QCommandLineParser::testStdinArgument() +{ + QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); + + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + parser.setSingleDashWordOptionMode(parsingMode); + parser.addOption(QCommandLineOption(QStringList() << "i" << "input", QStringLiteral("Input file."), QStringLiteral("filename"))); + parser.addOption(QCommandLineOption("b", QStringLiteral("Boolean option."))); + QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "--input" << "-")); + QCOMPARE(parser.value("input"), QString("-")); + QCOMPARE(parser.positionalArguments(), QStringList()); + QCOMPARE(parser.unknownOptionNames(), QStringList()); + + QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "--input" << "-" << "-b" << "arg")); + QCOMPARE(parser.value("input"), QString("-")); + QVERIFY(parser.isSet("b")); + QCOMPARE(parser.positionalArguments(), QStringList() << "arg"); + QCOMPARE(parser.unknownOptionNames(), QStringList()); + + QVERIFY(parser.parse(QStringList() << "tst_qcommandlineparser" << "-")); + QCOMPARE(parser.value("input"), QString()); + QVERIFY(!parser.isSet("b")); + QCOMPARE(parser.positionalArguments(), QStringList() << "-"); + QCOMPARE(parser.unknownOptionNames(), QStringList()); +} + +void tst_QCommandLineParser::testSingleDashWordOptionModes_data() +{ + QTest::addColumn("parsingMode"); + QTest::addColumn("commandLine"); + QTest::addColumn("expectedOptionNames"); + QTest::addColumn("expectedOptionValues"); + + QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-abc" << "val") + << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val"); + QTest::newRow("collapsed_with_equalsign_value") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-abc=val") + << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val"); + QTest::newRow("collapsed_explicit_longoption") << QCommandLineParser::ParseAsCompactedShortOptions << QStringList("--nn") + << QStringList("nn") << QStringList(); + QTest::newRow("collapsed_longoption_value") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "--abc" << "val") + << QStringList("abc") << QStringList("val"); + QTest::newRow("compiler") << QCommandLineParser::ParseAsCompactedShortOptions << QStringList("-cab") + << QStringList("c") << QStringList("ab"); + QTest::newRow("compiler_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val") + << QStringList("c") << QStringList("val"); + + QTest::newRow("implicitlylong") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-abc" << "val") + << QStringList("abc") << QStringList("val"); + QTest::newRow("implicitlylong_equal") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-abc=val") + << QStringList("abc") << QStringList("val"); + QTest::newRow("implicitlylong_longoption") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "--nn") + << QStringList("nn") << QStringList(); + QTest::newRow("implicitlylong_longoption_value") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "--abc" << "val") + << QStringList("abc") << QStringList("val"); + QTest::newRow("implicitlylong_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val") + << QStringList("c") << QStringList("val"); +} + +void tst_QCommandLineParser::testSingleDashWordOptionModes() +{ + QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); + QFETCH(QStringList, commandLine); + QFETCH(QStringList, expectedOptionNames); + QFETCH(QStringList, expectedOptionValues); + + commandLine.prepend("tst_QCommandLineParser"); + + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + parser.setSingleDashWordOptionMode(parsingMode); + parser.addOption(QCommandLineOption("a", QStringLiteral("a option."))); + parser.addOption(QCommandLineOption("b", QStringLiteral("b option."))); + parser.addOption(QCommandLineOption(QStringList() << "c" << "abc", QStringLiteral("c option."), QStringLiteral("value"))); + parser.addOption(QCommandLineOption("nn", QStringLiteral("nn option."))); + QVERIFY(parser.parse(commandLine)); + QCOMPARE(parser.optionNames(), expectedOptionNames); + for (int i = 0; i < expectedOptionValues.count(); ++i) + QCOMPARE(parser.value(parser.optionNames().at(i)), expectedOptionValues.at(i)); + QCOMPARE(parser.unknownOptionNames(), QStringList()); +} + +void tst_QCommandLineParser::testVersionOption() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE"); +#endif + QCoreApplication app(empty_argc, empty_argv); + QProcess process; + process.start("testhelper/qcommandlineparser_test_helper", QStringList() << "0" << "--version"); + QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QString output = process.readAll(); +#ifdef Q_OS_WIN + output.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); +#endif + QCOMPARE(output, QString("qcommandlineparser_test_helper 1.0\n")); +} + +void tst_QCommandLineParser::testHelpOption_data() +{ + QTest::addColumn("parsingMode"); + QTest::addColumn("expectedHelpOutput"); + + QString expectedOutput = + "Usage: testhelper/qcommandlineparser_test_helper [options] parsingMode command\n" + "Test helper\n" + "\n" + "Options:\n" + " -h, --help Displays this help.\n" + " -v, --version Displays version information.\n" + " --load Load file from URL.\n" + " -o, --output Set output file.\n" + " -D Define macro.\n" + " -n, --no-implicit-includes Disable automatic generation of implicit #include\n" + " -directives.\n" + "\n" + "Arguments:\n" + " parsingMode The parsing mode to test.\n" + " command The command to execute.\n"; +#ifdef Q_OS_WIN + expectedOutput.replace(" -h, --help Displays this help.\n", + " -?, -h, --help Displays this help.\n"); + expectedOutput.replace("testhelper/", "testhelper\\"); +#endif + + QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << expectedOutput; + QTest::newRow("long") << QCommandLineParser::ParseAsLongOptions << expectedOutput; +} + +void tst_QCommandLineParser::testHelpOption() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE"); +#endif + + QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); + QFETCH(QString, expectedHelpOutput); + QCoreApplication app(empty_argc, empty_argv); + QProcess process; + process.start("testhelper/qcommandlineparser_test_helper", QStringList() << QString::number(parsingMode) << "--help"); + QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QString output = process.readAll(); +#ifdef Q_OS_WIN + output.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); +#endif + QCOMPARE(output, expectedHelpOutput); + + process.start("testhelper/qcommandlineparser_test_helper", QStringList() << "0" << "resize" << "--help"); + QVERIFY(process.waitForFinished(5000)); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + output = process.readAll(); +#ifdef Q_OS_WIN + output.replace(QStringLiteral("\r\n"), QStringLiteral("\n")); +#endif + QByteArray expectedResizeHelp = + "Usage: testhelper/qcommandlineparser_test_helper [options] resize [resize_options]\n" + "Test helper\n" + "\n" + "Options:\n" + " -h, --help Displays this help.\n" + " -v, --version Displays version information.\n" + " --load Load file from URL.\n" + " -o, --output Set output file.\n" + " -D Define macro.\n" + " -n, --no-implicit-includes Disable automatic generation of implicit #include\n" + " -directives.\n" + " --size New size.\n" + "\n" + "Arguments:\n" + " resize Resize the object to a new size.\n"; +#ifdef Q_OS_WIN + expectedResizeHelp.replace(" -h, --help Displays this help.\n", + " -?, -h, --help Displays this help.\n"); + expectedResizeHelp.replace("testhelper/", "testhelper\\"); +#endif + QCOMPARE(output, QString(expectedResizeHelp)); +} + +QTEST_APPLESS_MAIN(tst_QCommandLineParser) +#include "tst_qcommandlineparser.moc" + diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.pro b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.pro new file mode 100644 index 0000000000..6d3e6d677f --- /dev/null +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.pro @@ -0,0 +1,4 @@ +CONFIG += testcase parallel_test +TARGET = tst_qcommandlineparser +QT = core testlib +SOURCES = tst_qcommandlineparser.cpp diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index afa5e5b613..fbc1b996f7 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -8,6 +8,7 @@ SUBDIRS=\ qbytedatabuffer \ qcache \ qchar \ + qcommandlineparser \ qcontiguouscache \ qcryptographichash \ qdate \ -- cgit v1.2.3