Skip to content

utest: re-org utest framework (initial version) #10534

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

unicornx
Copy link
Contributor

具体需求来源参考:#10513

本 PR 是本工作的第一步,主要做了如下工作:

将 utest 的 Kconfig 的入口从 examples/utest/testcases/Kconfig 改为 components/utilities/utest/Kconfig。单元测试对于内核来说是一个非常重要的模块,放在 examples 下不合适。

以后的 utest 的 testcase 源码会分别放到各个模块下自己维护,但是 Kconfig 的入口会放在 components/utilities/utest/Kconfig 中统一维护。这样在执行诸如 menuconfig 时可以统一从一个地方进入进行配置,避免在 menuconfig 界面中到处寻找 utest 的配置开关。

对于各个模块来说,以后可以按照如下方式统一维护单元测试用例:

  • 在自己的模块所在目录下新建一个名为 utest 的子目录
  • 在 utest 子目录中存放以下文件:
    • 本模块的单元测试用例程序代码 c 文件。
    • Kconfig 文件,为本模块的单元测试文件增加配置选项,推荐选项命名为 RT_UTEST_TC_USING_XXXX,XXXX 为本模块的全局唯一模块名。
    • SConscript 文件,注意在增加 src 文件时,除了依赖于 RT_UTEST_TC_USING_XXXX 还要依赖 RT_UTEST_USING_ALL_CASES,两者是 or 的关系。RT_UTEST_USING_ALL_CASES 的作用是一旦打开这个选项,则所有的单元测试都会启用,避免逐个选择。

目前整个内核源码树下基于 utest 框架实现的单元测试,除了 examples/utest/testcases 外,只有 components/drivers/audio/utest/src/klibc/utest/ 两处,本 PR 将这两处的 Kconfig 选项也集成到 components/utilities/utest/Kconfig 下。

注意:本 PR 并没有将 examples/utest/testcases 下的 c 源码挪到他们该属于的模块下去,这部分工作将作为后续工作逐渐展开。

本 PR 为方便 review,分为三个 commit:

  • ”utest: move entry from examples to utest“:将 utest 的 Kconfig 的入口从 examples/utest/testcases/Kconfig 改为 components/utilities/utest/Kconfig
  • ”utest: integrate config option for utest of klibc“:将 src/klibc/utest/ 的 Kconfig 选项也集成到 components/utilities/utest/Kconfig 下。
  • ”utest: integrate config option for utest of audio driver“: 将 components/drivers/audio/utest/ 的 Kconfig 选项也集成到 components/utilities/utest/Kconfig 下。

@unicornx
Copy link
Contributor Author

@Yaochenger @kurisaW 请 review。

@unicornx unicornx requested a review from kurisaW July 24, 2025 09:40
Copy link

github-actions bot commented Jul 24, 2025

📌 Code Review Assignment

🏷️ Tag: components

Reviewers: Maihuanyi

Changed Files (Click to expand)
  • components/drivers/audio/Kconfig
  • components/drivers/audio/utest/Kconfig
  • components/utilities/utest/Kconfig

🏷️ Tag: kernel

Reviewers: GorrayLi ReviewSun hamburger-os lianux-mm wdfk-prog xu18838022837

Changed Files (Click to expand)
  • src/klibc/Kconfig
  • src/klibc/utest/Kconfig

📊 Current Review Status (Last Updated: 2025-07-25 15:35 CST)

  • GorrayLi Pending Review
  • Maihuanyi Pending Review
  • ReviewSun Pending Review
  • hamburger-os Pending Review
  • lianux-mm Pending Review
  • wdfk-prog Pending Review
  • xu18838022837 Pending Review

📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

@kurisaW kurisaW requested a review from mysterywolf July 24, 2025 09:43
@kurisaW
Copy link
Member

kurisaW commented Jul 24, 2025

如果不支持相对路径的写法的话,建议可以使用环境变量,例如类似:

rsource "$RTT_DIR/examples/utest/testcases/utest/Kconfig"
image

@unicornx unicornx force-pushed the dev-utest-framework branch from a15c073 to 84bad87 Compare July 24, 2025 12:32
@unicornx
Copy link
Contributor Author

如果不支持相对路径的写法的话,建议可以使用环境变量,例如类似:

rsource "$RTT_DIR/examples/utest/testcases/utest/Kconfig"

