diff mbox series

[v2,3/4] shell: add kconfig parse api

Message ID 1641461121-2212-3-git-send-email-xuyang2018.jy@fujitsu.com
State Superseded
Headers show
Series [v2,1/4] lib/tst_kconfig: Modify the return type of tst_kconfig_check function | expand

Commit Message

Yang Xu Jan. 6, 2022, 9:25 a.m. UTC
Use tst_check_kconfigs command to call tst_kconfig_check function in internal.
It introduces two variables in tst_test.sh
TST_NEEDS_KCONFIGS
TST_NEEDS_KCONFIGS_IFS (default value is comma)

Also, we can use tst_check_kconfigs in your shell case if you want to skip subtest
case instead the whole test.

Fixes:#891
Suggested-by: Petr Vorel <pvorel@suse.cz>
Suggested-by: Cyril Hrubis <chrubis@suse.cz>
Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
---
 doc/shell-test-api.txt                        | 54 +++++++++++++------
 lib/newlib_tests/runtest.sh                   |  3 +-
 lib/newlib_tests/shell/tst_check_kconfig01.sh | 26 +++++++++
 lib/newlib_tests/shell/tst_check_kconfig02.sh | 16 ++++++
 lib/newlib_tests/shell/tst_check_kconfig03.sh | 15 ++++++
 lib/newlib_tests/shell/tst_check_kconfig04.sh | 16 ++++++
 lib/newlib_tests/shell/tst_check_kconfig05.sh | 26 +++++++++
 testcases/lib/.gitignore                      |  1 +
 testcases/lib/Makefile                        |  3 +-
 testcases/lib/tst_check_kconfigs.c            | 18 +++++++
 testcases/lib/tst_test.sh                     | 35 ++++++++++++
 11 files changed, 195 insertions(+), 18 deletions(-)
 create mode 100755 lib/newlib_tests/shell/tst_check_kconfig01.sh
 create mode 100755 lib/newlib_tests/shell/tst_check_kconfig02.sh
 create mode 100755 lib/newlib_tests/shell/tst_check_kconfig03.sh
 create mode 100755 lib/newlib_tests/shell/tst_check_kconfig04.sh
 create mode 100755 lib/newlib_tests/shell/tst_check_kconfig05.sh
 create mode 100644 testcases/lib/tst_check_kconfigs.c

Comments

Petr Vorel Jan. 6, 2022, 10:40 a.m. UTC | #1
Hi Xu,

