Using External Files in Tests

You might want to use external libraries, binaries, or other tools depending on your use case. For instance, if your test requires a specific tool or script, you can include it in your test workflow.

This example demonstrates how to include custom tooling in a test that power-cycles a board using the latest firmware build.

Step-by-Step Guide

  1. Add the Files

Use the fwci CLI to add, update, list, and delete files. To add files:

$ fwci files add <file-name> <path-to-file>

This uploads one file under the specified file-name. The server detects the format from the file’s content and unpacks it:

You uploadResult on the server
.tar, .zip, .7zUnpacked, directory layout preserved
.tar.gz, .tar.bz2, .tar.xz, .tar.zstUnpacked, directory layout preserved
Any single file (binary, script, .bin, no extension …)Stored as the only file, original name kept

A single compressed file is not an archive. Uploading tool.gz, firmware.bin.zst or any other standalone compressed file fails. Wrap it in a tar instead: tar czf tool.tar.gz tool.

Two more things worth knowing before you pack:

  • The extension must match the content. Detection uses both, so a text file named payload.zip is rejected with zip: not a valid zip file.
  • Symlinks inside an archive are skipped, without an error. Pack the real files — e.g. tar czhf lib.tar.gz lib/ (-h follows symlinks) — or the entry will be missing at test time.

The <file-name> may contain letters, digits and underscores only (my_python_lib, not my-python-lib) and must be unique within your organization.

Listing files should now result in a representation of the uploaded files:

$ fwci files get
files list:
0.  ID: 01JC3DDYRJ81EK6PM6NHZZY0Y5
  Name: my_file_1
  File-Tree:
  └── system-suite: 7372986 bytes
1.  ID: 01JCB0MT44NYJ1933RETVHY59X
  Name: my_file_2
  File-Tree:
  └── testing-binary: 14479360 bytes

The File-Tree is what the test environment will see, so use it to check that your archive unpacked the way you expected — the paths listed here are exactly the ones you write into the paths map in the next step.

Adding more files to an existing entry

There is no incremental add. fwci files update replaces the whole entry: the current contents are deleted, then the new upload is unpacked in their place. To extend an entry, repack the old files together with the new ones and upload the result:

$ tar czf tools.tar.gz -C tools .    # old contents plus whatever you added
$ fwci files update my_python_lib tools.tar.gz

Storage items reference the entry by name, so any storage.yaml with uri: fwci://my_python_lib picks up the new contents with no change. If you also rename the entry with -n, update every storage.yaml that points at the old name.

An entry cannot be deleted while a storage item still references it — delete or re-point the storage item first.

  1. Reference the files in a storage item

After uploading a file, you can reference it within a storage item. Storage items not only link to the files but also include an optional array of commands that are executed within the testing environment.

For a comprehensive explanation, refer to the Storage Configuration documentation.

Examplary storage.yaml

# Reference Name of the storage item
name: my_python_lib
# Optional commands executed inside the testing sandbox environment
commands: 
  - "apt update"
  - "apt install pip ipmitool inetutils-ping xvfb lsb-core -y"
  - "pip install robotframework"
paths: 
  bin: bin/executable
# Prefix the <files-name> with 'fwci://'
uri: fwci://my_python_lib

Add the storage.yaml file into a subdirectory within the .firmwareci/storage directory. The file structure should resemble the following:

$ tree .firmwareci

.firmwareci/
│   ....
├── storage
│   └── my_python_lib
│       └── storage.yaml
│   ....
  1. Reference the Storage Inside a Test

Modify the boot test to add a command that executes the testing library. When storage is referenced in a test, it’s automatically included at a path in the testing environment. Access the path using the template [[storage.<storage-name>]].

First copy files from the storage path to the device, then run the library as an executable.

For a comprehensive explanation, refer to the Templating documentation.

defaults:
  transport: &transport
    proto: ssh
    options:
      host: "[[attributes.Host]]"
      user: root
      password: root

stages:
  - name: Run Golang Power Test
    steps:
      - cmd: ping
        name: Wait for SSH service
        options:
          timeout: 2m
        parameters:
          host: "[[attributes.Host]]"

      - cmd: copy
        name: Copy tooling to DUT
        transport: *transport
        parameters:
          source: "[[storage.my_python_lib]]"
          destination: /tmp/lib
          recursive: true

      - cmd: cmd
        name: Run openbmc-test-go Power Test
        transport: *transport
        options:
          timeout: 20m
        parameters:
          executable: "/tmp/lib/[[storage.my_python_lib.bin]]"
          args:
            [
              "-user",
              "root",
              "-password",
              "root",
            ]