Skip to content

Commit de3daf9

Browse files
committed
feat: add new implementation of parser
1 parent 1059def commit de3daf9

File tree

7 files changed

+362
-481
lines changed

7 files changed

+362
-481
lines changed

parser-tests/parser-tests.cpp

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,20 @@ namespace parsertests
4141
TEST_CLASS(parsertests)
4242
{
4343
public:
44-
44+
bool check_value_in_vector(const std::vector<std::wstring>& vec, const std::wstring& value)
45+
{
46+
return std::find(vec.begin(), vec.end(), value) != vec.end();
47+
}
4548
TEST_METHOD(TEST_CORRECT_TEST_COMMAND)
4649
{
4750
const wchar_t* argv[] = { L"wperf", L"test", L"-v", L"--json" };
4851
int argc = 4;
4952
mock_arg_parser parser;
5053
parser.parse(argc, argv);
5154

52-
Assert::AreEqual(true, parser.do_verbose.get());
53-
Assert::AreEqual(true, parser.do_json.get());
54-
Assert::IsTrue(COMMAND_CLASS::TEST == parser.command);
55+
Assert::AreEqual(true, parser.do_verbose.is_set());
56+
Assert::AreEqual(true, parser.do_json.is_set());
57+
Assert::IsTrue(COMMAND_CLASS::TEST == parser.m_command);
5558
}
5659
TEST_METHOD(TEST_RANDOM_ARGS_REJECTION)
5760
{
@@ -71,8 +74,8 @@ namespace parsertests
7174
mock_arg_parser parser;
7275
parser.parse(argc, argv);
7376

74-
Assert::IsTrue(parser.do_help.get());
75-
Assert::IsTrue(COMMAND_CLASS::HELP == parser.command);
77+
Assert::IsTrue(parser.do_help.is_set());
78+
Assert::IsTrue(COMMAND_CLASS::HELP == parser.m_command);
7679
}
7780

7881
// Test parsing the 'version' command with no arguments
@@ -83,8 +86,8 @@ namespace parsertests
8386
mock_arg_parser parser;
8487
parser.parse(argc, argv);
8588

86-
Assert::IsTrue(parser.do_version.get());
87-
Assert::IsTrue(COMMAND_CLASS::VERSION == parser.command);
89+
Assert::IsTrue(parser.do_version.is_set());
90+
Assert::IsTrue(COMMAND_CLASS::VERSION == parser.m_command);
8891
}
8992

9093
// Test parsing the 'list' command with no arguments
@@ -95,8 +98,8 @@ namespace parsertests
9598
mock_arg_parser parser;
9699
parser.parse(argc, argv);
97100

98-
Assert::IsTrue(parser.do_list.get());
99-
Assert::IsTrue(COMMAND_CLASS::LIST == parser.command);
101+
Assert::IsTrue(parser.do_list.is_set());
102+
Assert::IsTrue(COMMAND_CLASS::LIST == parser.m_command);
100103
}
101104

102105
// Test parsing the 'record' command with command line separator and arguments
@@ -107,9 +110,9 @@ namespace parsertests
107110
mock_arg_parser parser;
108111
parser.parse(argc, argv);
109112

110-
Assert::IsTrue(parser.do_record.get());
111-
Assert::AreEqual(std::wstring(L"notepad.exe test_arg"), parser.double_dash.get());
112-
Assert::IsTrue(COMMAND_CLASS::RECORD == parser.command);
113+
Assert::IsTrue(parser.do_record.is_set());
114+
Assert::IsTrue(check_value_in_vector(parser.double_dash.get_values(), L"notepad.exe"));
115+
Assert::IsTrue(COMMAND_CLASS::RECORD == parser.m_command);
113116
}
114117

115118
// Test that missing required arguments cause exceptions
@@ -144,7 +147,7 @@ namespace parsertests
144147
mock_arg_parser parser;
145148
parser.parse(argc, argv);
146149

147-
Assert::AreEqual(std::wstring(L"2m"), parser.count_duration.get()); // 2 minutes in seconds
150+
Assert::IsTrue(check_value_in_vector(parser.count_duration.get_values(), L"2m"));
148151
}
149152