> +tst_require_kconfigs()
> +{
> +	[ $# -eq 0 ] && return 0
> +
> +	local kconfigs
> +	local kconfig_i
> +	local kconfig_max
> +
> +	kconfigs=$@

> +	[ -z "$kconfigs" ] && return 0
> +
> +	tst_check_cmds cut tr wc
> +	kconfig_max=$(( $(echo "$kconfigs" | tr -cd "$TST_NEEDS_KCONFIGS_IFS" | wc -c) +1))
> +	if [ $kconfig_max -gt 10 ]; then
> +		tst_brk TCONF "The max number of kconfig is 10!"
> +	fi
> +
> +	for kconfig_i in $(seq $kconfig_max); do
> +		eval "local kconfig$kconfig_i"
> +		eval "kconfig$kconfig_i='$(echo "$kconfigs" | cut -d"$TST_NEEDS_KCONFIGS_IFS" -f$kconfig_i)'"
Well, we use 2x eval and cut in order to have easy C code. How about move
splitting string to C (using e.g. strtok_r()? Although using this code is
probably safe for any shell (we use similar cut like delimiter in tst_test.sh),
I've had enough of fixing obscure shell bugs. And C code with strtok_r() is more
portable across libc than any shell code.

> +	done
> +
> +	tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 $kconfig6\
> +			$kconfig7 $kconfig8 $kconfig9 $kconfig10
Now I see the need for the need to limit. First, you need to quote parameters:

	tst_check_kconfigs "$kconfig1" "$kconfig2" "$kconfig3" "$kconfig4" "$kconfig5" "$kconfig6" \
			"$kconfig7" "$kconfig8" "$kconfig9" "$kconfig10"

Because there might be config value with space. I found only one which is not
going to be used:
CONFIG_CC_VERSION_TEXT="gcc (SUSE Linux) 11.2.1 20211124 [revision 7510c23c1ec53aa4a62705f0384079661342ff7b]"
but we cannot rely on that.

Kind regards,
Petr

> +	if [ $? -ne 0 ]; then
> +		tst_brk TCONF "Aborting due to unsuitable kernel config, see above!"
> +	fi
> +
> +	return 0
> +}
Cyril Hrubis Jan. 6, 2022, 11:19 a.m. UTC | #2
Hi!
> Use tst_check_kconfigs command to call tst_kconfig_check function in internal.
> It introduces two variables in tst_test.sh
> TST_NEEDS_KCONFIGS
> TST_NEEDS_KCONFIGS_IFS (default value is comma)
> 
> Also, we can use tst_check_kconfigs in your shell case if you want to skip subtest
> case instead the whole test.
> 
> Fixes:#891
> Suggested-by: Petr Vorel <pvorel@suse.cz>
> Suggested-by: Cyril Hrubis <chrubis@suse.cz>
> Signed-off-by: Yang Xu <xuyang2018.jy@fujitsu.com>
> ---
>  doc/shell-test-api.txt                        | 54 +++++++++++++------
>  lib/newlib_tests/runtest.sh                   |  3 +-
>  lib/newlib_tests/shell/tst_check_kconfig01.sh | 26 +++++++++
>  lib/newlib_tests/shell/tst_check_kconfig02.sh | 16 ++++++
>  lib/newlib_tests/shell/tst_check_kconfig03.sh | 15 ++++++
>  lib/newlib_tests/shell/tst_check_kconfig04.sh | 16 ++++++
>  lib/newlib_tests/shell/tst_check_kconfig05.sh | 26 +++++++++
>  testcases/lib/.gitignore                      |  1 +
>  testcases/lib/Makefile                        |  3 +-
>  testcases/lib/tst_check_kconfigs.c            | 18 +++++++
>  testcases/lib/tst_test.sh                     | 35 ++++++++++++
>  11 files changed, 195 insertions(+), 18 deletions(-)
>  create mode 100755 lib/newlib_tests/shell/tst_check_kconfig01.sh
>  create mode 100755 lib/newlib_tests/shell/tst_check_kconfig02.sh
>  create mode 100755 lib/newlib_tests/shell/tst_check_kconfig03.sh
>  create mode 100755 lib/newlib_tests/shell/tst_check_kconfig04.sh
>  create mode 100755 lib/newlib_tests/shell/tst_check_kconfig05.sh
>  create mode 100644 testcases/lib/tst_check_kconfigs.c
> 
> diff --git a/doc/shell-test-api.txt b/doc/shell-test-api.txt
> index b993a9e1e..a1ec6ba2a 100644
> --- a/doc/shell-test-api.txt
> +++ b/doc/shell-test-api.txt
> @@ -193,22 +193,25 @@ simply by setting right '$TST_NEEDS_FOO'.
>  
>  [options="header"]
>  |=============================================================================
> -| Variable name      | Action done
> -| 'TST_NEEDS_ROOT'   | Exit the test with 'TCONF' unless executed under root.
> -|                    | Alternatively the 'tst_require_root' command can be used.
> -| 'TST_NEEDS_TMPDIR' | Create test temporary directory and cd into it.
> -| 'TST_NEEDS_DEVICE' | Prepare test temporary device, the path to testing
> -                       device is stored in '$TST_DEVICE' variable.
> -                       The option implies 'TST_NEEDS_TMPDIR'.
> -| 'TST_NEEDS_CMDS'   | String with command names that has to be present for
> -                       the test (see below).
> -| 'TST_NEEDS_MODULE' | Test module name needed for the test (see below).
> -| 'TST_NEEDS_DRIVERS'| Checks kernel drivers support for the test.
> -| 'TST_TIMEOUT'      | Maximum timeout set for the test in sec. Must be int >= 1,
> -                       or -1 (special value to disable timeout), default is 300.
> -                       Variable is meant be set in tests, not by user.
> -                       It's an equivalent of `tst_test.timeout` in C, can be set
> -                       via 'tst_set_timeout(timeout)' after test has started.
> +| Variable name            | Action done
> +| 'TST_NEEDS_ROOT'         | Exit the test with 'TCONF' unless executed under root.
> +|                          | Alternatively the 'tst_require_root' command can be used.
> +| 'TST_NEEDS_TMPDIR'       | Create test temporary directory and cd into it.
> +| 'TST_NEEDS_DEVICE'       | Prepare test temporary device, the path to testing
> +                             device is stored in '$TST_DEVICE' variable.
> +                             The option implies 'TST_NEEDS_TMPDIR'.
> +| 'TST_NEEDS_CMDS'         | String with command names that has to be present for
> +                             the test (see below).
> +| 'TST_NEEDS_MODULE'       | Test module name needed for the test (see below).
> +| 'TST_NEEDS_DRIVERS'      | Checks kernel drivers support for the test.
> +| 'TST_NEEDS_KCONFIGS'     | Checks kernel kconfigs support for the test (see below).
> +| 'TST_NEEDS_KCONFIGS_IFS' | Used for splitting '$TST_NEEDS_KCONFIGS' variable,
> +                             default value is comma.
> +| 'TST_TIMEOUT'            | Maximum timeout set for the test in sec. Must be int >= 1,
> +                             or -1 (special value to disable timeout), default is 300.
> +                             Variable is meant be set in tests, not by user.
> +                             It's an equivalent of `tst_test.timeout` in C, can be set
> +                             via 'tst_set_timeout(timeout)' after test has started.
>  |=============================================================================
>  
>  [options="header"]
> @@ -742,3 +745,22 @@ TST_NEEDS_CHECKPOINTS=1
>  Since both the implementations are compatible, it's also possible to start
>  a child binary process from a shell test and synchronize with it. This process
>  must have checkpoints initialized by calling 'tst_reinit()'.
> +
> +1.7 Parsing kernel .config
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +The shell library provides an implementation of the kconfig parsing interface
> +compatible with the C version.
> +
> +It's possible to pass kernel kconfig list for tst_require_kconfigs API with
> +'$TST_NEEDS_KCONFIGS'.
> +Optional '$TST_NEEDS_KCONFIGS_IFS' is used for splitting, default value is comma.
> +
> +Now, we support the length of kconfig list is 10.
> +
> +-------------------------------------------------------------------------------
> +#!/bin/sh
> +TST_NEEDS_KCONFIGS="CONFIG_EXT4_FS, CONFIG_QUOTACTL=y"
> +
> +. tst_test.sh
> +-------------------------------------------------------------------------------
> diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
> index 8b2fe347a..b34a582b7 100755
> --- a/lib/newlib_tests/runtest.sh
> +++ b/lib/newlib_tests/runtest.sh
> @@ -6,7 +6,8 @@ tst_needs_cmds01 tst_needs_cmds02 tst_needs_cmds03 tst_needs_cmds06
>  tst_needs_cmds07 tst_bool_expr test_exec test_timer tst_res_hexd tst_strstatus
>  tst_fuzzy_sync03 test_zero_hugepage.sh}"
>  
> -LTP_SHELL_API_TESTS="${LTP_SHELL_API_TESTS:-shell/tst_check_driver.sh shell/net/*.sh}"
> +LTP_SHELL_API_TESTS="${LTP_SHELL_API_TESTS:-shell/tst_check_driver.sh
> +shell/tst_check_kconfig0[1-4].sh shell/net/*.sh}"
>  
>  cd $(dirname $0)
>  PATH="$PWD/../../testcases/lib/:$PATH"
> diff --git a/lib/newlib_tests/shell/tst_check_kconfig01.sh b/lib/newlib_tests/shell/tst_check_kconfig01.sh
> new file mode 100755
> index 000000000..90e76360e
> --- /dev/null
> +++ b/lib/newlib_tests/shell/tst_check_kconfig01.sh
> @@ -0,0 +1,26 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
> +
> +TST_TESTFUNC=do_test
> +TST_NEEDS_CMDS="tst_check_kconfigs"
> +TST_NEEDS_KCONFIGS="CONFIG_GENERIC_IRQ_PROBE=y,
> +CONFIG_GENERIC_IRQ_SHOW=y,
> +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y,
> +CONFIG_GENERIC_PENDING_IRQ=y,
> +CONFIG_GENERIC_IRQ_MIGRATION=y,
> +CONFIG_IRQ_DOMAIN=y,
> +CONFIG_IRQ_DOMAIN_HIERARCHY=y,
> +CONFIG_GENERIC_MSI_IRQ=y,
> +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y,
> +CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y,
> +CONFIG_GENERIC_IRQ_RESERVATION_MODE=y"
> +
> +. tst_test.sh
> +
> +do_test()
> +{
> +	tst_res TFAIL "kernel config check functionality only supports 10 kernel kconfigs"
> +}
> +
> +tst_run
> diff --git a/lib/newlib_tests/shell/tst_check_kconfig02.sh b/lib/newlib_tests/shell/tst_check_kconfig02.sh
> new file mode 100755
> index 000000000..065a20fd2
> --- /dev/null
> +++ b/lib/newlib_tests/shell/tst_check_kconfig02.sh
> @@ -0,0 +1,16 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
> +
> +TST_TESTFUNC=do_test
> +TST_NEEDS_CMDS="tst_check_kconfigs"
> +TST_NEEDS_KCONFIGS="CONFIG_EXT4"
> +
> +. tst_test.sh
> +
> +do_test()
> +{
> +	tst_res TFAIL "kernel .config doesn't have CONFIG_EXT4"
> +}
> +
> +tst_run
> diff --git a/lib/newlib_tests/shell/tst_check_kconfig03.sh b/lib/newlib_tests/shell/tst_check_kconfig03.sh
> new file mode 100755
> index 000000000..ebdec70f8
> --- /dev/null
> +++ b/lib/newlib_tests/shell/tst_check_kconfig03.sh
> @@ -0,0 +1,15 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
> +
> +TST_TESTFUNC=do_test
> +TST_NEEDS_CMDS="tst_check_kconfigs"
> +TST_NEEDS_KCONFIGS="CONFIG_EXT4_FS: CONFIG_XFS_FS"
> +. tst_test.sh
> +
> +do_test()
> +{
> +	tst_res TFAIL "invalid kconfig delimter"
> +}
> +
> +tst_run
> diff --git a/lib/newlib_tests/shell/tst_check_kconfig04.sh b/lib/newlib_tests/shell/tst_check_kconfig04.sh
> new file mode 100755
> index 000000000..c5f046b79
> --- /dev/null
> +++ b/lib/newlib_tests/shell/tst_check_kconfig04.sh
> @@ -0,0 +1,16 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
> +
> +TST_TESTFUNC=do_test
> +TST_NEEDS_CMDS="tst_check_kconfigs"
> +TST_NEEDS_KCONFIGS="CONFIG_EXT4_FS : CONFIG_XFS_FS"
> +TST_NEEDS_KCONFIGS_IFS=":"
> +. tst_test.sh
> +
> +do_test()
> +{
> +	tst_res TPASS "valid kconfig delimter"
> +}
> +
> +tst_run
> diff --git a/lib/newlib_tests/shell/tst_check_kconfig05.sh b/lib/newlib_tests/shell/tst_check_kconfig05.sh
> new file mode 100755
> index 000000000..1a214016a
> --- /dev/null
> +++ b/lib/newlib_tests/shell/tst_check_kconfig05.sh
> @@ -0,0 +1,26 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
> +
> +TST_TESTFUNC=do_test
> +TST_NEEDS_CMDS="tst_check_kconfigs"
> +. tst_test.sh
> +
> +do_test()
> +{
> +	tst_check_kconfigs "CONFIG_EXT4_FS"
> +	if [ $? -eq 0 ]; then
> +		tst_res TPASS "kernel .config has CONFIG_EXT4_fs"
> +	else
> +		tst_res TFAIL "kernel .config doesn't have CONFIG_EXT4_FS"
> +	fi
> +
> +	tst_check_kconfigs "CONFIG_EXT4"
> +	if [ $? -eq 0 ]; then
> +		tst_res TFAIL "kernel .config has CONFIG_EXT4"
> +	else
> +		tst_res TPASS "kernel .config doesn't have CONFIG_EXT4"
> +	fi
> +}
> +
> +tst_run
> diff --git a/testcases/lib/.gitignore b/testcases/lib/.gitignore
> index 9625d9043..c0d4dc851 100644
> --- a/testcases/lib/.gitignore
> +++ b/testcases/lib/.gitignore
> @@ -1,4 +1,5 @@
>  /tst_check_drivers
> +/tst_check_kconfigs
>  /tst_checkpoint
>  /tst_device
>  /tst_getconf
> diff --git a/testcases/lib/Makefile b/testcases/lib/Makefile
> index d6b4c7a91..f2de0c832 100644
> --- a/testcases/lib/Makefile
> +++ b/testcases/lib/Makefile
> @@ -11,6 +11,7 @@ INSTALL_TARGETS		:= *.sh
>  MAKE_TARGETS		:= tst_sleep tst_random tst_checkpoint tst_rod tst_kvcmp\
>  			   tst_device tst_net_iface_prefix tst_net_ip_prefix tst_net_vars\
>  			   tst_getconf tst_supported_fs tst_check_drivers tst_get_unused_port\
> -			   tst_get_median tst_hexdump tst_get_free_pids tst_timeout_kill
> +			   tst_get_median tst_hexdump tst_get_free_pids tst_timeout_kill\
> +			   tst_check_kconfigs
>  
>  include $(top_srcdir)/include/mk/generic_leaf_target.mk
> diff --git a/testcases/lib/tst_check_kconfigs.c b/testcases/lib/tst_check_kconfigs.c
> new file mode 100644
> index 000000000..5c387a62d
> --- /dev/null
> +++ b/testcases/lib/tst_check_kconfigs.c
> @@ -0,0 +1,18 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/* Copyright (c) 2022 FUJITSU LIMITED. All rights reserved. */
> +
> +#include <stdio.h>
> +#include "tst_kconfig.h"
> +
> +int main(int argc, const char *argv[])
> +{
> +	if (argc < 2) {
> +		fprintf(stderr, "Please provide kernel kconfig list\n");
> +		return 1;
> +	}
> +
> +	if (tst_kconfig_check(argv+1))
> +		return 1;
> +
> +	return 0;
> +}
> diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
> index 2556b28f5..0097c8d43 100644
> --- a/testcases/lib/tst_test.sh
> +++ b/testcases/lib/tst_test.sh
> @@ -412,6 +412,37 @@ tst_require_drivers()
>  	return 0
>  }
>  
> +tst_require_kconfigs()
> +{
> +	[ $# -eq 0 ] && return 0
> +
> +	local kconfigs
> +	local kconfig_i
> +	local kconfig_max
> +
> +	kconfigs=$@
> +	[ -z "$kconfigs" ] && return 0
> +
> +	tst_check_cmds cut tr wc
> +	kconfig_max=$(( $(echo "$kconfigs" | tr -cd "$TST_NEEDS_KCONFIGS_IFS" | wc -c) +1))
> +	if [ $kconfig_max -gt 10 ]; then
> +		tst_brk TCONF "The max number of kconfig is 10!"
> +	fi

There is really no reason to have this artificial limit if we are not
passing the configs in a set of variables.

> +	for kconfig_i in $(seq $kconfig_max); do
> +		eval "local kconfig$kconfig_i"
> +		eval "kconfig$kconfig_i='$(echo "$kconfigs" | cut -d"$TST_NEEDS_KCONFIGS_IFS" -f$kconfig_i)'"
> +	done

This part is a bit ugly, I guess that it may as well be easier to
process in C. A long as we pass it as:

tst_check_kconfigs "$TST_NEEDS_KCONFIGS_IFS" "$TST_NEEDS_KCONFIGS"

We can easily split the TST_NEEDS_KCONFIGS with strchr() and single
loop.

> +	tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 $kconfig6\
> +			$kconfig7 $kconfig8 $kconfig9 $kconfig10
> +	if [ $? -ne 0 ]; then
> +		tst_brk TCONF "Aborting due to unsuitable kernel config, see above!"
> +	fi
> +
> +	return 0
> +}
> +
>  tst_is_int()
>  {
>  	[ "$1" -eq "$1" ] 2>/dev/null
> @@ -587,6 +618,7 @@ tst_run()
>  			NEEDS_ROOT|NEEDS_TMPDIR|TMPDIR|NEEDS_DEVICE|DEVICE);;
>  			NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);;
>  			NEEDS_DRIVERS|FS_TYPE|MNTPOINT|MNT_PARAMS);;
> +			NEEDS_KCONFIGS|NEEDS_KCONFIGS_IFS);;
>  			IPV6|IPV6_FLAG|IPVER|TEST_DATA|TEST_DATA_IFS);;
>  			RETRY_FUNC|RETRY_FN_EXP_BACKOFF|TIMEOUT);;
>  			NET_DATAROOT|NET_MAX_PKT|NET_RHOST_RUN_DEBUG|NETLOAD_CLN_NUMBER);;
> @@ -627,6 +659,7 @@ tst_run()
>  	[ "$TST_DISABLE_SELINUX" = 1 ] && tst_disable_selinux
>  
>  	tst_require_cmds $TST_NEEDS_CMDS
> +	tst_require_kconfigs $TST_NEEDS_KCONFIGS
>  	tst_require_drivers $TST_NEEDS_DRIVERS
>  
>  	if [ -n "$TST_MIN_KVER" ]; then
> @@ -748,6 +781,8 @@ if [ -z "$TST_NO_DEFAULT_RUN" ]; then
>  
>  	TST_TEST_DATA_IFS="${TST_TEST_DATA_IFS:- }"
>  
> +	TST_NEEDS_KCONFIGS_IFS="${TST_NEEDS_KCONFIGS_IFS:-,}"
> +
>  	if [ -n "$TST_CNT" ]; then
>  		if ! tst_is_int "$TST_CNT"; then
>  			tst_brk TBROK "TST_CNT must be integer"
> -- 
> 2.23.0
> 
> 
> -- 
> Mailing list info: https://lists.linux.it/listinfo/ltp
Li Wang Jan. 7, 2022, 3:54 a.m. UTC | #3
Hi all,

