6bc5671491
Apply: git diff --full-index --binary anaconda-23.19.10-1..anaconda-25.20.9-1 And resolve conflicts. QubesOS/qubes-issues#2574
254 lines
9.1 KiB
Python
254 lines
9.1 KiB
Python
# unit tests for driver disk utilities (utils/dd)
|
|
|
|
import os
|
|
import shutil
|
|
import unittest
|
|
import tempfile
|
|
import subprocess
|
|
|
|
from contextlib import contextmanager
|
|
from collections import namedtuple
|
|
from rpmfluff import SourceFile, SimpleRpmBuild, expectedArch
|
|
from shutup import shutup
|
|
|
|
TOP_SRCDIR = os.environ.get("top_builddir", "../..")
|
|
UTILDIR = os.path.join(TOP_SRCDIR, "utils/dd")
|
|
|
|
# helpers for calling the utilities
|
|
Driver = namedtuple("Driver", "source name flags description")
|
|
def dd_list(dd_path, kernel_ver, anaconda_ver):
|
|
out = subprocess.check_output([os.path.join(UTILDIR, "dd_list"),
|
|
'-d', dd_path, '-k', kernel_ver, '-a', anaconda_ver],
|
|
stderr=open('/dev/null')).decode('utf-8')
|
|
return [Driver(*d.split('\n',3)) for d in out.split('\n---\n')[:-1]]
|
|
|
|
def dd_extract(rpm_path, outdir, kernel_ver, flags='-blmf'):
|
|
out = subprocess.check_output([os.path.join(UTILDIR, "dd_extract"),
|
|
flags, '-r', rpm_path, '-d', outdir, '-k', kernel_ver],
|
|
stderr=subprocess.STDOUT).decode('utf-8')
|
|
return out
|
|
|
|
# helpers for creating RPMs to test with
|
|
@contextmanager
|
|
def in_tempdir(prefix='tmp'):
|
|
oldcwd = os.getcwd()
|
|
tmpdir = tempfile.mkdtemp(prefix=prefix)
|
|
os.chdir(tmpdir)
|
|
yield
|
|
os.chdir(oldcwd)
|
|
shutil.rmtree(tmpdir)
|
|
|
|
def make_rpm(outdir, name='test', version='1.0', release='1', arch=None,
|
|
for_anaconda_ver=None, for_kernel_ver=None,
|
|
payload=None):
|
|
p = SimpleRpmBuild(name, version, release)
|
|
if for_anaconda_ver:
|
|
p.add_provides('installer-enhancement = %s' % for_anaconda_ver)
|
|
if for_kernel_ver:
|
|
p.add_provides('kernel-modules >= %s' % for_kernel_ver)
|
|
if payload is None:
|
|
payload = []
|
|
for item in payload:
|
|
p.add_installed_file(item.path,
|
|
SourceFile(item.srcpath, item.contents),
|
|
**item.kwargs)
|
|
with in_tempdir("anaconda-test-dd."):
|
|
with shutup():
|
|
p.make()
|
|
rpmfile = p.get_built_rpm(arch or expectedArch)
|
|
outfile = os.path.join(outdir, os.path.basename(rpmfile))
|
|
shutil.move(rpmfile, outfile)
|
|
return p
|
|
|
|
class RPMFile(object):
|
|
"""simple container object for information about RPM payloads"""
|
|
def __init__(self, path, srcpath=None, contents='', **kwargs):
|
|
self.path = path
|
|
self.srcpath = srcpath or os.path.basename(path)
|
|
self.contents = contents
|
|
self.kwargs = kwargs
|
|
|
|
binfile = RPMFile(
|
|
path="/usr/bin/fun",
|
|
contents="#!/bin/sh\necho WHEE\n",
|
|
mode="0755"
|
|
)
|
|
libfile = RPMFile(
|
|
path="/usr/lib/fun.so",
|
|
contents="I AM TOTALLY A SHARED LIBRARY",
|
|
mode="0755"
|
|
)
|
|
fwfile = RPMFile(
|
|
path="/lib/firmware/fun.fw",
|
|
contents="HELLO I AM FIRMWARE"
|
|
)
|
|
kofile = RPMFile(
|
|
path="/lib/modules/KERNELVER/extra/net/fun.ko",
|
|
contents="KERNEL MODULE??? YOU BETCHA"
|
|
)
|
|
|
|
# Finally, the actual test cases
|
|
class ASelfTestCase(unittest.TestCase):
|
|
def setUp(self):
|
|
self.tmpdir = tempfile.mkdtemp(prefix="dd_tests.")
|
|
|
|
def tearDown(self):
|
|
shutil.rmtree(self.tmpdir)
|
|
|
|
def test_rpmfluff_simple(self):
|
|
"""check if rpmfluff is working"""
|
|
p = make_rpm(outdir=self.tmpdir)
|
|
rpmfile = os.path.basename(p.get_built_rpm(expectedArch))
|
|
self.assertTrue(rpmfile in os.listdir(self.tmpdir))
|
|
|
|
def test_rpmfluff_payload(self):
|
|
"""check if rpmfluff can add files to built RPMs"""
|
|
p = make_rpm(outdir=self.tmpdir, payload=(binfile, kofile))
|
|
rpmfile = os.path.basename(p.get_built_rpm(expectedArch))
|
|
self.assertTrue(rpmfile in os.listdir(self.tmpdir))
|
|
|
|
def test_utils_exist(self):
|
|
"""check that the dd utilities exist"""
|
|
self.assertTrue("dd_list" in os.listdir(UTILDIR))
|
|
self.assertTrue("dd_extract" in os.listdir(UTILDIR))
|
|
|
|
class DD_List_TestCase(unittest.TestCase):
|
|
def setUp(self):
|
|
self.tmpdir = tempfile.mkdtemp(prefix="dd_tests.")
|
|
self.k_ver = "4.1.4-333"
|
|
self.a_ver = "22.0"
|
|
|
|
def dd_list(self, dd_dir=None, kernel_ver=None, anaconda_ver=None):
|
|
return dd_list(dd_dir or self.tmpdir,
|
|
kernel_ver or self.k_ver,
|
|
anaconda_ver or self.a_ver)
|
|
|
|
def tearDown(self):
|
|
shutil.rmtree(self.tmpdir)
|
|
|
|
def test_dd_list(self):
|
|
"""dd_list: check output format"""
|
|
rpm = make_rpm(self.tmpdir, for_kernel_ver=self.k_ver)
|
|
drivers = self.dd_list()
|
|
self.assertEqual(len(drivers), 1)
|
|
d = drivers[0]
|
|
self.assertEqual(d.name, rpm.name)
|
|
self.assertEqual(d.description, rpm.basePackage.description)
|
|
self.assertTrue(d.description)
|
|
self.assertTrue(os.path.exists(d.source))
|
|
self.assertIn("modules", d.flags)
|
|
self.assertIn("firmwares", d.flags)
|
|
self.assertNotIn("binaries", d.flags)
|
|
self.assertNotIn("libraries", d.flags)
|
|
|
|
def test_dd_list_multiple(self):
|
|
"""dd_list: multiple outputs for multiple packages"""
|
|
names = ['fun', 'even_more_fun', 'too_much_fun']
|
|
for name in names:
|
|
make_rpm(self.tmpdir, name=name, for_kernel_ver=self.k_ver)
|
|
drivers = self.dd_list()
|
|
self.assertEqual(len(drivers), len(names))
|
|
self.assertEqual(set(d.name for d in drivers), set(names))
|
|
|
|
def test_dd_list_binaries(self):
|
|
"""dd_list: 'Provides:installer-enhancement' implies bins/libs"""
|
|
make_rpm(self.tmpdir, for_anaconda_ver=self.a_ver)
|
|
drivers = self.dd_list()
|
|
self.assertFalse(drivers == [])
|
|
d = drivers[0]
|
|
self.assertIn("binaries", d.flags)
|
|
self.assertIn("libraries", d.flags)
|
|
self.assertNotIn("modules", d.flags)
|
|
self.assertNotIn("firmwares", d.flags)
|
|
|
|
def test_dd_list_old_kmods(self):
|
|
"""dd_list: ignore kmods if our kernel is too old"""
|
|
make_rpm(self.tmpdir, for_kernel_ver="5.0.1-555")
|
|
self.assertEqual(self.dd_list(), [])
|
|
|
|
def test_dd_list_z_stream_kmods(self):
|
|
"""dd_list: accept kmods for z-stream kernels (#1207831)"""
|
|
make_rpm(self.tmpdir, for_kernel_ver=self.k_ver)
|
|
drivers = self.dd_list(kernel_ver=self.k_ver+".3")
|
|
self.assertNotEqual(drivers, [])
|
|
d = drivers[0]
|
|
self.assertIn("modules", d.flags)
|
|
|
|
def test_dd_list_anaconda_old(self):
|
|
"""dd_list: ignore installer-enhancements if version doesn't match"""
|
|
make_rpm(self.tmpdir, for_anaconda_ver="23.0")
|
|
self.assertEqual(self.dd_list(), [])
|
|
|
|
def test_dd_list_no_rpms(self):
|
|
"""dd_list: empty directory returns no results"""
|
|
self.assertEqual(self.dd_list(), [])
|
|
|
|
def test_dd_list_missing_dir(self):
|
|
"""dd_list: missing directory returns no results"""
|
|
self.assertEqual(self.dd_list(dd_dir="/non/existent/path"), [])
|
|
|
|
def listfiles(dirname):
|
|
return set(os.path.join(root,f)
|
|
for root, dirs, files in os.walk(dirname)
|
|
for f in files)
|
|
|
|
class DD_Extract_TestCase(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(self):
|
|
self.k_ver = "4.1.4-333"
|
|
self.a_ver = "22.0"
|
|
self.tmpdir = tempfile.mkdtemp(prefix="dd_tests.")
|
|
self.rpmpayload = (binfile, kofile, fwfile, libfile)
|
|
make_rpm(self.tmpdir, payload=self.rpmpayload)
|
|
(self.rpmfile,) = listfiles(self.tmpdir)
|
|
|
|
def setUp(self):
|
|
self.outdir = os.path.join(self.tmpdir, "outdir")
|
|
os.mkdir(self.outdir)
|
|
|
|
def dd_extract(self, flags='-bmlf'):
|
|
dd_extract(self.rpmfile, self.outdir, self.k_ver, flags=flags)
|
|
return listfiles(self.outdir)
|
|
|
|
def tearDown(self):
|
|
shutil.rmtree(self.outdir)
|
|
|
|
@classmethod
|
|
def tearDownClass(self):
|
|
shutil.rmtree(self.tmpdir)
|
|
|
|
def test_dd_extract(self):
|
|
"""dd_extract: files are extracted correctly"""
|
|
self.dd_extract()
|
|
for f in self.rpmpayload:
|
|
self.assertEqual(f.contents, open(self.outdir+f.path).read())
|
|
|
|
def test_dd_extract_chmod(self):
|
|
"""dd_extract: files get correct mode (#1222056)"""
|
|
self.dd_extract()
|
|
for f in self.rpmpayload:
|
|
if 'mode' in f.kwargs:
|
|
binmode = os.stat(self.outdir+f.path).st_mode
|
|
expectmode = int(f.kwargs['mode'],8)
|
|
self.assertEqual(binmode & expectmode, expectmode)
|
|
|
|
def test_dd_extract_modules(self):
|
|
"""dd_extract: using --modules extracts only .ko files"""
|
|
outfiles = self.dd_extract(flags='--modules')
|
|
self.assertEqual(outfiles, set([self.outdir+kofile.path]))
|
|
|
|
def test_dd_extract_binaries(self):
|
|
"""dd_extract: using --binaries extracts only /bin, /sbin, etc."""
|
|
outfiles = self.dd_extract(flags='--binaries')
|
|
self.assertEqual(outfiles, set([self.outdir+binfile.path]))
|
|
|
|
def test_dd_extract_libs(self):
|
|
"""dd_extract: using --libraries extracts only /lib etc."""
|
|
outfiles = self.dd_extract(flags='--libraries')
|
|
self.assertEqual(outfiles, set([self.outdir+libfile.path]))
|
|
|
|
def test_dd_extract_firmware(self):
|
|
"""dd_extract: using --firmwares extracts only /lib/firmware"""
|
|
outfiles = self.dd_extract(flags='--firmwares')
|
|
self.assertEqual(outfiles, set([self.outdir+fwfile.path]))
|