改了,但是 ci 又报了其他的错误 :(

@Yaochenger
Copy link
Contributor

修改建议:
举例:原来的实现:

rsource "$RTT_DIR/examples/utest/testcases/utest/Kconfig"

建议修改为:

source "$(RTT_DIR)/examples/utest/testcases/utest/Kconfig"

rsource "$RTT_DIR替换为source "$(RTT_DIR)
使用当前提交的分支在本地menuconfig出现CI同样问题,修改后可正常使用。

@unicornx
Copy link
Contributor Author

修改建议: 举例:原来的实现:

rsource "$RTT_DIR/examples/utest/testcases/utest/Kconfig"

建议修改为:

source "$(RTT_DIR)/examples/utest/testcases/utest/Kconfig"

rsource "$RTT_DIR替换为source "$(RTT_DIR) 使用当前提交的分支在本地menuconfig出现CI同样问题,修改后可正常使用。

改了又出现原先最初的错误:
da505485536ad54abc5dc68fe2d4d8c
是不是 github 上运行时的 kconfiglib 的版本不一样啊?
我这里本地是 Version: 14.1.0

@unicornx unicornx closed this Jul 25, 2025
@unicornx unicornx force-pushed the dev-utest-framework branch from 7be5936 to d23006e Compare July 25, 2025 02:58
@unicornx unicornx reopened this Jul 25, 2025
@unicornx unicornx force-pushed the dev-utest-framework branch 2 times, most recently from 9a92ff8 to 1d38849 Compare July 25, 2025 06:31
unicornx added 3 commits July 25, 2025 15:25
Change the entry of utest's Kconfig from
examples/utest/testcases/Kconfig to
components/utilities/utest/Kconfig.

In the future, the testcase source code of
utest will be placed in each module for
maintenance, but the entry of Kconfig will all
be placed in components/utilities/utest/Kconfig
for unified maintenance. In this way, when
executing menuconfig, people can enter and
configure from one place, avoiding searching
for utest configuration switches here and
ther in the menuconfig interface.

For each module, you can maintain unit-test
in a unified manner in the following way:
- Create a subdirectory named 'utest' in the
  directory where your module is located.
- Store the following files in the utest subdirectory:
  - Unit test case program source code files for this
    module.
  - Kconfig file, add configuration options for the
    unit test files of this module, the recommended
    option is named RT_UTEST_TC_USING_XXXX, XXXX is the
    global unique module name of this module.
  - SConscript file, note that when adding src files,
    in addition to relying on RT_UTEST_TC_USING_XXXX,
    you must also rely on RT_UTEST_USING_ALL_CASES, the
    two dependencies are in an "or" relationship. The
    role of RT_UTEST_USING_ALL_CASES is that once this
    option is turned on, all unit tests will be enabled
    to avoid selecting one by one.

Signed-off-by: Chen Wang <[email protected]>
@unicornx unicornx force-pushed the dev-utest-framework branch from 1d38849 to 92aa975 Compare July 25, 2025 07:35
@unicornx
Copy link
Contributor Author

unicornx commented Jul 25, 2025

我发现导致 dist 的 ci 失败的原因是在于运行 scons --dist 时会执行 MkDist,并触发 tools/mkdist.py 中的 bsp_update_kconfig_testcases 函数,这个函数的代码如下:

def bsp_update_kconfig_testcases(dist_dir):
    # delete testcases in rt-thread/Kconfig
    if not os.path.isfile(os.path.join(dist_dir, 'rt-thread/Kconfig')):
        return

    with open(os.path.join(dist_dir, 'rt-thread/Kconfig'), 'r') as f:
        data = f.readlines()
    with open(os.path.join(dist_dir, 'rt-thread/Kconfig'), 'w') as f:
        for line in data:
            if line.find('examples/utest/testcases/Kconfig') == -1:
                f.write(line)

会跳过 'examples/utest/testcases/Kconfig 这一行生成 dist/project 中的 Kconfig 文件。这个 PR 的 ci check 失败就是因为,我们改了 Kconfig 中的 rsource 的文件路径,导致 bsp_update_kconfig_testcases 不起效果(仍然 rsource 了一个 example 下的 Kconfig),而 dist 后的 dist/project/rt-thread/ 去掉了 example 目录。 导致 ci check 运行 Project dist Tools 检查时发现路径不存在。解决方法是,这里的 'examples/utest/testcases/Kconfig 换成本 PR 中 Kconfig 里的 "components/utilities/utest/Kconfig" 即可。
P.S. 这个问题其实本地运行 dist 也会看到,和 ci 环境没有关系, 复现步骤如下。

cd bsp/stm32/stm32f407-atk-explorer/
scons --dist
cd dist/project/rt-thread/
scons --menuconfig
scons: Reading SConscript files ...
menuconfig: rt-thread/components/utilities/utest/Kconfig:10: 'rt-thread/components/utilities/utest/../../../examples/utest/testcases/utest/Kconfig' not found (in 'rsource "../../../examples/utest/testcases/utest/Kconfig"'). Check that environment variables are set correctly (e.g. $srctree, which is unset or blank). Also note that unset environment variables expand to the empty string.

但具体原因不知道是否有人可以解释一下, dist 中这里这么做的目的是什么,我发现在 dist 后的 dist/project/rt-thread/ 去掉了 example 目录,而 utest 的那些 utestcase 全部是在 example 下,我猜测这是原来代码中要去掉 rsource "examples/utest/testcases/Kconfig" 的原因。

这实际上存在一个悖论,就是以后 utest 的内容我们在 dist 中是否需要保留?因为以后的设计思路是 utest 的 testcase 都会放到各个模块自己的目录下,不像现在都是放在 example 的 utest 下,所以我不清楚当时设计 dist 时是怎么考虑这个问题的。如果沿袭原来的思路,utest 的testcase 是不参与 dist 的,但是按照我现在的思路,utest 作为每个模块的组成部分,和 example 不是一回事情。dist 时我理解是需要和模块一起打包的。

此外,我发现和 bsp_update_kconfig_testcases 类似的处理还有一处,就是 tools/env_utility.py 中的 exclude_utestcases 函数。摘录如下:

# Exclude utestcases
def exclude_utestcases(RTT_ROOT):
    if os.path.isfile(os.path.join(RTT_ROOT, 'examples/utest/testcases/Kconfig')):
        return

    if not os.path.isfile(os.path.join(RTT_ROOT, 'Kconfig')):
        return

    with open(os.path.join(RTT_ROOT, 'Kconfig'), 'r') as f:
        data = f.readlines()
    with open(os.path.join(RTT_ROOT, 'Kconfig'), 'w') as f:
        for line in data:
            if line.find('examples/utest/testcases/Kconfig') == -1:
                f.write(line)

这里也有类似的逻辑,搜索 exclude_utestcases 的调用处,分别是在 tools/env_utility.py 中的 menuconfig/guiconfig/defconfig 三处,目前还不清楚这里是何目的?

@kurisaW
Copy link
Member

kurisaW commented Jul 25, 2025

我个人猜测example原本的目的是不应该参与构建的(除了utest目录,其余似乎看起来都没有加构建脚本),仅作为一个参考设计,因此在dist中会被排除构建,所以起初utest被放到example中就是不合理的,建议直接放到如下路径,后面再慢慢推动utest的分布式构建:

components/utilities/utest

另外针对你的解决方法,我持赞同意见:

解决方法是,这里的 'examples/utest/testcases/Kconfig 换成本 PR 中 Kconfig 里的 "components/utilities/utest/Kconfig" 即可。

@unicornx unicornx marked this pull request as draft July 25, 2025 08:29
@unicornx unicornx marked this pull request as ready for review July 25, 2025 08:30
@unicornx unicornx marked this pull request as draft July 25, 2025 08:31
@Rbb666
Copy link
Member

Rbb666 commented Jul 30, 2025

我个人猜测example原本的目的是不应该参与构建的(除了utest目录,其余似乎看起来都没有加构建脚本),仅作为一个参考设计,因此在dist中会被排除构建,所以起初utest被放到example中就是不合理的,建议直接放到如下路径,后面再慢慢推动utest的分布式构建:

components/utilities/utest

另外针对你的解决方法,我持赞同意见:

解决方法是,这里的 'examples/utest/testcases/Kconfig 换成本 PR 中 Kconfig 里的 "components/utilities/utest/Kconfig" 即可。

我也同意这种改法,将example中的部分逐渐分布到各个目录下面,dist出的工程也可也保留测试用例内容

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants