1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qbs.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 #include "commandlineparser.h"
29
30 #include "exception.h"
31
32 #include <QtCore/qcommandlineoption.h>
33 #include <QtCore/qcommandlineparser.h>
34 #include <QtCore/qcoreapplication.h>
35 #include <QtCore/qfileinfo.h>
36
37 namespace qbsBenchmarker {
38
resolveActivity()39 static QString resolveActivity() { return "resolving"; }
ruleExecutionActivity()40 static QString ruleExecutionActivity() { return "rule-execution"; }
nullBuildActivity()41 static QString nullBuildActivity() { return "null-build"; }
allActivities()42 static QString allActivities() { return "all"; }
43
44 CommandLineParser::CommandLineParser() = default;
45
parse()46 void CommandLineParser::parse()
47 {
48 QCommandLineParser parser;
49 parser.setApplicationDescription("This tool aims to detect qbs performance regressions "
50 "using valgrind.");
51 parser.addHelpOption();
52 QCommandLineOption oldCommitOption(QStringList{"old-commit", "o"}, "The old qbs commit.",
53 "old commit");
54 parser.addOption(oldCommitOption);
55 QCommandLineOption newCommitOption(QStringList{"new-commit", "n"}, "The new qbs commit.",
56 "new commit");
57 parser.addOption(newCommitOption);
58 QCommandLineOption testProjectOption(QStringList{"test-project", "p"},
59 "The example project to use for the benchmark.", "project file path");
60 parser.addOption(testProjectOption);
61 QCommandLineOption qbsRepoOption(QStringList{"qbs-repo", "r"}, "The qbs repository.",
62 "repo path");
63 parser.addOption(qbsRepoOption);
64 QCommandLineOption activitiesOption(QStringList{"activities", "a"},
65 QStringLiteral("The activities to benchmark. Possible values (CSV): %1,%2,%3,%4")
66 .arg(resolveActivity(), ruleExecutionActivity(), nullBuildActivity(),
67 allActivities()), "activities", allActivities());
68 parser.addOption(activitiesOption);
69 QCommandLineOption thresholdOption(QStringList{"regression-threshold", "t"},
70 "A relative increase higher than this is considered a performance regression. "
71 "All temporary data from running the benchmarks will be kept if that happens.",
72 "value in per cent");
73 parser.addOption(thresholdOption);
74 parser.process(*QCoreApplication::instance());
75 const QList<QCommandLineOption> mandatoryOptions = QList<QCommandLineOption>()
76 << oldCommitOption << newCommitOption << testProjectOption << qbsRepoOption;
77 for (const QCommandLineOption &o : mandatoryOptions) {
78 if (!parser.isSet(o))
79 throwException(o.names().constFirst(), parser.helpText());
80 if (parser.value(o).isEmpty())
81 throwException(o.names().constFirst(), QString(), parser.helpText());
82 }
83 m_oldCommit = parser.value(oldCommitOption);
84 m_newCommit = parser.value(newCommitOption);
85 if (m_oldCommit == m_newCommit) {
86 throw Exception(QStringLiteral("Error parsing command line: "
87 "'new commit' and 'old commit' must be different commits.\n%1").arg(parser.helpText()));
88 }
89 m_testProjectFilePath = parser.value(testProjectOption);
90 m_qbsRepoDirPath = parser.value(qbsRepoOption);
91 const QStringList activitiesList = parser.value(activitiesOption).split(',');
92 m_activities = Activities();
93 for (const QString &activityString : activitiesList) {
94 if (activityString == allActivities()) {
95 m_activities = ActivityResolving | ActivityRuleExecution | ActivityNullBuild;
96 break;
97 } else if (activityString == resolveActivity()) {
98 m_activities = ActivityResolving;
99 } else if (activityString == ruleExecutionActivity()) {
100 m_activities |= ActivityRuleExecution;
101 } else if (activityString == nullBuildActivity()) {
102 m_activities |= ActivityNullBuild;
103 } else {
104 throwException(activitiesOption.names().constFirst(),
105 activityString,
106 parser.helpText());
107 }
108 }
109 m_regressionThreshold = 5;
110 if (parser.isSet(thresholdOption)) {
111 bool ok = true;
112 const QString rawThresholdValue = parser.value(thresholdOption);
113 m_regressionThreshold = rawThresholdValue.toInt(&ok);
114 if (!ok)
115 throwException(thresholdOption.names().constFirst(),
116 rawThresholdValue,
117 parser.helpText());
118 }
119 }
120
throwException(const QString & optionName,const QString & illegalValue,const QString & helpText)121 void CommandLineParser::throwException(const QString &optionName, const QString &illegalValue,
122 const QString &helpText)
123 {
124 const QString errorText(QStringLiteral("Error parsing command line: Illegal value '%1' "
125 "for option '--%2'.\n%3").arg(illegalValue, optionName, helpText));
126 throw Exception(errorText);
127 }
128
throwException(const QString & missingOption,const QString & helpText)129 void CommandLineParser::throwException(const QString &missingOption, const QString &helpText)
130 {
131 const QString errorText(QStringLiteral("Error parsing command line: Missing mandatory "
132 "option '--%1'.\n%3").arg(missingOption, helpText));
133 throw Exception(errorText);
134 }
135
136
137 } // namespace qbsBenchmarker
138