diff --git a/boottest.py b/boottest.py index 1ae174c..ec4682e 100644 --- a/boottest.py +++ b/boottest.py @@ -11,7 +11,52 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -from __future__ import print_function +import os + + +class TouchManifest(object): + """Parses a corresponding touch image manifest. + + Based on http://cdimage.u.c/ubuntu-touch/daily-preinstalled/pending/vivid-preinstalled-touch-armhf.manifest + + Assumes the deployment is arranged in a way the manifest is available + and fresh on: + + 'data/boottest/{distribution}/{series}/manifest' + + Only binary name matters, version is ignored, so callsites can: + + >>> manifest = TouchManifest('ubuntu', 'vivid') + >>> 'webbrowser-app' in manifest + True + >>> 'firefox' in manifest + False + + """ + + def __init__(self, distribution, series): + self.path = 'data/boottest/{}/{}/manifest'.format( + distribution, series) + self._manifest = self._load() + + def _load(self): + pkg_list = [] + + if not os.path.exists(self.path): + return pkg_list + + with open(self.path) as fd: + for line in fd.readlines(): + name, version = line.split() + name = name.split(':')[0] + if name == 'click': + continue + pkg_list.append(name) + + return sorted(pkg_list) + + def __contains__(self, key): + return key in self._manifest class BootTest(object): @@ -25,16 +70,7 @@ class BootTest(object): self.distribution = distribution self.series = series self.debug = debug - - - def _source_in_image(self, name): - """Whether or not the given source name is in the phone image.""" - # XXX cprov 20150120: replace with a phone image manifest/content - # check. - if name == 'apache2': - return False - - return True + self.phone_manifest = TouchManifest(self.distribution, self.series) def _get_status_label(self, name, version): """Return the current boottest status label.""" @@ -53,7 +89,7 @@ class BootTest(object): Annotate skipped packages (currently not in phone image) or add the current testing status (see `_get_status_label`). """ - if not self._source_in_image(excuse.name): + if excuse.name not in self.phone_manifest: label = 'SKIPPED' else: label = self._get_status_label(excuse.name, excuse.ver[1]) diff --git a/tests/test_boottest.py b/tests/test_boottest.py index 93e2789..92b7cb8 100644 --- a/tests/test_boottest.py +++ b/tests/test_boottest.py @@ -7,7 +7,9 @@ # (at your option) any later version. import os +import shutil import sys +import tempfile import unittest @@ -15,6 +17,53 @@ PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, PROJECT_DIR) from tests import TestBase +from boottest import TouchManifest + + +def create_manifest(manifest_dir, lines): + """Helper function for writing touch image manifests.""" + os.makedirs(manifest_dir) + with open(os.path.join(manifest_dir, 'manifest'), 'w') as fd: + fd.write('\n'.join(lines)) + + +class TestTouchManifest(unittest.TestCase): + + def setUp(self): + super(TestTouchManifest, self).setUp() + self.path = tempfile.mkdtemp(prefix='boottest') + os.chdir(self.path) + self.datadir = os.path.join(self.path, 'data/boottest/') + os.makedirs(self.datadir) + self.addCleanup(shutil.rmtree, self.path) + + def test_missing(self): + # Missing manifest file silently results in empty contents. + manifest = TouchManifest('ubuntu', 'vivid') + self.assertEqual([], manifest._manifest) + self.assertNotIn('foo', manifest) + + def test_simple(self): + # Existing manifest file allows callsites to properly check presence. + manifest_dir = os.path.join(self.datadir, 'ubuntu/vivid') + manifest_lines = [ + 'bar 1234', + 'foo:armhf 1~beta1', + 'boing1-1.2\t666', + 'click:com.ubuntu.shorts 0.2.346' + ] + create_manifest(manifest_dir, manifest_lines) + + manifest = TouchManifest('ubuntu', 'vivid') + # We can dig deeper on the manifest package names list ... + self.assertEqual( + ['bar', 'boing1-1.2', 'foo'], manifest._manifest) + # but the ' in manifest' API reads better. + self.assertIn('foo', manifest) + self.assertIn('boing1-1.2', manifest) + self.assertNotIn('baz', manifest) + # 'click' name is blacklisted due to the click package syntax. + self.assertNotIn('click', manifest) class TestBoottestEnd2End(TestBase): @@ -33,6 +82,17 @@ class TestBoottestEnd2End(TestBase): 'green', False, {'Depends': 'libc6 (>= 0.9), libgreen1'}) + self.create_manifest([ + 'green 1.0', + 'pyqt5:armhf 1.0', + ]) + + def create_manifest(self, lines): + """Create a manifest for this britney run context.""" + path = os.path.join( + self.data.path, + 'data/boottest/ubuntu/{}'.format(self.data.series)) + create_manifest(path, lines) def do_test(self, context, expect=None, no_expect=None): """Process the given package context and assert britney results."""