150153
TEST_METHOD(TEST_INVALID_TIMEOUT_WITH_WRONG_FORMAT)
@@ -166,22 +169,22 @@ namespace parsertests
166169
mock_arg_parser parser;
167170
parser.parse(argc, argv);
168171

169-
Assert::IsTrue(parser.do_detect.get());
170-
Assert::IsTrue(COMMAND_CLASS::DETECT == parser.command);
172+
Assert::IsTrue(parser.do_detect.is_set());
173+
Assert::IsTrue(COMMAND_CLASS::DETECT == parser.m_command);
171174
}
172175

173-
// Test parsing multiple flags together
176+
// Test parsing multiple flags tois_sether
174177
TEST_METHOD(TEST_MULTIPLE_FLAGS)
175178
{
176179
const wchar_t* argv[] = { L"wperf", L"sample", L"--verbose", L"-q", L"--json" };
177180
int argc = 5;
178181
mock_arg_parser parser;
179182
parser.parse(argc, argv);
180183

181-
Assert::IsTrue(parser.do_verbose.get());
182-
Assert::IsTrue(parser.is_quite.get());
183-
Assert::IsTrue(parser.do_json.get());
184-
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.command);
184+
Assert::IsTrue(parser.do_verbose.is_set());
185+
Assert::IsTrue(parser.is_quite.is_set());
186+
Assert::IsTrue(parser.do_json.is_set());
187+
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.m_command);
185188
}
186189

187190
// Test parsing sample command with symbol argument
@@ -192,8 +195,8 @@ namespace parsertests
192195
mock_arg_parser parser;
193196
parser.parse(argc, argv);
194197

195-
Assert::AreEqual(std::wstring(L"main"), parser.symbol_arg.get());
196-
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.command);
198+
Assert::IsTrue(check_value_in_vector(parser.symbol_arg.get_values(), L"main"));
199+
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.m_command);
197200
}
198201

199202
// Test parsing sample command with sample display row
@@ -204,8 +207,8 @@ namespace parsertests
204207
mock_arg_parser parser;
205208
parser.parse(argc, argv);
206209

207-
Assert::AreEqual(std::wstring(L"100"), parser.sample_display_row.get());
208-
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.command);
210+
Assert::IsTrue(check_value_in_vector(parser.sample_display_row.get_values(), L"100"));
211+
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.m_command);
209212
}
210213

211214
// Test parsing sample command with pe_file
@@ -217,8 +220,8 @@ namespace parsertests
217220

218221
parser.parse(argc, argv);
219222

220-
Assert::AreEqual(std::wstring(L"C:\\Program\\sample.exe"), parser.sample_pe_file.get());
221-
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.command);
223+
Assert::IsTrue(check_value_in_vector(parser.sample_pe_file.get_values(), L"C:\\Program\\sample.exe"));
224+
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.m_command);
222225
}
223226

224227
// Test parsing sample command with pdb_file
@@ -231,8 +234,8 @@ namespace parsertests
231234
// Similarly, adjust or mock check_file_path for testing
232235
parser.parse(argc, argv);
233236

234-
Assert::AreEqual(std::wstring(L"C:\\Program\\sample.pdb"), parser.sample_pdb_file.get());
235-
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.command);
237+
Assert::IsTrue(check_value_in_vector(parser.sample_pdb_file.get_values(), L"C:\\Program\\sample.pdb"));
238+
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.m_command);
236239
}
237240

238241
// Test parsing sample command with image_name
@@ -243,8 +246,8 @@ namespace parsertests
243246
mock_arg_parser parser;
244247
parser.parse(argc, argv);
245248

246-
Assert::AreEqual(std::wstring(L"notepad.exe"), parser.sample_image_name.get());
247-
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.command);
249+
Assert::IsTrue(check_value_in_vector(parser.sample_image_name.get_values(), L"notepad.exe"));
250+
Assert::IsTrue(COMMAND_CLASS::SAMPLE == parser.m_command);
248251
}
249252

