Guide 16. Macros with declarations

What you're going to learn

In this guide you're going to learn about the last type of macros available in Testo-lang: macros with declarations.

Preconditions

  1. Testo Framework is installed.
  2. Virt manager is installed.
  3. Host has the Internet access.
  4. Ubuntu server 16.04 image is downloaded and located here: /opt/iso/ubuntu_server_16.iso. The location may be different, but in this case the ISO_DIR command-line param has to be adjusted accordingly.
  5. Ubuntu server 20.04 image is downloaded and located here: /opt/iso/ubuntu_server_20.iso. The location may be different, but in this case the ISO_DIR command-line param has to be adjusted accordingly.
  6. Testo guest additions iso image is downloaded and located in the same folder as Ubuntu Server iso-images.
  7. (Recommended) Testo-lang syntax highlight for Sublime Text 3 is set up.
  8. (Recommended) Guide 9 is complete.

Introduction

Macros play a big role on Testo-lang. They allow you to put similar snippets of code into named blocks which you can reference later without the need to worry about their actual contents. In the 9th guide we've already got accustomed to the macros with actions and macros with commands. With macros we reduced the amount of copy-pasta in our code dramatically.

But there is one more type of macros which you need to learn to use the Test-lang capabilities to their fullest - macros with declarations. With this type of macros you can group up a bunch of tests or even whole tests benches!

What to begin with?

To grasp the concept of macros with declarations, we should go back to the 9th part of our guides (the guide which introduces macros). Let's take a look at our script we'd got at the end of the guide.

declarations.testo:

network internet {
    mode: "nat"
}

network LAN {
    mode: "internal"
}

param guest_additions_pkg "testo-guest-additions*"
param default_password "1111"

param client_hostname "client"
param client_login "client-login"

machine client {
    cpus: 1
    ram: 512Mb
    disk main: {
        size: 5Gb
    }
    iso: "${ISO_DIR}/ubuntu_server.iso"

    nic nat: {
        attached_to: "internet"
    }

    nic server_side: {
        attached_to: "LAN"
        mac: "52:54:00:00:00:AA"
    }
}

param server_hostname "server"
param server_login "server-login"

machine server {
    cpus: 1
    ram: 512Mb
    disk main: {
        size: 5Gb
    }
    iso: "${ISO_DIR}/ubuntu_server.iso"

    nic nat: {
        attached_to: "internet"
    }

    nic client_side: {
        attached_to: "LAN"
        mac: "52:54:00:00:00:BB"
    }
}

flash exchange_flash {
    fs: "ntfs"
    size: 8Mb
    folder: "./folder_to_copy"
}

macros.testo:

include "declarations.testo"

macro install_ubuntu(hostname, login, password = "${default_password}") {
    ...
}


macro install_guest_additions(hostname, login, password="${default_password}") {
    ...
}

macro unplug_nic(hostname, login, nic_name, password="${default_password}") {
    ...
}

# A macro encapsulating several actions:
# 1) Plugging a flash drive
# 2) Mounting the flash drive into the filesystem
# 3) Executing a bash script
# 4) Unmounting the flash drive from the filesystem
# 5) Unplugging the flash drive
macro process_flash(flash_name, command) {
    plug flash "${flash_name}"
    sleep 5s
    exec bash "mount /dev/sdb1 /media"
    exec bash "${command}"
    exec bash "umount /media"
    unplug flash "${flash_name}"
}

# A command macro suitable for copying a file between arbitrary vms
# Copies a file from vm to /media/filename on the flash
# Copies a file from the flash to another vm
macro copy_file_with_flash(vm_from, vm_to, copy_flash, file_from, file_to) {
    "${vm_from}" process_flash("${copy_flash}", "cp ${file_from} /media/$(basename ${file_from})")
    "${vm_to}" process_flash("${copy_flash}", "cp /media/$(basename ${file_from}) ${file_to}")
}

tests.testo:

include "macros.testo"

test server_install_ubuntu {
    server install_ubuntu("${server_hostname}", "${server_login}")
}

test server_install_guest_additions: server_install_ubuntu {
    server install_guest_additions("${server_hostname}", "${server_login}")
}

test server_unplug_nat: server_install_guest_additions {
    server unplug_nic("${server_hostname}", "${server_login}", "nat")
}

test server_prepare: server_unplug_nat {
    server {
        copyto "./rename_net.sh" "/opt/rename_net.sh"
        exec bash """
            chmod +x /opt/rename_net.sh
            /opt/rename_net.sh 52:54:00:00:00:bb client_side
            ip a a 192.168.1.1/24 dev client_side
            ip l s client_side up
            ip ad
        """
    }
}

test client_install_ubuntu {
    client install_ubuntu("${client_hostname}", "${client_login}")
}

test client_install_guest_additions: client_install_ubuntu {
    client install_guest_additions("${client_hostname}", "${client_login}")
}

test client_unplug_nat: client_install_guest_additions {
    client unplug_nic("${client_hostname}", "${client_login}", "nat")
}

test client_prepare: client_unplug_nat {
    client {
        process_flash("exchange_flash", "cp /media/rename_net.sh /opt/rename_net.sh")

        exec bash """
            chmod +x /opt/rename_net.sh
            /opt/rename_net.sh 52:54:00:00:00:aa server_side
            ip a a 192.168.1.2/24 dev server_side
            ip l s server_side up
            ip ad
        """
    }
}

test test_ping: client_prepare, server_prepare {
    client exec bash "ping 192.168.1.2 -c5"
    server exec bash "ping 192.168.1.1 -c5"
}

# Take a note, that the test is inherited not from
# the test_ping, but from the client_prepare and
# server_prepare tests.
# Which means that test_ping and exchange_files_with_flash
# both lay on the samy tests tree level
test exchange_files_with_flash: client_prepare, server_prepare {
    #Create a file to be transferred
    client exec bash "echo \"Hello from client!\" > /tmp/copy_me_to_server.txt"
    copy_file_with_flash("client", "server", "exchange_flash", "/tmp/copy_me_to_server.txt", "/tmp/copy_me_to_server.txt")
    server exec bash "cat /tmp/copy_me_to_server.txt"
}

Looks good and elegant, doesn't it? Indeed, we've come a long way in that guide: we managed to organize all the code into a good shape, minimizing the amount of copy-pasta.

But let's consider this: what if we need to check that our tests run OK not only with Ubuntu Server 16.04, but Ubuntu Server 20.04 as well? The current virtual machines have Ubuntu Server 16.04 onboard, so to test Ubuntu 20.04 we'd need another two VMs (don't forget to rename the old ones so we won't get confused). To complete the picture let's also imagine we want to connect the new VMs with a new set of networks. Finally, we'd like to use a new virtual usb stick to copy files:

declarations.testo:

param guest_additions_pkg "testo-guest-additions*"
param default_password "1111"

param client_hostname "client"
param client_login "client-login"

param server_hostname "server"
param server_login "server-login"

network internet_16 {
    mode: "nat"
}

network LAN_16 {
    mode: "internal"
}

machine client_16 {
    cpus: 1
    ram: 512Mb
    disk main: {
        size: 5Gb
    }
    iso: "${ISO_DIR}/ubuntu_server_16.iso"

    nic nat: {
        attached_to: "internet_16"
    }

    nic server_side: {
        attached_to: "LAN_16"
        mac: "52:54:00:00:00:AA"
    }
}

machine server_16 {
    cpus: 1
    ram: 512Mb
    disk main: {
        size: 5Gb
    }
    iso: "${ISO_DIR}/ubuntu_server_16.iso"

    nic nat: {
        attached_to: "internet_16"
    }

    nic client_side: {
        attached_to: "LAN_16"
        mac: "52:54:00:00:00:BB"
    }
}

flash exchange_flash_16 {
    fs: "ntfs"
    size: 8Mb
    folder: "./folder_to_copy"
}

network internet_20 {
    mode: "nat"
}

network LAN_20 {
    mode: "internal"
}

machine client_20 {
    cpus: 1
    ram: 1Gb
    disk main: {
        size: 8Gb
    }
    iso: "${ISO_DIR}/ubuntu_server_20.iso"

    nic nat: {
        attached_to: "internet_20"
    }

    nic server_side: {
        attached_to: "LAN_20"
        mac: "52:54:00:00:00:AA"
    }
}

