tbot.tc
- Builtin Testcases¶
tbot come bundled with a few builtin testcases. Here is an overview:
Common¶
- tbot.tc.testsuite(*args: Callable, **kwargs: Any) None [source]¶
Run a number of tests and report how many of them succeeded.
Note
If your goal is implementing a large testsuite using tbot, you may want to look at integrating tbot with pytest instead of using this function.
Check the pytest Integration guide for more info.
- Parameters:
args – Testcases
kwargs – Named-Arguments that should be given to each testcase. Be aware that this requires all testcases to have compatible signatures.
Example:
import tbot from tbot import tc, machine @tbot.testcase def test_a(lab: machine.linux.LinuxShell) -> None: lab.exec0("echo", "Test", "A") @tbot.testcase def test_b(lab: machine.linux.LinuxShell) -> None: lab.exec0("uname", "-a") @tbot.testcase def all_tests() -> None: with tbot.acquire_lab() as lh: tc.testsuite( test_a, test_b, lab=lh, )
Shell¶
- tbot.tc.shell.copy(p1: Path[H1], p2: Path[H2]) None [source]¶
Copy a file, possibly from one host to another.
Changed in version 0.10.2: This function has been moved to
tbot.machine.linux.copy()
. Please read its documentation for more details. The old name here is a compatibility alias.
- tbot.tc.shell.check_for_tool(host: LinuxShell, tool: str, force: bool = False) bool [source]¶
Check whether a certain tool/program is installed on a host.
Results from previous invocations are cached.
Example:
if shell.check_for_tool(lh, "wget"): lh.exec0("wget", download_url, "-O", lh.workdir / "download.tgz") elif shell.check_for_tool(lh, "curl"): lh.exec0("curl", download_url, "-o", lh.workdir / "download.tgz") else: raise Exception("Need either 'wget' or 'curl'!")
- Parameters:
host (linux.LinuxShell) – The host to ceck on.
tool (str) – Name of the binary to check for.
force (bool) – Forces the check by not using the cache, default value is
False
.
- Return type:
- Returns:
True
if the tool was found andFalse
otherwise.
Changed in version 0.10.3: Added the
force
parameter.
Git¶
- class tbot.tc.git.GitRepository(target: Path[H], url: str | None = None, *, clean: bool = True, fetch: bool = True, rev: str | None = None)[source]¶
Bases:
Path
[H
]Git repository.
Initialize a git repository from either a remote or an existing repo.
There are two modes in which a repo can be initialized:
Only supplying
target
: tbot assumes, that a repo exists attarget
already and will fail if this is not the case.Also supplying
url
: Iftarget
is not already a git repo, one will be created by cloningurl
.
If
clean
isTrue
, the repo will be hard reset and all untracked files/ changes will be removed. Ifrev
is also given, it will be checked out.If
fetch
isTrue
andurl
is given, the latest upstream revision will be checked out.- Parameters:
target (linux.Path) – Where the repository is supposed to be.
url (str) – Optional remote url. Whether this is set specifies the mode the repo is initialized in.
clean (bool) – Whether to clean the working tree. Defaults to
True
.fetch (bool) – Whether to fetch remote. Defaults to
True
.rev (str) – Optional revision to checkout. Only has an effect if clean is also set. If you don’t want to clean, but still perform a checkout, call
checkout()
.
Changed in version 0.6.1:
GitRepository
now fetches latest changes from remote by default.- git(*args: str | Path[H] | Special) Tuple[int, str] [source]¶
Run a git subcommand.
Behaves like calling
git -C <path/to/repo> <*args>
.
- git0(*args: str | Path[H] | Special) str [source]¶
Run a git subcommand and ensure its retcode is zero.
Behaves like calling
git -C <path/to/repo> <*args>
.- Parameters:
args – Command line parameters. First one should be a git subcommand.
- Return type:
- Returns:
Command output
- Raises:
CommandFailedException – If the command exited with a non-zero return code
- checkout(rev: str) None [source]¶
Checkout a revision or branch.
- Parameters:
rev (str) – Revision or branch name to be checked out.
- reset(rev: str, mode: ResetMode = ResetMode.MIXED) None [source]¶
Call
git --reset
.- Parameters:
rev (str) – Revision to reset to
mode (ResetMode) – Reset mode to be used. Refer to the
git-reset
man-page for more info.
- clean(force: bool = True, untracked: bool = False, noignore: bool = False) None [source]¶
Call
git clean
.Refer to the
git-clean
man-page for more info.
- am(patch: Path[H]) int [source]¶
Apply one or multiple patches.
- Parameters:
patch (linux.Path) – Either a path to a .patch file or to a directory containing patch files.
- Return type:
- Returns:
Number of patches applied
- apply(patch: Path[H]) int [source]¶
Apply one or multiple patches to the working tree.
- Parameters:
patch (linux.Path) – Either a path to a .patch file or to a directory containing patch files.
- Return type:
- Returns:
Number of patches applied
New in version 0.6.4.
- bisect(good: str, test: Callable[[...], bool]) str [source]¶
Run a git bisect to find the commit that introduced an error.
Todo
Add back the bisect example.
- Parameters:
good (str) – A known good commit, the current head will be assumed as bad.
test – A function to check the state of the current commit. Should return
True
if it is good andFalse
if it is bad. An exception is interpreded as an unexpected error while checking.
- Return type:
- Returns:
The first bad commit
Kconfig¶
tbot has a few testcases to manipulate a kconfig-file, as used in Linux or U-Boot. These are:
- tbot.tc.kconfig.enable(conf: Path, name: str) None [source]¶
Enable a kconfig option.
Example:
kconfig.enable(repo / ".config", "CONFIG_AUTO_COMPLETE")
- Parameters:
conf (linux.Path) – Path to kconfig file (usually .config)
name (str) – Name of the option (with leading
CONFIG_
)
- tbot.tc.kconfig.module(conf: Path, name: str) None [source]¶
Set a kconfig option to be built as module.
Example:
kconfig.module(repo / ".config", "CONFIG_BLK_DEV_NVME")
- Parameters:
conf (linux.Path) – Path to kconfig file (usually .config)
name (str) – Name of the option (with leading
CONFIG_
)
- tbot.tc.kconfig.disable(conf: Path, name: str) None [source]¶
Disable a kconfig option.
Example:
kconfig.disable(repo / ".config", "CONFIG_AUTO_COMPLETE")
- Parameters:
conf (linux.Path) – Path to kconfig file (usually .config)
name (str) – Name of the option (with leading
CONFIG_
)
- tbot.tc.kconfig.set_string_value(conf: Path, name: str, value: str) None [source]¶
Set a kconfig string value.
Example:
kconfig.set_string_value(repo / ".config", "CONFIG_LOCALVERSION", "-test")
- Parameters:
conf (linux.Path) – Path to kconfig file (usually .config)
name (str) – Name of the option (with leading
CONFIG_
)value (str) – New string value
- tbot.tc.kconfig.set_hex_value(conf: Path, name: str, value: int) None [source]¶
Set a kconfig hex value.
Example:
kconfig.set_hex_value(repo / ".config", "CONFIG_SYS_BASE", 0x10000)
- Parameters:
conf (linux.Path) – Path to kconfig file (usually .config)
name (str) – Name of the option (with leading
CONFIG_
)value (int) – Integer value that should be set (will be converted to hex)
U-Boot¶
tbot has testcases to automatically build U-Boot for your board. These integrate nicely with the Configuring a board.
- tbot.tc.uboot.build(builder: UBootBuilder | None = None, *, clean: bool = True, repo: GitRepository[BH] | None = None, unpatched_repo: GitRepository[BH] | None = None, path: Path[BH] | None = None, host: BH | None = None, lab: Lab | None = None) GitRepository[BH] ¶
Build U-Boot.
There are a few ways this testcase can be called:
From the commandline as
uboot_build
or in a testcase without any arguments: tbot will use the configured build-host and builder config (seeUBootBuilder
) to attempt building U-Boot. You can use theclean
parameter to specify whether the build should reuse existing artifacts or start from scratch.Specifying just the
lab
parameter: Uselab
as the lab-host from where tbot should connect to its default build-host.Specifying just the
host
parameter: Build U-Boot onhost
.Just the
path
parameter: Checkout U-Boot topath
onpath
’s associated host (which must be a build-host).Only the
unpatched_repo
: Apply the patch step onto an already checked out revision before attempting the build.Just the
repo
parameter: Use the already checked-out revision that is assumed to already have necessary patches applied.
In any case, tbot will attempt building U-Boot and if it succeeded, the testcase will return the git repo. Depending on the way it was called, it will skip certain steps (See list above). This can be used to build eg. with a pre-configured checkout or build in a bisect-run.
You can only specify one of
repo
,unpatched_repo
,path
,host
orlab
!- Parameters:
clean (bool) – Whether the U-Boot tree should be cleand of all leftovers from previous builds.
repo (git.GitRepository) – Build from existing, checkout-out revision.
unpatched_repo (git.GitRepository) – Build from existing, checkout-out revision, but also apply patches.
path (linux.Path) – Checkout U-Boot to
path
.host (linux.BuildMachine) – Build U-Boot on this host.
lab (linux.Lab) – Build U-Boot on the default build-host of this lab.
- Return type:
- Returns:
Location of the U-Boot tree containing build artifacts
- tbot.tc.uboot.checkout(builder: UBootBuilder | None = None, *, clean: bool = True, rev: str | None = None, path: Path[H] | None = None, host: H | None = None) GitRepository[H] ¶
Just checkout and patch a version of U-Boot without attempting to build it.
This function can either be called with
path
which will make it checkout U-Boot topath
or withhost
, which will checkout U-Boot to the path defined indo_repo_path()
.Only on of
path
orhost
is allowed!
- class tbot.tc.uboot.UBootBuilder[source]¶
Bases:
ABC
U-Boot build process description.
You will usually define it in your board config like this:
class MyUBootBuilder(tbot.tc.uboot.UBootBuilder): name = "my-board" defconfig = "myboard_defconfig" toolchain = "generic-armv7a-hf"
To make tbot aware of this config, you need to tell it in your U-Boot config:
class MyUBootMachine( board.Connector, board.UBootShell, ): # Create a builder instance build = MyUBootBuilder()
If you’ve done everything correctly, calling the
uboot_checkout
oruboot_build
testcases should then checkout and build U-Boot for your board!You can also manually trigger the checkout/build of a certain builder using the
checkout()
andbuild()
methods.- remote = 'https://gitlab.denx.de/u-boot/u-boot.git'¶
Where to fetch U-Boot from.
- revision = None¶
Optionally, which revision to check out. Can be any branch, tag, or commit.
- toolchain: str | None = None¶
Name of the toolchain to be used.
Must exist on the selected build-host.
- do_repo_path(bh: H) Path[H] [source]¶
Build-Step that defines where the U-Boot build-directory is.
The default path is
$workdir/uboot-$name
. Overwrite this step to set a custom path:def do_repo_path(self, bh: linux.Builder) -> linux.Path: return bh.workdir / "projects" / "foo" / "uboot"
- Parameters:
bh (linux.Builder) – Selected build-host. The returned path must be associated with this machine.
- Return type:
- Returns:
Path to the U-Boot build directory
- do_checkout(target: Path[H], clean: bool, rev: str | None) GitRepository[H] [source]¶
Build-Step that defines how to checkout U-Boot.
Overwrite this step if you have a custom checkout procedure:
def do_checkout(self, target: linux.Path, clean: bool) -> git.GitRepository: return git.GitRepository( target=target, url=self.remote, clean=clean, rev="v2018.09", )
- Parameters:
target (linux.Path) – Where to checkout U-Boot to. This build-step must be able to deal with an already checked out U-Boot source.
clean (bool) – Whether this build-step should clean the source-dir (like
git clean -fdx
).rev (str) – Revision to check out, or None to use the current revision.
- Return type:
- Returns:
A git repo of the checked out U-Boot sources
- do_patch(repo: GitRepository[H]) None [source]¶
Build-Step to patch the checked out U-Boot tree.
If you need to apply patches ontop of upstream U-Boot, you should do so in this step:
def do_patch(self, repo: git.GitRepository) -> None: repo.am(linux.Path(repo.host, "/path/to/patches"))
- do_toolchain(bh: BH) AbstractContextManager [source]¶
Build-Step to enable the toolchain.
This step should return a context-manager for a sub-shell which has the toolchain enabled. By default this step returns
bh.enable(self.toolchain)
.
- do_configure(bh: BH, repo: GitRepository[BH]) None [source]¶
Build-Step to generate the build configuration.
By default, this steps runs
make ${self.defconfig}
.
- do_build(bh: BH, repo: GitRepository[BH]) None [source]¶
Build-Step to actually build U-Boot.
By default, this steps runs
make -j $(nproc)
.
- checkout(*, clean: bool = True, path: Path[H] | None = None, host: H | None = None) GitRepository[H] [source]¶
Just checkout and patch a version of U-Boot without attempting to build it.
- build(*, clean: bool = True, repo: GitRepository[BH] | None = None, unpatched_repo: GitRepository[BH] | None = None, path: Path[BH] | None = None, host: BH | None = None, lab: Lab | None = None) GitRepository[BH] [source]¶
Build U-Boot.
U-Boot test/py¶
tbot can also run U-Boot’s test/py when U-Boot building is properly
configured. The uboot_testpy
testcase is used for this:
- tbot.tc.uboot.testpy(lh: Lab | None, *, build_host: Builder | None = None, uboot_builder: UBootBuilder | None = None, boardenv: str | None = None, testpy_args: List[str] = []) None [source]¶
Run U-Boot’s test/py test-framework against the selected board.
Warning
This testcase has been reworked as
tbot_contrib.uboot.testpy()
. If you are writing new code, please consider using that one instead.This testcase can be called from the command-line as
uboot_testpy
.- Parameters:
build_host (tbot.machine.linux.Builder) – Optional build-host where U-Boot should be built (and in this case, where test/py will run). By default,
tbot.acquire_lab().build()
is used.uboot_builder (tbot.tc.uboot.UBootBuilder) – Optional configuration for U-Boot checkout. By default,
tbot.acquire_uboot().build
is used (exactly likeuboot_build
does).boardenv (str) – Optional contents for the
boardenv.py
file. If this option is not given,UBootBuilder.testpy_boardenv
is used (or nothing).testpy_args (list(str)) – Additional arguments to be passed to test/py. Can be used, for example, to limit which tests should be run (using
testpy_args=["-k", "sf"]
).
Example:
The following additions to a board-config make it possible to call
tbot ... -vv uboot_testpy
:from tbot.tc import uboot class DHComUBootBuilder(uboot.UBootBuilder): name = "dhcom-pdk2" defconfig = "dh_imx6_defconfig" toolchain = "imx6q" testpy_boardenv = r"""# Config for dhcom pdk2 board # A list of sections of Flash memory to be tested. env__sf_configs = ( { # Where in SPI Flash should the test operate. 'offset': 0x140000, # This value is optional. # If present, specifies if the test can write to Flash offset # If missing, defaults to False. 'writeable': True, }, ) """ class DHComUBoot(board.Connector, board.UBootShell): name = "dhcom-uboot" prompt = "=> " # Don't forget this! build = DHComUBootBuilder()
Deprecated since version 0.9.5: Use
tbot_contrib.uboot.testpy()
instead.