tbot.machine

Machines are tbot’s abstraction over the different computers it can interact with. This includes the machine it is running on (LocalLabHost), the lab-host (LabHost), the device-under-test, as U-Boot (UBootMachine) and as Linux (LinuxMachine). Machines are composed of three different parts:

  1. The Connector which is responsible for establishing a connection to the machine. This can happen in many different ways, for example using Paramiko, by opening a serial-console, etc…

  2. Optionally, any number of Initializer s. These can, step by step, setup the channel into a state until the shell appears. Examples would be the UBootAutobootIntercept (catch the autoboot prompt and press a key) or the LinuxBootLogin (wait for the login prompt and then enter username & password).

  3. The Shell which defines how a testcase can interact with this machine. Typically this is an interface of methods for running commands.

Composition is done using multiple-inheritance, like this:

from tbot.machine import connector, linux

class MyLabHost(
    # The connector:
    connector.ParamikoConnector,

    # - No initializers here -

    # The shell:
    linux.Bash,
):
    # Options for the paramiko connector:
    hostname = "78.79.32.85"
    username = "tbot-user"

    # We can override anything we like to customize it
    @property
    def workdir(self):
        return linux.Workdir.static(self, "/opt/tbot-{self.username}")

Machines are used as context-managers. This means you will later on instantiate the above machine like this (if you were to hardcode the machine. You should probably use tbot’s Configuration mechanism instead):

@tbot.testcase
def footest():
    with MyLabHost() as lh:
        # Run a command:
        lh.exec0("uname", "-a")

For more information about the individual parts of a machine, take a look at tbot.machine.connector, tbot.machine.Initializer, and tbot.machine.shell. Specifically for interacting with Linux machines, you should head over to Linux Shells.

Base-Class

class tbot.machine.Machine[source]

Bases: ABC

Base class for all machines.

This class contains the necessary code to compose the different parts of a machine into a usable class. You won’t need to use it directly in most cases as Connector and Shell both inherit from it.

ch: Channel

Channel to communicate with this machine.

Warning

Please refrain from interacting with the channel directly. Instead, write a Shell that wraps around the channel interaction. That way, the state of the channel is only managed in a single place and you won’t have to deal with nasty bugs when multiple parties make assumptions about the state of the channel.

property name: str

Name of this machine.

By default, the name is derived from the class-name but you might want to customize it.

init() None[source]

An optional hook that allows running some code after the machine is initialized.

Example:

class FooUBoot(board.Connector, board.UBootShell):
    name = "foo-u-boot"
    prompt = "=> "

    def init(self):
        self.env("autoload", "no")
        self.exec0("dhcp")

        self.env("serverip", "192.168.1.2")

Initializers

class tbot.machine.Initializer[source]

Bases: Machine

Base-class for machine initializers.

abstract _init_machine() AbstractContextManager[source]

Run this initializer.

Implementations of this method can make use of self.ch as they will run after the connector has succeeded.

Todo

More docs for this …

ch: Channel

Channel to communicate with this machine.

Warning

Please refrain from interacting with the channel directly. Instead, write a Shell that wraps around the channel interaction. That way, the state of the channel is only managed in a single place and you won’t have to deal with nasty bugs when multiple parties make assumptions about the state of the channel.

class tbot.machine.PreConnectInitializer[source]

Bases: Machine

Base-class for pre-connection initializer context.

This initializer is run before connecting to the machine, before tbot.machine.Initializer._init_machine()

abstract _init_pre_connect() AbstractContextManager[source]

Pre-connection initialization context.

ch: Channel

Channel to communicate with this machine.

Warning

Please refrain from interacting with the channel directly. Instead, write a Shell that wraps around the channel interaction. That way, the state of the channel is only managed in a single place and you won’t have to deal with nasty bugs when multiple parties make assumptions about the state of the channel.

class tbot.machine.PostShellInitializer[source]

Bases: Machine

Base-class for post-shell initializer context.

This initializer is run after tbot.machine.Initializer._init_machine() and after the shell has been initialized.

ch: Channel

Channel to communicate with this machine.

Warning

Please refrain from interacting with the channel directly. Instead, write a Shell that wraps around the channel interaction. That way, the state of the channel is only managed in a single place and you won’t have to deal with nasty bugs when multiple parties make assumptions about the state of the channel.

abstract _init_post_shell() AbstractContextManager[source]

Post-shell initialization context.