diff options
| -rw-r--r-- | meta/lib/oeqa/selftest/devtool.py | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/meta/lib/oeqa/selftest/devtool.py b/meta/lib/oeqa/selftest/devtool.py new file mode 100644 index 0000000000..e8ff536c16 --- /dev/null +++ b/meta/lib/oeqa/selftest/devtool.py | |||
| @@ -0,0 +1,239 @@ | |||
| 1 | import unittest | ||
| 2 | import os | ||
| 3 | import logging | ||
| 4 | import re | ||
| 5 | import shutil | ||
| 6 | import tempfile | ||
| 7 | import glob | ||
| 8 | |||
| 9 | import oeqa.utils.ftools as ftools | ||
| 10 | from oeqa.selftest.base import oeSelfTest | ||
| 11 | from oeqa.utils.commands import runCmd, bitbake, get_bb_var | ||
| 12 | from oeqa.utils.decorators import testcase | ||
| 13 | |||
| 14 | class DevtoolTests(oeSelfTest): | ||
| 15 | |||
| 16 | def test_create_workspace(self): | ||
| 17 | # Check preconditions | ||
| 18 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
| 19 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
| 20 | result = runCmd('bitbake-layers show-layers') | ||
| 21 | self.assertTrue('/workspace' not in result.output, 'This test cannot be run with a workspace layer in bblayers.conf') | ||
| 22 | # Try creating a workspace layer with a specific path | ||
| 23 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
| 24 | self.track_for_cleanup(tempdir) | ||
| 25 | result = runCmd('devtool create-workspace %s' % tempdir) | ||
| 26 | self.assertTrue(os.path.isfile(os.path.join(tempdir, 'conf', 'layer.conf'))) | ||
| 27 | result = runCmd('bitbake-layers show-layers') | ||
| 28 | self.assertTrue(tempdir in result.output) | ||
| 29 | # Try creating a workspace layer with the default path | ||
| 30 | self.track_for_cleanup(workspacedir) | ||
| 31 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
| 32 | result = runCmd('devtool create-workspace') | ||
| 33 | self.assertTrue(os.path.isfile(os.path.join(workspacedir, 'conf', 'layer.conf'))) | ||
| 34 | result = runCmd('bitbake-layers show-layers') | ||
| 35 | self.assertTrue(tempdir not in result.output) | ||
| 36 | self.assertTrue(workspacedir in result.output) | ||
| 37 | |||
| 38 | def test_recipetool_create(self): | ||
| 39 | # Try adding a recipe | ||
| 40 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
| 41 | self.track_for_cleanup(tempdir) | ||
| 42 | tempsrc = os.path.join(tempdir, 'srctree') | ||
| 43 | os.makedirs(tempsrc) | ||
| 44 | recipefile = os.path.join(tempdir, 'logrotate_3.8.7.bb') | ||
| 45 | srcuri = 'https://fedorahosted.org/releases/l/o/logrotate/logrotate-3.8.7.tar.gz' | ||
| 46 | result = runCmd('recipetool create -o %s %s -x %s' % (recipefile, srcuri, tempsrc)) | ||
| 47 | self.assertTrue(os.path.isfile(recipefile)) | ||
| 48 | checkvars = {} | ||
| 49 | checkvars['LICENSE'] = 'GPLv2' | ||
| 50 | checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=18810669f13b87348459e611d31ab760' | ||
| 51 | checkvars['SRC_URI'] = 'https://fedorahosted.org/releases/l/o/logrotate/logrotate-${PV}.tar.gz' | ||
| 52 | checkvars['SRC_URI[md5sum]'] = '99e08503ef24c3e2e3ff74cc5f3be213' | ||
| 53 | checkvars['SRC_URI[sha256sum]'] = 'f6ba691f40e30e640efa2752c1f9499a3f9738257660994de70a45fe00d12b64' | ||
| 54 | with open(recipefile, 'r') as f: | ||
| 55 | for line in f: | ||
| 56 | if '=' in line: | ||
| 57 | splitline = line.split('=', 1) | ||
| 58 | var = splitline[0].rstrip() | ||
| 59 | value = splitline[1].strip().strip('"') | ||
| 60 | if var in checkvars: | ||
| 61 | needvalue = checkvars.pop(var) | ||
| 62 | self.assertEqual(value, needvalue) | ||
| 63 | if line.startswith('inherit '): | ||
| 64 | inherits = line.split()[1:] | ||
| 65 | |||
| 66 | self.assertEqual(checkvars, {}, 'Some variables not found') | ||
| 67 | |||
| 68 | def test_recipetool_create_git(self): | ||
| 69 | # Try adding a recipe | ||
| 70 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
| 71 | self.track_for_cleanup(tempdir) | ||
| 72 | tempsrc = os.path.join(tempdir, 'srctree') | ||
| 73 | os.makedirs(tempsrc) | ||
| 74 | recipefile = os.path.join(tempdir, 'libmatchbox.bb') | ||
| 75 | srcuri = 'git://git.yoctoproject.org/libmatchbox' | ||
| 76 | result = runCmd('recipetool create -o %s %s -x %s' % (recipefile, srcuri, tempsrc)) | ||
| 77 | self.assertTrue(os.path.isfile(recipefile)) | ||
| 78 | checkvars = {} | ||
| 79 | checkvars['LICENSE'] = 'LGPLv2.1' | ||
| 80 | checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=7fbc338309ac38fefcd64b04bb903e34' | ||
| 81 | checkvars['S'] = '${WORKDIR}/git' | ||
| 82 | checkvars['PV'] = '1.0+git${SRCPV}' | ||
| 83 | checkvars['SRC_URI'] = srcuri | ||
| 84 | checkvars['DEPENDS'] = 'libpng pango libx11 libxext' | ||
| 85 | inherits = [] | ||
| 86 | with open(recipefile, 'r') as f: | ||
| 87 | for line in f: | ||
| 88 | if '=' in line: | ||
| 89 | splitline = line.split('=', 1) | ||
| 90 | var = splitline[0].rstrip() | ||
| 91 | value = splitline[1].strip().strip('"') | ||
| 92 | if var in checkvars: | ||
| 93 | needvalue = checkvars.pop(var) | ||
| 94 | self.assertEqual(value, needvalue) | ||
| 95 | if line.startswith('inherit '): | ||
| 96 | inherits = line.split()[1:] | ||
| 97 | |||
| 98 | self.assertEqual(checkvars, {}, 'Some variables not found') | ||
| 99 | |||
| 100 | self.assertIn('autotools', inherits, 'Missing inherit of autotools') | ||
| 101 | self.assertIn('pkgconfig', inherits, 'Missing inherit of pkgconfig') | ||
| 102 | |||
| 103 | def test_devtool_add(self): | ||
| 104 | # Check preconditions | ||
| 105 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
| 106 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
| 107 | # Fetch source | ||
| 108 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
| 109 | self.track_for_cleanup(tempdir) | ||
| 110 | url = 'http://www.ivarch.com/programs/sources/pv-1.5.3.tar.bz2' | ||
| 111 | result = runCmd('wget %s' % url, cwd=tempdir) | ||
| 112 | result = runCmd('tar xfv pv-1.5.3.tar.bz2', cwd=tempdir) | ||
| 113 | srcdir = os.path.join(tempdir, 'pv-1.5.3') | ||
| 114 | self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure'))) | ||
| 115 | # Test devtool add | ||
| 116 | self.track_for_cleanup(workspacedir) | ||
| 117 | self.add_command_to_tearDown('bitbake -c cleansstate pv') | ||
| 118 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
| 119 | result = runCmd('devtool add pv %s' % srcdir) | ||
| 120 | self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created') | ||
| 121 | # Test devtool status | ||
| 122 | result = runCmd('devtool status') | ||
| 123 | self.assertIn('pv', result.output) | ||
| 124 | self.assertIn(srcdir, result.output) | ||
| 125 | # Clean up anything in the workdir/sysroot/sstate cache (have to do this *after* devtool add since the recipe only exists then) | ||
| 126 | bitbake('pv -c cleansstate') | ||
| 127 | # Test devtool build | ||
| 128 | result = runCmd('devtool build pv') | ||
| 129 | installdir = get_bb_var('D', 'pv') | ||
| 130 | self.assertTrue(installdir) | ||
| 131 | bindir = get_bb_var('bindir', 'pv') | ||
| 132 | self.assertTrue(bindir) | ||
| 133 | if bindir[0] == '/': | ||
| 134 | bindir = bindir[1:] | ||
| 135 | self.assertTrue(os.path.isfile(os.path.join(installdir, bindir, 'pv')), 'pv binary not found in D') | ||
| 136 | |||
| 137 | def test_devtool_modify(self): | ||
| 138 | # Check preconditions | ||
| 139 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
| 140 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
| 141 | # Clean up anything in the workdir/sysroot/sstate cache | ||
| 142 | bitbake('mdadm -c cleansstate') | ||
| 143 | # Try modifying a recipe | ||
| 144 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
| 145 | self.track_for_cleanup(tempdir) | ||
| 146 | self.track_for_cleanup(workspacedir) | ||
| 147 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
| 148 | self.add_command_to_tearDown('bitbake -c clean mdadm') | ||
| 149 | result = runCmd('devtool modify mdadm -x %s' % tempdir) | ||
| 150 | self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile')), 'Extracted source could not be found') | ||
| 151 | self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found') | ||
| 152 | self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created') | ||
| 153 | matches = glob.glob(os.path.join(workspacedir, 'appends', 'mdadm_*.bbappend')) | ||
| 154 | self.assertTrue(matches, 'bbappend not created') | ||
| 155 | # Test devtool status | ||
| 156 | result = runCmd('devtool status') | ||
| 157 | self.assertIn('mdadm', result.output) | ||
| 158 | self.assertIn(tempdir, result.output) | ||
| 159 | # Check git repo | ||
| 160 | result = runCmd('git status --porcelain', cwd=tempdir) | ||
| 161 | self.assertEqual(result.output.strip(), "", 'Created git repo is not clean') | ||
| 162 | result = runCmd('git symbolic-ref HEAD', cwd=tempdir) | ||
| 163 | self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo') | ||
| 164 | # Try building | ||
| 165 | bitbake('mdadm') | ||
| 166 | # Try making (minor) modifications to the source | ||
| 167 | result = runCmd("sed -i 's!^\.TH.*!.TH MDADM 8 \"\" v9.999-custom!' %s" % os.path.join(tempdir, 'mdadm.8.in')) | ||
| 168 | bitbake('mdadm -c package') | ||
| 169 | pkgd = get_bb_var('PKGD', 'mdadm') | ||
| 170 | self.assertTrue(pkgd) | ||
| 171 | mandir = get_bb_var('mandir', 'mdadm') | ||
| 172 | self.assertTrue(mandir) | ||
| 173 | if mandir[0] == '/': | ||
| 174 | mandir = mandir[1:] | ||
| 175 | with open(os.path.join(pkgd, mandir, 'man8', 'mdadm.8'), 'r') as f: | ||
| 176 | for line in f: | ||
| 177 | if line.startswith('.TH'): | ||
| 178 | self.assertEqual(line.rstrip(), '.TH MDADM 8 "" v9.999-custom', 'man file not modified') | ||
| 179 | # Test devtool reset | ||
| 180 | result = runCmd('devtool reset mdadm') | ||
| 181 | result = runCmd('devtool status') | ||
| 182 | self.assertNotIn('mdadm', result.output) | ||
| 183 | |||
| 184 | def test_devtool_update_recipe(self): | ||
| 185 | # Check preconditions | ||
| 186 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
| 187 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
| 188 | testrecipe = 'minicom' | ||
| 189 | recipefile = get_bb_var('FILE', testrecipe) | ||
| 190 | result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) | ||
| 191 | self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe) | ||
| 192 | # First, modify a recipe | ||
| 193 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
| 194 | self.track_for_cleanup(tempdir) | ||
| 195 | self.track_for_cleanup(workspacedir) | ||
| 196 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
| 197 | # (don't bother with cleaning the recipe on teardown, we won't be building it) | ||
| 198 | result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir)) | ||
| 199 | # Check git repo | ||
| 200 | self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found') | ||
| 201 | result = runCmd('git status --porcelain', cwd=tempdir) | ||
| 202 | self.assertEqual(result.output.strip(), "", 'Created git repo is not clean') | ||
| 203 | result = runCmd('git symbolic-ref HEAD', cwd=tempdir) | ||
| 204 | self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo') | ||
| 205 | # Add a couple of commits | ||
| 206 | # FIXME: this only tests adding, need to also test update and remove | ||
| 207 | result = runCmd('echo "Additional line" >> README', cwd=tempdir) | ||
| 208 | result = runCmd('git commit -a -m "Change the README"', cwd=tempdir) | ||
| 209 | result = runCmd('echo "A new file" > devtool-new-file', cwd=tempdir) | ||
| 210 | result = runCmd('git add devtool-new-file', cwd=tempdir) | ||
| 211 | result = runCmd('git commit -m "Add a new file"', cwd=tempdir) | ||
| 212 | self.add_command_to_tearDown('cd %s; rm %s/*.patch; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile))) | ||
| 213 | result = runCmd('devtool update-recipe %s' % testrecipe) | ||
| 214 | result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile)) | ||
| 215 | self.assertNotEqual(result.output.strip(), "", '%s recipe should be modified' % testrecipe) | ||
| 216 | status = result.output.splitlines() | ||
| 217 | self.assertEqual(len(status), 3, 'Less/more files modified than expected. Entire status:\n%s' % result.output) | ||
| 218 | for line in status: | ||
| 219 | if line.endswith('0001-Change-the-README.patch'): | ||
| 220 | self.assertEqual(line[:3], '?? ', 'Unexpected status in line: %s' % line) | ||
| 221 | elif line.endswith('0002-Add-a-new-file.patch'): | ||
| 222 | self.assertEqual(line[:3], '?? ', 'Unexpected status in line: %s' % line) | ||
| 223 | elif re.search('minicom_[^_]*.bb$', line): | ||
| 224 | self.assertEqual(line[:3], ' M ', 'Unexpected status in line: %s' % line) | ||
| 225 | else: | ||
| 226 | self.assertTrue(False, 'Unexpected modified file in status: %s' % line) | ||
| 227 | |||
| 228 | def test_devtool_extract(self): | ||
| 229 | # Check preconditions | ||
| 230 | workspacedir = os.path.join(self.builddir, 'workspace') | ||
| 231 | self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory') | ||
| 232 | tempdir = tempfile.mkdtemp(prefix='devtoolqa') | ||
| 233 | # Try devtool extract | ||
| 234 | self.track_for_cleanup(tempdir) | ||
| 235 | self.track_for_cleanup(workspacedir) | ||
| 236 | self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') | ||
| 237 | result = runCmd('devtool extract remake %s' % tempdir) | ||
| 238 | self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile.am')), 'Extracted source could not be found') | ||
| 239 | self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found') | ||
