def selftest_tc_git_bisect(lab: typing.Optional[selftest.SelftestHost] = None) -> None: """Test the git-bisect testcase.""" with lab or selftest.SelftestHost() as lh: remote = git_prepare(lh) target = lh.workdir / "selftest-git-bisect" if target.exists(): lh.exec0("rm", "-rf", target) repo = git.GitRepository(target, remote) good = git_increment_commits(repo) @tbot.testcase def check_counter(repo: git.GitRepository) -> bool: result = repo.host.exec("cat", repo / "counter.txt") return result[0] == 0 and int(result[1].strip()) < 17 head = repo.symbolic_head bad = repo.bisect(good=good, test=check_counter) tbot.log.message(f"Bad commit is {bad}!") repo.git0("show", bad, linux.Pipe, "cat") new_head = repo.symbolic_head assert ( new_head == head ), f"Bisect didn't clean up ... ({new_head!r} != {head!r})" lh.exec0("rm", "-rf", target)
def selftest_path_integrity( lab: typing.Optional[selftest.SelftestHost] = None) -> None: """Test if using a path on the wrong host fails.""" with lab or selftest.SelftestHost() as lh: p = lh.workdir / "folder" / "file.txt" with tbot.acquire_lab() as lh2: raised = False try: # mypy detects that this is wrong lh2.exec0("echo", p) # type: ignore except tbot.error.WrongHostError: raised = True assert raised # It is ok to clone a machine and reuse the path with lh.clone() as lh3: lh3.exec0("echo", p) lh.exec0("mkdir", "-p", p.parent) assert p.parent.is_dir() lh.exec0("uname", "-a", linux.RedirStdout(p)) assert p.is_file() lh.exec0("rm", "-r", p.parent) assert not p.exists() assert not p.parent.exists()
def selftest_tc_uboot_checkout(lab: typing.Optional[linux.Lab] = None) -> None: with lab or selftest.SelftestHost() as lh: builder = _uboot_prepare(lh) @tbot.testcase def checkout_with_host() -> None: repo = builder.checkout(host=lh) assert (repo / "Makefile").is_file(), "Makefile not found!" checkout_with_host() @tbot.testcase def checkout_with_path(clean: bool) -> None: path = lh.workdir / "selftest-uboot-clone" if path.exists(): lh.exec0("touch", path / "dirty") repo = builder.checkout(path=path, clean=clean) assert (repo / "Makefile").is_file(), "Makefile not found!" assert (not clean) == (repo / "dirty").exists(), "Cleaning failed!" tbot.log.message("Calling with cleaning ...") checkout_with_path(True) tbot.log.message("Calling without cleaning ...") checkout_with_path(False)
def selftest_with_lab(lab: typing.Optional[linux.Lab] = None) -> None: """Test the tbot.with_lab decorator.""" with lab or selftest.SelftestHost() as lh: # Call without parameter selftest_decorated_lab() # Call with parameter selftest_decorated_lab(lh)
def selftest_machine_reentrant( lab: typing.Optional[selftest.SelftestHost] = None, ) -> None: """Test if a machine can be entered multiple times.""" with lab or selftest.SelftestHost() as lh: with lh as h1: assert h1.exec0("echo", "FooBar") == "FooBar\n" with lh as h2: assert h2.exec0("echo", "FooBar2") == "FooBar2\n"
def selftest_machine_ssh_shell( lab: typing.Optional[selftest.SelftestHost] = None, ) -> None: """Test an SSH shell.""" from tbot.tc.selftest import minisshd with lab or selftest.SelftestHost() as lh: if not minisshd.check_minisshd(lh): tbot.skip("dropbear is not installed so ssh can't be tested") with minisshd.minisshd(lh) as ssh: selftest_machine_shell(ssh)
def selftest_tc_git_apply( lab: typing.Optional[selftest.SelftestHost] = None) -> None: """Test applying patches.""" with lab or selftest.SelftestHost() as lh: remote = git_prepare(lh) target = lh.workdir / "selftest-git-apply" if target.exists(): lh.exec0("rm", "-rf", target) tbot.log.message("Cloning repo ...") repo = git.GitRepository(target, remote) assert (repo / "README.md").is_file() assert not (repo / "file2.md").is_file() tbot.log.message("Apply patch ...") repo.apply(lh.workdir / "selftest-git.patch") assert (repo / "file2.md").is_file() repo.add(repo / "file2.md") repo.commit("Add file2 from patch", author="tbot Selftest <none@none>") lh.exec0( "echo", """\ # File 2 A second file that will have been added by patching. ## 2.2 This section was added by a second patch""", linux.RedirStdout(repo / "file2.md"), ) repo.add(repo / "file2.md") repo.commit("Update file2", author="tbot Selftest <none@none>") patch_dir = lh.workdir / "selftest-git-patches" lh.exec0("mkdir", "-p", patch_dir) repo.git0("format-patch", "-o", patch_dir, "HEAD~2") repo.reset("HEAD~2", git.ResetMode.HARD) assert not (repo / "file2.md").is_file() tbot.log.message("Apply multiple patches ...") repo.apply(patch_dir) assert lh.test("grep", "2.2", repo / "file2.md") lh.exec0("rm", "-rf", target) lh.exec0("rm", "-rf", patch_dir)
def selftest_with_linux(lab: typing.Optional[tbot.selectable.LabHost] = None) -> None: """Test the tbot.with_linux decorator.""" with lab or selftest.SelftestHost() as lh: with SubstituteBoard(): # Call without anything selftest_decorated_linux() # Call with labhost selftest_decorated_linux(lh) # Call with Linux with tbot.acquire_board(lh) as b: with tbot.acquire_linux(b) as lnx: selftest_decorated_linux(lnx)
def selftest_with_uboot(lab: typing.Optional[tbot.selectable.LabHost] = None) -> None: """Test the tbot.with_uboot decorator.""" with lab or selftest.SelftestHost() as lh: with SubstituteBoard(): # Call without anything selftest_decorated_uboot() # Call with labhost selftest_decorated_uboot(lh) # Call with U-Boot with tbot.acquire_board(lh) as b: with tbot.acquire_uboot(b) as ub: selftest_decorated_uboot(ub)
def selftest_tc(lab: typing.Optional[selftest.SelftestHost] = None) -> None: """Run selftests for builtin testcases.""" with lab or selftest.SelftestHost() as lh: tc.testsuite( selftest_tc_git_checkout, # noqa: F405 selftest_tc_git_am, # noqa: F405 selftest_tc_git_apply, # noqa: F405 selftest_tc_git_bisect, # noqa: F405 selftest_tc_shell_copy, # noqa: F405 selftest_tc_build_toolchain, # noqa: F405 selftest_tc_uboot_checkout, # noqa: F405 selftest_tc_uboot_build, # noqa: F405 selftest_tc_uboot_patched_bisect, # noqa: F405 selftest_tc_kconfig, # noqa: F405 lab=lh, )
def selftest_machine_sshlab_shell( lab: typing.Optional[selftest.SelftestHost] = None, ) -> None: """Test an SSH LabHost shell.""" from tbot.tc.selftest import minisshd with lab or selftest.SelftestHost() as lh: if not minisshd.check_minisshd(lh): tbot.skip("dropbear is not installed so ssh can't be tested") with minisshd.minisshd(lh) as ssh: ssh.exec0("true") tbot.log.message(tbot.log.c("Testing with paramiko ...").bold) with minisshd.MiniSSHLabHostParamiko(ssh.port) as slp: selftest_machine_shell(slp) tbot.log.message(tbot.log.c("Testing with plain ssh ...").bold) with minisshd.MiniSSHLabHostSSH(ssh.port) as sls: selftest_machine_shell(sls)
def selftest_tc_git_checkout( lab: typing.Optional[selftest.SelftestHost] = None, ) -> None: """Test checking out a repository.""" with lab or selftest.SelftestHost() as lh: remote = git_prepare(lh) target = lh.workdir / "selftest-git-checkout" if target.exists(): lh.exec0("rm", "-rf", target) tbot.log.message("Cloning repo ...") repo = git.GitRepository(target, remote) assert (repo / "README.md").is_file() assert not (repo / "file2.md").is_file() tbot.log.message("Make repo dirty ...") lh.exec0("echo", "Test 123", linux.RedirStdout(repo / "file.txt")) repo = git.GitRepository(target, remote, clean=False) assert (repo / "file.txt").is_file() repo = git.GitRepository(target, remote, clean=True) assert not (repo / "file.txt").is_file() tbot.log.message("Add dirty commit ...") lh.exec0("echo", "Test 123", linux.RedirStdout(repo / "file.txt")) repo.add(repo / "file.txt") repo.commit("Add file.txt", author="tbot Selftest <none@none>") repo = git.GitRepository(target, remote, clean=False) assert (repo / "file.txt").is_file() repo = git.GitRepository(target, remote, clean=True) assert not (repo / "file.txt").is_file() lh.exec0("rm", "-rf", target)
def selftest_machine_labhost_shell( lab: typing.Optional[selftest.SelftestHost] = None, ) -> None: """Test the LabHost's shell.""" with lab or selftest.SelftestHost() as lh: selftest_machine_shell(lh)
def selftest_tc_shell_copy( lab: typing.Optional[selftest.SelftestHost] = None) -> None: """Test ``shell.copy``.""" def do_test(a: linux.Path, b: linux.Path, msg: str) -> None: if b.exists(): b.host.exec0("rm", b) a.host.exec0("echo", msg, linux.RedirStdout(a)) shell.copy(a, b) out = b.host.exec0("cat", b).strip() assert out == msg, repr(out) + " != " + repr(msg) with lab or selftest.SelftestHost() as lh: tbot.log.message("Test copying a file on the same host ...") do_test( lh.workdir / ".selftest-copy-local1", lh.workdir / ".selftest-copy-local2", "Copy locally", ) if minisshd.check_minisshd(lh): with minisshd.minisshd(lh) as ssh: tbot.log.message( "Test downloading a file from an ssh host ...") do_test( ssh.workdir / ".selftest-copy-ssh1", lh.workdir / ".selftest-copy-ssh2", "Download via SCP", ) tbot.log.message("Test uploading a file to an ssh host ...") do_test( lh.workdir / ".selftest-copy-ssh1", ssh.workdir / ".selftest-copy-ssh2", "Upload via SCP", ) if not minisshd.has_paramiko: tbot.log.warning("Skipping paramiko test.") else: with minisshd.MiniSSHLabHostParamiko(ssh.port) as slp: tbot.log.message( "Test downloading a file from a paramiko ssh host ..." ) do_test( slp.workdir / ".selftest-copy-ssh4", lh.workdir / ".selftest-copy-ssh3", "Download via SCP Lab", ) tbot.log.message( "Test uploading a file to a paramiko ssh host ...") do_test( lh.workdir / ".selftest-copy-ssh3", slp.workdir / ".selftest-copy-ssh4", "Upload via SCP Lab", ) with minisshd.MiniSSHLabHostSSH(ssh.port) as sls: tbot.log.message( "Test downloading a file from a plain ssh host ...") do_test( sls.workdir / ".selftest-copy-ssh6", lh.workdir / ".selftest-copy-ssh5", "Download via SCP Lab", ) tbot.log.message( "Test uploading a file to a plain ssh host ...") do_test( lh.workdir / ".selftest-copy-ssh5", sls.workdir / ".selftest-copy-ssh6", "Upload via SCP Lab", ) else: tbot.log.message(tbot.log.c("Skip").yellow.bold + " ssh tests.")
def selftest_path_stat( lab: typing.Optional[selftest.SelftestHost] = None) -> None: """Test path stat utilities.""" with lab or selftest.SelftestHost() as lh: tbot.log.message("Setting up test files ...") symlink = lh.workdir / "symlink" if symlink.exists(): lh.exec0("rm", symlink) lh.exec0("ln", "-s", "/proc/version", symlink) fifo = lh.workdir / "fifo" if fifo.exists(): lh.exec0("rm", fifo) lh.exec0("mkfifo", fifo) nonexistent = lh.workdir / "nonexistent" if nonexistent.exists(): lh.exec0("rm", nonexistent) # Block device block_list = (lh.exec0( *["find", "/dev", "-type", "b"], linux.Raw("2>/dev/null"), linux.OrElse, "true", ).strip().split("\n")) block_dev = None if block_list != []: block_dev = linux.Path(lh, "/dev") / block_list[0] # Existence checks tbot.log.message("Checking existence ...") assert not (lh.workdir / "nonexistent").exists() assert symlink.exists() # File mode checks tbot.log.message("Checking file modes ...") assert linux.Path(lh, "/dev").is_dir() assert linux.Path(lh, "/proc/version").is_file() assert symlink.is_symlink() if block_dev is not None: assert linux.Path(lh, block_dev).is_block_device() assert linux.Path(lh, "/dev/tty").is_char_device() assert fifo.is_fifo() # File mode nonexistence checks tbot.log.message("Checking file modes on nonexistent files ...") assert not nonexistent.is_dir() assert not nonexistent.is_file() assert not nonexistent.is_symlink() assert not nonexistent.is_block_device() assert not nonexistent.is_char_device() assert not nonexistent.is_fifo() assert not nonexistent.is_socket() stat_list = [ (linux.Path(lh, "/dev"), stat.S_ISDIR), (linux.Path(lh, "/proc/version"), stat.S_ISREG), (symlink, stat.S_ISLNK), (linux.Path(lh, "/dev/tty"), stat.S_ISCHR), (fifo, stat.S_ISFIFO), ] if block_dev is not None: stat_list.insert(3, (linux.Path(lh, block_dev), stat.S_ISBLK)) tbot.log.message("Checking stat results ...") for p, check in stat_list: assert check(p.stat().st_mode)
def selftest_tc_kconfig(lab: typing.Optional[linux.Lab] = None) -> None: """Test kconig setting.""" with lab or selftest.SelftestHost() as lh: conf = lh.workdir / "selftest-kconfig" for i in range(4): lh.exec0( "echo", """\ # tbot-selftest kconfig file # DO NOT EDIT! (Deleting is ok, though) CONFIG_FOO=y CONFIG_BAR=m # CONFIG_BAZ is not set CONFIG_STRING="a happy string" CONFIG_HEX=0xC0FFEE""", linux.RedirStdout(conf), ) if i == 0: tbot.log.message("Enabling all ...") kconfig.enable(conf, "CONFIG_FOO") kconfig.enable(conf, "CONFIG_BAR") kconfig.enable(conf, "CONFIG_BAZ") assert ( lh.exec0("grep", "-c", "-E", "CONFIG_(FOO|BAR|BAZ)=y", conf).strip() == "3" ) elif i == 1: tbot.log.message("Disabling all ...") kconfig.disable(conf, "CONFIG_FOO") kconfig.disable(conf, "CONFIG_BAR") kconfig.disable(conf, "CONFIG_BAZ") assert ( lh.exec0("grep", "-c", "-E", "# CONFIG_(FOO|BAR|BAZ)", conf).strip() == "3" ) assert ( lh.exec("grep", "-c", "-E", "^CONFIG_(FOO|BAR|BAZ)", conf)[ 1 ].strip() == "0" ) elif i == 2: tbot.log.message("Moduling all ...") kconfig.module(conf, "CONFIG_FOO") kconfig.module(conf, "CONFIG_BAR") kconfig.module(conf, "CONFIG_BAZ") assert ( lh.exec0("grep", "-c", "-E", "CONFIG_(FOO|BAR|BAZ)=m", conf).strip() == "3" ) elif i == 3: tbot.log.message("Testing values ...") kconfig.set_string_value(conf, "CONFIG_STRING", "abcdef") kconfig.set_hex_value(conf, "CONFIG_HEX", 0xDEADBEEF) assert ( lh.exec0("grep", "-c", 'CONFIG_STRING="abcdef"', conf).strip() == "1" ) assert ( lh.exec0("grep", "-c", "CONFIG_HEX=0xdeadbeef", conf).strip() == "1" )
def selftest_path_files( lab: typing.Optional[selftest.SelftestHost] = None) -> None: """Test accessing file via the Path class""" with lab or selftest.SelftestHost() as lh: f = lh.workdir / "test-file.dat" tbot.log.message("Testing text file access ...") content = "This is a test file\nwith multiple lines.\n" f.write_text(content) output = f.read_text() assert output == content, f"Sending {content!r} resulted in {output!r}" tbot.log.message("Testing binary file access ...") content_bin = b"\x00\x1b[m\x04\x01\x10" assert f.write_bytes(content_bin) == len( content_bin), "Length mismatch" output_bin = f.read_bytes() assert (output_bin == content_bin ), f"Sending {content_bin!r} resulted in {output_bin!r}" tbot.log.message("Test reading/writing invalid file ...") f = lh.workdir / "path-test.50278c53-3cfc-4983-9770-d571b29b3955" # Writing/reading a directory should always fail lh.exec0("mkdir", "-p", f) raised = False try: f.write_text("Hello World\n") except Exception: raised = True assert raised, "Writing invalid file supposedly succeeded (text mode)" raised = False try: f.read_text() except Exception: raised = True assert raised, "Reading invalid file supposedly succeeded (text mode)" raised = False try: f.write_bytes(b"Hello World\n") except Exception: raised = True assert raised, "Writing invalid file supposedly succeeded (binary mode)" raised = False try: f.read_bytes() except Exception: raised = True assert raised, "Reading invalid file supposedly succeeded (binary mode)"