Fix apk handling of warnings/output problems

The parsing is still weak, but we do get around warnings or anything
else on stderr that would trip it up. This required refactoring the
tests which were mocking subprocess.check_output instead of
Popen/communicate which is what we use now.

Change-Id: Ie2d2fdfd27c728508213b4d23d3b58ad81a68ad2
This commit is contained in:
Clint Byrum 2018-09-13 13:06:48 -07:00
parent bacfe22438
commit be328a624d
2 changed files with 35 additions and 26 deletions

View File

@ -546,14 +546,12 @@ class Apk(Platform):
"""
def get_pkg_version(self, pkg_name):
try:
output = subprocess.check_output(
['apk', 'version', pkg_name],
stderr=subprocess.STDOUT).decode(getpreferredencoding(False))
except subprocess.CalledProcessError as e:
if e.returncode == 1:
return None
raise
apk = subprocess.Popen(
['apk', 'version', pkg_name], stdout=subprocess.PIPE)
output, _ = apk.communicate()
if apk.returncode == 1:
return None
output = output.decode(getpreferredencoding(False))
# output looks like
# version
output = output.strip()

View File

@ -715,32 +715,43 @@ class TestPacman(TestCase):
class TestApk(TestCase):
def test_unknown_package(self):
@mock.patch('subprocess.Popen')
def test_unknown_package(self, mock_popen):
platform = Apk()
def _side_effect_raise(*args, **kwargs):
raise subprocess.CalledProcessError(
1, [], b"Installed: Available:")
mock_checkoutput = self.useFixture(
fixtures.MockPatchObject(subprocess, "check_output")).mock
mock_checkoutput.side_effect = _side_effect_raise
proc_mock = mock.Mock()
proc_mock.communicate.return_value = (b'Installed: Available:\n', b'')
mock_popen.returncode = 1
mock_popen.return_value = proc_mock
self.assertEqual(None, platform.get_pkg_version("foo"))
mock_checkoutput.assert_called_once_with(
['apk', 'version', 'foo'],
stderr=subprocess.STDOUT)
mock_popen.assert_called_once_with(
['apk', 'version', 'foo'], stdout=subprocess.PIPE)
self.assertEqual(None, platform.get_pkg_version("foo"))
def test_installed_version(self):
@mock.patch('subprocess.Popen')
def test_installed_version(self, mock_popen):
platform = Apk()
mock_checkoutput = self.useFixture(
fixtures.MockPatchObject(subprocess, "check_output")).mock
mock_checkoutput.return_value = b'Insd: Able: foo-4.0.0-r1 = 4.0.0-r1'
proc_mock = mock.Mock()
proc_mock.communicate.return_value = (
b'Insd: Able: foo-4.0.0-r1 = 4.0.0-r1', b'')
mock_popen.return_value = proc_mock
self.assertEqual('4.0.0-r1', platform.get_pkg_version("foo"))
mock_checkoutput.assert_called_once_with(
['apk', 'version', 'foo'],
stderr=subprocess.STDOUT)
mock_popen.assert_called_once_with(
['apk', 'version', 'foo'], stdout=subprocess.PIPE)
@mock.patch('subprocess.Popen')
def test_handles_warnings(self, mock_popen):
platform = Apk()
process_mock = mock.Mock()
values = b'Installed: Available:\n'
warnings = b'WARNING: Ignoring APKINDEX.blah\nWARNING2: blah blah\n'
process_mock.communicate.return_value = (values, warnings)
mock_popen.return_value = process_mock
self.assertIsNone(platform.get_pkg_version("bar"))
mock_popen.assert_called_once_with(
['apk', 'version', 'bar'], stdout=subprocess.PIPE)
class TestRpm(TestCase):