On Thu, Jan 6, 2022 at 7:17 PM Cyril Hrubis <chrubis@suse.cz> wrote:

> > +| 'TST_NEEDS_KCONFIGS'     | Checks kernel kconfigs support for the test (see below).

> > +| 'TST_NEEDS_KCONFIGS_IFS' | Used for splitting '$TST_NEEDS_KCONFIGS' variable,
> > +                             default value is comma.


> > +     for kconfig_i in $(seq $kconfig_max); do
> > +             eval "local kconfig$kconfig_i"
> > +             eval "kconfig$kconfig_i='$(echo "$kconfigs" | cut -d"$TST_NEEDS_KCONFIGS_IFS" -f$kconfig_i)'"
> > +     done
>
> This part is a bit ugly, I guess that it may as well be easier to
> process in C. A long as we pass it as:
>
> tst_check_kconfigs "$TST_NEEDS_KCONFIGS_IFS" "$TST_NEEDS_KCONFIGS"
>
> We can easily split the TST_NEEDS_KCONFIGS with strchr() and single
> loop.

+1

I even don't think we need that 'TST_NEEDS_KCONFIGS_IFS'
variable for users. More flexible means more complicated to some
degree, if achieve a C process,  we can handle that by accepting
whatever the delimiter.

But strictly usage with a comma is enough for current kernel configs
parsing I guess.
Yang Xu Jan. 7, 2022, 4:08 a.m. UTC | #4
Hi Li, Cyril, Petr
> Hi all,
>
> On Thu, Jan 6, 2022 at 7:17 PM Cyril Hrubis<chrubis@suse.cz>  wrote:
>
>>> +| 'TST_NEEDS_KCONFIGS'     | Checks kernel kconfigs support for the test (see below).
>
>>> +| 'TST_NEEDS_KCONFIGS_IFS' | Used for splitting '$TST_NEEDS_KCONFIGS' variable,
>>> +                             default value is comma.
>
>
>>> +     for kconfig_i in $(seq $kconfig_max); do
>>> +             eval "local kconfig$kconfig_i"
>>> +             eval "kconfig$kconfig_i='$(echo "$kconfigs" | cut -d"$TST_NEEDS_KCONFIGS_IFS" -f$kconfig_i)'"
>>> +     done
>>
>> This part is a bit ugly, I guess that it may as well be easier to
>> process in C. A long as we pass it as:
>>
>> tst_check_kconfigs "$TST_NEEDS_KCONFIGS_IFS" "$TST_NEEDS_KCONFIGS"
>>
>> We can easily split the TST_NEEDS_KCONFIGS with strchr() and single
>> loop.
>
> +1
>
In fact, I used the c code(use strtok_r) in the beginning when I wrote 
this patch
code as below:

