Skip to content

Commit d3c7446

Browse files
committed
Tests for parsing the command line.
1 parent 9ce3008 commit d3c7446

File tree

3 files changed

+144
-36
lines changed

3 files changed

+144
-36
lines changed

include/cppcommandline.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ class Option
180180
++argument;
181181
}
182182
}
183-
else if(keyValue.key == longName() || keyValue.key == shortName())
183+
else if((isLongNameArgument(*argument) && keyValue.key == longName()) || (isShortNameArgument(*argument) && keyValue.key == shortName()))
184184
{
185185
if(d->type == Type::Bool)
186186
{
@@ -354,12 +354,12 @@ class Option
354354

355355
bool isLongNameArgument(std::string argument) const
356356
{
357-
return std::regex_match(argument, std::regex("^--[a-zA-Z][a-zA-Z\\d]+$"));
357+
return std::regex_match(argument, std::regex("^--[a-zA-Z][a-zA-Z\\d]*.*$"));
358358
}
359359

360360
bool isShortNameArgument(std::string argument) const
361361
{
362-
return std::regex_match(argument, std::regex("^-[a-zA-Z]$"));
362+
return std::regex_match(argument, std::regex("^-[a-zA-Z].*$"));
363363
}
364364

365365
bool isInteger(std::string argument) const
@@ -452,15 +452,18 @@ class Parser
452452
{
453453
auto start = arg;
454454

455-
for(auto option = options.begin(); option != options.end(); ++option)
455+
for(auto option = options.begin(); option != options.end();)
456456
{
457457
auto next = (*option)->match(arg, mArgs.cend());
458458

459459
if(next != arg)
460460
{
461-
options.erase(option);
461+
option = options.erase(option);
462462
arg = next;
463+
break;
463464
}
465+
else
466+
++option;
464467
}
465468

466469
if(arg == start)

test/cppcommandlinetest.cpp

Lines changed: 131 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@ void CppCommandLineTest::OptionDefaultCtor()
77
{
88
SCENARIO("Option default constructor")
99
cppcommandline::Option option;
10-
QCOMPARE(true, option.isPositional());
11-
QCOMPARE(std::string(), option.longName());
12-
QCOMPARE(std::string(), option.shortName());
13-
QCOMPARE(std::string(), option.description());
14-
QCOMPARE(false, option.isRequired());
15-
QCOMPARE(std::string(), option.defaultValue<std::string>());
16-
QCOMPARE(nullptr, option.boundValue<std::string>());
10+
QCOMPARE(option.isPositional(), true);
11+
QCOMPARE(option.longName(), std::string());
12+
QCOMPARE(option.shortName(), std::string());
13+
QCOMPARE(option.description(), std::string());
14+
QCOMPARE(option.isRequired(), false);
15+
QCOMPARE(option.defaultValue<std::string>(), std::string());
16+
QCOMPARE(option.boundValue<std::string>(), nullptr);
1717
}
1818

1919
void CppCommandLineTest::OptionLongNameCtor()
2020
{
2121
{
2222
SCENARIO("Option long name constructor")
2323
cppcommandline::Option option("longName1");
24-
QCOMPARE(std::string("longName1"), option.longName());
24+
QCOMPARE(option.longName(), std::string("longName1"));
2525
}
2626

2727
{
@@ -34,28 +34,28 @@ void CppCommandLineTest::OptionMoveCtor()
3434
{
3535
SCENARIO("Option move ctor")
3636
cppcommandline::Option option(cppcommandline::Option("longName"));
37-
QCOMPARE(std::string("longName"), option.longName());
37+
QCOMPARE(option.longName(), std::string("longName"));
3838
}
3939

4040
void CppCommandLineTest::OptionMoveAssignment()
4141
{
4242
SCENARIO("Option move assignment")
4343
cppcommandline::Option option = cppcommandline::Option("longName");
44-
QCOMPARE(std::string("longName"), option.longName());
44+
QCOMPARE(option.longName(), std::string("longName"));
4545
}
4646

4747
void CppCommandLineTest::positional()
4848
{
4949
{
5050
SCENARIO("Option is positional without any names")
5151
cppcommandline::Option option;
52-
QCOMPARE(true, option.isPositional());
52+
QCOMPARE(option.isPositional(), true);
5353
}
5454

5555
{
5656
SCENARIO("Option is not positional if it has a name")
5757
cppcommandline::Option option("longName");
58-
QCOMPARE(false, option.isPositional());
58+
QCOMPARE(option.isPositional(), false);
5959
}
6060
}
6161

@@ -64,7 +64,7 @@ void CppCommandLineTest::shortName()
6464
{
6565
SCENARIO("Option short name")
6666
cppcommandline::Option option = std::move(cppcommandline::Option("longName1").asShortName("o"));
67-
QCOMPARE(std::string("o"), option.shortName());
67+
QCOMPARE(option.shortName(), std::string("o"));
6868
}
6969

7070
{
@@ -77,15 +77,15 @@ void CppCommandLineTest::description()
7777
{
7878
SCENARIO("Option description")
7979
cppcommandline::Option option = std::move(cppcommandline::Option("longName").withDescription("My fancty description"));
80-
QCOMPARE(std::string("My fancty description"), option.description());
80+
QCOMPARE(option.description(), std::string("My fancty description"));
8181
}
8282

8383
void CppCommandLineTest::required()
8484
{
8585
{
8686
SCENARIO("Option required")
8787
cppcommandline::Option option = std::move(cppcommandline::Option("longName").required());
88-
QCOMPARE(true, option.isRequired());
88+
QCOMPARE(option.isRequired(), true);
8989
}
9090

9191
{
@@ -99,7 +99,7 @@ void CppCommandLineTest::defaultValue()
9999
{
100100
SCENARIO("Option default value")
101101
cppcommandline::Option option = std::move(cppcommandline::Option("longName").withDefaultValue(std::string("option")));
102-
QCOMPARE(std::string("option"), option.defaultValue<std::string>());
102+
QCOMPARE(option.defaultValue<std::string>(), std::string("option"));
103103
}
104104

105105
{
@@ -121,7 +121,7 @@ void CppCommandLineTest::boundValue()
121121
std::string boundValue;
122122
cppcommandline::Option option;
123123
option.bindTo(boundValue);
124-
QCOMPARE(&boundValue, option.boundValue<std::string>());
124+
QCOMPARE(option.boundValue<std::string>(), &boundValue);
125125
}
126126

127127
{
@@ -140,7 +140,7 @@ void CppCommandLineTest::match()
140140
std::string value;
141141
cppcommandline::Option option("longName");
142142
option.bindTo(value);
143-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
143+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
144144
QCOMPARE(std::string("value"), value);
145145
}
146146

@@ -150,7 +150,7 @@ void CppCommandLineTest::match()
150150
std::string value;
151151
cppcommandline::Option option("longName");
152152
option.bindTo(value);
153-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
153+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
154154
QCOMPARE(std::string("value"), value);
155155
}
156156

@@ -160,7 +160,7 @@ void CppCommandLineTest::match()
160160
bool value;
161161
cppcommandline::Option option;
162162
option.bindTo(value);
163-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
163+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
164164
QCOMPARE(true, value);
165165
}
166166

@@ -170,7 +170,7 @@ void CppCommandLineTest::match()
170170
std::string value;
171171
cppcommandline::Option option;
172172
option.bindTo(value);
173-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
173+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
174174
QCOMPARE(std::string("value"), value);
175175
}
176176

@@ -180,7 +180,7 @@ void CppCommandLineTest::match()
180180
int value = 0;
181181
cppcommandline::Option option;
182182
option.bindTo(value);
183-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
183+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
184184
QCOMPARE(10, value);
185185
}
186186

@@ -190,7 +190,7 @@ void CppCommandLineTest::match()
190190
int value = 0;
191191
cppcommandline::Option option;
192192
option.bindTo(value);
193-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
193+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
194194
QCOMPARE(-10, value);
195195
}
196196

@@ -200,7 +200,7 @@ void CppCommandLineTest::match()
200200
double value = 0;
201201
cppcommandline::Option option;
202202
option.bindTo(value);
203-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
203+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
204204
QCOMPARE(double(5.5), value);
205205
}
206206

@@ -210,7 +210,7 @@ void CppCommandLineTest::match()
210210
double value = 0;
211211
cppcommandline::Option option;
212212
option.bindTo(value);
213-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
213+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
214214
QCOMPARE(double(-5.5), value);
215215
}
216216

@@ -220,8 +220,8 @@ void CppCommandLineTest::match()
220220
qint64 value = 0;
221221
cppcommandline::Option option;
222222
option.bindTo(value);
223-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
224-
QCOMPARE(qint64(999999999999), value);
223+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
224+
QCOMPARE(value, qint64(999999999999));
225225
}
226226

