diff mbox series

[bpf-next,v1] bpf/selftests: improve arg parsing in test_verifier

Message ID 20230925233702.19466-1-Tony.Ambardar@gmail.com (mailing list archive)
State Changes Requested
Delegated to: BPF
Headers show
Series [bpf-next,v1] bpf/selftests: improve arg parsing in test_verifier | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for bpf-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 9 this patch: 9
netdev/cc_maintainers warning 9 maintainers not CCed: martin.lau@linux.dev jolsa@kernel.org haoluo@google.com kpsingh@kernel.org sdf@google.com john.fastabend@gmail.com yonghong.song@linux.dev mykolal@fb.com song@kernel.org
netdev/build_clang success Errors and warnings before: 9 this patch: 9
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 9 this patch: 9
netdev/checkpatch warning CHECK: From:/Signed-off-by: email comments mismatch: 'From: Tony Ambardar <tony.ambardar@gmail.com>' != 'Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>' CHECK: Unbalanced braces around else statement CHECK: braces {} should be used on all arms of this statement WARNING: Possible repeated word: 'die'
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-0 success Logs for ${{ matrix.test }} on ${{ matrix.arch }} with ${{ matrix.toolchain_full }}
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-4 fail Logs for build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-3 fail Logs for build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-2 fail Logs for build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-5 fail Logs for build for x86_64 with llvm-16
bpf/vmtest-bpf-next-VM_Test-7 success Logs for veristat
bpf/vmtest-bpf-next-VM_Test-6 success Logs for set-matrix

Commit Message

Tony Ambardar Sept. 25, 2023, 11:37 p.m. UTC
Current test_verifier provides little feedback or argument validation,
instead silently falling back to running all tests in case of user error
or even expected use cases. Trying to do manual exploratory testing,
switching between kernel versions (e.g. with varying tests), or working
around problematic tests (e.g. kernel hangs/crashes) can be a frustrating
experience.

Rework argument parsing to be more robust and strict, and provide basic
help on errors. Clamp test ranges to valid values and add an option to
list available built-in tests ("-l"). Default "test_verifier" behaviour
(run all tests) is unchanged and backwards-compatible. Updated examples:

     $ test_verifier die die die     # previously ran all tests
     Usage: test_verifier -l | [-v|-vv] [<tst_lo> [<tst_hi>]]

     $ test_verifier 700 9999        # runs test subset from 700 to end

Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
---
 tools/testing/selftests/bpf/test_verifier.c | 54 ++++++++++++---------
 1 file changed, 30 insertions(+), 24 deletions(-)

Comments

Jiri Olsa Sept. 26, 2023, 12:40 p.m. UTC | #1
On Mon, Sep 25, 2023 at 04:37:02PM -0700, Tony Ambardar wrote:
> Current test_verifier provides little feedback or argument validation,
> instead silently falling back to running all tests in case of user error
> or even expected use cases. Trying to do manual exploratory testing,
> switching between kernel versions (e.g. with varying tests), or working
> around problematic tests (e.g. kernel hangs/crashes) can be a frustrating
> experience.
> 
> Rework argument parsing to be more robust and strict, and provide basic
> help on errors. Clamp test ranges to valid values and add an option to
> list available built-in tests ("-l"). Default "test_verifier" behaviour
> (run all tests) is unchanged and backwards-compatible. Updated examples:
> 
>      $ test_verifier die die die     # previously ran all tests
>      Usage: test_verifier -l | [-v|-vv] [<tst_lo> [<tst_hi>]]
> 
>      $ test_verifier 700 9999        # runs test subset from 700 to end
> 
> Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
> ---
>  tools/testing/selftests/bpf/test_verifier.c | 54 ++++++++++++---------
>  1 file changed, 30 insertions(+), 24 deletions(-)
> 
> diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
> index 98107e0452d3..3712b5363f60 100644
> --- a/tools/testing/selftests/bpf/test_verifier.c
> +++ b/tools/testing/selftests/bpf/test_verifier.c
> @@ -10,9 +10,11 @@
>  #include <endian.h>
>  #include <asm/types.h>
>  #include <linux/types.h>
> +#include <linux/minmax.h>