// SPDX-License-Identifier: GPL-2.0-or-later
/* Copyright (c) 2021 FUJITSU LIMITED. All rights reserved.*/

#include <stdio.h>
#include <string.h>
#include "tst_kconfig.h"


int main(int argc, const char *argv[])
{
         char delims[] = ",";
         char kconfig[PATH_MAX];
         char str[PATH_MAX];
         char *result = NULL;
         char *next = NULL;
         int i = 0;

         if (argc < 2) {
                 fprintf(stderr, "Please provide kernel kconfig list\n");
                 return 1;
         }

         strcpy(str, argv[1]);
         result = strtok_r(str, delims, &next);

         while (result != NULL) {
                 strcpy(kconfig, result);
                 printf("%s %s %d\n", kconfig,result, i);
                 const char *const kconfigs[] = {
                         kconfig,
                         NULL
                 };
                 if (tst_kconfig_check(kconfigs)) {
                          fprintf(stderr, "Kernel config doesn't meet 
test's requirement!\n");
                          return 1;
                 }

                 i++;
                 result = strtok_r(NULL, delims, &next);
         }

         return 0;
}

But it must call tst_kconfig_check for every kconfig expression and 
print many info "Parsing kernel config ..." because we need to create a 
NULL terminated array for  tst_kconfig_check.

It seems also increase calculated complexity...

That is why I switch to filter them in shell.

If you want to use C, I will swich to use C for filter strings.
> I even don't think we need that 'TST_NEEDS_KCONFIGS_IFS'
> variable for users. More flexible means more complicated to some
> degree, if achieve a C process,  we can handle that by accepting
> whatever the delimiter.
>
> But strictly usage with a comma is enough for current kernel configs
> parsing I guess.
+1

Best Regards
Yang Xu
>
Li Wang Jan. 7, 2022, 7:04 a.m. UTC | #5
xuyang2018.jy@fujitsu.com <xuyang2018.jy@fujitsu.com> wrote:

> // SPDX-License-Identifier: GPL-2.0-or-later
> /* Copyright (c) 2021 FUJITSU LIMITED. All rights reserved.*/
>
> #include <stdio.h>
> #include <string.h>
> #include "tst_kconfig.h"
>
>
> int main(int argc, const char *argv[])
> {
>          char delims[] = ",";
>          char kconfig[PATH_MAX];
>          char str[PATH_MAX];
>          char *result = NULL;
>          char *next = NULL;
>          int i = 0;
>
>          if (argc < 2) {
>                  fprintf(stderr, "Please provide kernel kconfig list\n");
>                  return 1;
>          }
>
>          strcpy(str, argv[1]);
>          result = strtok_r(str, delims, &next);
>
>          while (result != NULL) {
>                  strcpy(kconfig, result);
>                  printf("%s %s %d\n", kconfig,result, i);
>                  const char *const kconfigs[] = {
>                          kconfig,
>                          NULL
>                  };
>                  if (tst_kconfig_check(kconfigs)) {
>                           fprintf(stderr, "Kernel config doesn't meet
> test's requirement!\n");
>                           return 1;
>                  }
>
>                  i++;
>                  result = strtok_r(NULL, delims, &next);
>          }
>
>          return 0;
> }
>
> But it must call tst_kconfig_check for every kconfig expression and
> print many info "Parsing kernel config ..." because we need to create a
> NULL terminated array for  tst_kconfig_check.

Maybe we can combine the arguments into one kconfigs struct and
just do once check? something like:

---------------------------
        strcpy(str, argv[1]);
        result = strtok_r(str, delims, &next);

        const char *kconfigs[64];

        for (i = 0; result != NULL; i++) {
                kconfigs[i] = result;
                result = strtok_r(NULL, delims, &next);
        }

        kconfigs[++i] = NULL;

        if (tst_kconfig_check(kconfigs)) {
                fprintf(stderr, "Kernel config doesn't meet test's
requirement!\n");
                return 1;
        }
        ...
Petr Vorel Jan. 7, 2022, 7:33 a.m. UTC | #6
> Hi all,

> On Thu, Jan 6, 2022 at 7:17 PM Cyril Hrubis <chrubis@suse.cz> wrote:

> > > +| 'TST_NEEDS_KCONFIGS'     | Checks kernel kconfigs support for the test (see below).

> > > +| 'TST_NEEDS_KCONFIGS_IFS' | Used for splitting '$TST_NEEDS_KCONFIGS' variable,
> > > +                             default value is comma.


> > > +     for kconfig_i in $(seq $kconfig_max); do
> > > +             eval "local kconfig$kconfig_i"
> > > +             eval "kconfig$kconfig_i='$(echo "$kconfigs" | cut -d"$TST_NEEDS_KCONFIGS_IFS" -f$kconfig_i)'"
> > > +     done

> > This part is a bit ugly, I guess that it may as well be easier to
> > process in C. A long as we pass it as:

> > tst_check_kconfigs "$TST_NEEDS_KCONFIGS_IFS" "$TST_NEEDS_KCONFIGS"

> > We can easily split the TST_NEEDS_KCONFIGS with strchr() and single
> > loop.

> +1

> I even don't think we need that 'TST_NEEDS_KCONFIGS_IFS'
> variable for users. More flexible means more complicated to some
> degree, if achieve a C process,  we can handle that by accepting
> whatever the delimiter.
I suppose any string can be part of kconfig, thus it'd be safer to be able to
redefine delimiter. But yes, TST_NEEDS_KCONFIGS_IFS should be for using in tests
(thus TST_ prefix).

Kind regards,
Petr

> But strictly usage with a comma is enough for current kernel configs
> parsing I guess.
Yang Xu Jan. 7, 2022, 8:28 a.m. UTC | #7
Hi Li
> xuyang2018.jy@fujitsu.com<xuyang2018.jy@fujitsu.com>  wrote:
>
>> // SPDX-License-Identifier: GPL-2.0-or-later
>> /* Copyright (c) 2021 FUJITSU LIMITED. All rights reserved.*/
>>
>> #include<stdio.h>
>> #include<string.h>
>> #include "tst_kconfig.h"
>>
>>
>> int main(int argc, const char *argv[])
>> {
>>           char delims[] = ",";
>>           char kconfig[PATH_MAX];
>>           char str[PATH_MAX];
>>           char *result = NULL;
>>           char *next = NULL;
>>           int i = 0;
>>
>>           if (argc<  2) {
>>                   fprintf(stderr, "Please provide kernel kconfig list\n");
>>                   return 1;
>>           }
>>
>>           strcpy(str, argv[1]);
>>           result = strtok_r(str, delims,&next);
>>
>>           while (result != NULL) {
>>                   strcpy(kconfig, result);
>>                   printf("%s %s %d\n", kconfig,result, i);
>>                   const char *const kconfigs[] = {
>>                           kconfig,
>>                           NULL
>>                   };
>>                   if (tst_kconfig_check(kconfigs)) {
>>                            fprintf(stderr, "Kernel config doesn't meet
>> test's requirement!\n");
>>                            return 1;
>>                   }
>>
>>                   i++;
>>                   result = strtok_r(NULL, delims,&next);
>>           }
>>
>>           return 0;
>> }
>>
>> But it must call tst_kconfig_check for every kconfig expression and
>> print many info "Parsing kernel config ..." because we need to create a
>> NULL terminated array for  tst_kconfig_check.
>
> Maybe we can combine the arguments into one kconfigs struct and
> just do once check? something like:
Yes, it works well. Thanks.

I checked the kernel config, it seems comma can not meet the CONFIG_LSM 
situation (Petr mention it but I don't notice before).
CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"

so I think we may TST_NEEDS_KCONFIGS_IFS variable and default value is 
comma.

Best Regards
Yang Xu
>
> ---------------------------
>          strcpy(str, argv[1]);
>          result = strtok_r(str, delims,&next);
>
>          const char *kconfigs[64];
>
>          for (i = 0; result != NULL; i++) {
>                  kconfigs[i] = result;
>                  result = strtok_r(NULL, delims,&next);
>          }
>
>          kconfigs[++i] = NULL;
>
>          if (tst_kconfig_check(kconfigs)) {
>                  fprintf(stderr, "Kernel config doesn't meet test's
> requirement!\n");
>                  return 1;
>          }
>          ...
>
>
>
Li Wang Jan. 7, 2022, 8:41 a.m. UTC | #8
Hi Petr, Xu,

> > Maybe we can combine the arguments into one kconfigs struct and
> > just do once check? something like:
> Yes, it works well. Thanks.

Btw, seems const char *kconfigs[64] is not enough for a long
string combination, you can dynamically allocate memory
according to arguments size. Or, just raise to a big number.

>
> I checked the kernel config, it seems comma can not meet the CONFIG_LSM
> situation (Petr mention it but I don't notice before).
> CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
>
> so I think we may TST_NEEDS_KCONFIGS_IFS variable and default value is
> comma.

Ok, I'm fine to keep that, and thanks for the instance.
Petr Vorel Jan. 7, 2022, 9:05 a.m. UTC | #9
Hi all,

> >> int main(int argc, const char *argv[])
> >> {
> >>           char delims[] = ",";
> >>           char kconfig[PATH_MAX];
> >>           char str[PATH_MAX];
> >>           char *result = NULL;
> >>           char *next = NULL;
> >>           int i = 0;

> >>           if (argc<  2) {
> >>                   fprintf(stderr, "Please provide kernel kconfig list\n");
> >>                   return 1;
> >>           }

> >>           strcpy(str, argv[1]);
> >>           result = strtok_r(str, delims,&next);

> >>           while (result != NULL) {
> >>                   strcpy(kconfig, result);
> >>                   printf("%s %s %d\n", kconfig,result, i);
> >>                   const char *const kconfigs[] = {
> >>                           kconfig,
> >>                           NULL
> >>                   };
> >>                   if (tst_kconfig_check(kconfigs)) {
> >>                            fprintf(stderr, "Kernel config doesn't meet
> >> test's requirement!\n");
> >>                            return 1;
> >>                   }

> >>                   i++;
> >>                   result = strtok_r(NULL, delims,&next);
> >>           }

> >>           return 0;
> >> }

> >> But it must call tst_kconfig_check for every kconfig expression and
> >> print many info "Parsing kernel config ..." because we need to create a
> >> NULL terminated array for  tst_kconfig_check.

> > Maybe we can combine the arguments into one kconfigs struct and
> > just do once check? something like:
> Yes, it works well. Thanks.

LGTM. NOTE: Cyril suggested strchr() with loop, maybe he thought about even
simpler solution.

> I checked the kernel config, it seems comma can not meet the CONFIG_LSM 
> situation (Petr mention it but I don't notice before).
> CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"

> so I think we may TST_NEEDS_KCONFIGS_IFS variable and default value is 
> comma.
Maybe use '|' as the default? That's very unlikely to be used
(but I'd still have TST_NEEDS_KCONFIGS_IFS).

Kind regards,
Petr
Yang Xu Jan. 7, 2022, 9:22 a.m. UTC | #10
Hi Petr
> Hi all,
>
>>>> int main(int argc, const char *argv[])
>>>> {
>>>>            char delims[] = ",";
>>>>            char kconfig[PATH_MAX];
>>>>            char str[PATH_MAX];
>>>>            char *result = NULL;
>>>>            char *next = NULL;
>>>>            int i = 0;
>
>>>>            if (argc<   2) {
>>>>                    fprintf(stderr, "Please provide kernel kconfig list\n");
>>>>                    return 1;
>>>>            }
>
>>>>            strcpy(str, argv[1]);
>>>>            result = strtok_r(str, delims,&next);
>
>>>>            while (result != NULL) {
>>>>                    strcpy(kconfig, result);
>>>>                    printf("%s %s %d\n", kconfig,result, i);
>>>>                    const char *const kconfigs[] = {
>>>>                            kconfig,
>>>>                            NULL
>>>>                    };
>>>>                    if (tst_kconfig_check(kconfigs)) {
>>>>                             fprintf(stderr, "Kernel config doesn't meet
>>>> test's requirement!\n");
>>>>                             return 1;
>>>>                    }
>
>>>>                    i++;
>>>>                    result = strtok_r(NULL, delims,&next);
>>>>            }
>
>>>>            return 0;
>>>> }
>
>>>> But it must call tst_kconfig_check for every kconfig expression and
>>>> print many info "Parsing kernel config ..." because we need to create a
>>>> NULL terminated array for  tst_kconfig_check.
>
>>> Maybe we can combine the arguments into one kconfigs struct and
>>> just do once check? something like:
>> Yes, it works well. Thanks.
>
> LGTM. NOTE: Cyril suggested strchr() with loop, maybe he thought about even
> simpler solution.
>
>> I checked the kernel config, it seems comma can not meet the CONFIG_LSM
>> situation (Petr mention it but I don't notice before).
>> CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor"
>
>> so I think we may TST_NEEDS_KCONFIGS_IFS variable and default value is
>> comma.
> Maybe use '|' as the default? That's very unlikely to be used
> (but I'd still have TST_NEEDS_KCONFIGS_IFS).
No, look test_kconfig01.c, we use '|' for a valid or operation.

Best Rgards
Yang Xu
>
> Kind regards,
> Petr
Cyril Hrubis Jan. 7, 2022, 9:46 a.m. UTC | #11
Hi!
> > > Maybe we can combine the arguments into one kconfigs struct and
> > > just do once check? something like:
> > Yes, it works well. Thanks.
> 
> Btw, seems const char *kconfigs[64] is not enough for a long
> string combination, you can dynamically allocate memory
> according to arguments size. Or, just raise to a big number.

Just loop over the string twice and count the occurencens of IFS
character in the first loop.
Yang Xu Jan. 7, 2022, 9:56 a.m. UTC | #12
Hi!
> Hi!
>>>> Maybe we can combine the arguments into one kconfigs struct and
>>>> just do once check? something like:
>>> Yes, it works well. Thanks.
>>
>> Btw, seems const char *kconfigs[64] is not enough for a long
>> string combination, you can dynamically allocate memory
>> according to arguments size. Or, just raise to a big number.
>
> Just loop over the string twice and count the occurencens of IFS
> character in the first loop.
Yes.

All,  I have rewrited this patchset, I will send a v3 on next Monday.

Best Regards
Yang Xu
>
Petr Vorel Jan. 7, 2022, 12:07 p.m. UTC | #13
Hi all,

...
> >> so I think we may TST_NEEDS_KCONFIGS_IFS variable and default value is
> >> comma.
> > Maybe use '|' as the default? That's very unlikely to be used
> > (but I'd still have TST_NEEDS_KCONFIGS_IFS).
> No, look test_kconfig01.c, we use '|' for a valid or operation.
Ah, correct. Then comma as the default is probably the best.

Kind regards,
Petr
diff mbox series

Patch

diff --git a/doc/shell-test-api.txt b/doc/shell-test-api.txt
index b993a9e1e..a1ec6ba2a 100644
--- a/doc/shell-test-api.txt
+++ b/doc/shell-test-api.txt
@@ -193,22 +193,25 @@  simply by setting right '$TST_NEEDS_FOO'.
 
 [options="header"]
 |=============================================================================
-| Variable name      | Action done
-| 'TST_NEEDS_ROOT'   | Exit the test with 'TCONF' unless executed under root.
-|                    | Alternatively the 'tst_require_root' command can be used.
-| 'TST_NEEDS_TMPDIR' | Create test temporary directory and cd into it.
-| 'TST_NEEDS_DEVICE' | Prepare test temporary device, the path to testing
-                       device is stored in '$TST_DEVICE' variable.
-                       The option implies 'TST_NEEDS_TMPDIR'.
-| 'TST_NEEDS_CMDS'   | String with command names that has to be present for
-                       the test (see below).
-| 'TST_NEEDS_MODULE' | Test module name needed for the test (see below).
-| 'TST_NEEDS_DRIVERS'| Checks kernel drivers support for the test.
-| 'TST_TIMEOUT'      | Maximum timeout set for the test in sec. Must be int >= 1,
-                       or -1 (special value to disable timeout), default is 300.
-                       Variable is meant be set in tests, not by user.
-                       It's an equivalent of `tst_test.timeout` in C, can be set
-                       via 'tst_set_timeout(timeout)' after test has started.
+| Variable name            | Action done
+| 'TST_NEEDS_ROOT'         | Exit the test with 'TCONF' unless executed under root.
+|                          | Alternatively the 'tst_require_root' command can be used.
+| 'TST_NEEDS_TMPDIR'       | Create test temporary directory and cd into it.
+| 'TST_NEEDS_DEVICE'       | Prepare test temporary device, the path to testing
+                             device is stored in '$TST_DEVICE' variable.
+                             The option implies 'TST_NEEDS_TMPDIR'.
+| 'TST_NEEDS_CMDS'         | String with command names that has to be present for
+                             the test (see below).
+| 'TST_NEEDS_MODULE'       | Test module name needed for the test (see below).
+| 'TST_NEEDS_DRIVERS'      | Checks kernel drivers support for the test.
+| 'TST_NEEDS_KCONFIGS'     | Checks kernel kconfigs support for the test (see below).
+| 'TST_NEEDS_KCONFIGS_IFS' | Used for splitting '$TST_NEEDS_KCONFIGS' variable,
+                             default value is comma.
+| 'TST_TIMEOUT'            | Maximum timeout set for the test in sec. Must be int >= 1,
+                             or -1 (special value to disable timeout), default is 300.
+                             Variable is meant be set in tests, not by user.
+                             It's an equivalent of `tst_test.timeout` in C, can be set
+                             via 'tst_set_timeout(timeout)' after test has started.
 |=============================================================================
 
 [options="header"]
@@ -742,3 +745,22 @@  TST_NEEDS_CHECKPOINTS=1
 Since both the implementations are compatible, it's also possible to start
 a child binary process from a shell test and synchronize with it. This process
 must have checkpoints initialized by calling 'tst_reinit()'.
+
+1.7 Parsing kernel .config
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The shell library provides an implementation of the kconfig parsing interface
+compatible with the C version.
+
+It's possible to pass kernel kconfig list for tst_require_kconfigs API with
+'$TST_NEEDS_KCONFIGS'.
+Optional '$TST_NEEDS_KCONFIGS_IFS' is used for splitting, default value is comma.
+
+Now, we support the length of kconfig list is 10.
+
+-------------------------------------------------------------------------------
+#!/bin/sh
+TST_NEEDS_KCONFIGS="CONFIG_EXT4_FS, CONFIG_QUOTACTL=y"
+
+. tst_test.sh
+-------------------------------------------------------------------------------
diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
index 8b2fe347a..b34a582b7 100755
--- a/lib/newlib_tests/runtest.sh
+++ b/lib/newlib_tests/runtest.sh
@@ -6,7 +6,8 @@  tst_needs_cmds01 tst_needs_cmds02 tst_needs_cmds03 tst_needs_cmds06
 tst_needs_cmds07 tst_bool_expr test_exec test_timer tst_res_hexd tst_strstatus
 tst_fuzzy_sync03 test_zero_hugepage.sh}"
 
-LTP_SHELL_API_TESTS="${LTP_SHELL_API_TESTS:-shell/tst_check_driver.sh shell/net/*.sh}"
+LTP_SHELL_API_TESTS="${LTP_SHELL_API_TESTS:-shell/tst_check_driver.sh
+shell/tst_check_kconfig0[1-4].sh shell/net/*.sh}"
 
 cd $(dirname $0)
 PATH="$PWD/../../testcases/lib/:$PATH"
diff --git a/lib/newlib_tests/shell/tst_check_kconfig01.sh b/lib/newlib_tests/shell/tst_check_kconfig01.sh
new file mode 100755
index 000000000..90e76360e
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_check_kconfig01.sh
@@ -0,0 +1,26 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
+
+TST_TESTFUNC=do_test
+TST_NEEDS_CMDS="tst_check_kconfigs"
+TST_NEEDS_KCONFIGS="CONFIG_GENERIC_IRQ_PROBE=y,
+CONFIG_GENERIC_IRQ_SHOW=y,
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y,
+CONFIG_GENERIC_PENDING_IRQ=y,
+CONFIG_GENERIC_IRQ_MIGRATION=y,
+CONFIG_IRQ_DOMAIN=y,
+CONFIG_IRQ_DOMAIN_HIERARCHY=y,
+CONFIG_GENERIC_MSI_IRQ=y,
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y,
+CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y,
+CONFIG_GENERIC_IRQ_RESERVATION_MODE=y"
+
+. tst_test.sh
+
+do_test()
+{
+	tst_res TFAIL "kernel config check functionality only supports 10 kernel kconfigs"
+}
+
+tst_run
diff --git a/lib/newlib_tests/shell/tst_check_kconfig02.sh b/lib/newlib_tests/shell/tst_check_kconfig02.sh
new file mode 100755
index 000000000..065a20fd2
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_check_kconfig02.sh
@@ -0,0 +1,16 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
+
+TST_TESTFUNC=do_test
+TST_NEEDS_CMDS="tst_check_kconfigs"
+TST_NEEDS_KCONFIGS="CONFIG_EXT4"
+
+. tst_test.sh
+
+do_test()
+{
+	tst_res TFAIL "kernel .config doesn't have CONFIG_EXT4"
+}
+
+tst_run
diff --git a/lib/newlib_tests/shell/tst_check_kconfig03.sh b/lib/newlib_tests/shell/tst_check_kconfig03.sh
new file mode 100755
index 000000000..ebdec70f8
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_check_kconfig03.sh
@@ -0,0 +1,15 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
+
+TST_TESTFUNC=do_test
+TST_NEEDS_CMDS="tst_check_kconfigs"
+TST_NEEDS_KCONFIGS="CONFIG_EXT4_FS: CONFIG_XFS_FS"
+. tst_test.sh
+
+do_test()
+{
+	tst_res TFAIL "invalid kconfig delimter"
+}
+
+tst_run
diff --git a/lib/newlib_tests/shell/tst_check_kconfig04.sh b/lib/newlib_tests/shell/tst_check_kconfig04.sh
new file mode 100755
index 000000000..c5f046b79
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_check_kconfig04.sh
@@ -0,0 +1,16 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
+
+TST_TESTFUNC=do_test
+TST_NEEDS_CMDS="tst_check_kconfigs"
+TST_NEEDS_KCONFIGS="CONFIG_EXT4_FS : CONFIG_XFS_FS"
+TST_NEEDS_KCONFIGS_IFS=":"
+. tst_test.sh
+
+do_test()
+{
+	tst_res TPASS "valid kconfig delimter"
+}
+
+tst_run
diff --git a/lib/newlib_tests/shell/tst_check_kconfig05.sh b/lib/newlib_tests/shell/tst_check_kconfig05.sh
new file mode 100755
index 000000000..1a214016a
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_check_kconfig05.sh
@@ -0,0 +1,26 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2022 FUJITSU LIMITED. All rights reserved.
+
+TST_TESTFUNC=do_test
+TST_NEEDS_CMDS="tst_check_kconfigs"
+. tst_test.sh
+
+do_test()
+{
+	tst_check_kconfigs "CONFIG_EXT4_FS"
+	if [ $? -eq 0 ]; then
+		tst_res TPASS "kernel .config has CONFIG_EXT4_fs"
+	else
+		tst_res TFAIL "kernel .config doesn't have CONFIG_EXT4_FS"
+	fi
+
+	tst_check_kconfigs "CONFIG_EXT4"
+	if [ $? -eq 0 ]; then
+		tst_res TFAIL "kernel .config has CONFIG_EXT4"
+	else
+		tst_res TPASS "kernel .config doesn't have CONFIG_EXT4"
+	fi
+}
+
+tst_run
diff --git a/testcases/lib/.gitignore b/testcases/lib/.gitignore
index 9625d9043..c0d4dc851 100644
--- a/testcases/lib/.gitignore
+++ b/testcases/lib/.gitignore
@@ -1,4 +1,5 @@ 
 /tst_check_drivers
+/tst_check_kconfigs
 /tst_checkpoint
 /tst_device
 /tst_getconf
diff --git a/testcases/lib/Makefile b/testcases/lib/Makefile
index d6b4c7a91..f2de0c832 100644
--- a/testcases/lib/Makefile
+++ b/testcases/lib/Makefile
@@ -11,6 +11,7 @@  INSTALL_TARGETS		:= *.sh
 MAKE_TARGETS		:= tst_sleep tst_random tst_checkpoint tst_rod tst_kvcmp\
 			   tst_device tst_net_iface_prefix tst_net_ip_prefix tst_net_vars\
 			   tst_getconf tst_supported_fs tst_check_drivers tst_get_unused_port\
-			   tst_get_median tst_hexdump tst_get_free_pids tst_timeout_kill
+			   tst_get_median tst_hexdump tst_get_free_pids tst_timeout_kill\
+			   tst_check_kconfigs
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/lib/tst_check_kconfigs.c b/testcases/lib/tst_check_kconfigs.c
new file mode 100644
index 000000000..5c387a62d
--- /dev/null
+++ b/testcases/lib/tst_check_kconfigs.c
@@ -0,0 +1,18 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) 2022 FUJITSU LIMITED. All rights reserved. */
+
+#include <stdio.h>
+#include "tst_kconfig.h"
+
+int main(int argc, const char *argv[])
+{
+	if (argc < 2) {
+		fprintf(stderr, "Please provide kernel kconfig list\n");
+		return 1;
+	}
+
+	if (tst_kconfig_check(argv+1))
+		return 1;
+
+	return 0;
+}
diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
index 2556b28f5..0097c8d43 100644
--- a/testcases/lib/tst_test.sh
+++ b/testcases/lib/tst_test.sh
@@ -412,6 +412,37 @@  tst_require_drivers()
 	return 0
 }
 
+tst_require_kconfigs()
+{
+	[ $# -eq 0 ] && return 0
+
+	local kconfigs
+	local kconfig_i
+	local kconfig_max
+
+	kconfigs=$@
+	[ -z "$kconfigs" ] && return 0
+
+	tst_check_cmds cut tr wc
+	kconfig_max=$(( $(echo "$kconfigs" | tr -cd "$TST_NEEDS_KCONFIGS_IFS" | wc -c) +1))
+	if [ $kconfig_max -gt 10 ]; then
+		tst_brk TCONF "The max number of kconfig is 10!"
+	fi
+
+	for kconfig_i in $(seq $kconfig_max); do
+		eval "local kconfig$kconfig_i"
+		eval "kconfig$kconfig_i='$(echo "$kconfigs" | cut -d"$TST_NEEDS_KCONFIGS_IFS" -f$kconfig_i)'"
+	done
+
+	tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 $kconfig6\
+			$kconfig7 $kconfig8 $kconfig9 $kconfig10
+	if [ $? -ne 0 ]; then
+		tst_brk TCONF "Aborting due to unsuitable kernel config, see above!"
+	fi
+
+	return 0
+}
+
 tst_is_int()
 {
 	[ "$1" -eq "$1" ] 2>/dev/null
@@ -587,6 +618,7 @@  tst_run()
 			NEEDS_ROOT|NEEDS_TMPDIR|TMPDIR|NEEDS_DEVICE|DEVICE);;
 			NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);;
 			NEEDS_DRIVERS|FS_TYPE|MNTPOINT|MNT_PARAMS);;
+			NEEDS_KCONFIGS|NEEDS_KCONFIGS_IFS);;
 			IPV6|IPV6_FLAG|IPVER|TEST_DATA|TEST_DATA_IFS);;
 			RETRY_FUNC|RETRY_FN_EXP_BACKOFF|TIMEOUT);;
 			NET_DATAROOT|NET_MAX_PKT|NET_RHOST_RUN_DEBUG|NETLOAD_CLN_NUMBER);;
@@ -627,6 +659,7 @@  tst_run()
 	[ "$TST_DISABLE_SELINUX" = 1 ] && tst_disable_selinux
 
 	tst_require_cmds $TST_NEEDS_CMDS
+	tst_require_kconfigs $TST_NEEDS_KCONFIGS
 	tst_require_drivers $TST_NEEDS_DRIVERS
 
 	if [ -n "$TST_MIN_KVER" ]; then
@@ -748,6 +781,8 @@  if [ -z "$TST_NO_DEFAULT_RUN" ]; then
 
 	TST_TEST_DATA_IFS="${TST_TEST_DATA_IFS:- }"
 
+	TST_NEEDS_KCONFIGS_IFS="${TST_NEEDS_KCONFIGS_IFS:-,}"
+
 	if [ -n "$TST_CNT" ]; then
 		if ! tst_is_int "$TST_CNT"; then
 			tst_brk TBROK "TST_CNT must be integer"