diff mbox series

[v3,2/5] t/helper/test-config: return exit codes consistently

Message ID 43402007adb0916846f92c3e4ff86d4131056ce0.1590627264.git.matheus.bernardino@usp.br (mailing list archive)
State New, archived
Headers show
Series grep: honor sparse checkout and add option to ignore it | expand

Commit Message

Matheus Tavares May 28, 2020, 1:13 a.m. UTC
The test-config helper may exit with a variety of at least four
different codes, to reflect the status of the requested operations.
These codes are sometimes checked in the tests, but not all of the codes
are returned consistently by the helper: 1 will usually refer to a
"value not found", but usage errors can also return 1 or 128. The latter
is also expected on errors within the configset functions. These
inconsistent uses of the exit codes can lead to false positives in the
tests. Although all tests that currently check the helper's exit code,
on errors, do also check the output, it's still better to standardize
the exit codes and avoid future problems in new tests. While we are
here, let's also check that we have the expected argc for
configset_get_value and configset_get_value_multi, before trying to use
argv.

Note: this change is implemented with the unification of the exit
labels. This might seem unnecessary, for now, but it will benefit the
next patch, which will increase the cleanup section.

Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
 t/helper/test-config.c | 76 ++++++++++++++++++++++--------------------
 1 file changed, 40 insertions(+), 36 deletions(-)

Comments

Elijah Newren May 30, 2020, 2:29 p.m. UTC | #1
On Wed, May 27, 2020 at 6:13 PM Matheus Tavares
<matheus.bernardino@usp.br> wrote:
>
> The test-config helper may exit with a variety of at least four
> different codes, to reflect the status of the requested operations.
> These codes are sometimes checked in the tests, but not all of the codes
> are returned consistently by the helper: 1 will usually refer to a
> "value not found", but usage errors can also return 1 or 128. The latter

I'm not sure what "The latter" refers to here.

> is also expected on errors within the configset functions. These
> inconsistent uses of the exit codes can lead to false positives in the
> tests. Although all tests that currently check the helper's exit code,
> on errors, do also check the output, it's still better to standardize
> the exit codes and avoid future problems in new tests. While we are

That last sentence was slightly hard for me to parse.  Maybe something like:

...Although all tests which expect errors and check the helper's exit
code currently also check the output, it's still better...