250253
// Test parsing with --force-lock flag
@@ -255,8 +258,8 @@ namespace parsertests
255258
mock_arg_parser parser;
256259
parser.parse(argc, argv);
257260

258-
Assert::IsTrue(parser.do_force_lock.get());
259-
Assert::IsTrue(COMMAND_CLASS::TEST == parser.command);
261+
Assert::IsTrue(parser.do_force_lock.is_set());
262+
Assert::IsTrue(COMMAND_CLASS::TEST == parser.m_command);
260263
}
261264

262265
// Test parsing the 'stat' command (not fully implemented in the parser)
@@ -268,7 +271,7 @@ namespace parsertests
268271
parser.parse(argc, argv);
269272

270273
// Assuming command is set correctly
271-
Assert::IsTrue(COMMAND_CLASS::STAT == parser.command);
274+
Assert::IsTrue(COMMAND_CLASS::STAT == parser.m_command);
272275
}
273276

274277
// Test parsing with unknown flags
@@ -302,15 +305,15 @@ namespace parsertests
302305
int argc = 10;
303306
mock_arg_parser parser;
304307
parser.parse(argc, argv);
305-
Assert::IsTrue(COMMAND_CLASS::STAT == parser.command);
308+
Assert::IsTrue(COMMAND_CLASS::STAT == parser.m_command);
306309
Assert::IsTrue(parser.raw_events.is_set());
307310
Assert::IsTrue(parser.output_filename.is_set());
308311
Assert::IsTrue(parser.cores_idx.is_set());
309312
Assert::IsTrue(parser.count_duration.is_set());
310-
Assert::AreEqual(wstring(L"5"), parser.count_duration.get());
311-
Assert::AreEqual(wstring(L"0"), parser.cores_idx.get());
312-
Assert::AreEqual(wstring(L"_output_02.json"),parser.output_filename.get());
313-
Assert::AreEqual(wstring(L"inst_spec,vfp_spec,ase_spec,dp_spec,ld_spec,st_spec,br_immed_spec,crypto_spec"), parser.raw_events.get());
313+
Assert::IsTrue(check_value_in_vector(parser.count_duration.get_values(), L"5"));
314+
Assert::IsTrue(check_value_in_vector(parser.cores_idx.get_values(), L"0"));
315+
Assert::IsTrue(check_value_in_vector(parser.output_filename.get_values(), L"_output_02.json"));
316+
Assert::IsTrue(check_value_in_vector(parser.raw_events.get_values(), L"inst_spec,vfp_spec,ase_spec,dp_spec,ld_spec,st_spec,br_immed_spec,crypto_spec"));
314317
}
315318
};
316319
}

parser-tests/parser-tests.vcxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
<Link>
104104
<SubSystem>Windows</SubSystem>
105105
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories);$(SolutionDir)parser\$(Platform)\$(Configuration)\</AdditionalLibraryDirectories>
106-
<AdditionalDependencies>$(CoreLibraryDependencies);%(AdditionalDependencies);$(SolutionDir)parser\$(Platform)\$(Configuration)\arg-parser.obj</AdditionalDependencies>
106+
<AdditionalDependencies>$(CoreLibraryDependencies);%(AdditionalDependencies);$(SolutionDir)parser\$(Platform)\$(Configuration)\arg-parser.obj;$(SolutionDir)parser\$(Platform)\$(Configuration)\arg-parser-arg.obj</AdditionalDependencies>
107107
</Link>
108108
</ItemDefinitionGroup>
109109
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

parser/arg-parser-arg.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#include "arg-parser-arg.h"
2+
#include <stdexcept>
23

34
arg_parser_arg::arg_parser_arg(
45
const std::wstring name,
56
const std::vector<std::wstring> alias,
67
const std::wstring description,
8+
const std::vector<std::wstring> default_values,
79
const int arg_count
8-
) : m_name(name), m_aliases(alias), m_description(description), m_arg_count(arg_count) {};
10+
) : m_name(name), m_aliases(alias), m_description(description), m_arg_count(arg_count), m_values(default_values) {};
911