this fails to compile

  BINARY   test_verifier
test_verifier.c:13:10: fatal error: linux/minmax.h: No such file or directory
   13 | #include <linux/minmax.h>
      |          ^~~~~~~~~~~~~~~~

looks like you could use perhaps <linux/kernel.h> instead?

jirka


>  #include <stdint.h>
>  #include <stdio.h>
>  #include <stdlib.h>
> +#include <ctype.h>
>  #include <unistd.h>
>  #include <errno.h>
>  #include <string.h>
> @@ -1848,36 +1850,40 @@ int main(int argc, char **argv)
>  {
>  	unsigned int from = 0, to = ARRAY_SIZE(tests);
>  	bool unpriv = !is_admin();
> -	int arg = 1;
> -
> -	if (argc > 1 && strcmp(argv[1], "-v") == 0) {
> +	int i, arg = 1;
> +
> +	while (argc > 1 && *argv[arg] == '-') {
> +		if (strcmp(argv[arg], "-l") == 0) {
> +			for (i = from; i < to; i++)
> +				printf("#%d %s\n", i, tests[i].descr);
> +			return EXIT_SUCCESS;
> +		} else if (strcmp(argv[arg], "-v") == 0) {
> +			verbose = true;
> +			verif_log_level = 1;
> +		} else if (strcmp(argv[arg], "-vv") == 0) {
> +			verbose = true;
> +			verif_log_level = 2;
> +		} else
> +			goto out_help;
>  		arg++;
> -		verbose = true;
> -		verif_log_level = 1;
>  		argc--;
>  	}
> -	if (argc > 1 && strcmp(argv[1], "-vv") == 0) {
> -		arg++;
> -		verbose = true;
> -		verif_log_level = 2;
> -		argc--;
> -	}
> -
> -	if (argc == 3) {
> -		unsigned int l = atoi(argv[arg]);
> -		unsigned int u = atoi(argv[arg + 1]);
>  
> -		if (l < to && u < to) {
> -			from = l;
> -			to   = u + 1;
> -		}
> -	} else if (argc == 2) {
> -		unsigned int t = atoi(argv[arg]);
> +	for (i = 1; i <= 2 && argc > 1; i++, arg++, argc--) {
> +		unsigned int t = min(atoi(argv[arg]), ARRAY_SIZE(tests) - 1);
>  
> -		if (t < to) {
> +		if (!isdigit(*argv[arg]))
> +			goto out_help;
> +		if (i == 1)
>  			from = t;
> -			to   = t + 1;
> -		}
> +		to = t + 1;
> +	}
> +
> +	if (argc > 1) {
> +out_help:
> +		printf("Usage: %s -l | [-v|-vv] [<tst_lo> [<tst_hi>]]\n",
> +		       argv[0]);
> +		return EXIT_FAILURE;
>  	}
>  
>  	unpriv_disabled = get_unpriv_disabled();
> -- 
> 2.34.1
> 
>
Jiri Olsa Sept. 26, 2023, 12:54 p.m. UTC | #2
On Mon, Sep 25, 2023 at 04:37:02PM -0700, Tony Ambardar wrote:

SNIP

> @@ -1848,36 +1850,40 @@ int main(int argc, char **argv)
>  {
>  	unsigned int from = 0, to = ARRAY_SIZE(tests);
>  	bool unpriv = !is_admin();
> -	int arg = 1;
> -
> -	if (argc > 1 && strcmp(argv[1], "-v") == 0) {
> +	int i, arg = 1;
> +
> +	while (argc > 1 && *argv[arg] == '-') {
> +		if (strcmp(argv[arg], "-l") == 0) {
> +			for (i = from; i < to; i++)
> +				printf("#%d %s\n", i, tests[i].descr);
> +			return EXIT_SUCCESS;
> +		} else if (strcmp(argv[arg], "-v") == 0) {
> +			verbose = true;
> +			verif_log_level = 1;
> +		} else if (strcmp(argv[arg], "-vv") == 0) {
> +			verbose = true;
> +			verif_log_level = 2;
> +		} else
> +			goto out_help;
>  		arg++;
> -		verbose = true;
> -		verif_log_level = 1;
>  		argc--;
>  	}
> -	if (argc > 1 && strcmp(argv[1], "-vv") == 0) {
> -		arg++;
> -		verbose = true;
> -		verif_log_level = 2;
> -		argc--;
> -	}
> -
> -	if (argc == 3) {
> -		unsigned int l = atoi(argv[arg]);
> -		unsigned int u = atoi(argv[arg + 1]);
>  
> -		if (l < to && u < to) {
> -			from = l;
> -			to   = u + 1;
> -		}
> -	} else if (argc == 2) {
> -		unsigned int t = atoi(argv[arg]);
> +	for (i = 1; i <= 2 && argc > 1; i++, arg++, argc--) {
> +		unsigned int t = min(atoi(argv[arg]), ARRAY_SIZE(tests) - 1);

this looks like unnecessary loop, the code before is easy to understand,
could we just do the args check on isdigit and valid index value in there?

jirka

>  
> -		if (t < to) {
> +		if (!isdigit(*argv[arg]))
> +			goto out_help;
> +		if (i == 1)
>  			from = t;
> -			to   = t + 1;
> -		}
> +		to = t + 1;
> +	}
> +
> +	if (argc > 1) {
> +out_help:
> +		printf("Usage: %s -l | [-v|-vv] [<tst_lo> [<tst_hi>]]\n",
> +		       argv[0]);
> +		return EXIT_FAILURE;
>  	}
>  
>  	unpriv_disabled = get_unpriv_disabled();
> -- 
> 2.34.1
> 
>
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 98107e0452d3..3712b5363f60 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -10,9 +10,11 @@ 
 #include <endian.h>
 #include <asm/types.h>
 #include <linux/types.h>
+#include <linux/minmax.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <ctype.h>
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
@@ -1848,36 +1850,40 @@  int main(int argc, char **argv)
 {
 	unsigned int from = 0, to = ARRAY_SIZE(tests);
 	bool unpriv = !is_admin();
-	int arg = 1;
-
-	if (argc > 1 && strcmp(argv[1], "-v") == 0) {
+	int i, arg = 1;
+
+	while (argc > 1 && *argv[arg] == '-') {
+		if (strcmp(argv[arg], "-l") == 0) {
+			for (i = from; i < to; i++)
+				printf("#%d %s\n", i, tests[i].descr);
+			return EXIT_SUCCESS;
+		} else if (strcmp(argv[arg], "-v") == 0) {
+			verbose = true;
+			verif_log_level = 1;
+		} else if (strcmp(argv[arg], "-vv") == 0) {
+			verbose = true;
+			verif_log_level = 2;
+		} else
+			goto out_help;
 		arg++;
-		verbose = true;
-		verif_log_level = 1;
 		argc--;
 	}
-	if (argc > 1 && strcmp(argv[1], "-vv") == 0) {
-		arg++;
-		verbose = true;
-		verif_log_level = 2;
-		argc--;
-	}
-
-	if (argc == 3) {
-		unsigned int l = atoi(argv[arg]);
-		unsigned int u = atoi(argv[arg + 1]);
 
-		if (l < to && u < to) {
-			from = l;
-			to   = u + 1;
-		}
-	} else if (argc == 2) {
-		unsigned int t = atoi(argv[arg]);
+	for (i = 1; i <= 2 && argc > 1; i++, arg++, argc--) {
+		unsigned int t = min(atoi(argv[arg]), ARRAY_SIZE(tests) - 1);
 
-		if (t < to) {
+		if (!isdigit(*argv[arg]))
+			goto out_help;
+		if (i == 1)
 			from = t;
-			to   = t + 1;
-		}
+		to = t + 1;
+	}
+
+	if (argc > 1) {
+out_help:
+		printf("Usage: %s -l | [-v|-vv] [<tst_lo> [<tst_hi>]]\n",
+		       argv[0]);
+		return EXIT_FAILURE;
 	}
 
 	unpriv_disabled = get_unpriv_disabled();