> here, let's also check that we have the expected argc for
> configset_get_value and configset_get_value_multi, before trying to use
> argv.
>
> Note: this change is implemented with the unification of the exit
> labels. This might seem unnecessary, for now, but it will benefit the
> next patch, which will increase the cleanup section.
>
> Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
> ---
>  t/helper/test-config.c | 76 ++++++++++++++++++++++--------------------
>  1 file changed, 40 insertions(+), 36 deletions(-)
>
> diff --git a/t/helper/test-config.c b/t/helper/test-config.c
> index 234c722b48..1c8e965840 100644
> --- a/t/helper/test-config.c
> +++ b/t/helper/test-config.c
> @@ -30,6 +30,14 @@
>   * iterate -> iterate over all values using git_config(), and print some
>   *            data for each
>   *
> + * Exit codes:
> + *     0:   success
> + *     1:   value not found for the given config key
> + *     2:   config file path given as argument is inaccessible or doesn't exist
> + *     129: test-config usage error
> + *
> + * Note: tests may also expect 128 for die() calls in the config machinery.
> + *
>   * Examples:
>   *
>   * To print the value with highest priority for key "foo.bAr Baz.rock":
> @@ -64,35 +72,42 @@ static int early_config_cb(const char *var, const char *value, void *vdata)
>         return 0;
>  }
>
> +enum test_config_exit_code {
> +       TC_SUCCESS = 0,
> +       TC_VALUE_NOT_FOUND = 1,
> +       TC_CONFIG_FILE_ERROR = 2,
> +       TC_USAGE_ERROR = 129,
> +};
> +
>  int cmd__config(int argc, const char **argv)
>  {
>         int i, val;
>         const char *v;
>         const struct string_list *strptr;
>         struct config_set cs;
> +       enum test_config_exit_code ret = TC_SUCCESS;
>
>         if (argc == 3 && !strcmp(argv[1], "read_early_config")) {
>                 read_early_config(early_config_cb, (void *)argv[2]);
> -               return 0;
> +               return TC_SUCCESS;
>         }
>
>         setup_git_directory();
>
>         git_configset_init(&cs);
>
> -       if (argc < 2) {
> -               fprintf(stderr, "Please, provide a command name on the command-line\n");
> -               goto exit1;
> -       } else if (argc == 3 && !strcmp(argv[1], "get_value")) {
> +       if (argc < 2)
> +               goto print_usage_error;
> +
> +       if (argc == 3 && !strcmp(argv[1], "get_value")) {
>                 if (!git_config_get_value(argv[2], &v)) {
>                         if (!v)
>                                 printf("(NULL)\n");
>                         else
>                                 printf("%s\n", v);
> -                       goto exit0;
>                 } else {
>                         printf("Value not found for \"%s\"\n", argv[2]);
> -                       goto exit1;
> +                       ret = TC_VALUE_NOT_FOUND;
>                 }
>         } else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
>                 strptr = git_config_get_value_multi(argv[2]);
> @@ -104,41 +119,38 @@ int cmd__config(int argc, const char **argv)
>                                 else
>                                         printf("%s\n", v);
>                         }
> -                       goto exit0;
>                 } else {
>                         printf("Value not found for \"%s\"\n", argv[2]);
> -                       goto exit1;
> +                       ret = TC_VALUE_NOT_FOUND;
>                 }
>         } else if (argc == 3 && !strcmp(argv[1], "get_int")) {
>                 if (!git_config_get_int(argv[2], &val)) {
>                         printf("%d\n", val);
> -                       goto exit0;
>                 } else {
>                         printf("Value not found for \"%s\"\n", argv[2]);
> -                       goto exit1;
> +                       ret = TC_VALUE_NOT_FOUND;
>                 }
>         } else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
>                 if (!git_config_get_bool(argv[2], &val)) {
>                         printf("%d\n", val);
> -                       goto exit0;
>                 } else {
>                         printf("Value not found for \"%s\"\n", argv[2]);
> -                       goto exit1;
> +                       ret = TC_VALUE_NOT_FOUND;
>                 }
>         } else if (argc == 3 && !strcmp(argv[1], "get_string")) {
>                 if (!git_config_get_string_const(argv[2], &v)) {
>                         printf("%s\n", v);
> -                       goto exit0;
>                 } else {
>                         printf("Value not found for \"%s\"\n", argv[2]);
> -                       goto exit1;
> +                       ret = TC_VALUE_NOT_FOUND;
>                 }
> -       } else if (!strcmp(argv[1], "configset_get_value")) {
> +       } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
>                 for (i = 3; i < argc; i++) {
>                         int err;
>                         if ((err = git_configset_add_file(&cs, argv[i]))) {
>                                 fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
> -                               goto exit2;
> +                               ret = TC_CONFIG_FILE_ERROR;
> +                               goto out;
>                         }
>                 }
>                 if (!git_configset_get_value(&cs, argv[2], &v)) {
> @@ -146,17 +158,17 @@ int cmd__config(int argc, const char **argv)
>                                 printf("(NULL)\n");
>                         else
>                                 printf("%s\n", v);
> -                       goto exit0;
>                 } else {
>                         printf("Value not found for \"%s\"\n", argv[2]);
> -                       goto exit1;
> +                       ret = TC_VALUE_NOT_FOUND;
>                 }
> -       } else if (!strcmp(argv[1], "configset_get_value_multi")) {
> +       } else if (argc >= 3 && !strcmp(argv[1], "configset_get_value_multi")) {
>                 for (i = 3; i < argc; i++) {
>                         int err;
>                         if ((err = git_configset_add_file(&cs, argv[i]))) {
>                                 fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
> -                               goto exit2;
> +                               ret = TC_CONFIG_FILE_ERROR;
> +                               goto out;
>                         }
>                 }
>                 strptr = git_configset_get_value_multi(&cs, argv[2]);
> @@ -168,27 +180,19 @@ int cmd__config(int argc, const char **argv)
>                                 else
>                                         printf("%s\n", v);
>                         }
> -                       goto exit0;
>                 } else {
>                         printf("Value not found for \"%s\"\n", argv[2]);
> -                       goto exit1;
> +                       ret = TC_VALUE_NOT_FOUND;
>                 }
>         } else if (!strcmp(argv[1], "iterate")) {
>                 git_config(iterate_cb, NULL);
> -               goto exit0;
> +       } else {
> +print_usage_error:
> +               fprintf(stderr, "Invalid syntax. Usage: test-tool config <cmd> [args]\n");
> +               ret = TC_USAGE_ERROR;
>         }
>
> -       die("%s: Please check the syntax and the function name", argv[0]);
> -
> -exit0:
> -       git_configset_clear(&cs);
> -       return 0;
> -
> -exit1:
> -       git_configset_clear(&cs);
> -       return 1;
> -
> -exit2:
> +out:
>         git_configset_clear(&cs);
> -       return 2;
> +       return ret;
>  }
> --
> 2.26.2