1012
inline bool arg_parser_arg::operator==(const std::wstring& other_arg) const
1113
{
@@ -64,15 +66,31 @@ void arg_parser_arg::set_is_parsed()
6466
m_is_parsed = true;
6567
}
6668

69+
bool arg_parser_arg::is_parsed()
70+
{
71+
return m_is_parsed;
72+
}
73+
74+
bool arg_parser_arg::is_set()
75+
{
76+
return is_parsed() && m_values.size() == m_arg_count;
77+
}
78+
79+
std::vector<std::wstring> arg_parser_arg::get_values()
80+
{
81+
return m_values;
82+
}
83+
6784
bool arg_parser_arg::parse(std::vector<std::wstring> arg_vect)
6885
{
86+
if (arg_vect.size() == 0 || !is_match(arg_vect[0]))
87+
return false;
88+
6989
if (m_arg_count == -1 && arg_vect.size() > 0) m_arg_count = arg_vect.size() - 1;
7090

7191
if (arg_vect.size() < m_arg_count + 1)
72-
return false;
92+
throw std::invalid_argument("Not enough arguments provided.");
7393

74-
if (!is_match(arg_vect[0]))
75-
return false;
7694
if (m_arg_count == 0)
7795
{
7896
set_is_parsed();
@@ -84,10 +102,9 @@ bool arg_parser_arg::parse(std::vector<std::wstring> arg_vect)
84102
for (auto& check_func : m_check_funcs)
85103
{
86104
if (!check_func(arg_vect[i]))
87-
return false;
105+
throw std::invalid_argument("Invalid arguments provided.");
88106
}
89107
m_values.push_back(arg_vect[i]);
90-
91108
}
92109
set_is_parsed();
93110
return true;

parser/arg-parser-arg.h

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ struct arg_parser_arg {
2222
const std::wstring name,
2323
const std::vector<std::wstring> alias,
2424
const std::wstring description,
25-
const int arg_count
25+
const std::vector<std::wstring> default_values = {},
26+
const int arg_count = 0
2627
);
2728
bool is_match(const std::wstring& arg) const;
2829
virtual std::wstring get_help() const;
@@ -33,34 +34,30 @@ struct arg_parser_arg {
3334
std::wstring get_alias_string() const;
3435
arg_parser_arg add_check_func(std::function<bool(const std::wstring&)> check_func);
3536
void set_is_parsed();
37+
bool is_parsed();
38+
bool is_set();
39+
std::vector<std::wstring> get_values();
3640
bool parse(std::vector<std::wstring> arg_vect);
3741
};
3842

39-
class arg_parser_arg_opt : arg_parser_arg {
43+
class arg_parser_arg_opt : public arg_parser_arg {
44+
public:
4045
arg_parser_arg_opt(
4146
const std::wstring name,
4247
const std::vector<std::wstring> alias,
4348
const std::wstring description,
44-
const int arg_count
45-
) : arg_parser_arg(name, alias, description, 0) {};
49+
const std::vector<std::wstring> default_values = {}
50+
) : arg_parser_arg(name, alias, description, default_values, 0) {};
4651
};
4752

48-
class arg_parser_arg_pos : arg_parser_arg {
53+
class arg_parser_arg_pos : public arg_parser_arg {
54+
public:
4955
arg_parser_arg_pos(
5056
const std::wstring name,
5157
const std::vector<std::wstring> alias,
5258
const std::wstring description,
53-
const int arg_count
54-
) : arg_parser_arg(name, alias, description, arg_count) {};
59+
const std::vector<std::wstring> default_values = {},
60+
const int arg_count = 1
61+
) : arg_parser_arg(name, alias, description, default_values, arg_count) {};
5562
};
5663

57-
class arg_parser_arg_command : arg_parser_arg {
58-
arg_parser_arg_command(
59-
const std::wstring name,
60-
const std::vector<std::wstring> alias,
61-
const std::wstring description,
62-
const int arg_count,
63-
const std::wstring examples
64-
) : arg_parser_arg(name, alias, description, 1) {};
65-
const std::wstring m_examples;
66-
};

0 commit comments

Comments
 (0)