Skip to content

Commit ef9ff9c

Browse files
simarkjgalar
authored andcommitted
lttng: list valid condition / action names if missing or unknown
I think it would be helpful to the user to list the condition and action names, when the condition or action name is missing or unrecognized. This patch implements that, here are some examples of the result: $ lttng add-trigger --action notify --condition Error: While parsing argument #4: Missing required argument for option `--condition` Error: Valid condition names are: Error: event-rule-matches $ lttng add-trigger --action notify --condition pouet Error: While parsing argument #5: Unknown condition name 'pouet' Error: Valid condition names are: Error: event-rule-matches $ lttng add-trigger --condition event-rule-matches --action Error: While parsing argument #4: Missing required argument for option `--action` Error: Valid action names are: Error: notify $ lttng add-trigger --condition event-rule-matches --action pouet Error: While parsing argument #5: Unknown action name: pouet Error: Valid action names are: Error: notify To achieve this, add a new optional out argument to parse_next_item, to allow the caller to get the argpar_error object if a parsing error happened. Because of this, the callers must now be able to differentiate parsing error from memory errors: in the latter case, no argpar_error object is returned. So, add a new PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY status, and make users of parse_next_item handle it. In the add-trigger command implementation, handle the "missing opt arg" case of OPT_ACTION and OPT_CONDITION specially to print the valid names. Handle unknown names in parse_action and parse_condition. Add a test for an unknown action name, it seems to be missing. Change the error message format slightly to make it match the messages for unknown condition names. Change-Id: I4c13cecacb3a2ff4367e391c4aba0d05f1f28f22 Signed-off-by: Simon Marchi <[email protected]> Signed-off-by: Jérémie Galarneau <[email protected]>
1 parent e776cf4 commit ef9ff9c

File tree

6 files changed

+104
-21
lines changed

6 files changed

+104
-21
lines changed

src/bin/lttng/commands/add_trigger.cpp

+56-10
Original file line numberDiff line numberDiff line change
@@ -697,8 +697,9 @@ struct parse_event_rule_res parse_event_rule(int *argc, const char ***argv,
697697
enum parse_next_item_status status;
698698

699699
status = parse_next_item(argpar_iter, &argpar_item,
700-
argc_offset, *argv, false, NULL);
701-
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
700+
argc_offset, *argv, false, NULL, NULL);
701+
if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
702+
status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
702703
goto error;
703704
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
704705
break;
@@ -1414,6 +1415,18 @@ struct condition_descr condition_descrs[] = {
14141415
{ "event-rule-matches", handle_condition_event },
14151416
};
14161417

