diff mbox series

[v1,2/3] shell: add kconfig parse api

Message ID 1641279439-2421-2-git-send-email-xuyang2018.jy@fujitsu.com
State Changes Requested
Headers show
Series [v1,1/3] lib/tst_kconfig: Modify the return type of tst_kconfig_check function | expand

Commit Message

Yang Xu \(Fujitsu\) Jan. 4, 2022, 6:57 a.m. UTC
Use tst_check_kconfigs command to call tst_kconfig_check function in internal.
It introduces three variables in tst_test.sh
TST_NEEDS_KCONFIGS
TST_NEEDS_KCONFIG_IFS (default value is comma)
TST_TCONF_IF_KCONFIG (default value is 1, 0 means to use TWRAN and case continue)

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

ps:Don't use array in tst_require_kconfigs because dash doesn't support shell array.

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                        | 57 +++++++++++++------
 lib/newlib_tests/runtest.sh                   |  4 +-
 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 +++++++++
 lib/newlib_tests/shell/tst_check_kconfig06.sh | 17 ++++++
 testcases/lib/.gitignore                      |  1 +
 testcases/lib/Makefile                        |  4 +-
 testcases/lib/tst_check_kconfigs.c            | 17 ++++++
 testcases/lib/tst_test.sh                     | 41 +++++++++++++
 12 files changed, 221 insertions(+), 19 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 100755 lib/newlib_tests/shell/tst_check_kconfig06.sh
 create mode 100644 testcases/lib/tst_check_kconfigs.c

Comments

Petr Vorel Jan. 4, 2022, 11:04 a.m. UTC | #1
Hi Xu,

> Use tst_check_kconfigs command to call tst_kconfig_check function in internal.
> It introduces three variables in tst_test.sh
> TST_NEEDS_KCONFIGS
> TST_NEEDS_KCONFIG_IFS (default value is comma)
> TST_TCONF_IF_KCONFIG (default value is 1, 0 means to use TWRAN and case continue)

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

> ps:Don't use array in tst_require_kconfigs because dash doesn't support shell array.
IFS instead of array is has been used since tst_test.sh creation, maybe we can
omit this info.

> 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>

> +++ b/doc/shell-test-api.txt
> @@ -193,22 +193,23 @@ 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).
+1 for adding TST_NEEDS_KCONFIG_IFS, it's needed e.g. for: CONFIG_LSM="integrity,apparmor"
Could you please mention TST_NEEDS_KCONFIG_IFS and TST_TCONF_IF_KCONFIG here in docs?

> +| '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 +743,27 @@ 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
nit: s/api/API/ (it's an abbreviation). Also before merge please update git commit message.

> +'$TST_NEEDS_KCONFIGS'.
> +Optional '$TST_NEEDS_KCONFIG_IFS' is used for splitting, default value is comma.
> +Optional '$TST_TCONF_IF_KCONFIG' is used for deciding how to exit the test if kernel
> +.config doesn't meet test's requirement, default value is 1(TCONF). Otherwise, just
I wonder if we need TST_TCONF_IF_KCONFIG functionality in the test or if it's an
user request (i.e. user like variable LTP_TCONF_IF_KCONFIG doc/user-guide.txt).
Because I'm not sure whether test would need it, but I can imagine user want to
have test running even kernel config is not available (e.g. embedded platforms).
Or maybe we need both user variable and test variable.

Also not sure about TST_TCONF_IF_KCONFIG name, IMHO "IF" should be replaced to
something which describes what it does.

Also this patchset is about syncing C API functionality with shell API. But you
introduce TST_TCONF_IF_KCONFIG only for shell. Shouldn't it be functionality for
both parts?

More notes about this variable also below.

BTW github actions have probably kernel config on expected place, which means
that most of the new tests TCONF, but tst_check_kconfig05.sh TFAIL.

tst_rhost_run 1 TCONF: veth(null)      0  TWARN  :  /__w/ltp/ltp/lib/tst_kernel.c:110: expected file /lib/modules/5.11.0-1022-azure/modules.dep does not exist or not a file
320
(null)      0  TWARN  :  /__w/ltp/ltp/lib/tst_kernel.c:110: expected file /lib/modules/5.11.0-1022-azure/modules.builtin does not exist or not a file driver not available

> +use TWRAN and continue to run test.
> +
> +Now, we support the length of kconfig list is 10.
Why 10? Cyril suggested that in PR, where he suggested to use separated
variables:
https://github.com/linux-test-project/ltp/issues/891#issuecomment-989712350

But for string used like array there is no performance limitation, thus I'd use
something like 50 or 100. Because for certain IMA tests there are at least 6
kconfig requirements, thus > 10 could be hit.

...
> 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..dc09b6092
> --- /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) 2021 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 "Kconfig api only supports 10 kernel kconfigs!"
s/api/API

