Tests for guest image tools

Adding Testcases for the functions used by guest-image-tools. The
tests are executed by python and integrated into the py27 and py35
test jobs.

Sometimes the guest image tools call external commands
(like ip, zneconf,...). for this case dummy versions of those
executeables are placed in a faked root directory. The test takes
care of exectuing those commands in this directory, therefore the
dummy (bash) executables are chosen over the real ones.
However those dummy executeables cannot replace mocks where a lot
of assertions can be done. As workaround the dummy executeable just
check if it was called with a certain list of arguments. The test
needs to exactly pass those arguments in order to succeed.

Ideally those tests would be functional tests running on a real
system z envrionement. Doing so we could verify if the real
operations are working as well.

Change-Id: I35d0840c2e4bb9d216d57a5927f20b3f0ff182c0
This commit is contained in:
Andreas Scheuring 2017-02-20 13:00:12 +01:00
parent dad341f2ff
commit 93929b09a3
8 changed files with 252 additions and 5 deletions

View File

@ -41,6 +41,25 @@ function log {
fi
}
function _change_root {
# $1 = input path or command
# returns new path
local path=$1
if [ -z "$ROOT_DIR" ]; then
# Changing root dir not set
echo "$path"
return 0
fi
if [[ "$path" == /* ]]; then
echo "$ROOT_DIR$path"
else
# command called without a path
echo "$ROOT_DIR/$path"
fi
}
function extract_devno {
# Extracts the device number out of a device path
# $1 = the device path, e.g. "/devices/qeth/0.0.0001/net/enc1"
@ -133,8 +152,8 @@ function get_ip_cmd {
local paths=("/usr/sbin/ip" "/sbin/ip")
for path in "${paths[@]}"; do
local full_path=$ROOT_DIR$path
if [[ -x $full_path ]]; then
local full_path=$(_change_root "$path")
if [[ -x "$full_path" ]]; then
echo "$full_path"
return 0
fi
@ -180,7 +199,7 @@ function device_exists {
local dev_bus_id="$1"
# Check if device is already configured
path="/sys/bus/ccwgroup/devices/$dev_bus_id"
local path=$(_change_root "/sys/bus/ccwgroup/devices/$dev_bus_id")
if ! [ -d "$path" ]; then
return 1
fi
@ -195,11 +214,12 @@ function configure_device {
# TODO(andreas_s): Do not depend on znetconf
# Errors of the following command are written to stderr, and therefore
# show up in the systemd units journal
znetconf -a $dev_bus_id -o portno=$port_no,layer2=1
local cmd=$(_change_root "znetconf -a $dev_bus_id -o portno=$port_no,layer2=1")
eval "$cmd"
return "$?"
}
function get_cmdline {
#Example: "some stuff nics=0001,0,aabbccddeeff;abcd,1,001122334455;"
echo $(cat /proc/cmdline)
echo $(cat $(_change_root "/proc/cmdline"))
}

View File

@ -0,0 +1 @@
this-is-the-cmd-line

View File

@ -0,0 +1,19 @@
#! /bin/bash
# $ip_cmd link set $if_name address $mac
echo "foo"
if ! [[ "$1" == "link" ]]; then
exit 1
fi
if ! [[ "$2" == "set" ]]; then
exit 1
fi
# TODO: Check if_name
if ! [[ "$4" == "address" ]]; then
exit 1
fi
# TODO: check_mac

View File

@ -0,0 +1,6 @@
#! /bin/bash
# znetconf -a $dev_bus_id -o portno=$port,layer2=1
if ! [[ "$@" == "-a 0.0.0001 -o portno=1,layer2=1" ]]; then
exit 1
fi

View File

@ -0,0 +1,162 @@
# Copyright 2017 IBM Corp.
#
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
from subprocess import PIPE
from subprocess import Popen
from oslotest import base
base_path = os.path.dirname(os.path.realpath(__file__))
test_root_dir = base_path + "/root_dir_default"
class TestDPMGuestImageTools(base.BaseTestCase):
def setUp(self):
super(TestDPMGuestImageTools, self).setUp()
# Change the root directory to the default root dir that contains the
# fake commands
self.env = dict(os.environ, ROOT_DIR=test_root_dir)
def _execute_command(self, cmd):
proc = Popen(cmd, stdout=PIPE, env=self.env)
stdout, stderr = proc.communicate()
# convert stdout from byte to unicode. Required for python 3
stdout = stdout.decode("utf-8")
self.stdout = stdout.strip("\n")
self.stderr = stderr
self.rc = proc.returncode
print(self.stdout)
def _test_function(self, func_name, args):
"""Calling a guest image tool bash function for test
:param func_name: The bash function name to be called
:param args: List of arguments to be passed into the function
"""
tools_path =\
"nova_dpm/tests/unit/guest_image_tools/test_wrapper.sh"
cmd = [tools_path, func_name] + args
self._execute_command(cmd)
def _assert(self, rc, stdout="", stderr=None):
self.assertEqual(rc, self.rc)
self.assertEqual(stdout, self.stdout)
self.assertEqual(stderr, self.stderr)
def test_extract_interface_name(self):
args = ["/devices/qeth/0.0.0001/net/enc1"]
self._test_function("extract_interface_name", args)
self._assert(0, stdout="enc1")
def test_extract_interface_name_invalid_input(self):
args = ["foobar"]
self._test_function("extract_interface_name", args)
self._assert(1)
def test_extract_devno(self):
args = ["/devices/qeth/0.0.0001/net/enc1"]
self._test_function("extract_devno", args)
self._assert(0, stdout="0001")
def test_extract_devno_invalid_input(self):
args = ["foobar"]
self._test_function("extract_devno", args)
self._assert(1)
def test_extract_mac(self):
args = ["0001", "foo 0001,0,aabbccddeeff;0004,1,112233445566;"]
self._test_function("extract_mac", args)
self._assert(0, stdout="aa:bb:cc:dd:ee:ff")
def test_extract_mac_invalid_mac(self):
args = ["0001", "foo 0001,0,aabbccddeeffaa;"]
self._test_function("extract_mac", args)
self._assert(1)
def test_extract_mac_not_found(self):
args = ["aaaa", "foo 0001,0,aabbccddeeff;0004,1,112233445566;"]
self._test_function("extract_mac", args)
self._assert(1)
def test_is_locally_administered_mac_yes(self):
local_macs = ["0a0000000000", "020000000000", "060000000000",
"0e0000000000"]
for mac in local_macs:
self._test_function("is_locally_administered_mac", [mac])
self._assert(0)
def test_is_locally_administered_mac_no(self):
local_macs = ["010000000000", "030000000000", "040000000000",
"050000000000", "070000000000", "080000000000",
"090000000000", "0b0000000000", "0c0000000000",
"0d0000000000"]
for mac in local_macs:
self._test_function("is_locally_administered_mac", [mac])
self._assert(1)
def test_get_ip_cmd(self):
self._test_function("get_ip_cmd", [])
self._assert(0, test_root_dir + "/sbin/ip")
def test_set_mac(self):
self._test_function("set_mac", ["eth0", "0a0000000000"])
self._assert(0)
def test_device_exists(self):
self._test_function("device_exists", ["0.0.0001"])
self._assert(0)
def test_device_exists_not(self):
self._test_function("device_exists", ["0.0.0002"])
self._assert(1)
def test_get_cmdline(self):
self._test_function("get_cmdline", [])
self._assert(0, "this-is-the-cmd-line")
def test_configure_device(self):
self._test_function("configure_device", ["0.0.0001", "1"])
self._assert(0)
def test_configure_device_fail(self):
self._test_function("configure_device", ["foo", "1"])
self._assert(1)
def test_get_device_bus_id(self):
self._test_function("get_device_bus_id", ["0001"])
self._assert(0, "0.0.0001")
def test__change_root_cmd(self):
self._test_function("_change_root", ["cmd"])
self._assert(0, test_root_dir + "/cmd")
def test__change_root_cmd_no_root_dir_set(self):
# Unset the default root dir variable
self.env = dict()
self._test_function("_change_root", ["cmd"])
self._assert(0, "cmd")
def test__change_root_path(self):
self._test_function("_change_root", ["/foo/bar"])
self._assert(0, test_root_dir + "/foo/bar")
def test__change_root_path_no_root_dir_set(self):
# Unset the default root dir variable
self.env = dict()
self._test_function("_change_root", ["/foo/bar"])
self._assert(0, "/foo/bar")

View File

@ -0,0 +1,39 @@
#! /bin/bash
# Copyright 2017 IBM Corp. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This is a test wrapper. It's only job is to help executing certain functions
# of other shell scripts.
# This script is called from the projects root directory. Therefore all paths
# must be specified relative to it.
# Manual execution
# nova_dpm/tests/unit/guest_image_tools/test_wrapper.sh <method_name> <args>
source guest_image_tools/usr/bin/dpm_guest_image_tools_common
# $1 = The function to be called
# $2,3... = the parameters for the function
func="$1"
# Remove the first argument from $@
shift 1
# Make sure only defined function are called
if [[ $(type -t $func) == "function" ]]; then
# Call function with arguments passed in as $2,3,...
$func "$@"
exit $?
else
exit 1
fi