Skip to content
This repository was archived by the owner on Jan 17, 2025. It is now read-only.

Commit 9b0112c

Browse files
Adding arg parser files (#74)
* feat: add arg parser files to the project * remove redundant filters that were automatically added * added test case for duplicate flag is_set * fix: fixed m_arg_count type and used function from utils * fix: add edge case new line test * fix: update implementation of utils functions
1 parent 9648e5c commit 9b0112c

11 files changed

+1646
-117
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
// BSD 3-Clause License
2+
//
3+
// Copyright (c) 2024, Arm Limited
4+
// All rights reserved.
5+
//
6+
// Redistribution and use in source and binary forms, with or without
7+
// modification, are permitted provided that the following conditions are met:
8+
//
9+
// 1. Redistributions of source code must retain the above copyright notice, this
10+
// list of conditions and the following disclaimer.
11+
//
12+
// 2. Redistributions in binary form must reproduce the above copyright notice,
13+
// this list of conditions and the following disclaimer in the documentation
14+
// and/or other materials provided with the distribution.
15+
//
16+
// 3. Neither the name of the copyright holder nor the names of its
17+
// contributors may be used to endorse or promote products derived from
18+
// this software without specific prior written permission.
19+
//
20+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
31+
#include "pch.h"
32+
#include "CppUnitTest.h"
33+
#include <unordered_map>
34+
#include "wperf/arg-parser-arg.h"
35+
36+
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
37+
using namespace ArgParserArg;
38+
39+
namespace arg_parser_arg_tests
40+
{
41+
42+
TEST_CLASS(ArgParserArgTests)
43+
{
44+
public:
45+
TEST_METHOD(TestConstructor)
46+
{
47+
arg_parser_arg arg(L"--name", { L"-n" }, L"Description of the argument", { L"default" }, 1);
48+
Assert::AreEqual(std::wstring(L"--name"), arg.get_name());
49+
Assert::AreEqual(std::wstring(L"-n"), arg.get_alias_string());
50+
auto values = arg.get_values();
51+
Assert::AreEqual(size_t(1), values.size());
52+
Assert::AreEqual(std::wstring(L"default"), values[0]);
53+
Assert::AreEqual(std::wstring(L"Description of the argument"), arg.get_usage_text());
54+
}
55+
56+
TEST_METHOD(TestIsMatch)
57+
{
58+
arg_parser_arg arg(L"--name", { L"-n" }, L"Test argument");
59+
Assert::IsTrue(arg.is_match(L"--name"));
60+
Assert::IsTrue(arg.is_match(L"-n"));
61+
Assert::IsFalse(arg.is_match(L"--unknown"));
62+
}
63+
64+
TEST_METHOD(TestAddAlias)
65+
{
66+
arg_parser_arg arg(L"--name", { L"-n" }, L"Test argument");
67+
arg.add_alias(L"-alias");
68+
Assert::AreEqual(std::wstring(L"-n, -alias"), arg.get_alias_string());
69+
Assert::AreEqual(std::wstring(L"--name, -n, -alias"), arg.get_all_flags_string());
70+
}
71+
72+
TEST_METHOD(TestAddCheckFunc)
73+
{
74+
arg_parser_arg arg(L"--name", {}, L"Test argument", {}, 1);
75+
arg.add_check_func([](const std::wstring& value) { return value.length() < 10; });
76+
Assert::ExpectException<std::invalid_argument>([&]() {
77+
arg.parse({ L"--name", L"value_that_is_too_long" });
78+
});
79+
}
80+
81+
TEST_METHOD(TestParseSuccess)
82+
{
83+
arg_parser_arg arg(L"--name", {}, L"Test argument", {}, 1);
84+
Assert::IsTrue(arg.parse({ L"--name", L"value" }));
85+
auto values = arg.get_values();
86+
Assert::AreEqual(size_t(1), values.size());
87+
Assert::AreEqual(std::wstring(L"value"), values[0]);
88+
}
89+
90+
TEST_METHOD(TestParseFailure)
91+
{
92+
arg_parser_arg arg(L"--name", {}, L"Test argument", {}, 1);
93+
Assert::ExpectException<std::invalid_argument>([&]() {
94+
arg.parse({ L"--name" }); // Not enough arguments
95+
});
96+
}
97+
98+
TEST_METHOD(TestGetHelp)
99+
{
100+
arg_parser_arg arg(L"--help", { L"-h" }, L"Shows help information");
101+
auto help_text = arg.get_help();
102+
Assert::IsTrue(help_text.find(L"--help, -h") != std::wstring::npos);
103+
Assert::IsTrue(help_text.find(L"Shows help information") != std::wstring::npos);
104+
}
105+
106+
TEST_METHOD(TestOptionalArgument)
107+
{
108+
arg_parser_arg_opt arg(L"--optional", {}, L"An optional argument");
109+
Assert::AreEqual(0, arg.get_arg_count());
110+
Assert::IsTrue(arg.parse({ L"--optional" }));
111+
Assert::IsTrue(arg.is_set());
112+
}
113+
114+
TEST_METHOD(TestPositionalArgument)
115+
{
116+
arg_parser_arg_pos arg(L"filename", {}, L"Input file", {}, 1);
117+
Assert::AreEqual(1, arg.get_arg_count());
118+
Assert::IsTrue(arg.parse({ L"filename", L"input.txt" }));
119+
auto values = arg.get_values();
120+
Assert::AreEqual(std::wstring(L"input.txt"), values[0]);
121+
Assert::IsTrue(arg.is_set());
122+
}
123+
TEST_METHOD(TestGetHelpSingleAlias)
124+
{
125+
arg_parser_arg arg(L"--help", { L"-h" }, L"Displays help information.");
126+
auto help_text = arg.get_help();
127+
128+
// Check if the help text includes all flags and description
129+
Assert::IsTrue(help_text.find(L"--help, -h") != std::wstring::npos);
130+
// Check if the help text does not include an extra ',' at the end
131+
Assert::IsFalse(help_text.find(L"--help, -h,") != std::wstring::npos);
132+
Assert::IsTrue(help_text.find(L"Displays help information.") != std::wstring::npos);
133+
}
134+
135+
TEST_METHOD(TestGetHelpMultipleAliases)
136+
{
137+
arg_parser_arg arg(L"--output", { L"-o", L"-out" }, L"Specifies the output file.");
138+
auto help_text = arg.get_help();
139+
140+
// Verify the help output contains all aliases and description
141+
Assert::IsTrue(help_text.find(L"--output, -o, -out") != std::wstring::npos);
142+
Assert::IsTrue(help_text.find(L"Specifies the output file.") != std::wstring::npos);
143+
}
144+
145+
TEST_METHOD(TestGetHelpWithoutAliases)
146+
{
147+
arg_parser_arg arg(L"--verbose", {}, L"Enables verbose mode.");
148+
auto help_text = arg.get_help();
149+
150+
// Ensure the help text only includes the main name when no aliases are defined
151+
Assert::IsTrue(help_text.find(L"--verbose") != std::wstring::npos);
152+
Assert::IsFalse(help_text.find(L",") != std::wstring::npos); // No aliases
153+
Assert::IsTrue(help_text.find(L"Enables verbose mode.") != std::wstring::npos);
154+
}
155+
156+
TEST_METHOD(TestGetAllFlagsStringSingleAlias)
157+
{
158+
arg_parser_arg arg(L"--help", { L"-h" }, L"Displays help information.");
159+
auto flags = arg.get_all_flags_string();
160+
161+
// Verify that all flags are correctly concatenated
162+
Assert::AreEqual(std::wstring(L"--help, -h"), flags);
163+
}
164+
165+
TEST_METHOD(TestGetAllFlagsStringMultipleAliases)
166+
{
167+
arg_parser_arg arg(L"--input", { L"-i", L"-in" }, L"Specifies the input file.");
168+
auto flags = arg.get_all_flags_string();
169+
170+
// Check concatenation of all flags with multiple aliases
171+
Assert::AreEqual(std::wstring(L"--input, -i, -in"), flags);
172+
}
173+
174+
TEST_METHOD(TestGetAllFlagsStringNoAlias)
175+
{
176+
arg_parser_arg arg(L"--quiet", {}, L"Enables quiet mode.");
177+
auto flags = arg.get_all_flags_string();
178+
179+
// Ensure that the main flag name is returned without extra formatting
180+
Assert::AreEqual(std::wstring(L"--quiet"), flags);
181+
}
182+
};
183+
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// BSD 3-Clause License
2+
//
3+
// Copyright (c) 2024, Arm Limited
4+
// All rights reserved.
5+
//
6+
// Redistribution and use in source and binary forms, with or without
7+
// modification, are permitted provided that the following conditions are met:
8+
//
9+
// 1. Redistributions of source code must retain the above copyright notice, this
10+
// list of conditions and the following disclaimer.
11+
//
12+
// 2. Redistributions in binary form must reproduce the above copyright notice,
13+
// this list of conditions and the following disclaimer in the documentation
14+
// and/or other materials provided with the distribution.
15+
//
16+
// 3. Neither the name of the copyright holder nor the names of its
17+
// contributors may be used to endorse or promote products derived from
18+
// this software without specific prior written permission.
19+
//
20+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30+
31+
#include "pch.h"
32+
#include "CppUnitTest.h"
33+
#include <unordered_map>
34+
#include "wperf/arg-parser-arg.h"
35+
36+
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
37+
using namespace ArgParserArg;
38+
39+
namespace arg_parser_arg_utils_tests
40+
{
41+
42+
TEST_CLASS(ArgParserArgFormatToLengthTests)
43+
{
44+
public:
45+
TEST_METHOD(TestEmptyString)
46+
{
47+
std::wstring input = L"";
48+
size_t max_width = 10;
49+
std::wstring expected = L"";
50+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
51+
}
52+
53+
TEST_METHOD(TestSingleShortLine)
54+
{
55+
std::wstring input = L"Short line.";
56+
size_t max_width = 20;
57+
std::wstring expected = L"Short line.";
58+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
59+
}
60+
61+
TEST_METHOD(TestSingleLongLine)
62+
{
63+
std::wstring input = L"This is a line that exceeds the width.";
64+
size_t max_width = 15;
65+
std::wstring expected = L"This is a line\nthat exceeds the\nwidth.";
66+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
67+
}
68+
TEST_METHOD(TestMultipleLines)
69+
{
70+
std::wstring input = L"Line one.\nLine two is a bit longer.\nShort.";
71+
size_t max_width = 15;
72+
std::wstring expected = L"Line one.\n\nLine two is a\nbit longer.\n\nShort.";
73+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
74+
}
75+
TEST_METHOD(TestTrailingNewlineRemoval)
76+
{
77+
std::wstring input = L"Line one.\nLine two is a bit longer.\nShort.\n";
78+
size_t max_width = 15;
79+
std::wstring expected = L"Line one.\n\nLine two is a\nbit longer.\n\nShort.";
80+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
81+
}
82+
TEST_METHOD(TestMultipleLinesAndMultipleTrailingReturnToLines)
83+
{
84+
std::wstring input = L"Line one.\nLine two is a bit longer.\nShort.\n\n\n\n\n\n\n";
85+
size_t max_width = 15;
86+
std::wstring expected = L"Line one.\n\nLine two is a\nbit longer.\n\nShort.\n\n\n\n\n\n";
87+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
88+
}
89+
TEST_METHOD(MultipleRetrunToLines)
90+
{
91+
std::wstring input = L"\n\n\n";
92+
size_t max_width = 15;
93+
std::wstring expected = L"\n\n\n";
94+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
95+
}
96+
TEST_METHOD(TestExactFit)
97+
{
98+
std::wstring input = L"Exactly fifteen";
99+
size_t max_width = 15;
100+
std::wstring expected = L"Exactly fifteen";
101+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
102+
}
103+
104+
TEST_METHOD(TestSingleWordExceedsWidth)
105+
{
106+
std::wstring input = L"Supercalifragilisticexpialidocious";
107+
size_t max_width = 10;
108+
std::wstring expected = L"Supercalifragilisticexpialidocious";
109+
Assert::AreEqual(expected, arg_parser_format_string_to_length(input, max_width));
110+
}
111+
};
112+
TEST_CLASS(ArgParserAddPrefixTests)
113+
{
114+
public:
115+
TEST_METHOD(TestEmptyString)
116+
{
117+
std::wstring input = L"";
118+
std::wstring prefix = L"-> ";
119+
std::wstring expected = L"";
120+
Assert::AreEqual(expected, arg_parser_add_wstring_behind_multiline_text(input, prefix));
121+
}
122+
123+
TEST_METHOD(TestSingleLineWithPrefix)
124+
{
125+
std::wstring input = L"Hello, world!";
126+
std::wstring prefix = L"\t-> ";
127+
std::wstring expected = L"\t-> Hello, world!";
128+
Assert::AreEqual(expected, arg_parser_add_wstring_behind_multiline_text(input, prefix));
129+
}
130+
131+
TEST_METHOD(TestMultipleLinesWithPrefix)
132+
{
133+
std::wstring input = L"Line one.\nLine two.\nLine three.";
134+
std::wstring prefix = L"\t* ";
135+
std::wstring expected = L"\t* Line one.\n\t* Line two.\n\t* Line three.";
136+
Assert::AreEqual(expected, arg_parser_add_wstring_behind_multiline_text(input, prefix));
137+
}
138+
139+
TEST_METHOD(TestLinesWithEmptyLines)
140+
{
141+
std::wstring input = L"Line one.\n\nLine three.";
142+
std::wstring prefix = L"# ";
143+
std::wstring expected = L"# Line one.\n\n# Line three.";
144+
Assert::AreEqual(expected, arg_parser_add_wstring_behind_multiline_text(input, prefix));
145+
}
146+
147+
TEST_METHOD(TestNoPrefixOnEmptyLines)
148+
{
149+
std::wstring input = L"\n\n";
150+
std::wstring prefix = L"-> ";
151+
std::wstring expected = L"\n\n";
152+
Assert::AreEqual(expected, arg_parser_add_wstring_behind_multiline_text(input, prefix));
153+
}
154+
155+
TEST_METHOD(TestPrefixWithSpecialCharacters)
156+
{
157+
std::wstring input = L"Special line.";
158+
std::wstring prefix = L"*** ";
159+
std::wstring expected = L"*** Special line.";
160+
Assert::AreEqual(expected, arg_parser_add_wstring_behind_multiline_text(input, prefix));
161+
}
162+
TEST_METHOD(TestPrefixWithSeriesOfNewLines)
163+
{
164+
std::wstring input = L"\n\n\n";
165+
std::wstring prefix = L"*** ";
166+
std::wstring expected = L"\n\n\n";
167+
Assert::AreEqual(expected, arg_parser_add_wstring_behind_multiline_text(input, prefix));
168+
}
169+
TEST_METHOD(TestPrefixAndMultilineSpacing)
170+
{
171+
std::wstring input = L"Line one.\n\nLine two.\n\n";
172+
std::wstring prefix = L"--> ";
173+
std::wstring expected = L"--> Line one.\n\n--> Line two.\n";
174+
Assert::AreEqual(expected, arg_parser_add_wstring_behind_multiline_text(input, prefix));
175+
}
176+
177+
};
178+
}

0 commit comments

Comments
 (0)