Skip to content

Commit

Permalink
tests: add dd_tests
Browse files Browse the repository at this point in the history
Add a test suite for the dd_list and dd_extract utilities (in utils/dd).

Note that there are two tests that fail here - test_dd_extract_chmod()
covers a known bug (#1222056), but test_dd_extract_libs() fails due to a
previously-unknown bug in the handling of `dd_extract --libraries`.

So, y'know. If you want proof that writing tests *does* help find/fix
bugs..  there you go!
  • Loading branch information
wgwoods committed Jun 24, 2015
1 parent 111a7d4 commit 6d0f0d1
Showing 1 changed file with 252 additions and 0 deletions.
252 changes: 252 additions & 0 deletions tests/dd_tests/dd_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
#!/usr/bin/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

TOP_SRCDIR = os.environ.get("top_srcdir", "../..")
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'))
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)
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."):
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]))

0 comments on commit 6d0f0d1

Please sign in to comment.