#!/usr/bin/python
import mock
# subp returns basically stdout and stderr of invoking the command
#
##
## I'm trying to write and test a 'lsb_release()' function
## which returns basically what lsb_release --<codename|release> would do
## i'd like to cache the result for future calls, and
## am doing that via use of a global
##
## since the 'util' module is only opened once, the cache of __lsb_release
## is working correctly, and my tests are not able to wrap
## calls to the 'lsb_release' command. since the result gets cached.
##
## Note, though that using 'reset_lsb()' works as expected.
__lsb_release = None
def reset_lsb():
global __lsb_release
__lsb_release = None
def lsb_release(field="codename"):
fields = ('description', 'release', 'codename', 'id')
if field not in fields:
raise ValueError("Invalid field: %s. Must be one of %s" %
(field, ','.join(fields)))
global __lsb_release
if __lsb_release is None:
data = {}
for k in fields:
try:
out, err = subp(['lsb_release', '--short', '--%s' % k],
capture=True)
data[k] = out.strip()
except ProcessExecutionError as e:
LOG.warn("Unable to get lsb_release/%s: %s", k, e)
data[k] = "UNAVAILABLE"
__lsb_release = data
return __lsb_release
## test classes
class TestLsbRelease(TestCase):
@mock.patch("curtin.util.subp")
def test_expected(self, mock_subp):
### HELP ####
## This works
util.__reset_lsb()
## This does not. The __lsb_release doesn't get set to None
## and the cached value from the other run is used.
#util.__lsb_release = None
rdata = {'id': 'Ubuntu', 'description': 'Ubuntu 14.04.3 LTS',
'codename': 'trusty', 'release': '14.04'}
def fake_subp(cmd, capture=False):
if cmd[0:2] == ["lsb_release", "--short"]:
field = cmd[2].replace("--", "")
return (rdata[field], "")
return mock.DEFAULT
mock_subp.side_effect = fake_subp
found = util.lsb_release()
mock_subp.assert_called_with(['lsb_release', '--short', '--id'],
capture=True)
self.assertEqual(found, rdata)
@mock.patch("curtin.util.subp")
def test_unavailable(self, mock_subp):
util.__lsb_release = None
def doraise(*args, **kwargs):
raise util.ProcessExecutionError("bar")
mock_subp.side_effect = doraise
expected = {k: "UNAVAILABLE" for k in
('id', 'description', 'codename', 'release')}
self.assertEqual(util.lsb_release(), expected)