...
> +++ 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) 2021 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."
nit: I'd also remove dot at the end (we don't use it in tests).

> +	else
> +		tst_res TFAIL "kerenl .config doesn't have CONFIG_EXT4_FS."
s/kerenl/kernel/
> +	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/lib/newlib_tests/shell/tst_check_kconfig06.sh b/lib/newlib_tests/shell/tst_check_kconfig06.sh
> new file mode 100755
> index 000000000..6a6d68fd7
> --- /dev/null
> +++ b/lib/newlib_tests/shell/tst_check_kconfig06.sh
> @@ -0,0 +1,17 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (c) 2021 FUJITSU LIMITED. All rights reserved.
> +
> +TST_TESTFUNC=do_test
> +TST_NEEDS_CMDS="tst_check_kconfigs"
> +TST_NEEDS_KCONFIGS="CONFIG_EXT4"
> +TST_TCONF_IF_KCONFIG=0
IMHO in shell is better to have empty value for "false", not zero.
Also, we use it that way for shell variables.

But that would mean you'd have to allow to be empty, i.e. use : instead of :-:
+TST_TCONF_IF_KCONFIG="${TST_TCONF_IF_KCONFIG:-1}"
-TST_TCONF_IF_KCONFIG="${TST_TCONF_IF_KCONFIG:1}"

But maybe it'd be better to have variable which is off by default (thus variable
with reverse meaning).

...
> +++ b/testcases/lib/tst_check_kconfigs.c
> @@ -0,0 +1,17 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/* Copyright (c) 2021 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;
nit: I'd add space here (readability).
> +	return 0;
> +}
> diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
> index 2556b28f5..c8134692e 100644
...

> --- a/testcases/lib/tst_test.sh
> +	tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 $kconfig6\
> +			$kconfig7 $kconfig8 $kconfig9 $kconfig10
> +	if [ $? -ne 0 ]; then
> +		if [ $TST_TCONF_IF_KCONFIG -eq 1 ]; then
> +			tst_brk TCONF "kconfig not available"

> +		else
> +			tst_res TWARN "kconfig not available"
This is quite strong: either test "fails" due TWARN non-zero exit code or it's
skipped. I'd prefer to have user variable for systems which are properly
configured (user will make sure all kconfig options are set), but it's just
missing kconfig due system configuration.

Kind regards,
Petr
Yang Xu \(Fujitsu\) Jan. 5, 2022, 7:15 a.m. UTC | #2
Hi Petr
> Hi Xu,
>
>> Use tst_check_kconfigs command to call tst_kconfig_check function in internal.
>> It introduces three variables in tst_test.sh
>> TST_NEEDS_KCONFIGS
>> TST_NEEDS_KCONFIG_IFS (default value is comma)
>> TST_TCONF_IF_KCONFIG (default value is 1, 0 means to use TWRAN and case continue)
>
>> Also, we can use tst_check_kconfigs in your shell case if you want to skip subtest
>> case instead the whole test.
>
>> ps:Don't use array in tst_require_kconfigs because dash doesn't support shell array.
> IFS instead of array is has been used since tst_test.sh creation, maybe we can
> omit this info.
Now, I know. Will remove this info.
>
>> 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>
>
>> +++ b/doc/shell-test-api.txt
>> @@ -193,22 +193,23 @@ 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).
> +1 for adding TST_NEEDS_KCONFIG_IFS, it's needed e.g. for: CONFIG_LSM="integrity,apparmor"
> Could you please mention TST_NEEDS_KCONFIG_IFS and TST_TCONF_IF_KCONFIG here in docs?
of course.
>
>> +| '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 +743,27 @@ 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
> nit: s/api/API/ (it's an abbreviation). Also before merge please update git commit message.
>
>> +'$TST_NEEDS_KCONFIGS'.
>> +Optional '$TST_NEEDS_KCONFIG_IFS' is used for splitting, default value is comma.
>> +Optional '$TST_TCONF_IF_KCONFIG' is used for deciding how to exit the test if kernel
>> +.config doesn't meet test's requirement, default value is 1(TCONF). Otherwise, just
> I wonder if we need TST_TCONF_IF_KCONFIG functionality in the test or if it's an
> user request (i.e. user like variable LTP_TCONF_IF_KCONFIG doc/user-guide.txt).
> Because I'm not sure whether test would need it, but I can imagine user want to
> have test running even kernel config is not available (e.g. embedded platforms).
> Or maybe we need both user variable and test variable.
Oh, I misunderstand the usage.

I should use TST_TCONF_IF_KCONFIG for non-found kconfig file instead of 
non-found kconfig list.

I think one variable is enough.

>
> Also not sure about TST_TCONF_IF_KCONFIG name, IMHO "IF" should be replaced to
> something which describes what it does.
Thinking a good name isn't a easy thing.

how about TCONF_IF_NO_KCONFIG?

>
> Also this patchset is about syncing C API functionality with shell API. But you
> introduce TST_TCONF_IF_KCONFIG only for shell. Shouldn't it be functionality for
> both parts?
Yes, code maybe as below:

void tst_kconfig_read(struct tst_kconfig_var vars[], size_t vars_len)
+static char kconfig_flag;
+
+int tst_kconfig_read(struct tst_kconfig_var vars[], size_t vars_len)
  {
         char line[128];
         unsigned int vars_found = 0;
+       const char *flag = getenv("TWARN_IF_NO_KCONFIG");
+
+       if (flag && !strcmp(flag,"y"))
+               kconfig_flag = 'y';

         FILE *fp = open_kconfig();
-       if (!fp)
+       if (!fp) {
+               if (kconfig_flag == 'y') {
+                       tst_res(TWARN, "Cannot parse kernel .config");
+                       return 1;
+               }
                 tst_brk(TBROK, "Cannot parse kernel .config");
-
+       }
         while (fgets(line, sizeof(line), fp)) {
                 if (kconfig_parse_line(line, vars, vars_len))
                         vars_found++;
@@ -198,6 +210,7 @@ void tst_kconfig_read(struct tst_kconfig_var vars[], 
size_t vars_len)

  exit:
         close_kconfig(fp);
+       return 0;
  }

  static size_t array_len(const char *const kconfigs[])
@@ -504,7 +517,9 @@ int tst_kconfig_check(const char *const kconfigs[])

         var_cnt = populate_vars(exprs, expr_cnt, vars);

-       tst_kconfig_read(vars, var_cnt);
+       ret = tst_kconfig_read(vars, var_cnt);
+       if (ret)
+               return kconfig_flag == 'y' ? 0 : 1;



>
> More notes about this variable also below.
>
> BTW github actions have probably kernel config on expected place, which means
> that most of the new tests TCONF, but tst_check_kconfig05.sh TFAIL.
I guess we can export the  KCONFIG_PATH to solve this problem. But I 
don't know the expected place on github actions.
>
> tst_rhost_run 1 TCONF: veth(null)      0  TWARN  :  /__w/ltp/ltp/lib/tst_kernel.c:110: expected file /lib/modules/5.11.0-1022-azure/modules.dep does not exist or not a file
> 320
> (null)      0  TWARN  :  /__w/ltp/ltp/lib/tst_kernel.c:110: expected file /lib/modules/5.11.0-1022-azure/modules.builtin does not exist or not a file driver not available
>
>> +use TWRAN and continue to run test.
>> +
>> +Now, we support the length of kconfig list is 10.
> Why 10? Cyril suggested that in PR, where he suggested to use separated
> variables:
> https://github.com/linux-test-project/ltp/issues/891#issuecomment-989712350
>
> But for string used like array there is no performance limitation, thus I'd use
> something like 50 or 100. Because for certain IMA tests there are at least 6
> kconfig requirements, thus>  10 could be hit.
If case needs more than 10 kconfigs, we can use & ie
"CONFIG_EX4_FS & CONFIG_XFS_FS & CONFIG_QUOTAL_FS, CONFIG_PROC_FS..."
>
> ...
>> 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..dc09b6092
>> --- /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) 2021 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 "Kconfig api only supports 10 kernel kconfigs!"
> s/api/API
OK
>
> ...
>> +++ 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) 2021 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."
> nit: I'd also remove dot at the end (we don't use it in tests).
OK
>
>> +	else
>> +		tst_res TFAIL "kerenl .config doesn't have CONFIG_EXT4_FS."
> s/kerenl/kernel/
Sorry.
>> +	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/lib/newlib_tests/shell/tst_check_kconfig06.sh b/lib/newlib_tests/shell/tst_check_kconfig06.sh
>> new file mode 100755
>> index 000000000..6a6d68fd7
>> --- /dev/null
>> +++ b/lib/newlib_tests/shell/tst_check_kconfig06.sh
>> @@ -0,0 +1,17 @@
>> +#!/bin/sh
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +# Copyright (c) 2021 FUJITSU LIMITED. All rights reserved.
>> +
>> +TST_TESTFUNC=do_test
>> +TST_NEEDS_CMDS="tst_check_kconfigs"
>> +TST_NEEDS_KCONFIGS="CONFIG_EXT4"
>> +TST_TCONF_IF_KCONFIG=0
> IMHO in shell is better to have empty value for "false", not zero.
> Also, we use it that way for shell variables.
>
OK
> But that would mean you'd have to allow to be empty, i.e. use : instead of :-:
> +TST_TCONF_IF_KCONFIG="${TST_TCONF_IF_KCONFIG:-1}"
> -TST_TCONF_IF_KCONFIG="${TST_TCONF_IF_KCONFIG:1}"
>
> But maybe it'd be better to have variable which is off by default (thus variable
> with reverse meaning).
OK
>
> ...
>> +++ b/testcases/lib/tst_check_kconfigs.c
>> @@ -0,0 +1,17 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/* Copyright (c) 2021 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;
> nit: I'd add space here (readability).
>> +	return 0;
>> +}
>> diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh
>> index 2556b28f5..c8134692e 100644
> ...
>
>> --- a/testcases/lib/tst_test.sh
>> +	tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 $kconfig6\
>> +			$kconfig7 $kconfig8 $kconfig9 $kconfig10
>> +	if [ $? -ne 0 ]; then
>> +		if [ $TST_TCONF_IF_KCONFIG -eq 1 ]; then
>> +			tst_brk TCONF "kconfig not available"
>
>> +		else
>> +			tst_res TWARN "kconfig not available"
> This is quite strong: either test "fails" due TWARN non-zero exit code or it's
> skipped. I'd prefer to have user variable for systems which are properly
> configured (user will make sure all kconfig options are set), but it's just
> missing kconfig due system configuration.
I plan to fix the variable usage for non-found kconfig path/file instead 
of kconfig list.

Best Regards
Yang Xu
>
> Kind regards,
> Petr
Petr Vorel Jan. 5, 2022, 2:34 p.m. UTC | #3
Hi Xu,

> >> +'$TST_NEEDS_KCONFIGS'.
> >> +Optional '$TST_NEEDS_KCONFIG_IFS' is used for splitting, default value is comma.
> >> +Optional '$TST_TCONF_IF_KCONFIG' is used for deciding how to exit the test if kernel
> >> +.config doesn't meet test's requirement, default value is 1(TCONF). Otherwise, just
> > I wonder if we need TST_TCONF_IF_KCONFIG functionality in the test or if it's an
> > user request (i.e. user like variable LTP_TCONF_IF_KCONFIG doc/user-guide.txt).
> > Because I'm not sure whether test would need it, but I can imagine user want to
> > have test running even kernel config is not available (e.g. embedded platforms).
> > Or maybe we need both user variable and test variable.
> Oh, I misunderstand the usage.

> I should use TST_TCONF_IF_KCONFIG for non-found kconfig file instead of 
> non-found kconfig list.

> I think one variable is enough.

OK, but I'd like to know others' opinion what's needed.
Cyril, Li?

> > Also not sure about TST_TCONF_IF_KCONFIG name, IMHO "IF" should be replaced to
> > something which describes what it does.
> Thinking a good name isn't a easy thing.

> how about TCONF_IF_NO_KCONFIG?

Well, I was not sure about "IF" part. For use in test code it should have "TST_"
prefix, for users to set it should have "LTP_" prefix.

> > Also this patchset is about syncing C API functionality with shell API. But you
> > introduce TST_TCONF_IF_KCONFIG only for shell. Shouldn't it be functionality for
> > both parts?
> Yes, code maybe as below:

> void tst_kconfig_read(struct tst_kconfig_var vars[], size_t vars_len)
> +static char kconfig_flag;
> +
> +int tst_kconfig_read(struct tst_kconfig_var vars[], size_t vars_len)
>   {
>          char line[128];
>          unsigned int vars_found = 0;
> +       const char *flag = getenv("TWARN_IF_NO_KCONFIG");
> +
> +       if (flag && !strcmp(flag,"y"))
> +               kconfig_flag = 'y';

>          FILE *fp = open_kconfig();
> -       if (!fp)
> +       if (!fp) {
> +               if (kconfig_flag == 'y') {
> +                       tst_res(TWARN, "Cannot parse kernel .config");
> +                       return 1;
> +               }
>                  tst_brk(TBROK, "Cannot parse kernel .config");
> -
> +       }
>          while (fgets(line, sizeof(line), fp)) {
>                  if (kconfig_parse_line(line, vars, vars_len))
>                          vars_found++;
> @@ -198,6 +210,7 @@ void tst_kconfig_read(struct tst_kconfig_var vars[], 
> size_t vars_len)

>   exit:
>          close_kconfig(fp);
> +       return 0;
>   }

Sure, once we agree what should be implemented.

>   static size_t array_len(const char *const kconfigs[])
> @@ -504,7 +517,9 @@ int tst_kconfig_check(const char *const kconfigs[])

>          var_cnt = populate_vars(exprs, expr_cnt, vars);

> -       tst_kconfig_read(vars, var_cnt);
> +       ret = tst_kconfig_read(vars, var_cnt);
> +       if (ret)
> +               return kconfig_flag == 'y' ? 0 : 1;




> > More notes about this variable also below.

> > BTW github actions have probably kernel config on expected place, which means
> > that most of the new tests TCONF, but tst_check_kconfig05.sh TFAIL.
> I guess we can export the  KCONFIG_PATH to solve this problem. But I 
> don't know the expected place on github actions.

Sure, for github we can find config place.
But this can happen to user who runs the test. IMHO test should not fail if
user's system is without config. That's why I'd like to have a variable making
errors non-fatal.

> > tst_rhost_run 1 TCONF: veth(null)      0  TWARN  :  /__w/ltp/ltp/lib/tst_kernel.c:110: expected file /lib/modules/5.11.0-1022-azure/modules.dep does not exist or not a file
> > 320
> > (null)      0  TWARN  :  /__w/ltp/ltp/lib/tst_kernel.c:110: expected file /lib/modules/5.11.0-1022-azure/modules.builtin does not exist or not a file driver not available

> >> +use TWRAN and continue to run test.
> >> +
> >> +Now, we support the length of kconfig list is 10.
> > Why 10? Cyril suggested that in PR, where he suggested to use separated
> > variables:
> > https://github.com/linux-test-project/ltp/issues/891#issuecomment-989712350

> > But for string used like array there is no performance limitation, thus I'd use
> > something like 50 or 100. Because for certain IMA tests there are at least 6
> > kconfig requirements, thus>  10 could be hit.
> If case needs more than 10 kconfigs, we can use & ie
> "CONFIG_EX4_FS & CONFIG_XFS_FS & CONFIG_QUOTAL_FS, CONFIG_PROC_FS..."
Sure. I just meant there is no reason to put low number and then workaround it.

> >> --- a/testcases/lib/tst_test.sh
> >> +	tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 $kconfig6\
> >> +			$kconfig7 $kconfig8 $kconfig9 $kconfig10
> >> +	if [ $? -ne 0 ]; then
> >> +		if [ $TST_TCONF_IF_KCONFIG -eq 1 ]; then
> >> +			tst_brk TCONF "kconfig not available"

> >> +		else
> >> +			tst_res TWARN "kconfig not available"
> > This is quite strong: either test "fails" due TWARN non-zero exit code or it's
> > skipped. I'd prefer to have user variable for systems which are properly
> > configured (user will make sure all kconfig options are set), but it's just
> > missing kconfig due system configuration.
> I plan to fix the variable usage for non-found kconfig path/file instead 
> of kconfig list.

> Best Regards
> Yang Xu

Kind regards,
Petr
Yang Xu \(Fujitsu\) Jan. 6, 2022, 5:59 a.m. UTC | #4
Hi Petr
> Hi Xu,
>
>>>> +'$TST_NEEDS_KCONFIGS'.
>>>> +Optional '$TST_NEEDS_KCONFIG_IFS' is used for splitting, default value is comma.
>>>> +Optional '$TST_TCONF_IF_KCONFIG' is used for deciding how to exit the test if kernel
>>>> +.config doesn't meet test's requirement, default value is 1(TCONF). Otherwise, just
>>> I wonder if we need TST_TCONF_IF_KCONFIG functionality in the test or if it's an
>>> user request (i.e. user like variable LTP_TCONF_IF_KCONFIG doc/user-guide.txt).
>>> Because I'm not sure whether test would need it, but I can imagine user want to
>>> have test running even kernel config is not available (e.g. embedded platforms).
>>> Or maybe we need both user variable and test variable.
>> Oh, I misunderstand the usage.
>
>> I should use TST_TCONF_IF_KCONFIG for non-found kconfig file instead of
>> non-found kconfig list.
>
>> I think one variable is enough.
>
> OK, but I'd like to know others' opinion what's needed.
> Cyril, Li?
>
>>> Also not sure about TST_TCONF_IF_KCONFIG name, IMHO "IF" should be replaced to
>>> something which describes what it does.
>> Thinking a good name isn't a easy thing.
>
>> how about TCONF_IF_NO_KCONFIG?
>
> Well, I was not sure about "IF" part. For use in test code it should have "TST_"
> prefix, for users to set it should have "LTP_" prefix.
When I write this v2 patch, I think we may introuce a 
LTP_KCONFIG_DISABLE macro that can disable kconfig parser function whole 
for the situation that some embedded platforms doesn't have config. So 
we don't need to distinguish whether kconfig file doesn't exist or perms 
leak or invalid config expression.

code may below
static int tst_kconfig_disable()
{
         static int check;

         if (check)
                 return check - 1;

         char *env = getenv("LTP_KCONFIG_DISABLE");

         if (env) {
                 if (!strcmp(env, "n") || !strcmp(env, "0"))
                         check = 1;
                 if (!strcmp(env, "y") || !strcmp(env, "1"))
                         check = 2;
                 return check - 1;
         }

         check = 1;
         return 0;
}

...
int tst_kconfig_check(const char *const kconfigs[])
{
         size_t expr_cnt = array_len(kconfigs);
         struct tst_expr *exprs[expr_cnt];
         unsigned int i, var_cnt;
         int ret = 0;

	if (tst_kconfig_disable())
		return 0
	...
}

Also, this macro is easy to understand and we don't need macro ie 
CONF_IF_NO_KCONFIG or TWARN_NO_IF_KCONFIG. Any idea?

Best Regards
Yang Xu
>
>>> Also this patchset is about syncing C API functionality with shell API. But you
>>> introduce TST_TCONF_IF_KCONFIG only for shell. Shouldn't it be functionality for
>>> both parts?
>> Yes, code maybe as below:
>
>> void tst_kconfig_read(struct tst_kconfig_var vars[], size_t vars_len)
>> +static char kconfig_flag;
>> +
>> +int tst_kconfig_read(struct tst_kconfig_var vars[], size_t vars_len)
>>    {
>>           char line[128];
>>           unsigned int vars_found = 0;
>> +       const char *flag = getenv("TWARN_IF_NO_KCONFIG");
>> +
>> +       if (flag&&  !strcmp(flag,"y"))
>> +               kconfig_flag = 'y';
>
>>           FILE *fp = open_kconfig();
>> -       if (!fp)
>> +       if (!fp) {
>> +               if (kconfig_flag == 'y') {
>> +                       tst_res(TWARN, "Cannot parse kernel .config");
>> +                       return 1;
>> +               }
>>                   tst_brk(TBROK, "Cannot parse kernel .config");
>> -
>> +       }
>>           while (fgets(line, sizeof(line), fp)) {
>>                   if (kconfig_parse_line(line, vars, vars_len))
>>                           vars_found++;
>> @@ -198,6 +210,7 @@ void tst_kconfig_read(struct tst_kconfig_var vars[],
>> size_t vars_len)
>
>>    exit:
>>           close_kconfig(fp);
>> +       return 0;
>>    }
>
> Sure, once we agree what should be implemented.
>
>>    static size_t array_len(const char *const kconfigs[])
>> @@ -504,7 +517,9 @@ int tst_kconfig_check(const char *const kconfigs[])
>
>>           var_cnt = populate_vars(exprs, expr_cnt, vars);
>
>> -       tst_kconfig_read(vars, var_cnt);
>> +       ret = tst_kconfig_read(vars, var_cnt);
>> +       if (ret)
>> +               return kconfig_flag == 'y' ? 0 : 1;
>
>
>
>
>>> More notes about this variable also below.
>
>>> BTW github actions have probably kernel config on expected place, which means
>>> that most of the new tests TCONF, but tst_check_kconfig05.sh TFAIL.
>> I guess we can export the  KCONFIG_PATH to solve this problem. But I
>> don't know the expected place on github actions.
>
> Sure, for github we can find config place.
> But this can happen to user who runs the test. IMHO test should not fail if
> user's system is without config. That's why I'd like to have a variable making
> errors non-fatal.
>
>>> tst_rhost_run 1 TCONF: veth(null)      0  TWARN  :  /__w/ltp/ltp/lib/tst_kernel.c:110: expected file /lib/modules/5.11.0-1022-azure/modules.dep does not exist or not a file
>>> 320
>>> (null)      0  TWARN  :  /__w/ltp/ltp/lib/tst_kernel.c:110: expected file /lib/modules/5.11.0-1022-azure/modules.builtin does not exist or not a file driver not available
>
>>>> +use TWRAN and continue to run test.
>>>> +
>>>> +Now, we support the length of kconfig list is 10.
>>> Why 10? Cyril suggested that in PR, where he suggested to use separated
>>> variables:
>>> https://github.com/linux-test-project/ltp/issues/891#issuecomment-989712350
>
>>> But for string used like array there is no performance limitation, thus I'd use
>>> something like 50 or 100. Because for certain IMA tests there are at least 6
>>> kconfig requirements, thus>   10 could be hit.
>> If case needs more than 10 kconfigs, we can use&  ie
>> "CONFIG_EX4_FS&  CONFIG_XFS_FS&  CONFIG_QUOTAL_FS, CONFIG_PROC_FS..."
> Sure. I just meant there is no reason to put low number and then workaround it.
>
>>>> --- a/testcases/lib/tst_test.sh
>>>> +	tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 $kconfig6\
>>>> +			$kconfig7 $kconfig8 $kconfig9 $kconfig10
>>>> +	if [ $? -ne 0 ]; then
>>>> +		if [ $TST_TCONF_IF_KCONFIG -eq 1 ]; then
>>>> +			tst_brk TCONF "kconfig not available"
>
>>>> +		else
>>>> +			tst_res TWARN "kconfig not available"
>>> This is quite strong: either test "fails" due TWARN non-zero exit code or it's
>>> skipped. I'd prefer to have user variable for systems which are properly
>>> configured (user will make sure all kconfig options are set), but it's just
>>> missing kconfig due system configuration.
>> I plan to fix the variable usage for non-found kconfig path/file instead
>> of kconfig list.
>
>> Best Regards
>> Yang Xu
>
> Kind regards,
> Petr
Yang Xu \(Fujitsu\) Jan. 6, 2022, 8:16 a.m. UTC | #5
Hi Petr

>>>>> +
>>>>> +Now, we support the length of kconfig list is 10.
>>>> Why 10? Cyril suggested that in PR, where he suggested to use separated
>>>> variables:
>>>> https://github.com/linux-test-project/ltp/issues/891#issuecomment-989712350
>>
>>>> But for string used like array there is no performance limitation, thus I'd use
>>>> something like 50 or 100. Because for certain IMA tests there are at least 6
>>>> kconfig requirements, thus>    10 could be hit.
>>> If case needs more than 10 kconfigs, we can use&   ie
>>> "CONFIG_EX4_FS&   CONFIG_XFS_FS&   CONFIG_QUOTAL_FS, CONFIG_PROC_FS..."
>> Sure. I just meant there is no reason to put low number and then workaround it.
 From my understanding, we split kconfig list for kconfig1,2... variables.

Then I need to call tst_check_kconfigs with pass fixed number paremeters 
one ie 10). code ie
tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 
$kconfig6\
$kconfig7 $kconfig8 $kconfig9 $kconfig10

So do you have simple code to replace them or you just want to increase 
the number to 20?

ps: In fact, I am not good at writting shell script. So if wrong or have 
better way, please tell me.

Best Regards
Yang Xu

>
diff mbox series

Patch

diff --git a/doc/shell-test-api.txt b/doc/shell-test-api.txt
index b993a9e1e..c742fff39 100644
--- a/doc/shell-test-api.txt
+++ b/doc/shell-test-api.txt
@@ -193,22 +193,23 @@  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_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 +743,27 @@  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_KCONFIG_IFS' is used for splitting, default value is comma.
+Optional '$TST_TCONF_IF_KCONFIG' is used for deciding how to exit the test if kernel
+.config doesn't meet test's requirement, default value is 1(TCONF). Otherwise, just
+use TWRAN and continue to run test.
+
+Now, we support the length of kconfig list is 10.
+
+-------------------------------------------------------------------------------
+#!/bin/sh
+TST_NEEDS_KCONFIGS="CONFIG_FS_EXT4 , CONFIG_QUOTACTL=y"
+TST_NEEDS_KCONFIG_IFS=","
+TST_TCONF_IF_KCONFIG=1
+
+. tst_test.sh
+-------------------------------------------------------------------------------
diff --git a/lib/newlib_tests/runtest.sh b/lib/newlib_tests/runtest.sh
index 8b2fe347a..1fb9e7f21 100755
--- a/lib/newlib_tests/runtest.sh
+++ b/lib/newlib_tests/runtest.sh
@@ -6,7 +6,9 @@  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-5].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..dc09b6092
--- /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) 2021 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 "Kconfig api 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..d79f96ff2
--- /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) 2021 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..c70f378f8
--- /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) 2021 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..42b07d287
--- /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) 2021 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_KCONFIG_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..6e5d5368b
--- /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) 2021 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 "kerenl .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/lib/newlib_tests/shell/tst_check_kconfig06.sh b/lib/newlib_tests/shell/tst_check_kconfig06.sh
new file mode 100755
index 000000000..6a6d68fd7
--- /dev/null
+++ b/lib/newlib_tests/shell/tst_check_kconfig06.sh
@@ -0,0 +1,17 @@ 
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2021 FUJITSU LIMITED. All rights reserved.
+
+TST_TESTFUNC=do_test
+TST_NEEDS_CMDS="tst_check_kconfigs"
+TST_NEEDS_KCONFIGS="CONFIG_EXT4"
+TST_TCONF_IF_KCONFIG=0
+
+. tst_test.sh
+
+do_test()
+{
+	tst_res TPASS "Kernel .config doesn't have CONFIG_EXT4!"
+}
+
+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..0e40cc7e3 100644
--- a/testcases/lib/Makefile
+++ b/testcases/lib/Makefile
@@ -11,6 +11,6 @@  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..fda322746
--- /dev/null
+++ b/testcases/lib/tst_check_kconfigs.c
@@ -0,0 +1,17 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (c) 2021 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..c8134692e 100644
--- a/testcases/lib/tst_test.sh
+++ b/testcases/lib/tst_test.sh
@@ -412,6 +412,41 @@  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_KCONFIG_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_KCONFIG_IFS" -f$kconfig_i)'"
+	done
+
+	tst_check_kconfigs $kconfig1 $kconfig2 $kconfig3 $kconfig4 $kconfig5 $kconfig6\
+			$kconfig7 $kconfig8 $kconfig9 $kconfig10
+	if [ $? -ne 0 ]; then
+		if [ $TST_TCONF_IF_KCONFIG -eq 1 ]; then
+			tst_brk TCONF "kconfig not available"
+		else
+			tst_res TWARN "kconfig not available"
+		fi
+	fi
+
+	return 0
+}
+
 tst_is_int()
 {
 	[ "$1" -eq "$1" ] 2>/dev/null
@@ -586,6 +621,7 @@  tst_run()
 			OPTS|USAGE|PARSE_ARGS|POS_ARGS);;
 			NEEDS_ROOT|NEEDS_TMPDIR|TMPDIR|NEEDS_DEVICE|DEVICE);;
 			NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);;
+			NEEDS_KCONFIGS|NEEDS_KCONFIG_IFS|TCONF_IF_KCONFIG);;
 			NEEDS_DRIVERS|FS_TYPE|MNTPOINT|MNT_PARAMS);;
 			IPV6|IPV6_FLAG|IPVER|TEST_DATA|TEST_DATA_IFS);;
 			RETRY_FUNC|RETRY_FN_EXP_BACKOFF|TIMEOUT);;
@@ -626,6 +662,7 @@  tst_run()
 	[ "$TST_DISABLE_APPARMOR" = 1 ] && tst_disable_apparmor
 	[ "$TST_DISABLE_SELINUX" = 1 ] && tst_disable_selinux
 
+	tst_require_kconfigs $TST_NEEDS_KCONFIGS
 	tst_require_cmds $TST_NEEDS_CMDS
 	tst_require_drivers $TST_NEEDS_DRIVERS
 
@@ -748,6 +785,10 @@  if [ -z "$TST_NO_DEFAULT_RUN" ]; then
 
 	TST_TEST_DATA_IFS="${TST_TEST_DATA_IFS:- }"
 
+	TST_NEEDS_KCONFIG_IFS="${TST_NEEDS_KCONFIG_IFS:-,}"
+
+	TST_TCONF_IF_KCONFIG="${TST_TCONF_IF_KCONFIG:-1}"
+
 	if [ -n "$TST_CNT" ]; then
 		if ! tst_is_int "$TST_CNT"; then
 			tst_brk TBROK "TST_CNT must be integer"