1418+
static
1419+
void print_valid_condition_names(void)
1420+
{
1421+
unsigned int i;
1422+
1423+
ERR("Valid condition names are:");
1424+
1425+
for (i = 0; i < ARRAY_SIZE(condition_descrs); ++i) {
1426+
ERR(" %s", condition_descrs[i].name);
1427+
}
1428+
}
1429+
14171430
static
14181431
struct lttng_condition *parse_condition(const char *condition_name, int *argc,
14191432
const char ***argv, int argc_offset, int orig_arg_index,
@@ -1433,6 +1446,7 @@ struct lttng_condition *parse_condition(const char *condition_name, int *argc,
14331446
if (!descr) {
14341447
ERR(WHILE_PARSING_ARG_N_ARG_FMT "Unknown condition name '%s'",
14351448
orig_arg_index + 1, orig_arg, condition_name);
1449+
print_valid_condition_names();
14361450
goto error;
14371451
}
14381452

@@ -1547,9 +1561,10 @@ struct lttng_action *handle_action_notify(int *argc, const char ***argv,
15471561
enum parse_next_item_status status;
15481562

15491563
status = parse_next_item(argpar_iter, &argpar_item,
1550-
argc_offset, *argv, false,
1564+
argc_offset, *argv, false, NULL,
15511565
"While parsing `notify` action:");
1552-
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
1566+
if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
1567+
status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
15531568
goto error;
15541569
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
15551570
break;
@@ -1653,9 +1668,10 @@ static struct lttng_action *handle_action_simple_session_with_policy(int *argc,
16531668
enum parse_next_item_status status;
16541669

16551670
status = parse_next_item(argpar_iter, &argpar_item, argc_offset,
1656-
*argv, false,
1671+
*argv, false, NULL,
16571672
"While parsing `%s` action:", action_name);
1658-
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
1673+
if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
1674+
status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
16591675
goto error;
16601676
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
16611677
break;
@@ -1813,8 +1829,9 @@ struct lttng_action *handle_action_snapshot_session(int *argc,
18131829
enum parse_next_item_status status;
18141830

18151831
status = parse_next_item(argpar_iter, &argpar_item, argc_offset,
1816-
*argv, false, "While parsing `snapshot` action:");
1817-
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
1832+
*argv, false, NULL, "While parsing `snapshot` action:");
1833+
if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
1834+
status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
18181835
goto error;
18191836
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
18201837
break;
@@ -2097,6 +2114,18 @@ struct action_descr action_descrs[] = {
20972114
{ "snapshot-session", handle_action_snapshot_session },
20982115
};
20992116

2117+
static
2118+
void print_valid_action_names(void)
2119+
{
2120+
unsigned int i;
2121+
2122+
ERR("Valid action names are:");
2123+
2124+
for (i = 0; i < ARRAY_SIZE(condition_descrs); ++i) {
2125+
ERR(" %s", action_descrs[i].name);
2126+
}
2127+
}
2128+
21002129
static
21012130
struct lttng_action *parse_action(const char *action_name, int *argc,
21022131
const char ***argv, int argc_offset, int orig_arg_index,
@@ -2114,8 +2143,9 @@ struct lttng_action *parse_action(const char *action_name, int *argc,
21142143
}
21152144

21162145
if (!descr) {
2117-
ERR(WHILE_PARSING_ARG_N_ARG_FMT "Unknown action name: %s",
2146+
ERR(WHILE_PARSING_ARG_N_ARG_FMT "Unknown action name '%s'",
21182147
orig_arg_index + 1, orig_arg, action_name);
2148+
print_valid_action_names();
21192149
goto error;
21202150
}
21212151

@@ -2160,6 +2190,7 @@ int cmd_add_trigger(int argc, const char **argv)
21602190
struct lttng_dynamic_pointer_array actions;
21612191
struct argpar_iter *argpar_iter = NULL;
21622192
const struct argpar_item *argpar_item = NULL;
2193+
const struct argpar_error *argpar_error = NULL;
21632194
struct lttng_action *action_list = NULL;
21642195
struct lttng_action *action = NULL;
21652196
struct lttng_trigger *trigger = NULL;
@@ -2211,8 +2242,22 @@ int cmd_add_trigger(int argc, const char **argv)
22112242
}
22122243

22132244
status = parse_next_item(argpar_iter, &argpar_item,
2214-
argc - my_argc, my_argv, true, NULL);
2245+
argc - my_argc, my_argv, true, &argpar_error, NULL);
22152246
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
2247+
2248+
if (argpar_error_type(argpar_error) ==
2249+
ARGPAR_ERROR_TYPE_MISSING_OPT_ARG) {
2250+
int opt_id = argpar_error_opt_descr(argpar_error, NULL)->id;
2251+
2252+
if (opt_id == OPT_CONDITION) {
2253+
print_valid_condition_names();
2254+
} else if (opt_id == OPT_ACTION) {
2255+
print_valid_action_names();
2256+
}
2257+
}
2258+
2259+
goto error;
2260+
} else if (status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
22162261
goto error;
22172262
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
22182263
break;
@@ -2432,6 +2477,7 @@ int cmd_add_trigger(int argc, const char **argv)
24322477
}
24332478

24342479
cleanup:
2480+
argpar_error_destroy(argpar_error);
24352481
argpar_iter_destroy(argpar_iter);
24362482
argpar_item_destroy(argpar_item);
24372483
lttng_dynamic_pointer_array_reset(&actions);

src/bin/lttng/commands/list_triggers.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1336,8 +1336,9 @@ int cmd_list_triggers(int argc, const char **argv)
13361336
enum parse_next_item_status status;
13371337

13381338
status = parse_next_item(argpar_iter, &argpar_item, 1, argv,
1339-
true, NULL);
1340-
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
1339+
true, NULL, NULL);
1340+
if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
1341+
status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
13411342
goto error;
13421343
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
13431344
break;

src/bin/lttng/commands/remove_trigger.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,9 @@ int cmd_remove_trigger(int argc, const char **argv)
112112
enum parse_next_item_status status;
113113

114114
status = parse_next_item(argpar_iter, &argpar_item, 1, argv,
115-
true, NULL);
116-
if (status == PARSE_NEXT_ITEM_STATUS_ERROR) {
115+
true, NULL, NULL);
116+
if (status == PARSE_NEXT_ITEM_STATUS_ERROR ||
117+
status == PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY) {
117118
goto error;
118119
} else if (status == PARSE_NEXT_ITEM_STATUS_END) {
119120
break;

src/common/argpar-utils/argpar-utils.c

+8-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ char *format_arg_error_v(const struct argpar_error *error, int argc_offset,
120120
enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
121121
const struct argpar_item **item, int argc_offset,
122122
const char **argv, bool unknown_opt_is_error,
123+
const struct argpar_error **error_out,
123124
const char *context_fmt, ...)
124125
{
125126
enum argpar_iter_next_status status;
@@ -132,7 +133,7 @@ enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
132133
switch (status) {
133134
case ARGPAR_ITER_NEXT_STATUS_ERROR_MEMORY:
134135
ERR("Failed to get next argpar item.");
135-
ret = PARSE_NEXT_ITEM_STATUS_ERROR;
136+
ret = PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY;
136137
break;
137138
case ARGPAR_ITER_NEXT_STATUS_ERROR:
138139
{
@@ -170,6 +171,12 @@ enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
170171
abort();
171172
}
172173

174+
if (error_out) {
175+
argpar_error_destroy(*error_out);
176+
*error_out = error;
177+
error = NULL;
178+
}
179+
173180
argpar_error_destroy(error);
174181

175182
return ret;

src/common/argpar-utils/argpar-utils.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ enum parse_next_item_status
2525
PARSE_NEXT_ITEM_STATUS_OK = 0,
2626
PARSE_NEXT_ITEM_STATUS_END = 1,
2727
PARSE_NEXT_ITEM_STATUS_ERROR = -1,
28+
PARSE_NEXT_ITEM_STATUS_ERROR_MEMORY = -2,
2829
};
2930

3031
/*
@@ -45,11 +46,16 @@ enum parse_next_item_status
4546
*
4647
* If `unknown_opt_is_error` is true, an unknown option is considered an error.
4748
* Otherwise, it is considered as the end of the argument list.
49+
*
50+
* If `error_out` is given and PARSE_NEXT_ITEM_STATUS_ERROR is returned, set
51+
* `*error_out` to the argpar_error object corresponding to the error. The
52+
* caller must free the object with `argpar_error_destroy`.
4853
*/
49-
ATTR_FORMAT_PRINTF(6, 7)
54+
ATTR_FORMAT_PRINTF(7, 8)
5055
enum parse_next_item_status parse_next_item(struct argpar_iter *iter,
5156
const struct argpar_item **item, int argc_offset,
5257
const char **argv, bool unknown_opt_is_error,
58+
const struct argpar_error **error_out,
5359
const char *context_fmt, ...);
5460

5561
#ifdef __cplusplus

tests/regression/tools/trigger/test_add_trigger_cli

+27-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ TESTDIR="$CURDIR/../../.."
2323
# shellcheck source=../../../utils/utils.sh
2424
source "$TESTDIR/utils/utils.sh"
2525

26-
plan_tests 289
26+
plan_tests 295
2727

2828
FULL_LTTNG_BIN="${TESTDIR}/../src/bin/lttng/${LTTNG_BIN}"
2929

@@ -450,13 +450,19 @@ test_failure "invalid argument to --rate-policy: unknown policy type" \
450450

451451
# `--condition` failures
452452
test_failure "missing args after --condition" \
453-
"Error: While parsing argument #2 (\`--condition\`): Missing required argument for option \`--condition\`" \
453+
"Error: While parsing argument #2 (\`--condition\`): Missing required argument for option \`--condition\`
454+
Error: Valid condition names are:
455+
Error: event-rule-matches" \
454456
--condition
455457
test_failure "unknown --condition" \
456-
"Error: While parsing argument #2 (\`--condition\`): Unknown condition name 'zoofest'" \
458+
"Error: While parsing argument #2 (\`--condition\`): Unknown condition name 'zoofest'
459+
Error: Valid condition names are:
460+
Error: event-rule-matches" \
457461
--condition zoofest
458462
test_failure "unknown --condition=" \
459-
"Error: While parsing argument #2 (\`--condition=zoofest\`): Unknown condition name 'zoofest'" \
463+
"Error: While parsing argument #2 (\`--condition=zoofest\`): Unknown condition name 'zoofest'
464+
Error: Valid condition names are:
465+
Error: event-rule-matches" \
460466
--condition=zoofest
461467

462468
# `--condition event-rule-matches` failures
@@ -551,10 +557,26 @@ test_failure "--condition event-rule-matches --capture: missing colon in app-spe
551557

552558
# `--action` failures
553559
test_failure "missing args after --action" \
554-
"Error: While parsing argument #5 (\`--action\`): Missing required argument for option \`--action\`" \
560+
"Error: While parsing argument #5 (\`--action\`): Missing required argument for option \`--action\`
561+
Error: Valid action names are:
562+
Error: notify" \
555563
--condition event-rule-matches --type=user \
556564
--action
557565

566+
test_failure "unknown --action" \
567+
"Error: While parsing argument #5 (\`--action\`): Unknown action name 'zoofest'
568+
Error: Valid action names are:
569+
Error: notify" \
570+
--condition event-rule-matches --type=user \
571+
--action zoofest
572+
573+
test_failure "unknown --action=" \
574+
"Error: While parsing argument #5 (\`--action=zoofest\`): Unknown action name 'zoofest'
575+
Error: Valid action names are:
576+
Error: notify" \
577+
--condition event-rule-matches --type=user \
578+
--action=zoofest
579+
558580
# `--action notify` failures
559581
test_failure "extra arg after --action notify" \
560582
"Error: Unexpected argument \`bob\`." \

0 commit comments

Comments
 (0)