3 #include "../conversion/stringbuilder.h" 5 #include "../application/argumentparser.h" 6 #include "../application/argumentparserprivate.h" 7 #include "../application/failure.h" 8 #include "../application/fakeqtconfigarguments.h" 10 #include "../io/path.h" 12 #include "resources/config.h" 14 #include <cppunit/extensions/HelperMacros.h> 15 #include <cppunit/TestFixture.h> 32 CPPUNIT_TEST(testArgument);
33 CPPUNIT_TEST(testParsing);
34 CPPUNIT_TEST(testCallbacks);
35 CPPUNIT_TEST(testBashCompletion);
36 CPPUNIT_TEST_SUITE_END();
45 void testBashCompletion();
64 Argument argument(
"test",
't',
"some description");
65 CPPUNIT_ASSERT_EQUAL(argument.
isRequired(),
false);
67 CPPUNIT_ASSERT_EQUAL(argument.
isRequired(),
true);
68 Argument subArg(
"sub",
's',
"sub arg");
70 CPPUNIT_ASSERT_EQUAL(subArg.parents().at(0), &argument);
71 CPPUNIT_ASSERT(!subArg.conflictsWithArgument());
76 CPPUNIT_ASSERT(!strcmp(argument.
firstValue(), getenv(
"PATH")));
92 Argument verboseArg(
"verbose",
'v',
"be verbose");
94 Argument fileArg(
"file",
'f',
"specifies the path of the file to be opened");
98 Argument filesArg(
"files",
'f',
"specifies the path of the file(s) to be opened");
101 Argument outputFileArg(
"output-file",
'o',
"specifies the path of the output file");
106 Argument printFieldNamesArg(
"print-field-names",
'\0',
"prints available field names");
107 Argument displayFileInfoArg(
"display-file-info",
'i',
"displays general file information");
108 Argument notAlbumArg(
"album",
'a',
"should not be confused with album value");
110 displayFileInfoArg.
setSubArguments({&fileArg, &verboseArg, ¬AlbumArg});
111 Argument fieldsArg(
"fields",
'\0',
"specifies the fields");
113 fieldsArg.
setValueNames({
"title",
"album",
"artist",
"trackpos"});
115 Argument displayTagInfoArg(
"get",
'p',
"displays the values of all specified tag fields (displays all fields if none specified)");
117 displayTagInfoArg.
setSubArguments({&fieldsArg, &filesArg, &verboseArg, ¬AlbumArg});
118 parser.
setMainArguments({&qtConfigArgs.qtWidgetsGuiArg(), &printFieldNamesArg, &displayTagInfoArg, &displayFileInfoArg, &helpArg});
121 const char *argv[] = {
"tageditor",
"get",
"album",
"title",
"diskpos",
"-f",
"somefile"};
125 CPPUNIT_FAIL(
"Exception expected.");
127 CPPUNIT_ASSERT(!strcmp(e.
what(),
"The argument \"files\" can not be combined with \"fields\"."));
135 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
136 CPPUNIT_ASSERT(!displayFileInfoArg.
isPresent());
137 CPPUNIT_ASSERT(!strcmp(parser.
executable(),
"tageditor"));
139 CPPUNIT_ASSERT(displayTagInfoArg.
isPresent());
141 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(0),
"album"));
142 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(1),
"title"));
143 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(2),
"diskpos"));
144 CPPUNIT_ASSERT_THROW(displayTagInfoArg.
values().at(3), out_of_range);
147 const char *argv2[] = {
"tageditor",
"",
"-p",
"album",
"title",
"diskpos",
"",
"--files",
"somefile"};
152 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
153 CPPUNIT_ASSERT(!displayFileInfoArg.
isPresent());
155 CPPUNIT_ASSERT(displayTagInfoArg.
isPresent());
157 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(0),
"album"));
158 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(1),
"title"));
159 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(2),
"diskpos"));
160 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(3),
""));
161 CPPUNIT_ASSERT_THROW(fieldsArg.
values().at(4), out_of_range);
163 CPPUNIT_ASSERT(!strcmp(filesArg.
values().at(0),
"somefile"));
166 const char *argv3[] = {
"tageditor",
"album",
"title",
"diskpos",
"--files",
"somefile"};
170 CPPUNIT_FAIL(
"Exception expected.");
172 CPPUNIT_ASSERT(!strcmp(e.
what(),
"The specified argument \"album\" is unknown and will be ignored."));
179 streambuf *regularCerrBuffer = cerr.rdbuf(buffer.rdbuf());
184 cerr.rdbuf(regularCerrBuffer);
187 cerr.rdbuf(regularCerrBuffer);
188 CPPUNIT_ASSERT_EQUAL(
"The specified argument \"album\" is unknown and will be ignored.\n"s
189 "The specified argument \"title\" is unknown and will be ignored.\n"s
190 "The specified argument \"diskpos\" is unknown and will be ignored.\n"s
191 "The specified argument \"--files\" is unknown and will be ignored.\n"s
192 "The specified argument \"somefile\" is unknown and will be ignored.\n"s,
195 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
196 CPPUNIT_ASSERT(!displayFileInfoArg.
isPresent());
197 CPPUNIT_ASSERT(!displayTagInfoArg.
isPresent());
202 const char *argv4[] = {
"tageditor",
"-i",
"-vf",
"test"};
206 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
207 CPPUNIT_ASSERT(displayFileInfoArg.
isPresent());
209 CPPUNIT_ASSERT(!displayTagInfoArg.
isPresent());
212 CPPUNIT_ASSERT(!strcmp(fileArg.
values().at(0),
"test"));
213 CPPUNIT_ASSERT_THROW(fileArg.
values().at(1), out_of_range);
219 CPPUNIT_FAIL(
"Exception expected.");
221 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
222 CPPUNIT_ASSERT(!strcmp(e.
what(),
"The argument \"verbose\" mustn't be specified more than 1 time."));
229 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
235 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
238 const char *argv5[] = {
"tageditor",
"-i",
"-f",
"test"};
242 CPPUNIT_FAIL(
"Exception expected.");
244 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
245 CPPUNIT_ASSERT(!strcmp(e.
what(),
"The argument \"verbose\" must be specified at least 1 time."));
250 const char *argv10[] = {
"tageditor",
"-pf",
"test"};
253 CPPUNIT_ASSERT(displayTagInfoArg.
isPresent());
254 CPPUNIT_ASSERT(!displayFileInfoArg.
isPresent());
257 CPPUNIT_ASSERT_EQUAL(filesArg.
values(0).size(),
static_cast<vector<const char *>::size_type
>(1));
258 CPPUNIT_ASSERT(!strcmp(filesArg.
values(0).front(),
"test"));
259 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
262 const char *argv6[] = {
"tageditor",
"-g"};
265 CPPUNIT_ASSERT(qtConfigArgs.qtWidgetsGuiArg().isPresent());
268 const char *argv7[] = {
"tageditor",
"-f",
"test"};
272 CPPUNIT_FAIL(
"Exception expected.");
274 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
275 CPPUNIT_ASSERT(!strcmp(e.
what(),
"The specified argument \"-f\" is unknown and will be ignored."));
279 const char *argv11[] = {
"tageditor",
"-if=test"};
284 CPPUNIT_ASSERT_EQUAL(fileArg.
values(0).size(),
static_cast<vector<const char *>::size_type
>(1));
285 CPPUNIT_ASSERT(!strcmp(fileArg.
values(0).front(),
"test"));
288 const char *argv12[] = {
"tageditor",
"-iftest"};
293 CPPUNIT_ASSERT_EQUAL(fileArg.
values(0).size(),
static_cast<vector<const char *>::size_type
>(1));
294 CPPUNIT_ASSERT(!strcmp(fileArg.
values(0).front(),
"test"));
297 const char *argv8[] = {
"tageditor"};
300 CPPUNIT_ASSERT(qtConfigArgs.qtWidgetsGuiArg().isPresent());
301 CPPUNIT_ASSERT(!displayFileInfoArg.
isPresent());
303 CPPUNIT_ASSERT(!displayTagInfoArg.
isPresent());
308 CPPUNIT_ASSERT(!strcmp(fileArg.
firstValue(), getenv(
"PATH")));
314 const char *argv13[] = {
"tageditor",
"get",
"--fields",
"album=test",
"title",
"diskpos",
"--files",
"somefile"};
319 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
320 CPPUNIT_ASSERT(!displayFileInfoArg.
isPresent());
322 CPPUNIT_ASSERT(displayTagInfoArg.
isPresent());
324 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(0),
"album=test"));
325 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(1),
"title"));
326 CPPUNIT_ASSERT(!strcmp(fieldsArg.
values().at(2),
"diskpos"));
327 CPPUNIT_ASSERT_THROW(fieldsArg.
values().at(3), out_of_range);
329 CPPUNIT_ASSERT(!strcmp(filesArg.
values().at(0),
"somefile"));
330 CPPUNIT_ASSERT(!notAlbumArg.
isPresent());
333 const char *argv9[] = {
"tageditor",
"-p",
"album",
"title",
"diskpos"};
338 CPPUNIT_FAIL(
"Exception expected.");
340 CPPUNIT_ASSERT(!qtConfigArgs.qtWidgetsGuiArg().isPresent());
341 CPPUNIT_ASSERT(!strcmp(e.
what(),
"Not all parameter for argument \"fields\" provided. You have to provide the following parameter: title album artist trackpos"));
351 Argument callbackArg(
"with-callback",
't',
"callback test");
354 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), occurrence.
index);
355 CPPUNIT_ASSERT(occurrence.
path.empty());
356 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), occurrence.
values.size());
357 CPPUNIT_ASSERT(!strcmp(occurrence.
values[0],
"val1"));
358 CPPUNIT_ASSERT(!strcmp(occurrence.
values[1],
"val2"));
361 Argument noCallbackArg(
"no-callback",
'l',
"callback test");
366 const char *argv[] = {
"test",
"-t",
"val1",
"val2"};
370 CPPUNIT_ASSERT_EQUAL(i, 42);
375 const char *argv2[] = {
"test",
"-l",
"val1",
"val2"};
388 Argument verboseArg(
"verbose",
'v',
"be verbose");
390 Argument filesArg(
"files",
'f',
"specifies the path of the file(s) to be opened");
393 Argument nestedSubArg(
"nested-sub",
'\0',
"nested sub arg");
394 Argument subArg(
"sub",
'\0',
"sub arg");
396 Argument displayFileInfoArg(
"display-file-info",
'i',
"displays general file information");
399 Argument fieldsArg(
"fields",
'\0',
"specifies the fields");
403 Argument valuesArg(
"values",
'\0',
"specifies the fields");
407 valuesArg.
setValueCompletionBehavior(ValueCompletionBehavior::PreDefinedValues | ValueCompletionBehavior::AppendEquationSign);
408 Argument getArg(
"get",
'g',
"gets tag values");
410 Argument setArg(
"set",
's',
"sets tag values");
417 streambuf *regularCoutBuffer = cout.rdbuf(buffer.rdbuf());
421 const char *
const argv1[] = {
"se"};
424 parser.printBashCompletion(1, argv1, 0, reader);
425 cout.rdbuf(regularCoutBuffer);
426 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=()\n"s, buffer.str());
429 buffer.str(
string());
430 cout.rdbuf(buffer.rdbuf());
433 parser.printBashCompletion(1, argv1, 0, reader);
434 cout.rdbuf(regularCoutBuffer);
435 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('set' )\n"s, buffer.str());
438 const char *
const argv2[] = {
"set"};
439 buffer.str(
string());
440 cout.rdbuf(buffer.rdbuf());
443 parser.printBashCompletion(1, argv2, 0, reader);
444 cout.rdbuf(regularCoutBuffer);
445 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('set' )\n"s, buffer.str());
448 buffer.str(
string());
449 cout.rdbuf(buffer.rdbuf());
452 parser.printBashCompletion(1, argv2, 1, reader);
453 cout.rdbuf(regularCoutBuffer);
454 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('--files' '--values' )\n"s, buffer.str());
457 buffer.str(
string());
458 cout.rdbuf(buffer.rdbuf());
461 parser.printBashCompletion(0,
nullptr, 0, reader);
462 cout.rdbuf(regularCoutBuffer);
463 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('display-file-info' 'get' 'set' '--help' )\n"s, buffer.str());
466 const char *
const argv3[] = {
"get",
"--fields"};
467 buffer.str(
string());
468 cout.rdbuf(buffer.rdbuf());
471 parser.printBashCompletion(2, argv3, 2, reader);
472 cout.rdbuf(regularCoutBuffer);
473 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('title' 'album' 'artist' 'trackpos' '--files' )\n"s, buffer.str());
476 const char *
const argv4[] = {
"set",
"--values",
"a"};
477 buffer.str(
string());
478 cout.rdbuf(buffer.rdbuf());
481 parser.printBashCompletion(3, argv4, 2, reader);
482 cout.rdbuf(regularCoutBuffer);
483 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('album=' 'artist=' ); compopt -o nospace\n"s, buffer.str());
487 iniFilePath.resize(iniFilePath.size() - 4);
489 mkvFilePath.resize(mkvFilePath.size() - 17);
491 const char *
const argv5[] = {
"get",
"--files", iniFilePath.c_str()};
492 buffer.str(
string());
493 cout.rdbuf(buffer.rdbuf());
496 parser.printBashCompletion(3, argv5, 2, reader);
497 cout.rdbuf(regularCoutBuffer);
499 const string res(buffer.str());
500 if(res.find(
".mkv") < res.find(
".ini")) {
501 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('" % mkvFilePath %
" '\"'\"'with quote'\"'\"'.mkv' '" % iniFilePath +
".ini' ); compopt -o filenames\n", buffer.str());
503 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('" % iniFilePath %
".ini' '" % mkvFilePath +
" '\"'\"'with quote'\"'\"'.mkv' ); compopt -o filenames\n", buffer.str());
507 const char *
const argv6[] = {
"set",
"--"};
508 buffer.str(
string());
509 cout.rdbuf(buffer.rdbuf());
512 parser.printBashCompletion(2, argv6, 1, reader);
513 cout.rdbuf(regularCoutBuffer);
514 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('--files' '--values' )\n"s, buffer.str());
517 const char *
const argv7[] = {
"-i",
"--sub",
"--"};
518 buffer.str(
string());
519 cout.rdbuf(buffer.rdbuf());
522 parser.printBashCompletion(3, argv7, 2, reader);
523 cout.rdbuf(regularCoutBuffer);
524 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('--files' '--nested-sub' '--verbose' )\n"s, buffer.str());
527 const char *
const argv8[] = {
"set",
"--values",
"t"};
528 buffer.str(
string());
529 cout.rdbuf(buffer.rdbuf());
532 parser.printBashCompletion(3, argv8, 2, reader);
533 cout.rdbuf(regularCoutBuffer);
534 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('title=' 'trackpos=' ); compopt -o nospace\n"s, buffer.str());
537 const char *
const argv9[] = {
"-gf"};
538 buffer.str(
string());
539 cout.rdbuf(buffer.rdbuf());
542 parser.printBashCompletion(1, argv9, 0, reader);
543 cout.rdbuf(regularCoutBuffer);
544 CPPUNIT_ASSERT_EQUAL(
"COMPREPLY=('-gf' )\n"s, buffer.str());
546 buffer.str(
string());
547 cout.rdbuf(buffer.rdbuf());
550 parser.printBashCompletion(1, argv9, 1, reader);
551 cout.rdbuf(regularCoutBuffer);
552 CPPUNIT_ASSERT_EQUAL(static_cast<string::size_type>(0), buffer.str().find(
"COMPREPLY=('--fields' "));
555 cout.rdbuf(regularCoutBuffer);
void testBashCompletion()
Tests bash completion.
void resetArgs()
Resets all Argument instances assigned as mainArguments() and sub arguments.
#define QT_CONFIG_ARGUMENTS
void setImplicit(bool value)
Sets whether the argument is an implicit argument.
std::size_t index
The index of the occurrence.
void testParsing()
Tests parsing command line arguments.
void setCombinable(bool value)
Sets whether this argument can be combined.
void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior)
Sets how unknown arguments are treated.
virtual const char * what() const USE_NOTHROW
Returns a C-style character string describing the cause of the Failure.
Contains currently only ArgumentParser and related classes.
void setMainArguments(const ArgumentInitializerList &mainArguments)
Sets the main arguments for the parser.
void testArgument()
Tests the behaviour of the argument class.
bool isRequired() const
Returns an indication whether the argument is mandatory.
void testCallbacks()
Tests whether callbacks are called correctly.
void setRequired(bool required)
Sets whether this argument is mandatory or not.
void parseArgs(int argc, const char *const *argv)
Parses the specified command line arguments.
const char * firstValue() const
Returns the first parameter value of the first occurrence of the argument.
The ArgumentParserTests class tests the ArgumentParser and Argument classes.
void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences)
Sets the allowed number of occurrences.
void setValueCompletionBehavior(ValueCompletionBehavior valueCompletionBehaviour)
Sets the items to be considered when generating completion for the values.
#define SET_APPLICATION_INFO
SET_APPLICATION_INFO
const std::vector< const char * > & values(std::size_t occurrence=0) const
Returns the parameter values for the specified occurrence of argument.
Contains several functions providing conversions between different data types.
const char * executable() const
Returns the name of the current executable.
void read()
Reads the commands line arguments specified when constructing the object.
The Argument class is a wrapper for command line argument information.
void setCallback(CallbackFunction callback)
Sets a callback function which will be called by the parser if the argument could be found and no par...
void setPreDefinedCompletionValues(const char *preDefinedCompletionValues)
Assignes the values to be used when generating completion for the values.
ApplicationUtilities::ArgumentReader & reset(const char *const *argv, const char *const *end)
Resets the ArgumentReader to continue reading new argv.
std::vector< Argument * > path
The "path" of the occurrence (the parent elements which have been specified before).
void addSubArgument(Argument *arg)
Adds arg as a secondary argument for this argument.
void setEnvironmentVariable(const char *environmentVariable)
Sets the environment variable queried when firstValue() is called.
The ArgumentOccurrence struct holds argument values for an occurrence of an argument.
bool isPresent() const
Returns an indication whether the argument could be detected when parsing.
The HelpArgument class prints help information for an argument parser when present (–help...
CPPUNIT_TEST_SUITE_REGISTRATION(ArgumentParserTests)
The Failure class is thrown by an ArgumentParser when a parsing error occurs.
void setDenotesOperation(bool denotesOperation)
Sets whether the argument denotes the operation.
void reset()
Resets occurrences (indices, values and paths).
void setRequiredValueCount(std::size_t requiredValueCount)
Sets the number of values which are required to be given for this argument.
void setSubArguments(const ArgumentInitializerList &subArguments)
Sets the secondary arguments for this arguments.
CPP_UTILITIES_EXPORT std::string testFilePath(const std::string &name)
Convenience function which returns the full path of the test file with the specified name...
The ArgumentParser class provides a means for handling command line arguments.
void setValueNames(std::initializer_list< const char *> valueNames)
Sets the names of the requried values.
std::vector< const char * > values
The parameter values which have been specified after the occurrence of the argument.