python/mozbuild/mozpack/test/test_manifests.py

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 4
michael@0 5 from __future__ import unicode_literals
michael@0 6
michael@0 7 import os
michael@0 8
michael@0 9 import mozunit
michael@0 10
michael@0 11 from mozpack.copier import (
michael@0 12 FileCopier,
michael@0 13 FileRegistry,
michael@0 14 )
michael@0 15 from mozpack.manifests import (
michael@0 16 InstallManifest,
michael@0 17 )
michael@0 18 from mozpack.test.test_files import TestWithTmpDir
michael@0 19
michael@0 20
michael@0 21 class TestInstallManifest(TestWithTmpDir):
michael@0 22 def test_construct(self):
michael@0 23 m = InstallManifest()
michael@0 24 self.assertEqual(len(m), 0)
michael@0 25
michael@0 26 def test_adds(self):
michael@0 27 m = InstallManifest()
michael@0 28 m.add_symlink('s_source', 's_dest')
michael@0 29 m.add_copy('c_source', 'c_dest')
michael@0 30 m.add_required_exists('e_dest')
michael@0 31 m.add_optional_exists('o_dest')
michael@0 32 m.add_pattern_symlink('ps_base', 'ps/*', 'ps_dest')
michael@0 33 m.add_pattern_copy('pc_base', 'pc/**', 'pc_dest')
michael@0 34 m.add_preprocess('p_source', 'p_dest', 'p_source.pp')
michael@0 35
michael@0 36 self.assertEqual(len(m), 7)
michael@0 37 self.assertIn('s_dest', m)
michael@0 38 self.assertIn('c_dest', m)
michael@0 39 self.assertIn('p_dest', m)
michael@0 40 self.assertIn('e_dest', m)
michael@0 41 self.assertIn('o_dest', m)
michael@0 42
michael@0 43 with self.assertRaises(ValueError):
michael@0 44 m.add_symlink('s_other', 's_dest')
michael@0 45
michael@0 46 with self.assertRaises(ValueError):
michael@0 47 m.add_copy('c_other', 'c_dest')
michael@0 48
michael@0 49 with self.assertRaises(ValueError):
michael@0 50 m.add_preprocess('p_other', 'p_dest', 'p_other.pp')
michael@0 51
michael@0 52 with self.assertRaises(ValueError):
michael@0 53 m.add_required_exists('e_dest')
michael@0 54
michael@0 55 with self.assertRaises(ValueError):
michael@0 56 m.add_optional_exists('o_dest')
michael@0 57
michael@0 58 with self.assertRaises(ValueError):
michael@0 59 m.add_pattern_symlink('ps_base', 'ps/*', 'ps_dest')
michael@0 60
michael@0 61 with self.assertRaises(ValueError):
michael@0 62 m.add_pattern_copy('pc_base', 'pc/**', 'pc_dest')
michael@0 63
michael@0 64 def _get_test_manifest(self):
michael@0 65 m = InstallManifest()
michael@0 66 m.add_symlink(self.tmppath('s_source'), 's_dest')
michael@0 67 m.add_copy(self.tmppath('c_source'), 'c_dest')
michael@0 68 m.add_preprocess(self.tmppath('p_source'), 'p_dest', self.tmppath('p_source.pp'), '#', {'FOO':'BAR', 'BAZ':'QUX'})
michael@0 69 m.add_required_exists('e_dest')
michael@0 70 m.add_optional_exists('o_dest')
michael@0 71 m.add_pattern_symlink('ps_base', '*', 'ps_dest')
michael@0 72 m.add_pattern_copy('pc_base', '**', 'pc_dest')
michael@0 73
michael@0 74 return m
michael@0 75
michael@0 76 def test_serialization(self):
michael@0 77 m = self._get_test_manifest()
michael@0 78
michael@0 79 p = self.tmppath('m')
michael@0 80 m.write(path=p)
michael@0 81 self.assertTrue(os.path.isfile(p))
michael@0 82
michael@0 83 with open(p, 'rb') as fh:
michael@0 84 c = fh.read()
michael@0 85
michael@0 86 self.assertEqual(c.count('\n'), 8)
michael@0 87
michael@0 88 lines = c.splitlines()
michael@0 89 self.assertEqual(len(lines), 8)
michael@0 90
michael@0 91 self.assertEqual(lines[0], '4')
michael@0 92
michael@0 93 m2 = InstallManifest(path=p)
michael@0 94 self.assertEqual(m, m2)
michael@0 95 p2 = self.tmppath('m2')
michael@0 96 m2.write(path=p2)
michael@0 97
michael@0 98 with open(p2, 'rb') as fh:
michael@0 99 c2 = fh.read()
michael@0 100
michael@0 101 self.assertEqual(c, c2)
michael@0 102
michael@0 103 def test_populate_registry(self):
michael@0 104 m = self._get_test_manifest()
michael@0 105 r = FileRegistry()
michael@0 106 m.populate_registry(r)
michael@0 107
michael@0 108 self.assertEqual(len(r), 5)
michael@0 109 self.assertEqual(r.paths(), ['c_dest', 'e_dest', 'o_dest', 'p_dest', 's_dest'])
michael@0 110
michael@0 111 def test_pattern_expansion(self):
michael@0 112 source = self.tmppath('source')
michael@0 113 os.mkdir(source)
michael@0 114 os.mkdir('%s/base' % source)
michael@0 115 os.mkdir('%s/base/foo' % source)
michael@0 116
michael@0 117 with open('%s/base/foo/file1' % source, 'a'):
michael@0 118 pass
michael@0 119
michael@0 120 with open('%s/base/foo/file2' % source, 'a'):
michael@0 121 pass
michael@0 122
michael@0 123 m = InstallManifest()
michael@0 124 m.add_pattern_symlink('%s/base' % source, '**', 'dest')
michael@0 125
michael@0 126 c = FileCopier()
michael@0 127 m.populate_registry(c)
michael@0 128 self.assertEqual(c.paths(), ['dest/foo/file1', 'dest/foo/file2'])
michael@0 129
michael@0 130 def test_or(self):
michael@0 131 m1 = self._get_test_manifest()
michael@0 132 orig_length = len(m1)
michael@0 133 m2 = InstallManifest()
michael@0 134 m2.add_symlink('s_source2', 's_dest2')
michael@0 135 m2.add_copy('c_source2', 'c_dest2')
michael@0 136
michael@0 137 m1 |= m2
michael@0 138
michael@0 139 self.assertEqual(len(m2), 2)
michael@0 140 self.assertEqual(len(m1), orig_length + 2)
michael@0 141
michael@0 142 self.assertIn('s_dest2', m1)
michael@0 143 self.assertIn('c_dest2', m1)
michael@0 144
michael@0 145 def test_copier_application(self):
michael@0 146 dest = self.tmppath('dest')
michael@0 147 os.mkdir(dest)
michael@0 148
michael@0 149 to_delete = self.tmppath('dest/to_delete')
michael@0 150 with open(to_delete, 'a'):
michael@0 151 pass
michael@0 152
michael@0 153 with open(self.tmppath('s_source'), 'wt') as fh:
michael@0 154 fh.write('symlink!')
michael@0 155
michael@0 156 with open(self.tmppath('c_source'), 'wt') as fh:
michael@0 157 fh.write('copy!')
michael@0 158
michael@0 159 with open(self.tmppath('p_source'), 'wt') as fh:
michael@0 160 fh.write('#define FOO 1\npreprocess!')
michael@0 161
michael@0 162 with open(self.tmppath('dest/e_dest'), 'a'):
michael@0 163 pass
michael@0 164
michael@0 165 with open(self.tmppath('dest/o_dest'), 'a'):
michael@0 166 pass
michael@0 167
michael@0 168 m = self._get_test_manifest()
michael@0 169 c = FileCopier()
michael@0 170 m.populate_registry(c)
michael@0 171 result = c.copy(dest)
michael@0 172
michael@0 173 self.assertTrue(os.path.exists(self.tmppath('dest/s_dest')))
michael@0 174 self.assertTrue(os.path.exists(self.tmppath('dest/c_dest')))
michael@0 175 self.assertTrue(os.path.exists(self.tmppath('dest/p_dest')))
michael@0 176 self.assertTrue(os.path.exists(self.tmppath('dest/e_dest')))
michael@0 177 self.assertTrue(os.path.exists(self.tmppath('dest/o_dest')))
michael@0 178 self.assertFalse(os.path.exists(to_delete))
michael@0 179
michael@0 180 with open(self.tmppath('dest/s_dest'), 'rt') as fh:
michael@0 181 self.assertEqual(fh.read(), 'symlink!')
michael@0 182
michael@0 183 with open(self.tmppath('dest/c_dest'), 'rt') as fh:
michael@0 184 self.assertEqual(fh.read(), 'copy!')
michael@0 185
michael@0 186 with open(self.tmppath('dest/p_dest'), 'rt') as fh:
michael@0 187 self.assertEqual(fh.read(), 'preprocess!')
michael@0 188
michael@0 189 self.assertEqual(result.updated_files, set(self.tmppath(p) for p in (
michael@0 190 'dest/s_dest', 'dest/c_dest', 'dest/p_dest')))
michael@0 191 self.assertEqual(result.existing_files,
michael@0 192 set([self.tmppath('dest/e_dest'), self.tmppath('dest/o_dest')]))
michael@0 193 self.assertEqual(result.removed_files, {to_delete})
michael@0 194 self.assertEqual(result.removed_directories, set())
michael@0 195
michael@0 196 def test_preprocessor(self):
michael@0 197 manifest = self.tmppath('m')
michael@0 198 deps = self.tmppath('m.pp')
michael@0 199 dest = self.tmppath('dest')
michael@0 200 include = self.tmppath('p_incl')
michael@0 201
michael@0 202 with open(include, 'wt') as fh:
michael@0 203 fh.write('#define INCL\n')
michael@0 204 time = os.path.getmtime(include) - 3
michael@0 205 os.utime(include, (time, time))
michael@0 206
michael@0 207 with open(self.tmppath('p_source'), 'wt') as fh:
michael@0 208 fh.write('#ifdef FOO\n#if BAZ == QUX\nPASS1\n#endif\n#endif\n')
michael@0 209 fh.write('#ifdef DEPTEST\nPASS2\n#endif\n')
michael@0 210 fh.write('#include p_incl\n#ifdef INCLTEST\nPASS3\n#endif\n')
michael@0 211 time = os.path.getmtime(self.tmppath('p_source')) - 3
michael@0 212 os.utime(self.tmppath('p_source'), (time, time))
michael@0 213
michael@0 214 # Create and write a manifest with the preprocessed file, then apply it.
michael@0 215 # This should write out our preprocessed file.
michael@0 216 m = InstallManifest()
michael@0 217 m.add_preprocess(self.tmppath('p_source'), 'p_dest', deps, '#', {'FOO':'BAR', 'BAZ':'QUX'})
michael@0 218 m.write(path=manifest)
michael@0 219
michael@0 220 m = InstallManifest(path=manifest)
michael@0 221 c = FileCopier()
michael@0 222 m.populate_registry(c)
michael@0 223 c.copy(dest)
michael@0 224
michael@0 225 self.assertTrue(os.path.exists(self.tmppath('dest/p_dest')))
michael@0 226
michael@0 227 with open(self.tmppath('dest/p_dest'), 'rt') as fh:
michael@0 228 self.assertEqual(fh.read(), 'PASS1\n')
michael@0 229
michael@0 230 # Create a second manifest with the preprocessed file, then apply it.
michael@0 231 # Since this manifest does not exist on the disk, there should not be a
michael@0 232 # dependency on it, and the preprocessed file should not be modified.
michael@0 233 m2 = InstallManifest()
michael@0 234 m2.add_preprocess(self.tmppath('p_source'), 'p_dest', deps, '#', {'DEPTEST':True})
michael@0 235 c = FileCopier()
michael@0 236 m2.populate_registry(c)
michael@0 237 result = c.copy(dest)
michael@0 238
michael@0 239 self.assertFalse(self.tmppath('dest/p_dest') in result.updated_files)
michael@0 240 self.assertTrue(self.tmppath('dest/p_dest') in result.existing_files)
michael@0 241
michael@0 242 # Write out the second manifest, then load it back in from the disk.
michael@0 243 # This should add the dependency on the manifest file, so our
michael@0 244 # preprocessed file should be regenerated with the new defines.
michael@0 245 # We also set the mtime on the destination file back, so it will be
michael@0 246 # older than the manifest file.
michael@0 247 m2.write(path=manifest)
michael@0 248 time = os.path.getmtime(manifest) - 1
michael@0 249 os.utime(self.tmppath('dest/p_dest'), (time, time))
michael@0 250 m2 = InstallManifest(path=manifest)
michael@0 251 c = FileCopier()
michael@0 252 m2.populate_registry(c)
michael@0 253 self.assertTrue(c.copy(dest))
michael@0 254
michael@0 255 with open(self.tmppath('dest/p_dest'), 'rt') as fh:
michael@0 256 self.assertEqual(fh.read(), 'PASS2\n')
michael@0 257
michael@0 258 # Set the time on the manifest back, so it won't be picked up as
michael@0 259 # modified in the next test
michael@0 260 time = os.path.getmtime(manifest) - 1
michael@0 261 os.utime(manifest, (time, time))
michael@0 262
michael@0 263 # Update the contents of a file included by the source file. This should
michael@0 264 # cause the destination to be regenerated.
michael@0 265 with open(include, 'wt') as fh:
michael@0 266 fh.write('#define INCLTEST\n')
michael@0 267
michael@0 268 time = os.path.getmtime(include) - 1
michael@0 269 os.utime(self.tmppath('dest/p_dest'), (time, time))
michael@0 270 c = FileCopier()
michael@0 271 m2.populate_registry(c)
michael@0 272 self.assertTrue(c.copy(dest))
michael@0 273
michael@0 274 with open(self.tmppath('dest/p_dest'), 'rt') as fh:
michael@0 275 self.assertEqual(fh.read(), 'PASS2\nPASS3\n')
michael@0 276
michael@0 277 def test_preprocessor_dependencies(self):
michael@0 278 manifest = self.tmppath('m')
michael@0 279 deps = self.tmppath('m.pp')
michael@0 280 dest = self.tmppath('dest')
michael@0 281 source = self.tmppath('p_source')
michael@0 282 destfile = self.tmppath('dest/p_dest')
michael@0 283 include = self.tmppath('p_incl')
michael@0 284 os.mkdir(dest)
michael@0 285
michael@0 286 with open(source, 'wt') as fh:
michael@0 287 fh.write('#define SRC\nSOURCE\n')
michael@0 288 time = os.path.getmtime(source) - 3
michael@0 289 os.utime(source, (time, time))
michael@0 290
michael@0 291 with open(include, 'wt') as fh:
michael@0 292 fh.write('INCLUDE\n')
michael@0 293 time = os.path.getmtime(source) - 3
michael@0 294 os.utime(include, (time, time))
michael@0 295
michael@0 296 # Create and write a manifest with the preprocessed file.
michael@0 297 m = InstallManifest()
michael@0 298 m.add_preprocess(source, 'p_dest', deps, '#', {'FOO':'BAR', 'BAZ':'QUX'})
michael@0 299 m.write(path=manifest)
michael@0 300
michael@0 301 time = os.path.getmtime(source) - 5
michael@0 302 os.utime(manifest, (time, time))
michael@0 303
michael@0 304 # Now read the manifest back in, and apply it. This should write out
michael@0 305 # our preprocessed file.
michael@0 306 m = InstallManifest(path=manifest)
michael@0 307 c = FileCopier()
michael@0 308 m.populate_registry(c)
michael@0 309 self.assertTrue(c.copy(dest))
michael@0 310
michael@0 311 with open(destfile, 'rt') as fh:
michael@0 312 self.assertEqual(fh.read(), 'SOURCE\n')
michael@0 313
michael@0 314 # Next, modify the source to #INCLUDE another file.
michael@0 315 with open(source, 'wt') as fh:
michael@0 316 fh.write('SOURCE\n#include p_incl\n')
michael@0 317 time = os.path.getmtime(source) - 1
michael@0 318 os.utime(destfile, (time, time))
michael@0 319
michael@0 320 # Apply the manifest, and confirm that it also reads the newly included
michael@0 321 # file.
michael@0 322 m = InstallManifest(path=manifest)
michael@0 323 c = FileCopier()
michael@0 324 m.populate_registry(c)
michael@0 325 c.copy(dest)
michael@0 326
michael@0 327 with open(destfile, 'rt') as fh:
michael@0 328 self.assertEqual(fh.read(), 'SOURCE\nINCLUDE\n')
michael@0 329
michael@0 330 # Set the time on the source file back, so it won't be picked up as
michael@0 331 # modified in the next test.
michael@0 332 time = os.path.getmtime(source) - 1
michael@0 333 os.utime(source, (time, time))
michael@0 334
michael@0 335 # Now, modify the include file (but not the original source).
michael@0 336 with open(include, 'wt') as fh:
michael@0 337 fh.write('INCLUDE MODIFIED\n')
michael@0 338 time = os.path.getmtime(include) - 1
michael@0 339 os.utime(destfile, (time, time))
michael@0 340
michael@0 341 # Apply the manifest, and confirm that the change to the include file
michael@0 342 # is detected. That should cause the preprocessor to run again.
michael@0 343 m = InstallManifest(path=manifest)
michael@0 344 c = FileCopier()
michael@0 345 m.populate_registry(c)
michael@0 346 c.copy(dest)
michael@0 347
michael@0 348 with open(destfile, 'rt') as fh:
michael@0 349 self.assertEqual(fh.read(), 'SOURCE\nINCLUDE MODIFIED\n')
michael@0 350
michael@0 351 if __name__ == '__main__':
michael@0 352 mozunit.main()

mercurial