So, the primary purpose of the commit is getting making the return
status clearer, but most the code changes actually center around
reducing the gotos and unification of the exit labels.  Might have
been slightly easier to read if those two issues had been split, but
the patch is small enough that it's not a big deal.  Makes sense.
Matheus Tavares June 1, 2020, 4:36 a.m. UTC | #2
On Sat, May 30, 2020 at 11:29 AM Elijah Newren <newren@gmail.com> wrote:
>
> On Wed, May 27, 2020 at 6:13 PM Matheus Tavares
> <matheus.bernardino@usp.br> wrote:
> >
> > The test-config helper may exit with a variety of at least four
> > different codes, to reflect the status of the requested operations.
> > These codes are sometimes checked in the tests, but not all of the codes
> > are returned consistently by the helper: 1 will usually refer to a
> > "value not found", but usage errors can also return 1 or 128. The latter
>
> I'm not sure what "The latter" refers to here.

It would be the 128 exit code. I'll try to reword that for clarity.

> > is also expected on errors within the configset functions. These
> > inconsistent uses of the exit codes can lead to false positives in the
> > tests. Although all tests that currently check the helper's exit code,
> > on errors, do also check the output, it's still better to standardize
> > the exit codes and avoid future problems in new tests. While we are
>
> That last sentence was slightly hard for me to parse.  Maybe something like:
>
> ...Although all tests which expect errors and check the helper's exit
> code currently also check the output, it's still better...

Sounds better, I will use that for the next version. Thanks.
diff mbox series

Patch

diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index 234c722b48..1c8e965840 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -30,6 +30,14 @@ 
  * iterate -> iterate over all values using git_config(), and print some
  *            data for each
  *
+ * Exit codes:
+ *     0:   success
+ *     1:   value not found for the given config key
+ *     2:   config file path given as argument is inaccessible or doesn't exist
+ *     129: test-config usage error
+ *
+ * Note: tests may also expect 128 for die() calls in the config machinery.
+ *
  * Examples:
  *
  * To print the value with highest priority for key "foo.bAr Baz.rock":
@@ -64,35 +72,42 @@  static int early_config_cb(const char *var, const char *value, void *vdata)
 	return 0;
 }
 