machine server_20 {
    cpus: 1
    ram: 1Gb
    disk main: {
        size: 8Gb
    }
    iso: "${ISO_DIR}/ubuntu_server_20.iso"

    nic nat: {
        attached_to: "internet_20"
    }

    nic client_side: {
        attached_to: "LAN_20"
        mac: "52:54:00:00:00:BB"
    }
}

flash exchange_flash_20 {
    fs: "ntfs"
    size: 8Mb
    folder: "./folder_to_copy"
}

Keep in mind that we had to increase the RAM and disk memory size for Ubuntu 20 VMs. Ubuntu 20 won't work with the amount of memory specified for Ubuntu 16.

Ok, but what's up with the tests? How do we need to change them? Ideally we'd want to copy the tests for Ubuntu 16 and just change the VM names in them... But there're a couple of issues.

First, the OS installation steps for Ubuntu 16 and 20 differ quite a lot. Which means we need a new macro:

macro install_ubuntu_server_20(nat_interface, hostname, login, password = "${default_password}") {
    unplug nic "${nat_interface}"
    start
    if (check "Language" timeout 5s) {
        press Enter
        wait "Install Ubuntu Server"; press Enter
    }
    wait "Welcome!" timeout 5m; press Enter

    wait "Please select your keyboard layout"; press Enter
    wait "Configure at least one interface"; press Enter
    wait "Proxy address"; press Enter
    wait "Mirror address"; press Enter
    wait "Continue without updating"; press Enter
    wait "Use an entire disk"; press Down*5; wait js "find_text().match('Done').match_background('green').size() > 0"; press Enter
    wait "FILE SYSTEM SUMMARY"; press Enter
    wait "Confirm destructive action"; press Down, Enter
    wait "Enter the username"; type "${login}"; press Tab
    type "${hostname}"; press Tab
    type "${login}"; press Tab
    type "${password}"; press Tab
    type "${password}"; press Enter*2
    wait "SSH Setup"; press Tab, Enter
    wait "Installing system"
    wait "Installation complete!" timeout 15m
    press Enter
    wait "Please remove the installation medium"
    unplug dvd; press Enter
    wait "${hostname} login" timeout 3m

    stop; plug nic "${nat_interface}"; start

    wait "GNU GRUB"; press Enter

    wait "${hostname} login" timeout 3m
    type "${login}"; press Enter
    wait "Password"; type "${password}"; press Enter

    wait "${login}@${hostname}"
}

Let's rename the old macro into install_ubuntu_server_16 to keep things streamlined.

And now we're going to combine both installation macros into one:

macro install_ubuntu_server(version, nat_interface, hostname, login, password = "${default_password}") {
    if ("${version}" STREQUAL "16") {
        install_ubuntu_server_16("${hostname}", "${login}", "${password}")
    } else if ("${version}" STREQUAL "20") {
        install_ubuntu_server_20("${nat_interface}","${hostname}", "${login}", "${password}")
    } else {
        abort "Unknown version:  ${version}"
    }
}

So now there is just a single macro which chooses the OS installation steps based on the version argument. With that issue settled, we're moving on.

Second, the rename_net.sh wouldn't work with Ubuntu 20.04 because the newer Ubuntu doesn't have the ipconfig utility installed (by default). We can solve this issue with a new script rename_net_20.sh using the ip utility:

#!/bin/bash

set -e

mac=$1

oldname=`ip -o link | grep ${mac,,} | awk '{print substr($2, 1, length($2) - 1)}'`
newname=$2

echo SUBSYSTEM==\"net\", ACTION==\"add\", ATTR{address}==\"$mac\", NAME=\"$newname\", DRIVERS==\"?*\" >> /lib/udev/rules.d/70-test-tools.rules

