diskimage-builder/diskimage_builder/elements/package-installs/tests/test_package_squash.py
Ian Wienand b71d1c60d2 package-installs : allow a list of parameters
The change Ia6f10741fa6be24b11d6991c8a6b6e07951ff68d introduced having
"when:" as a list of values.  However, this was actually not
sufficient to express the logic required for arm64/x86_64/xenial
kernel matching we wanted.

Because the package name is a key, we can't have multiple entires in
the package-map YAML files.  This means we can't do more advanced
matching and thus we need to be able to match through multiple
parameters.  Similar to Ia6f10741fa6be24b11d6991c8a6b6e07951ff68d we
modify the matching rules to allow a list.

A an example of using this is provided in the README.rst, and this
same example worked through by the unit tests.

This also slightly updates the matching logic to be more sequential.
After each check we either continue on or log the failure and continue
to the next check (rather than set a list of flags then check that at
the end).  This makes it much easier to understand what is being
matched in the logging output from the tool.

Change-Id: Idff7b067ad4255e6fc4138f7eff313a81b75c8ba
2020-05-27 06:17:57 +10:00

225 lines
7.3 KiB
Python

# Copyright 2018 Red Hat, Inc.
#
# 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 collections
import functools
import imp
import mock
import os
from oslotest import base
from testtools.matchers import Mismatch
installs_squash_src = (os.path.dirname(os.path.realpath(__file__)) +
'/../bin/package-installs-squash')
installs_squash = imp.load_source('installs_squash', installs_squash_src)
class IsMatchingInstallList(object):
def __init__(self, expected):
self.expected = expected
def match(self, actual):
for phase, ops in self.expected.items():
if phase not in actual:
# missing the phase
return Mismatch(
"Phase %d does not exist in %s" % (phase, actual))
for op, pkgs in ops.items():
if op not in actual[phase]:
# missing op (install/uninstall)
return Mismatch(
"Operation %s does not exist in %s" % (op, ops))
# on py2 these can be out of order, we just want a match
expected_phase_ops = sorted(self.expected[phase][op])
actual_phase_ops = sorted(actual[phase][op])
if expected_phase_ops != actual_phase_ops:
return Mismatch(
"Operation list %s does not match expected %s" %
(actual[phase][op], self.expected[phase][op]))
class TestPackageInstall(base.BaseTestCase):
def setUp(self):
super(TestPackageInstall, self).setUp()
self.final_dict = collections.defaultdict(
functools.partial(collections.defaultdict, list))
def test_simple(self):
'''Test a basic package install'''
objs = {
'test_package': ''
}
result = installs_squash.collect_data(
self.final_dict, objs, 'test_element')
expected = {
'install.d': {
'install': [('test_package', 'test_element')]
}
}
self.assertThat(result, IsMatchingInstallList(expected))
@mock.patch.object(os, 'environ', dict(ARCH='arm64', **os.environ))
def test_arch(self):
'''Exercise the arch and not-arch flags'''
objs = {
'test_package': '',
'test_arm64_package': {
'arch': 'arm64'
},
'do_not_install': {
'not-arch': 'arm64'
}
}
result = installs_squash.collect_data(
self.final_dict, objs, 'test_element')
expected = {
'install.d': {
'install': [('test_package', 'test_element'),
('test_arm64_package', 'test_element')]
}
}
self.assertThat(result, IsMatchingInstallList(expected))
kernel_objs = {
'linux-image-generic': [
{
'not-arch': 'arm64',
'when': 'DIB_UBUNTU_KERNEL = linux-image-generic',
},
{
'arch': 'arm64',
'when': (
'DIB_RELEASE != xenial',
'DIB_UBUNTU_KERNEL = linux-image-generic',
)
},
],
'linux-generic-hwe-16.04': {
'arch': 'arm64',
'when': (
'DIB_RELEASE = xenial',
'DIB_UBUNTU_KERNEL = linux-image-generic',
)
},
}
def _test_kernel_objs_match(self, arch, release, expected):
with mock.patch.object(os, 'environ',
dict(ARCH=arch,
DIB_UBUNTU_KERNEL='linux-image-generic',
DIB_RELEASE=release,
**os.environ)):
result = installs_squash.collect_data(
self.final_dict, self.kernel_objs, 'test_element')
expected = {
'install.d': {
'install': [(expected, 'test_element')]
}
}
self.assertThat(result, IsMatchingInstallList(expected))
def test_param_list_x86(self):
self._test_kernel_objs_match('x86_64', 'focal', 'linux-image-generic')
def test_param_list_arm64_xenial(self):
self._test_kernel_objs_match('arm64', 'xenial',
'linux-generic-hwe-16.04')
def test_param_list_arm64_focal(self):
self._test_kernel_objs_match('arm64', 'focal', 'linux-image-generic')
@mock.patch.object(os, 'environ', dict(DIB_FEATURE='1', **os.environ))
def test_skip_when(self):
'''Exercise the when flag'''
objs = {
'skipped_package': {
'when': 'DIB_FEATURE=0'
},
'not_skipped_package': {
'when': 'DIB_FEATURE=1'
},
'not_equal_package': {
'when': 'DIB_FEATURE!=0'
},
'not_equal_skipped_package': {
'when': 'DIB_FEATURE!=1'
},
}
result = installs_squash.collect_data(
self.final_dict, objs, 'test_element')
expected = {
'install.d': {
'install': [('not_skipped_package', 'test_element'),
('not_equal_package', 'test_element')]
}
}
self.assertThat(result, IsMatchingInstallList(expected))
def test_skip_no_var(self):
'''Exercise the skip_when missing variable failure case'''
objs = {
'package': {
'when': 'MISSING_VAR=1'
},
}
self.assertRaises(RuntimeError, installs_squash.collect_data,
self.final_dict, objs, 'test_element')
@mock.patch.object(os, 'environ',
dict(
DIB_A_FEATURE='1',
DIB_B_FEATURE='1',
DIB_C_FEATURE='1',
**os.environ))
def test_skip_when_list(self):
'''Exercise the when flag with lists'''
objs = {
'not_skipped_package': {
'when': [
'DIB_A_FEATURE=1',
'DIB_B_FEATURE=1',
'DIB_C_FEATURE=1'
]
},
'skipped_package': {
'when': [
'DIB_A_FEATURE=1',
'DIB_B_FEATURE=0',
'DIB_C_FEATURE=1',
]
},
}
result = installs_squash.collect_data(
self.final_dict, objs, 'test_element')
expected = {
'install.d': {
'install': [('not_skipped_package', 'test_element')]
}
}
self.assertThat(result, IsMatchingInstallList(expected))