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.

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

mercurial