rm -f /etc/network/interfaces
echo source /etc/network/interfaces.d/* >> /etc/network/interfaces
echo auto lo >> /etc/network/interfaces
echo iface lo inet loopback >> /etc/network/interfaces

ip link set $oldname down
ip link set $oldname name $newname
ip link set $newname up

echo "Renaming success"

And again, we're going to rename the rename_net.sh script into rename_net_16.sh to keep things streamlined.

That is all - this 2 issues aside, the tests for Ubuntu 20 and Ubuntu 16 are prety much the same thing. So let's put everything together and we'll see the next verion of tests.testo:

include "macros.testo"

test server_16_install_ubuntu {
    server_16 install_ubuntu_server("16", "nat", "${server_hostname}", "${server_login}")
}

test server_16_install_guest_additions: server_16_install_ubuntu {
    server_16 install_guest_additions("${server_hostname}", "${server_login}")
}

test server_16_unplug_nat: server_16_install_guest_additions {
    server_16 unplug_nic("${server_hostname}", "${server_login}", "nat")
}

test server_16_prepare: server_16_unplug_nat {
    server_16 {
        copyto "./rename_net_16.sh" "/opt/rename_net.sh"
        exec bash """
            chmod +x /opt/rename_net.sh
            /opt/rename_net.sh 52:54:00:00:00:bb client_side
            ip a a 192.168.1.1/24 dev client_side
            ip l s client_side up
            ip ad
        """
    }
}

test client_16_install_ubuntu {
    client_16 install_ubuntu_server("16", "nat", "${client_hostname}", "${client_login}")
}

test client_16_install_guest_additions: client_16_install_ubuntu {
    client_16 install_guest_additions("${client_hostname}", "${client_login}")
}

test client_16_unplug_nat: client_16_install_guest_additions {
    client_16 unplug_nic("${client_hostname}", "${client_login}", "nat")
}

test client_16_prepare: client_16_unplug_nat {
    client_16 {
        process_flash("exchange_flash_16", "cp /media/rename_net_16.sh /opt/rename_net.sh")

        exec bash """
            chmod +x /opt/rename_net.sh
            /opt/rename_net.sh 52:54:00:00:00:aa server_side
            ip a a 192.168.1.2/24 dev server_side
            ip l s server_side up
            ip ad
        """
    }
}

test test_ping_16: client_16_prepare, server_16_prepare {
    client_16 exec bash "ping 192.168.1.2 -c5"
    server_16 exec bash "ping 192.168.1.1 -c5"
}

# Take a note, that the test is inherited not from
# the test_ping, but from the client_prepare and
# server_prepare tests.
# Which means that test_ping and exchange_files_with_flash
# both lay on the samy tests tree level
test exchange_files_with_flash_16: client_16_prepare, server_16_prepare {
    #Create a file to be transferred
    client_16 exec bash "echo \"Hello from client!\" > /tmp/copy_me_to_server.txt"
    copy_file_with_flash("client_16", "server_16", "exchange_flash_16", "/tmp/copy_me_to_server.txt", "/tmp/copy_me_to_server.txt")
    server_16 exec bash "cat /tmp/copy_me_to_server.txt"
}


test server_20_install_ubuntu {
    server_20 install_ubuntu_server("20", "nat", "${server_hostname}", "${server_login}")
}

test server_20_install_guest_additions: server_20_install_ubuntu {
    server_20 install_guest_additions("${server_hostname}", "${server_login}")
    server_20 {
        exec bash """
            ip l s ens7 up
            dhclient ens7
            apt install -y net-tools
        """
    }
}

test server_20_unplug_nat: server_20_install_guest_additions {
    server_20 unplug_nic("${server_hostname}", "${server_login}", "nat")
}

test server_20_prepare: server_20_unplug_nat {
    server_20 {
        copyto "./rename_net_20.sh" "/opt/rename_net.sh"
        exec bash """
            chmod +x /opt/rename_net.sh
            /opt/rename_net.sh 52:54:00:00:00:bb client_side
            ip a a 192.168.1.1/24 dev client_side
            ip l s client_side up
            ip ad
        """
    }
}

test client_20_install_ubuntu {
    client_20 install_ubuntu_server("20", "nat", "${client_hostname}", "${client_login}")
}

test client_20_install_guest_additions: client_20_install_ubuntu {
    client_20 install_guest_additions("${client_hostname}", "${client_login}")
    client_20 {
        exec bash """
            ip l s ens7 up
            dhclient ens7
            apt install -y net-tools
        """
    }
}

test client_20_unplug_nat: client_20_install_guest_additions {
    client_20 unplug_nic("${client_hostname}", "${client_login}", "nat")
}

test client_20_prepare: client_20_unplug_nat {
    client_20 {
        process_flash("exchange_flash_20", "cp /media/rename_net_20.sh /opt/rename_net.sh")

        exec bash """
            chmod +x /opt/rename_net.sh
            /opt/rename_net.sh 52:54:00:00:00:aa server_side
            ip a a 192.168.1.2/24 dev server_side
            ip l s server_side up
            ip ad
        """
    }
}

test test_ping_20: client_20_prepare, server_20_prepare {
    client_20 exec bash "ping 192.168.1.2 -c5"
    server_20 exec bash "ping 192.168.1.1 -c5"
}

# Take a note, that the test is inherited not from
# the test_ping, but from the client_prepare and
# server_prepare tests.
# Which means that test_ping and exchange_files_with_flash
# both lay on the samy tests tree level
test exchange_files_with_flash_20: client_20_prepare, server_20_prepare {
    #Create a file to be transferred
    client_20 exec bash "echo \"Hello from client!\" > /tmp/copy_me_to_server.txt"
    copy_file_with_flash("client_20", "server_20", "exchange_flash_20", "/tmp/copy_me_to_server.txt", "/tmp/copy_me_to_server.txt")
    server_20 exec bash "cat /tmp/copy_me_to_server.txt"
}

Let's make sure this works:

user$ sudo testo run ./ --stop_on_fail --param ISO_DIR /opt/iso
TESTS TO RUN:
server_16_install_ubuntu
server_16_install_guest_additions
server_16_unplug_nat
server_16_prepare
client_16_install_ubuntu
client_16_install_guest_additions
client_16_unplug_nat
client_16_prepare
test_ping_16
exchange_files_with_flash_16
server_20_install_ubuntu
server_20_install_guest_additions
server_20_unplug_nat
server_20_prepare
client_20_install_ubuntu
client_20_install_guest_additions
client_20_unplug_nat
client_20_prepare
test_ping_20
exchange_files_with_flash_20
[ 0%] Preparing the environment for test server_16_install_ubuntu
[ 0%] Creating virtual machine server_16
[ 0%] Taking snapshot initial for virtual machine server_16
[ 0%] Running test server_16_install_ubuntu
[ 0%] Calling macro install_ubuntu_server(version="16", nat_interface="nat", hostname="server", login="server-login", password="1111") in virtual machine server_16
[ 0%] Calling macro install_ubuntu_server_16(hostname="server", login="server-login", password="1111") in virtual machine server_16
[ 0%] Starting virtual machine server_16
[ 0%] Waiting "English" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Install Ubuntu Server" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Choose the language" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Select your location" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Detect keyboard layout?" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Country of origin for the keyboard" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Keyboard layout" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Primary network interface" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Hostname:" for 5m with interval 1s in virtual machine server_16
[ 0%] Pressing key BACKSPACE 36 times in virtual machine server_16
[ 0%] Typing "server" with interval 30ms in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Full name for the new user" for 1m with interval 1s in virtual machine server_16
[ 0%] Typing "server-login" with interval 30ms in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Username for your account" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Choose a password for the new user" for 1m with interval 1s in virtual machine server_16
[ 0%] Typing "1111" with interval 30ms in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Re-enter password to verify" for 1m with interval 1s in virtual machine server_16
[ 0%] Typing "1111" with interval 30ms in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Use weak password?" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key LEFT in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Encrypt your home directory?" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Is this time zone correct?" for 2m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Partitioning method" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Select disk to partition" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Write the changes to disks and configure LVM?" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key LEFT in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Amount of volume group to use for guided partitioning" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Write the changes to disks?" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key LEFT in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "HTTP proxy information" for 3m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "How do you want to manage upgrades" for 6m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Choose software to install" for 1m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Install the GRUB boot loader to the master boot record?" for 10m with interval 1s in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Installation complete" for 1m with interval 1s in virtual machine server_16
[ 0%] Unplugging dvd from virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "server login:" for 2m with interval 1s in virtual machine server_16
[ 0%] Typing "server-login" with interval 30ms in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Password:" for 1m with interval 1s in virtual machine server_16
[ 0%] Typing "1111" with interval 30ms in virtual machine server_16
[ 0%] Pressing key ENTER in virtual machine server_16
[ 0%] Waiting "Welcome to Ubuntu" for 1m with interval 1s in virtual machine server_16
[ 0%] Taking snapshot server_16_install_ubuntu for virtual machine server_16
[ 5%] Test server_16_install_ubuntu PASSED in 0h:4m:22s
[ 5%] Preparing the environment for test server_16_install_guest_additions
[ 5%] Running test server_16_install_guest_additions
[ 5%] Calling macro install_guest_additions(hostname="server", login="server-login", password="1111") in virtual machine server_16
[ 5%] Plugging dvd /home/alex/work/iso/testo-guest-additions.iso into virtual machine server_16
[ 5%] Typing "sudo su" with interval 30ms in virtual machine server_16
[ 5%] Pressing key ENTER in virtual machine server_16
[ 5%] Waiting "password for server-login" for 1m with interval 1s in virtual machine server_16
[ 5%] Typing "1111" with interval 30ms in virtual machine server_16
[ 5%] Pressing key ENTER in virtual machine server_16
[ 5%] Waiting "root@server" for 1m with interval 1s in virtual machine server_16
[ 5%] Typing "mount /dev/cdrom /media" with interval 30ms in virtual machine server_16
[ 5%] Pressing key ENTER in virtual machine server_16
[ 5%] Waiting "read-only" for 1m with interval 1s in virtual machine server_16
[ 5%] Typing "dpkg -i /media/testo-guest-additions*" with interval 30ms in virtual machine server_16
[ 5%] Pressing key ENTER in virtual machine server_16
[ 5%] Waiting "Setting up testo-guest-additions" for 1m with interval 1s in virtual machine server_16
[ 5%] Typing "umount /media" with interval 30ms in virtual machine server_16
[ 5%] Pressing key ENTER in virtual machine server_16
[ 5%] Sleeping in virtual machine server_16 for 2s
[ 5%] Unplugging dvd from virtual machine server_16
[ 5%] Taking snapshot server_16_install_guest_additions for virtual machine server_16
[ 10%] Test server_16_install_guest_additions PASSED in 0h:0m:9s
[ 10%] Preparing the environment for test server_16_unplug_nat
[ 10%] Running test server_16_unplug_nat
[ 10%] Calling macro unplug_nic(hostname="server", login="server-login", nic_name="nat", password="1111") in virtual machine server_16
[ 10%] Shutting down virtual machine server_16 with timeout 1m
[ 10%] Unplugging nic nat from virtual machine server_16
[ 10%] Starting virtual machine server_16
[ 10%] Waiting "server login:" for 2m with interval 1s in virtual machine server_16
[ 10%] Typing "server-login" with interval 30ms in virtual machine server_16
[ 10%] Pressing key ENTER in virtual machine server_16
[ 10%] Waiting "Password:" for 1m with interval 1s in virtual machine server_16
[ 10%] Typing "1111" with interval 30ms in virtual machine server_16
[ 10%] Pressing key ENTER in virtual machine server_16
[ 10%] Waiting "Welcome to Ubuntu" for 1m with interval 1s in virtual machine server_16
[ 10%] Taking snapshot server_16_unplug_nat for virtual machine server_16
[ 15%] Test server_16_unplug_nat PASSED in 0h:0m:20s
[ 15%] Preparing the environment for test server_16_prepare
[ 15%] Running test server_16_prepare
[ 15%] Copying /home/alex/work/testo-related/testo-tutorials/16 - macros_with_declarations/./rename_net_16.sh to virtual machine server_16 to destination /opt/rename_net.sh with timeout 10m
[ 15%] Executing bash command in virtual machine server_16 with timeout 10m
+ chmod +x /opt/rename_net.sh
+ /opt/rename_net.sh 52:54:00:00:00:bb client_side
Renaming success
+ ip a a 192.168.1.1/24 dev client_side
+ ip l s client_side up
+ ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen
1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: client_side: <BROADCAST,MULTICAST
,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:00:00:bb brd ff:ff:ff:ff:ff:ff
inet 192.168.1.1/24 scope global client_side
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe00:bb/
64 scope link tentative
valid_lft forever preferred_lft forever
[ 15%] Taking snapshot server_16_prepare for virtual machine server_16
[ 20%] Test server_16_prepare PASSED in 0h:0m:1s
[ 20%] Preparing the environment for test client_16_install_ubuntu
[ 20%] Creating virtual machine client_16
[ 20%] Taking snapshot initial for virtual machine client_16
[ 20%] Running test client_16_install_ubuntu
[ 20%] Calling macro install_ubuntu_server(version="16", nat_interface="nat", hostname="client", login="client-login", password="1111") in virtual machine client_16
[ 20%] Calling macro install_ubuntu_server_16(hostname="client", login="client-login", password="1111") in virtual machine client_16
[ 20%] Starting virtual machine client_16
[ 20%] Waiting "English" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Install Ubuntu Server" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Choose the language" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Select your location" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Detect keyboard layout?" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Country of origin for the keyboard" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Keyboard layout" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Primary network interface" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Hostname:" for 5m with interval 1s in virtual machine client_16
[ 20%] Pressing key BACKSPACE 36 times in virtual machine client_16
[ 20%] Typing "client" with interval 30ms in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Full name for the new user" for 1m with interval 1s in virtual machine client_16
[ 20%] Typing "client-login" with interval 30ms in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Username for your account" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Choose a password for the new user" for 1m with interval 1s in virtual machine client_16
[ 20%] Typing "1111" with interval 30ms in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Re-enter password to verify" for 1m with interval 1s in virtual machine client_16
[ 20%] Typing "1111" with interval 30ms in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Use weak password?" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key LEFT in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Encrypt your home directory?" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Is this time zone correct?" for 2m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Partitioning method" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Select disk to partition" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Write the changes to disks and configure LVM?" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key LEFT in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Amount of volume group to use for guided partitioning" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Write the changes to disks?" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key LEFT in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "HTTP proxy information" for 3m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "How do you want to manage upgrades" for 6m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Choose software to install" for 1m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Install the GRUB boot loader to the master boot record?" for 10m with interval 1s in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Installation complete" for 1m with interval 1s in virtual machine client_16
[ 20%] Unplugging dvd from virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "client login:" for 2m with interval 1s in virtual machine client_16
[ 20%] Typing "client-login" with interval 30ms in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Password:" for 1m with interval 1s in virtual machine client_16
[ 20%] Typing "1111" with interval 30ms in virtual machine client_16
[ 20%] Pressing key ENTER in virtual machine client_16
[ 20%] Waiting "Welcome to Ubuntu" for 1m with interval 1s in virtual machine client_16
[ 20%] Taking snapshot client_16_install_ubuntu for virtual machine client_16
[ 25%] Test client_16_install_ubuntu PASSED in 0h:4m:24s
[ 25%] Preparing the environment for test client_16_install_guest_additions
[ 25%] Running test client_16_install_guest_additions
[ 25%] Calling macro install_guest_additions(hostname="client", login="client-login", password="1111") in virtual machine client_16
[ 25%] Plugging dvd /home/alex/work/iso/testo-guest-additions.iso into virtual machine client_16
[ 25%] Typing "sudo su" with interval 30ms in virtual machine client_16
[ 25%] Pressing key ENTER in virtual machine client_16
[ 25%] Waiting "password for client-login" for 1m with interval 1s in virtual machine client_16
[ 25%] Typing "1111" with interval 30ms in virtual machine client_16
[ 25%] Pressing key ENTER in virtual machine client_16
[ 25%] Waiting "root@client" for 1m with interval 1s in virtual machine client_16
[ 25%] Typing "mount /dev/cdrom /media" with interval 30ms in virtual machine client_16
[ 25%] Pressing key ENTER in virtual machine client_16
[ 25%] Waiting "read-only" for 1m with interval 1s in virtual machine client_16
[ 25%] Typing "dpkg -i /media/testo-guest-additions*" with interval 30ms in virtual machine client_16
[ 25%] Pressing key ENTER in virtual machine client_16
[ 25%] Waiting "Setting up testo-guest-additions" for 1m with interval 1s in virtual machine client_16
[ 25%] Typing "umount /media" with interval 30ms in virtual machine client_16
[ 25%] Pressing key ENTER in virtual machine client_16
[ 25%] Sleeping in virtual machine client_16 for 2s
[ 25%] Unplugging dvd from virtual machine client_16
[ 25%] Taking snapshot client_16_install_guest_additions for virtual machine client_16
[ 30%] Test client_16_install_guest_additions PASSED in 0h:0m:10s
[ 30%] Preparing the environment for test client_16_unplug_nat
[ 30%] Running test client_16_unplug_nat
[ 30%] Calling macro unplug_nic(hostname="client", login="client-login", nic_name="nat", password="1111") in virtual machine client_16
[ 30%] Shutting down virtual machine client_16 with timeout 1m
[ 30%] Unplugging nic nat from virtual machine client_16
[ 30%] Starting virtual machine client_16
[ 30%] Waiting "client login:" for 2m with interval 1s in virtual machine client_16
[ 30%] Typing "client-login" with interval 30ms in virtual machine client_16
[ 30%] Pressing key ENTER in virtual machine client_16
[ 30%] Waiting "Password:" for 1m with interval 1s in virtual machine client_16
[ 30%] Typing "1111" with interval 30ms in virtual machine client_16
[ 30%] Pressing key ENTER in virtual machine client_16
[ 30%] Waiting "Welcome to Ubuntu" for 1m with interval 1s in virtual machine client_16
[ 30%] Taking snapshot client_16_unplug_nat for virtual machine client_16
[ 35%] Test client_16_unplug_nat PASSED in 0h:0m:20s
[ 35%] Preparing the environment for test client_16_prepare
[ 35%] Creating flash drive exchange_flash_16
[ 35%] Taking snapshot initial for flash drive exchange_flash_16
[ 35%] Running test client_16_prepare
[ 35%] Calling macro process_flash(flash_name="exchange_flash_16", command="cp /media/rename_net_16.sh /opt/rename_net.sh") in virtual machine client_16
[ 35%] Plugging flash drive exchange_flash_16 into virtual machine client_16
[ 35%] Sleeping in virtual machine client_16 for 5s
[ 35%] Executing bash command in virtual machine client_16 with timeout 10m
+ mount /dev/sdb1 /media
[ 35%] Executing bash command in virtual machine client_16 with timeout 10m
+ cp /media/rename_net_16.sh /opt/rename_net.sh
[ 35%] Executing bash command in virtual machine client_16 with timeout 10m
+ umount /media
[ 35%] Unplugging flash drive exchange_flash_16 from virtual machine client_16
[ 35%] Executing bash command in virtual machine client_16 with timeout 10m
+ chmod +x /opt/rename_net.sh
+ /opt/rename_net.sh 52:54:00:00:00:aa server_side
Renaming success
+ ip a a 192.168.1.2/24 dev server_side
+ ip l s server_side up
+ ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen
1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: server_side: <BROADCAST,MULTICAST
,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:00:00:aa brd ff:ff:ff:ff:ff:ff
inet 192.168.1.2/24 scope global server_side
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe00:aa/
64 scope link tentative
valid_lft forever preferred_lft forever
[ 35%] Taking snapshot client_16_prepare for virtual machine client_16
[ 35%] Taking snapshot client_16_prepare for flash drive exchange_flash_16
[ 40%] Test client_16_prepare PASSED in 0h:0m:10s
[ 40%] Preparing the environment for test test_ping_16
[ 40%] Running test test_ping_16
[ 40%] Executing bash command in virtual machine client_16 with timeout 10m
+ ping 192.168.1.2 -c5
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.022 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.024 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=0.024 ms
64
bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=0.028 ms
64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=0.029 ms

--- 192.168.1.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3997ms
rtt min/avg/max/mdev = 0.022/0.025/0.029/
0.005 ms
[ 40%] Executing bash command in virtual machine server_16 with timeout 10m
+ ping 192.168.1.1 -c5
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.018 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.024 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.024 ms
64
bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=0.024 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=0.028 ms

--- 192.168.1.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3996ms
rtt min/avg/max/mdev = 0.018/0.023/0.028/
0.006 ms
[ 40%] Taking snapshot test_ping_16 for virtual machine client_16
[ 40%] Taking snapshot test_ping_16 for virtual machine server_16
[ 40%] Taking snapshot test_ping_16 for flash drive exchange_flash_16
[ 45%] Test test_ping_16 PASSED in 0h:0m:11s
[ 45%] Preparing the environment for test exchange_files_with_flash_16
[ 45%] Restoring snapshot server_16_prepare for virtual machine server_16
[ 45%] Restoring snapshot client_16_prepare for virtual machine client_16
[ 45%] Restoring snapshot client_16_prepare for flash drive exchange_flash_16
[ 45%] Running test exchange_files_with_flash_16
[ 45%] Executing bash command in virtual machine client_16 with timeout 10m
+ echo 'Hello from client!'
[ 45%] Calling command macro copy_file_with_flash(vm_from="client_16", vm_to="server_16", copy_flash="exchange_flash_16", file_from="/tmp/copy_me_to_server.txt", file_to="/tmp/copy_me_to_server.txt")
[ 45%] Calling macro process_flash(flash_name="exchange_flash_16", command="cp /tmp/copy_me_to_server.txt /media/$(basename /tmp/copy_me_to_server.txt)") in virtual machine client_16
[ 45%] Plugging flash drive exchange_flash_16 into virtual machine client_16
[ 45%] Sleeping in virtual machine client_16 for 5s
[ 45%] Executing bash command in virtual machine client_16 with timeout 10m
+ mount /dev/sdb1 /media
[ 45%] Executing bash command in virtual machine client_16 with timeout 10m
++ basename /tmp/copy_me_to_server.txt
+ cp /tmp/copy_me_to_server.txt /media/copy_me_to_server.txt
[ 45%] Executing bash command in virtual machine client_16 with timeout 10m
+ umount /media
[ 45%] Unplugging flash drive exchange_flash_16 from virtual machine client_16
[ 45%] Calling macro process_flash(flash_name="exchange_flash_16", command="cp /media/$(basename /tmp/copy_me_to_server.txt) /tmp/copy_me_to_server.txt") in virtual machine server_16
[ 45%] Plugging flash drive exchange_flash_16 into virtual machine server_16
[ 45%] Sleeping in virtual machine server_16 for 5s
[ 45%] Executing bash command in virtual machine server_16 with timeout 10m
+ mount /dev/sdb1 /media
[ 45%] Executing bash command in virtual machine server_16 with timeout 10m
++ basename /tmp/copy_me_to_server.txt
+ cp /media/copy_me_to_server.txt /tmp/copy_me_to_server.txt
[ 45%] Executing bash command in virtual machine server_16 with timeout 10m
+ umount /media
[ 45%] Unplugging flash drive exchange_flash_16 from virtual machine server_16
[ 45%] Executing bash command in virtual machine server_16 with timeout 10m
+ cat /tmp/copy_me_to_server.txt
Hello from client!
[ 45%] Taking snapshot exchange_files_with_flash_16 for virtual machine client_16
[ 45%] Taking snapshot exchange_files_with_flash_16 for virtual machine server_16
[ 45%] Taking snapshot exchange_files_with_flash_16 for flash drive exchange_flash_16
[ 50%] Test exchange_files_with_flash_16 PASSED in 0h:0m:19s
[ 50%] Preparing the environment for test server_20_install_ubuntu
[ 50%] Creating virtual machine server_20
[ 50%] Taking snapshot initial for virtual machine server_20
[ 50%] Running test server_20_install_ubuntu
[ 50%] Calling macro install_ubuntu_server(version="20", nat_interface="nat", hostname="server", login="server-login", password="1111") in virtual machine server_20
[ 50%] Calling macro install_ubuntu_server_20(nat_interface="nat", hostname="server", login="server-login", password="1111") in virtual machine server_20
[ 50%] Unplugging nic nat from virtual machine server_20
[ 50%] Starting virtual machine server_20
[ 50%] Checking "Language" for 5s in virtual machine server_20
[ 50%] Waiting "Welcome!" for 5m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Please select your keyboard layout" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Configure at least one interface" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Proxy address" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Mirror address" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Continue without updating" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Use an entire disk" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key DOWN 5 times in virtual machine server_20
[ 50%] Waiting "find_text().match('Done').match_background('green').size() > 0" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "FILE SYSTEM SUMMARY" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Confirm destructive action" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key DOWN in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Enter the username" for 1m with interval 1s in virtual machine server_20
[ 50%] Typing "server-login" with interval 30ms in virtual machine server_20
[ 50%] Pressing key TAB in virtual machine server_20
[ 50%] Typing "server" with interval 30ms in virtual machine server_20
[ 50%] Pressing key TAB in virtual machine server_20
[ 50%] Typing "server-login" with interval 30ms in virtual machine server_20
[ 50%] Pressing key TAB in virtual machine server_20
[ 50%] Typing "1111" with interval 30ms in virtual machine server_20
[ 50%] Pressing key TAB in virtual machine server_20
[ 50%] Typing "1111" with interval 30ms in virtual machine server_20
[ 50%] Pressing key ENTER 2 times in virtual machine server_20
[ 50%] Waiting "SSH Setup" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key TAB in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Installing system" for 1m with interval 1s in virtual machine server_20
[ 50%] Waiting "Installation complete!" for 15m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Please remove the installation medium" for 1m with interval 1s in virtual machine server_20
[ 50%] Unplugging dvd from virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "server login" for 3m with interval 1s in virtual machine server_20
[ 50%] Stopping virtual machine server_20
[ 50%] Plugging nic nat into virtual machine server_20
[ 50%] Starting virtual machine server_20
[ 50%] Waiting "GNU GRUB" for 1m with interval 1s in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "server login" for 3m with interval 1s in virtual machine server_20
[ 50%] Typing "server-login" with interval 30ms in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "Password" for 1m with interval 1s in virtual machine server_20
[ 50%] Typing "1111" with interval 30ms in virtual machine server_20
[ 50%] Pressing key ENTER in virtual machine server_20
[ 50%] Waiting "server-login@server" for 1m with interval 1s in virtual machine server_20
[ 50%] Taking snapshot server_20_install_ubuntu for virtual machine server_20
[ 55%] Test server_20_install_ubuntu PASSED in 0h:3m:50s
[ 55%] Preparing the environment for test server_20_install_guest_additions
[ 55%] Running test server_20_install_guest_additions
[ 55%] Calling macro install_guest_additions(hostname="server", login="server-login", password="1111") in virtual machine server_20
[ 55%] Plugging dvd /home/alex/work/iso/testo-guest-additions.iso into virtual machine server_20
[ 55%] Typing "sudo su" with interval 30ms in virtual machine server_20
[ 55%] Pressing key ENTER in virtual machine server_20
[ 55%] Waiting "password for server-login" for 1m with interval 1s in virtual machine server_20
[ 55%] Typing "1111" with interval 30ms in virtual machine server_20
[ 55%] Pressing key ENTER in virtual machine server_20
[ 55%] Waiting "root@server" for 1m with interval 1s in virtual machine server_20
[ 55%] Typing "mount /dev/cdrom /media" with interval 30ms in virtual machine server_20
[ 55%] Pressing key ENTER in virtual machine server_20
[ 55%] Waiting "read-only" for 1m with interval 1s in virtual machine server_20
[ 55%] Typing "dpkg -i /media/testo-guest-additions*" with interval 30ms in virtual machine server_20
[ 55%] Pressing key ENTER in virtual machine server_20
[ 55%] Waiting "Setting up testo-guest-additions" for 1m with interval 1s in virtual machine server_20
[ 55%] Typing "umount /media" with interval 30ms in virtual machine server_20
[ 55%] Pressing key ENTER in virtual machine server_20
[ 55%] Sleeping in virtual machine server_20 for 2s
[ 55%] Unplugging dvd from virtual machine server_20
[ 55%] Executing bash command in virtual machine server_20 with timeout 10m
+ ip l s ens7 up
+ dhclient ens7
cmp: EOF on /tmp/tmp.rwmiaB2Mhz which is empty
+ apt install -y net-tools

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state
information...
The following NEW packages will be installed:
net-tools
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 196 kB of archives.
After this operation, 864 kB of additional disk space will be used.
Get:1 http://archive
.ubuntu.com/ubuntu focal/main amd64 net-tools amd64 1.60+git20180626.aebd88e-1ubuntu1 [196 kB]
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debc
onf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:
Fetched 196 kB in 0s (552 kB/s)
Selecting previously unselected packa
ge net-tools.
(Reading database ... (Reading database ... 5% (Reading database ... 10% (Reading database ... 15% (Reading database ... 20% (Reading database ... 25% (Reading database ... 30% (Reading database ... 35% (Reading database ... 40% (Reading da
tabase ... 45% (Reading database ... 50% (Reading database ... 55% (Reading database ... 60% (Reading database ... 65% (Reading database ... 70% (Reading database ... 75% (Reading database ... 80% (Reading database ... 85% (Reading database ... 90% (Reading database ... 95% (Reading database ... 100% (Reading database ... 67943 files and directories currently installed.)
Preparing to unpack .../net-tools_1.60+git20180626.aebd88e-1ubuntu1_amd64.deb ...
Unpacking net-tools (1.60+git20180626.aebd88e-1ubuntu1
) ...
Setting up net-tools (1.60+git20180626.aebd88e-1ubuntu1) ...
Processing triggers for man-db (2.9.1-1) ...
[ 55%] Taking snapshot server_20_install_guest_additions for virtual machine server_20
[ 60%] Test server_20_install_guest_additions PASSED in 0h:0m:15s
[ 60%] Preparing the environment for test server_20_unplug_nat
[ 60%] Running test server_20_unplug_nat
[ 60%] Calling macro unplug_nic(hostname="server", login="server-login", nic_name="nat", password="1111") in virtual machine server_20
[ 60%] Shutting down virtual machine server_20 with timeout 1m
[ 60%] Unplugging nic nat from virtual machine server_20
[ 60%] Starting virtual machine server_20
[ 60%] Waiting "server login:" for 2m with interval 1s in virtual machine server_20
[ 60%] Typing "server-login" with interval 30ms in virtual machine server_20
[ 60%] Pressing key ENTER in virtual machine server_20
[ 60%] Waiting "Password:" for 1m with interval 1s in virtual machine server_20
[ 60%] Typing "1111" with interval 30ms in virtual machine server_20
[ 60%] Pressing key ENTER in virtual machine server_20
[ 60%] Waiting "Welcome to Ubuntu" for 1m with interval 1s in virtual machine server_20
[ 60%] Taking snapshot server_20_unplug_nat for virtual machine server_20
[ 65%] Test server_20_unplug_nat PASSED in 0h:0m:40s
[ 65%] Preparing the environment for test server_20_prepare
[ 65%] Running test server_20_prepare
[ 65%] Copying /home/alex/work/testo-related/testo-tutorials/16 - macros_with_declarations/./rename_net_20.sh to virtual machine server_20 to destination /opt/rename_net.sh with timeout 10m
[ 65%] Executing bash command in virtual machine server_20 with timeout 10m
+ chmod +x /opt/rename_net.sh
+ /opt/rename_net.sh 52:54:00:00:00:bb client_side
Renaming success
+ ip a a 192.168.1.1/24 dev client_side
+ ip l s client_side up
+ ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen
1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: client_side: <BROADCAST,MULTIC
AST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:00:00:bb brd ff:ff:ff:ff:ff:ff
inet 192.168.1.1/24 scope global client_side
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe00:bb
/64 scope link tentative
valid_lft forever preferred_lft forever
[ 65%] Taking snapshot server_20_prepare for virtual machine server_20
[ 70%] Test server_20_prepare PASSED in 0h:0m:3s
[ 70%] Preparing the environment for test client_20_install_ubuntu
[ 70%] Creating virtual machine client_20
[ 70%] Taking snapshot initial for virtual machine client_20
[ 70%] Running test client_20_install_ubuntu
[ 70%] Calling macro install_ubuntu_server(version="20", nat_interface="nat", hostname="client", login="client-login", password="1111") in virtual machine client_20
[ 70%] Calling macro install_ubuntu_server_20(nat_interface="nat", hostname="client", login="client-login", password="1111") in virtual machine client_20
[ 70%] Unplugging nic nat from virtual machine client_20
[ 70%] Starting virtual machine client_20
[ 70%] Checking "Language" for 5s in virtual machine client_20
[ 70%] Waiting "Welcome!" for 5m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Please select your keyboard layout" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Configure at least one interface" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Proxy address" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Mirror address" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Continue without updating" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Use an entire disk" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key DOWN 5 times in virtual machine client_20
[ 70%] Waiting "find_text().match('Done').match_background('green').size() > 0" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "FILE SYSTEM SUMMARY" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Confirm destructive action" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key DOWN in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Enter the username" for 1m with interval 1s in virtual machine client_20
[ 70%] Typing "client-login" with interval 30ms in virtual machine client_20
[ 70%] Pressing key TAB in virtual machine client_20
[ 70%] Typing "client" with interval 30ms in virtual machine client_20
[ 70%] Pressing key TAB in virtual machine client_20
[ 70%] Typing "client-login" with interval 30ms in virtual machine client_20
[ 70%] Pressing key TAB in virtual machine client_20
[ 70%] Typing "1111" with interval 30ms in virtual machine client_20
[ 70%] Pressing key TAB in virtual machine client_20
[ 70%] Typing "1111" with interval 30ms in virtual machine client_20
[ 70%] Pressing key ENTER 2 times in virtual machine client_20
[ 70%] Waiting "SSH Setup" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key TAB in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Installing system" for 1m with interval 1s in virtual machine client_20
[ 70%] Waiting "Installation complete!" for 15m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Please remove the installation medium" for 1m with interval 1s in virtual machine client_20
[ 70%] Unplugging dvd from virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "client login" for 3m with interval 1s in virtual machine client_20
[ 70%] Stopping virtual machine client_20
[ 70%] Plugging nic nat into virtual machine client_20
[ 70%] Starting virtual machine client_20
[ 70%] Waiting "GNU GRUB" for 1m with interval 1s in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "client login" for 3m with interval 1s in virtual machine client_20
[ 70%] Typing "client-login" with interval 30ms in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "Password" for 1m with interval 1s in virtual machine client_20
[ 70%] Typing "1111" with interval 30ms in virtual machine client_20
[ 70%] Pressing key ENTER in virtual machine client_20
[ 70%] Waiting "client-login@client" for 1m with interval 1s in virtual machine client_20
[ 70%] Taking snapshot client_20_install_ubuntu for virtual machine client_20
[ 75%] Test client_20_install_ubuntu PASSED in 0h:3m:54s
[ 75%] Preparing the environment for test client_20_install_guest_additions
[ 75%] Running test client_20_install_guest_additions
[ 75%] Calling macro install_guest_additions(hostname="client", login="client-login", password="1111") in virtual machine client_20
[ 75%] Plugging dvd /home/alex/work/iso/testo-guest-additions.iso into virtual machine client_20
[ 75%] Typing "sudo su" with interval 30ms in virtual machine client_20
[ 75%] Pressing key ENTER in virtual machine client_20
[ 75%] Waiting "password for client-login" for 1m with interval 1s in virtual machine client_20
[ 75%] Typing "1111" with interval 30ms in virtual machine client_20
[ 75%] Pressing key ENTER in virtual machine client_20
[ 75%] Waiting "root@client" for 1m with interval 1s in virtual machine client_20
[ 75%] Typing "mount /dev/cdrom /media" with interval 30ms in virtual machine client_20
[ 75%] Pressing key ENTER in virtual machine client_20
[ 75%] Waiting "read-only" for 1m with interval 1s in virtual machine client_20
[ 75%] Typing "dpkg -i /media/testo-guest-additions*" with interval 30ms in virtual machine client_20
[ 75%] Pressing key ENTER in virtual machine client_20
[ 75%] Waiting "Setting up testo-guest-additions" for 1m with interval 1s in virtual machine client_20
[ 75%] Typing "umount /media" with interval 30ms in virtual machine client_20
[ 75%] Pressing key ENTER in virtual machine client_20
[ 75%] Sleeping in virtual machine client_20 for 2s
[ 75%] Unplugging dvd from virtual machine client_20
[ 75%] Executing bash command in virtual machine client_20 with timeout 10m
+ ip l s ens7 up
+ dhclient ens7
cmp: EOF on /tmp/tmp.hQxtodoogv which is empty
+ apt install -y net-tools

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

Reading package lists...
Building dependency tree...
Reading state
information...
The following NEW packages will be installed:
net-tools
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 196 kB of archives.
After this operation, 864 kB of additional disk space will be used.
Get:1 http://archive
.ubuntu.com/ubuntu focal/main amd64 net-tools amd64 1.60+git20180626.aebd88e-1ubuntu1 [196 kB]
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debc
onf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:
Fetched 196 kB in 0s (562 kB/s)
Selecting previously unselected packa
ge net-tools.
(Reading database ... (Reading database ... 5% (Reading database ... 10% (Reading database ... 15% (Reading database ... 20% (Reading database ... 25% (Reading database ... 30% (Reading database ... 35% (Reading database ... 40% (Reading da
tabase ... 45% (Reading database ... 50% (Reading database ... 55% (Reading database ... 60% (Reading database ... 65% (Reading database ... 70% (Reading database ... 75% (Reading database ... 80% (Reading database ... 85% (Reading database ... 90% (Reading database ... 95% (Reading database ... 100% (Reading database ... 67943 files and directories currently installed.)
Preparing to unpack .../net-tools_1.60+git20180626.aebd88e-1ubuntu1_amd64.deb ...
Unpacking net-tools (1.60+git20180626.aebd88e-1ubuntu1
) ...
Setting up net-tools (1.60+git20180626.aebd88e-1ubuntu1) ...
Processing triggers for man-db (2.9.1-1) ...
[ 75%] Taking snapshot client_20_install_guest_additions for virtual machine client_20
[ 80%] Test client_20_install_guest_additions PASSED in 0h:0m:15s
[ 80%] Preparing the environment for test client_20_unplug_nat
[ 80%] Running test client_20_unplug_nat
[ 80%] Calling macro unplug_nic(hostname="client", login="client-login", nic_name="nat", password="1111") in virtual machine client_20
[ 80%] Shutting down virtual machine client_20 with timeout 1m
[ 80%] Unplugging nic nat from virtual machine client_20
[ 80%] Starting virtual machine client_20
[ 80%] Waiting "client login:" for 2m with interval 1s in virtual machine client_20
[ 80%] Typing "client-login" with interval 30ms in virtual machine client_20
[ 80%] Pressing key ENTER in virtual machine client_20
[ 80%] Waiting "Password:" for 1m with interval 1s in virtual machine client_20
[ 80%] Typing "1111" with interval 30ms in virtual machine client_20
[ 80%] Pressing key ENTER in virtual machine client_20
[ 80%] Waiting "Welcome to Ubuntu" for 1m with interval 1s in virtual machine client_20
[ 80%] Taking snapshot client_20_unplug_nat for virtual machine client_20
[ 85%] Test client_20_unplug_nat PASSED in 0h:0m:38s
[ 85%] Preparing the environment for test client_20_prepare
[ 85%] Creating flash drive exchange_flash_20
[ 85%] Taking snapshot initial for flash drive exchange_flash_20
[ 85%] Running test client_20_prepare
[ 85%] Calling macro process_flash(flash_name="exchange_flash_20", command="cp /media/rename_net_20.sh /opt/rename_net.sh") in virtual machine client_20
[ 85%] Plugging flash drive exchange_flash_20 into virtual machine client_20
[ 85%] Sleeping in virtual machine client_20 for 5s
[ 85%] Executing bash command in virtual machine client_20 with timeout 10m
+ mount /dev/sdb1 /media
[ 85%] Executing bash command in virtual machine client_20 with timeout 10m
+ cp /media/rename_net_20.sh /opt/rename_net.sh
[ 85%] Executing bash command in virtual machine client_20 with timeout 10m
+ umount /media
[ 85%] Unplugging flash drive exchange_flash_20 from virtual machine client_20
[ 85%] Executing bash command in virtual machine client_20 with timeout 10m
+ chmod +x /opt/rename_net.sh
+ /opt/rename_net.sh 52:54:00:00:00:aa server_side
Renaming success
+ ip a a 192.168.1.2/24 dev server_side
+ ip l s server_side up
+ ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen
1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: server_side: <BROADCAST,MULTIC
AST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:00:00:aa brd ff:ff:ff:ff:ff:ff
inet 192.168.1.2/24 scope global server_side
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe00:aa
/64 scope link tentative
valid_lft forever preferred_lft forever
[ 85%] Taking snapshot client_20_prepare for virtual machine client_20
[ 85%] Taking snapshot client_20_prepare for flash drive exchange_flash_20
[ 90%] Test client_20_prepare PASSED in 0h:0m:12s
[ 90%] Preparing the environment for test test_ping_20
[ 90%] Running test test_ping_20
[ 90%] Executing bash command in virtual machine client_20 with timeout 10m
+ ping 192.168.1.2 -c5
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.019 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.028 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=0.030 ms
64
bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=0.032 ms
64 bytes from 192.168.1.2: icmp_seq=5 ttl=64 time=0.032 ms

--- 192.168.1.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4084ms
rtt min/avg/max/mdev = 0.019/0.028/0.032/
0.004 ms
[ 90%] Executing bash command in virtual machine server_20 with timeout 10m
+ ping 192.168.1.1 -c5
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.020 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=0.036 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.031 ms
64
bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=0.030 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=0.031 ms

--- 192.168.1.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4086ms
rtt min/avg/max/mdev = 0.020/0.029/0.036/
0.005 ms
[ 90%] Taking snapshot test_ping_20 for virtual machine server_20
[ 90%] Taking snapshot test_ping_20 for virtual machine client_20
[ 90%] Taking snapshot test_ping_20 for flash drive exchange_flash_20
[ 95%] Test test_ping_20 PASSED in 0h:0m:14s
[ 95%] Preparing the environment for test exchange_files_with_flash_20
[ 95%] Restoring snapshot server_20_prepare for virtual machine server_20
[ 95%] Restoring snapshot client_20_prepare for flash drive exchange_flash_20
[ 95%] Restoring snapshot client_20_prepare for virtual machine client_20
[ 95%] Running test exchange_files_with_flash_20
[ 95%] Executing bash command in virtual machine client_20 with timeout 10m
+ echo 'Hello from client!'
[ 95%] Calling command macro copy_file_with_flash(vm_from="client_20", vm_to="server_20", copy_flash="exchange_flash_20", file_from="/tmp/copy_me_to_server.txt", file_to="/tmp/copy_me_to_server.txt")
[ 95%] Calling macro process_flash(flash_name="exchange_flash_20", command="cp /tmp/copy_me_to_server.txt /media/$(basename /tmp/copy_me_to_server.txt)") in virtual machine client_20
[ 95%] Plugging flash drive exchange_flash_20 into virtual machine client_20
[ 95%] Sleeping in virtual machine client_20 for 5s
[ 95%] Executing bash command in virtual machine client_20 with timeout 10m
+ mount /dev/sdb1 /media
[ 95%] Executing bash command in virtual machine client_20 with timeout 10m
++ basename /tmp/copy_me_to_server.txt
+ cp /tmp/copy_me_to_server.txt /media/copy_me_to_server.txt
[ 95%] Executing bash command in virtual machine client_20 with timeout 10m
+ umount /media
[ 95%] Unplugging flash drive exchange_flash_20 from virtual machine client_20
[ 95%] Calling macro process_flash(flash_name="exchange_flash_20", command="cp /media/$(basename /tmp/copy_me_to_server.txt) /tmp/copy_me_to_server.txt") in virtual machine server_20
[ 95%] Plugging flash drive exchange_flash_20 into virtual machine server_20
[ 95%] Sleeping in virtual machine server_20 for 5s
[ 95%] Executing bash command in virtual machine server_20 with timeout 10m
+ mount /dev/sdb1 /media
[ 95%] Executing bash command in virtual machine server_20 with timeout 10m
++ basename /tmp/copy_me_to_server.txt
+ cp /media/copy_me_to_server.txt /tmp/copy_me_to_server.txt
[ 95%] Executing bash command in virtual machine server_20 with timeout 10m
+ umount /media
[ 95%] Unplugging flash drive exchange_flash_20 from virtual machine server_20
[ 95%] Executing bash command in virtual machine server_20 with timeout 10m
+ cat /tmp/copy_me_to_server.txt
Hello from client!
[ 95%] Taking snapshot exchange_files_with_flash_20 for virtual machine server_20
[ 95%] Taking snapshot exchange_files_with_flash_20 for virtual machine client_20
[ 95%] Taking snapshot exchange_files_with_flash_20 for flash drive exchange_flash_20
[100%] Test exchange_files_with_flash_20 PASSED in 0h:0m:27s
PROCESSED TOTAL 20 TESTS IN 0h:21m:4s
UP-TO-DATE: 0
RUN SUCCESSFULLY: 20
FAILED: 0

All done! We're managed to do the job, but once again we're forced to do copy-paste: we virtually duplicated the code for virtual machines, networks, flash drives and the tests themselves.

But we can fix that with a new type of macros in Testo-lang: macros with declarations.

Macro with test bench declarations

Macros with declarations let you grouo up some of the top-level statements in Testl-lang: virtual entities declarations (machine, flash, network) and tests declarations. However, It is prohibited to declare params and other macros inside the macro body. You also can't use the include directive inside a macro. But on the other hand, you can call other macros with declarations.

We'll start with grouping up the VM, flash drive and network declarations into a new macro generate_bench:

macro generate_bench(version, ram_size, disk_size) {
    network "internet_${version}" {
        mode: "nat"
    }

    network "LAN_${version}" {
        mode: "internal"
    }

    machine "client_${version}" {
        cpus: 1
        ram: "${ram_size}"
        disk main: {
            size: "${disk_size}"
        }
        iso: "${ISO_DIR}/ubuntu_server_${version}.iso"

        nic nat: {
            attached_to: "internet_${version}"
        }

        nic server_side: {
            attached_to: "LAN_${version}"
            mac: "52:54:00:00:00:AA"
        }
    }

    machine "server_${version}" {
        cpus: 1
        ram: "${ram_size}"
        disk main: {
            size: "${disk_size}"
        }
        iso: "${ISO_DIR}/ubuntu_server_${version}.iso"

        nic nat: {
            attached_to: "internet_${version}"
        }

        nic client_side: {
            attached_to: "LAN_${version}"
            mac: "52:54:00:00:00:BB"
        }
    }

    flash "exchange_flash_${version}" {
        fs: "ntfs"
        size: 8Mb
        folder: "./folder_to_copy"
    }
}

generate_bench("16", "512Mb", "5Gb")
generate_bench("20", "1Gb", "8Gb")

A couple of things worth noticing.

Inside the macro we incapsulated the virtual test bench declaration: two vritual machines, two networks and a flash drive. Each generate_bench macro call will generate a whole new test bench. To prevent the virtual entities from "overplapping" each other with several macro calls, we made all the entities' names parameterized. To do so, we've used the Testo-lang feature of declaring entities' names with strings instead of identifiers (as we've been doing pretty much all the time before). And inside the strings we can reference the macro arguments.

So the macro generate_bench call with the version = "16" (Ubuntu Server version 16) will generate entities network internet_16, network LAN_16, machine client_16, machine server_16 and flash exchange_flash_16. To generate the entities for Ubuntu 20 we just need to call the macro generate_bench with the version = "16" instead. This will "instruct" the virtual machines to carry the ubuntu_server_20.iso ISO-image (where the Ubuntu Server 20.04 image should be placed) instead of ubuntu_server_16.iso.

The next interesting thing is adjustable RAM (ram) and disk (size) sizes. As mentioned above, Ubuntu Server 20 wouldn't requires more memory (RAM and disk) thatn Ubuntu 16.04. It would be nice to have the opportunity to specify the memory amount for different test bench versions. We're going to do just that with the ram_size and disk_size arguments.

After the arguments get inside the macro, we can reference them inside the ram and size attributes. We're used to specifiy the memory amount in attributes with literals (512Mb, 5Gb) but in Testo-lang it is also possible to do that with strings ("512Mb", "5Gb"). Using the strings has a benefit of its own: you can reference macro args inside them, which is exactly what we did.

At the same time, the macro arguments values must be convertible to a memory amount specifier. It you tried to pass a wrong value (for instance, "5"), an error would be generated.

We declared the generate_bench macro, but it doesn't mean we declared toe virtuam machines, networks and flash drive themselves. To do that, we need to actually call the macro. The calls are made in the end of the declarations.testo and after the calls two separate and independent sets of machines, networks and flash drives are generated. Tou should also notice that the calls take place at the top level - the same level where all the usual declarations take place.

Macro with tests declarations

It's time to move on to the tests. Tests' declarations (as well as virtual machines' declarations) can be encapsulated insode a macro (it's also possible to combine both tests and virtual machines declarations inside the same macro). Let's try to do this:

tests.testo:

include "macros.testo"

macro generate_tests(version) {

    test "server_${version}_install_ubuntu" {
        "server_${version}" install_ubuntu_server("${version}", "nat", "${server_hostname}", "${server_login}")
    }

    test "server_${version}_install_guest_additions": "server_${version}_install_ubuntu" {
        "server_${version}" install_guest_additions("${server_hostname}", "${server_login}")
    }

    test "server_${version}_unplug_nat": "server_${version}_install_guest_additions" {
        "server_${version}" unplug_nic("${server_hostname}", "${server_login}", "nat")
    }

    test "server_${version}_prepare": "server_${version}_unplug_nat" {
        "server_${version}" {
            copyto "./rename_net_${version}.sh" "/opt/rename_net.sh"
            exec bash """
                chmod +x /opt/rename_net.sh
                /opt/rename_net.sh 52:54:00:00:00:bb client_side
                ip a a 192.168.1.1/24 dev client_side
                ip l s client_side up
                ip ad
            """
        }
    }

    test "client_${version}_install_ubuntu" {
        "client_${version}" install_ubuntu_server("${version}", "nat", "${client_hostname}", "${client_login}")
    }

    test "client_${version}_install_guest_additions": "client_${version}_install_ubuntu" {
        "client_${version}" install_guest_additions("${client_hostname}", "${client_login}")
    }

    test "client_${version}_unplug_nat": "client_${version}_install_guest_additions" {
        "client_${version}" unplug_nic("${client_hostname}", "${client_login}", "nat")
    }

    test "client_${version}_prepare": "client_${version}_unplug_nat" {
        "client_${version}" {
            process_flash("exchange_flash_${version}", "cp /media/rename_net_${version}.sh /opt/rename_net.sh")

            exec bash """
                chmod +x /opt/rename_net.sh
                /opt/rename_net.sh 52:54:00:00:00:aa server_side
                ip a a 192.168.1.2/24 dev server_side
                ip l s server_side up
                ip ad
            """
        }
    }

    test "test_ping_${version}": "client_${version}_prepare", "server_${version}_prepare" {
        "client_${version}" exec bash "ping 192.168.1.2 -c5"
        "server_${version}" exec bash "ping 192.168.1.1 -c5"
    }

    # Take a note, that the test is inherited not from
    # the test_ping, but from the client_prepare and
    # server_prepare tests.
    # Which means that test_ping and exchange_files_with_flash
    # both lay on the samy tests tree level
    test "exchange_files_with_flash_${version}": "client_${version}_prepare", "server_${version}_prepare" {
        #Create a file to be transferred
        "client_${version}" exec bash "echo \"Hello from client!\" > /tmp/copy_me_to_server.txt"
        copy_file_with_flash("client_${version}", "server_${version}", "exchange_flash_${version}", "/tmp/copy_me_to_server.txt", "/tmp/copy_me_to_server.txt")
        "server_${version}" exec bash "cat /tmp/copy_me_to_server.txt"
    }
}

generate_tests("16")
generate_tests("20")

The generate_tests macro generates a whole bunch of tests: from the OS installation to the ping probing. Thanks to this macro, we're able to generalize the tests for Ubuntu 16.04 and Ubuntu 20.04. Let's take a look at a couple of interesting things.

First, let's taka a look at the tests' names. Just like we did before for the virtual entities, we're going to specify the tests' names with strings rather thatn identifiers. With strings we can access the macro arguments. We're also going to exploit the feature of specifying the tests parents' names with strings.

Second, inside the generate_tests macro we can call other types of macros: macros with actions (install_ubuntu_server, for instance) and with commands (copy_file_with_flash).

Keep in mind, that the installation proccess differs for Ubuntu Server 16.04 and Ubuntu Server 20.04. But we can pay no attention to that in our tests: since we've combined both installation types in the single install_ubuntu_server macro, inside the server_${version}_install_ubuntu we may not care about the actual way the installation is done. This is "the problem" of the install_ubuntu_server macro.

To generate the tests themselves, we need to call the generate_tests macro. We're going to call it two times: one for generating the tests collection for Ubuntu Server 16.04 (generate_tests("16")) and one more time to generate the tests collection for Ubuntu Server 20.04 (generate_tests("20")).

After that we can try out out new script and check that everythings works as planned.

Conclusions

With macros it is possible to group up not only actions and commands, but whole declarations (virtual test benches and tests) as well. If you need to generate a bunch of similar-looking tests, then macros with declaration are really worth the considerations to do just that.

You can find the complete test scripts here.

Congratulations! You've learned all the Testo-lang basics and may now proceed to creating your own test scripts!