+enum test_config_exit_code {
+	TC_SUCCESS = 0,
+	TC_VALUE_NOT_FOUND = 1,
+	TC_CONFIG_FILE_ERROR = 2,
+	TC_USAGE_ERROR = 129,
+};
+
 int cmd__config(int argc, const char **argv)
 {
 	int i, val;
 	const char *v;
 	const struct string_list *strptr;
 	struct config_set cs;
+	enum test_config_exit_code ret = TC_SUCCESS;
 
 	if (argc == 3 && !strcmp(argv[1], "read_early_config")) {
 		read_early_config(early_config_cb, (void *)argv[2]);
-		return 0;
+		return TC_SUCCESS;
 	}
 
 	setup_git_directory();
 
 	git_configset_init(&cs);
 
-	if (argc < 2) {
-		fprintf(stderr, "Please, provide a command name on the command-line\n");
-		goto exit1;
-	} else if (argc == 3 && !strcmp(argv[1], "get_value")) {
+	if (argc < 2)
+		goto print_usage_error;
+
+	if (argc == 3 && !strcmp(argv[1], "get_value")) {
 		if (!git_config_get_value(argv[2], &v)) {
 			if (!v)
 				printf("(NULL)\n");
 			else
 				printf("%s\n", v);
-			goto exit0;
 		} else {
 			printf("Value not found for \"%s\"\n", argv[2]);
-			goto exit1;
+			ret = TC_VALUE_NOT_FOUND;
 		}
 	} else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
 		strptr = git_config_get_value_multi(argv[2]);
@@ -104,41 +119,38 @@  int cmd__config(int argc, const char **argv)
 				else
 					printf("%s\n", v);
 			}
-			goto exit0;
 		} else {
 			printf("Value not found for \"%s\"\n", argv[2]);
-			goto exit1;
+			ret = TC_VALUE_NOT_FOUND;
 		}
 	} else if (argc == 3 && !strcmp(argv[1], "get_int")) {
 		if (!git_config_get_int(argv[2], &val)) {
 			printf("%d\n", val);
-			goto exit0;
 		} else {
 			printf("Value not found for \"%s\"\n", argv[2]);
-			goto exit1;
+			ret = TC_VALUE_NOT_FOUND;
 		}
 	} else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
 		if (!git_config_get_bool(argv[2], &val)) {
 			printf("%d\n", val);
-			goto exit0;
 		} else {
 			printf("Value not found for \"%s\"\n", argv[2]);
-			goto exit1;
+			ret = TC_VALUE_NOT_FOUND;
 		}
 	} else if (argc == 3 && !strcmp(argv[1], "get_string")) {
 		if (!git_config_get_string_const(argv[2], &v)) {
 			printf("%s\n", v);
-			goto exit0;
 		} else {
 			printf("Value not found for \"%s\"\n", argv[2]);
-			goto exit1;
+			ret = TC_VALUE_NOT_FOUND;
 		}
-	} else if (!strcmp(argv[1], "configset_get_value")) {
+	} else if (argc >= 3 && !strcmp(argv[1], "configset_get_value")) {
 		for (i = 3; i < argc; i++) {
 			int err;
 			if ((err = git_configset_add_file(&cs, argv[i]))) {
 				fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
-				goto exit2;
+				ret = TC_CONFIG_FILE_ERROR;
+				goto out;
 			}
 		}
 		if (!git_configset_get_value(&cs, argv[2], &v)) {
@@ -146,17 +158,17 @@  int cmd__config(int argc, const char **argv)
 				printf("(NULL)\n");
 			else
 				printf("%s\n", v);
-			goto exit0;
 		} else {
 			printf("Value not found for \"%s\"\n", argv[2]);
-			goto exit1;
+			ret = TC_VALUE_NOT_FOUND;
 		}
-	} else if (!strcmp(argv[1], "configset_get_value_multi")) {
+	} else if (argc >= 3 && !strcmp(argv[1], "configset_get_value_multi")) {
 		for (i = 3; i < argc; i++) {
 			int err;
 			if ((err = git_configset_add_file(&cs, argv[i]))) {
 				fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
-				goto exit2;
+				ret = TC_CONFIG_FILE_ERROR;
+				goto out;
 			}
 		}
 		strptr = git_configset_get_value_multi(&cs, argv[2]);
@@ -168,27 +180,19 @@  int cmd__config(int argc, const char **argv)
 				else
 					printf("%s\n", v);
 			}
-			goto exit0;
 		} else {
 			printf("Value not found for \"%s\"\n", argv[2]);
-			goto exit1;
+			ret = TC_VALUE_NOT_FOUND;
 		}
 	} else if (!strcmp(argv[1], "iterate")) {
 		git_config(iterate_cb, NULL);
-		goto exit0;
+	} else {
+print_usage_error:
+		fprintf(stderr, "Invalid syntax. Usage: test-tool config <cmd> [args]\n");
+		ret = TC_USAGE_ERROR;
 	}
 
-	die("%s: Please check the syntax and the function name", argv[0]);
-
-exit0:
-	git_configset_clear(&cs);
-	return 0;
-
-exit1:
-	git_configset_clear(&cs);
-	return 1;
-
-exit2:
+out:
 	git_configset_clear(&cs);
-	return 2;
+	return ret;
 }