227227
{
@@ -230,26 +230,126 @@ void CppCommandLineTest::match()
230230
qint64 value = 0;
231231
cppcommandline::Option option;
232232
option.bindTo(value);
233-
QCOMPARE(arguments.cend(), option.match(arguments.cbegin(), arguments.cend()));
234-
QCOMPARE(qint64(-999999999999), value);
233+
QCOMPARE(option.match(arguments.cbegin(), arguments.cend()), arguments.cend());
234+
QCOMPARE(value, qint64(-999999999999));
235235
}
236236
}
237237

238238
void CppCommandLineTest::ParserOption()
239239
{
240240
SCENARIO("Parser returns a default constructed option")
241241
cppcommandline::Parser parser;
242-
QCOMPARE(cppcommandline::Option(), parser.option());
242+
QCOMPARE(parser.option(), cppcommandline::Option());
243243
}
244244

245245
void CppCommandLineTest::ParserOptionLongName()
246246
{
247247
SCENARIO("Parser returns a default constructed option")
248248
cppcommandline::Parser parser;
249-
QCOMPARE(cppcommandline::Option("longName"), parser.option("longName"));
249+
QCOMPARE(parser.option("longName"), cppcommandline::Option("longName"));
250250
}
251251

252252
void CppCommandLineTest::parse()
253+
{
254+
{
255+
SCENARIO("Single positional option")
256+
std::vector<const char*> args{"value"};
257+
cppcommandline::Parser parser;
258+
std::string value;
259+
parser.option().bindTo(value);
260+
parser.parse(static_cast<int>(args.size()), const_cast<char**>(args.data()));
261+
QCOMPARE(value, std::string("value"));
262+
}
263+
264+
{
265+
SCENARIO("Multiple positional options")
266+
std::vector<const char*> args{"value", "-10", "5.5"};
267+
cppcommandline::Parser parser;
268+
std::string value;
269+
int iValue = 0;
270+
double dValue = 0.0;
271+
parser.option().bindTo(iValue);
272+
parser.option().bindTo(dValue);
273+
parser.option().bindTo(value);
274+
parser.parse(static_cast<int>(args.size()), const_cast<char**>(args.data()));
275+
QCOMPARE(value, std::string("value"));
276+
QCOMPARE(iValue, -10);
277+
QCOMPARE(dValue, 5.5);
278+
}
279+
280+
{
281+
SCENARIO("Single long name option")
282+
std::vector<const char*> args{"--value"};
283+
cppcommandline::Parser parser;
284+
bool value;
285+
parser.option("value").bindTo(value);
286+
parser.parse(static_cast<int>(args.size()), const_cast<char**>(args.data()));
287+
QCOMPARE(value, true);
288+
}
289+
290+
{
291+
SCENARIO("Multiple long name options")
292+
std::vector<const char*> args{"--value", "--option=file", "--yetanother", "10"};
293+
cppcommandline::Parser parser;
294+
bool value;
295+
std::string option;
296+
int another = 0;
297+
parser.option("value").bindTo(value);
298+
parser.option("option").bindTo(option);
299+
parser.option("yetanother").bindTo(another);
300+
parser.parse(static_cast<int>(args.size()), const_cast<char**>(args.data()));
301+
QCOMPARE(value, true);
302+
QCOMPARE(option, std::string("file"));
303+
QCOMPARE(another, 10);
304+
}
305+
306+
{
307+
SCENARIO("Single short name option")
308+
std::vector<const char*> args{"-v"};
309+
cppcommandline::Parser parser;
310+
bool value;
311+
parser.option("value").asShortName("v").bindTo(value);
312+
parser.parse(static_cast<int>(args.size()), const_cast<char**>(args.data()));
313+
QCOMPARE(value, true);
314+
}
315+
316+
{
317+
SCENARIO("Multiple short name options")
318+
std::vector<const char*> args{"-v", "-o=file", "-y", "10"};
319+
cppcommandline::Parser parser;
320+
bool value;
321+
std::string option;
322+
int another = 0;
323+
parser.option("value").asShortName("v").bindTo(value);
324+
parser.option("option").asShortName("o").bindTo(option);
325+
parser.option("yetanother").asShortName("y").bindTo(another);
326+
parser.parse(static_cast<int>(args.size()), const_cast<char**>(args.data()));
327+
QCOMPARE(value, true);
328+
QCOMPARE(option, std::string("file"));
329+
QCOMPARE(another, 10);
330+
}
331+
332+
{
333+
SCENARIO("Mixed options")
334+
std::vector<const char*> args{"-v", "-o=file", "--yetanother", "10", "somefile"};
335+
cppcommandline::Parser parser;
336+
bool value;
337+
std::string option;
338+
int another = 0;
339+
std::string positional;
340+
parser.option("value").asShortName("v").bindTo(value);
341+
parser.option("option").asShortName("o").bindTo(option);
342+
parser.option("yetanother").bindTo(another);
343+
parser.option().bindTo(positional);
344+
parser.parse(static_cast<int>(args.size()), const_cast<char**>(args.data()));
345+
QCOMPARE(value, true);
346+
QCOMPARE(option, std::string("file"));
347+
QCOMPARE(another, 10);
348+
QCOMPARE(positional, std::string("somefile"));
349+
}
350+
}
351+
352+
void CppCommandLineTest::parseFailed()
253353
{
254354

255355
}

test/cppcommandlinetest.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <QObject>
4+
#include <memory>
45

56
class CppCommandLineTest : public QObject
67
{
@@ -20,4 +21,8 @@ private slots:
2021
void ParserOption();
2122
void ParserOptionLongName();
2223
void parse();
24+
void parseFailed();
25+
26+
private:
27+
std::unique_ptr<char**, void(*)(char**)> createArguments(std::vector<std::string> arguments);
2328
};

0 commit comments

Comments
 (0)