OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
| 6 import fnmatch |
6 import tempfile | 7 import tempfile |
7 import unittest | 8 import unittest |
| 9 import zipfile |
8 | 10 |
9 import md5_check # pylint: disable=W0403 | 11 import md5_check # pylint: disable=W0403 |
10 | 12 |
11 | 13 |
| 14 def _WriteZipFile(path, entries): |
| 15 with zipfile.ZipFile(path, 'w') as zip_file: |
| 16 for subpath, data in entries: |
| 17 zip_file.writestr(subpath, data) |
| 18 |
| 19 |
12 class TestMd5Check(unittest.TestCase): | 20 class TestMd5Check(unittest.TestCase): |
13 def setUp(self): | 21 def setUp(self): |
14 self.called = False | 22 self.called = False |
| 23 self.changes = None |
15 | 24 |
16 def testCallAndRecordIfStale(self): | 25 def testCallAndRecordIfStale(self): |
17 input_strings = ['string1', 'string2'] | 26 input_strings = ['string1', 'string2'] |
18 input_file1 = tempfile.NamedTemporaryFile() | 27 input_file1 = tempfile.NamedTemporaryFile(suffix='.txt') |
19 input_file2 = tempfile.NamedTemporaryFile() | 28 input_file2 = tempfile.NamedTemporaryFile(suffix='.zip') |
20 file1_contents = 'input file 1' | 29 file1_contents = 'input file 1' |
21 file2_contents = 'input file 2' | |
22 input_file1.write(file1_contents) | 30 input_file1.write(file1_contents) |
23 input_file1.flush() | 31 input_file1.flush() |
24 input_file2.write(file2_contents) | 32 # Test out empty zip file to start. |
25 input_file2.flush() | 33 _WriteZipFile(input_file2.name, []) |
26 input_files = [input_file1.name, input_file2.name] | 34 input_files = [input_file1.name, input_file2.name] |
27 | 35 |
28 record_path = tempfile.NamedTemporaryFile(suffix='.stamp') | 36 record_path = tempfile.NamedTemporaryFile(suffix='.stamp') |
29 | 37 |
30 def CheckCallAndRecord(should_call, message, force=False, | 38 def CheckCallAndRecord(should_call, message, force=False, |
31 outputs_specified=False, outputs_missing=False): | 39 outputs_specified=False, outputs_missing=False, |
| 40 expected_changes=None, added_or_modified_only=None): |
32 output_paths = None | 41 output_paths = None |
33 if outputs_specified: | 42 if outputs_specified: |
34 output_file1 = tempfile.NamedTemporaryFile() | 43 output_file1 = tempfile.NamedTemporaryFile() |
35 if outputs_missing: | 44 if outputs_missing: |
36 output_file1.close() # Gets deleted on close(). | 45 output_file1.close() # Gets deleted on close(). |
37 output_paths = [output_file1.name] | 46 output_paths = [output_file1.name] |
38 | 47 |
39 self.called = False | 48 self.called = False |
40 def MarkCalled(): | 49 self.changes = None |
41 self.called = True | 50 if expected_changes or added_or_modified_only is not None: |
| 51 def MarkCalled(changes): |
| 52 self.called = True |
| 53 self.changes = changes |
| 54 else: |
| 55 def MarkCalled(): |
| 56 self.called = True |
| 57 |
42 md5_check.CallAndRecordIfStale( | 58 md5_check.CallAndRecordIfStale( |
43 MarkCalled, | 59 MarkCalled, |
44 record_path=record_path.name, | 60 record_path=record_path.name, |
45 input_paths=input_files, | 61 input_paths=input_files, |
46 input_strings=input_strings, | 62 input_strings=input_strings, |
47 output_paths=output_paths, | 63 output_paths=output_paths, |
48 force=force) | 64 force=force, |
49 self.failUnlessEqual(should_call, self.called, message) | 65 pass_changes=(expected_changes or added_or_modified_only) is not None) |
| 66 self.assertEqual(should_call, self.called, message) |
| 67 if expected_changes: |
| 68 description = self.changes.DescribeDifference() |
| 69 self.assertTrue(fnmatch.fnmatch(description, expected_changes), |
| 70 'Expected %s to match %s' % ( |
| 71 repr(description), repr(expected_changes))) |
| 72 if should_call and added_or_modified_only is not None: |
| 73 self.assertEqual(added_or_modified_only, |
| 74 self.changes.AddedOrModifiedOnly()) |
50 | 75 |
51 CheckCallAndRecord(True, 'should call when record doesn\'t exist') | 76 CheckCallAndRecord(True, 'should call when record doesn\'t exist', |
| 77 expected_changes='Previous stamp file not found.', |
| 78 added_or_modified_only=False) |
52 CheckCallAndRecord(False, 'should not call when nothing changed') | 79 CheckCallAndRecord(False, 'should not call when nothing changed') |
53 CheckCallAndRecord(False, 'should not call when nothing changed2', | 80 CheckCallAndRecord(False, 'should not call when nothing changed #2', |
54 outputs_specified=True, outputs_missing=False) | 81 outputs_specified=True, outputs_missing=False) |
55 CheckCallAndRecord(True, 'should call when output missing', | 82 CheckCallAndRecord(True, 'should call when output missing', |
56 outputs_specified=True, outputs_missing=True) | 83 outputs_specified=True, outputs_missing=True, |
57 CheckCallAndRecord(True, force=True, message='should call when forced') | 84 expected_changes='Outputs do not exist:*', |
| 85 added_or_modified_only=False) |
| 86 CheckCallAndRecord(True, force=True, message='should call when forced', |
| 87 expected_changes='force=True', |
| 88 added_or_modified_only=False) |
58 | 89 |
59 input_file1.write('some more input') | 90 input_file1.write('some more input') |
60 input_file1.flush() | 91 input_file1.flush() |
61 CheckCallAndRecord(True, 'changed input file should trigger call') | 92 CheckCallAndRecord(True, 'changed input file should trigger call', |
| 93 expected_changes='*Modified: %s' % input_file1.name, |
| 94 added_or_modified_only=True) |
62 | 95 |
63 input_files = input_files[::-1] | 96 input_files = input_files[::-1] |
64 CheckCallAndRecord(False, 'reordering of inputs shouldn\'t trigger call') | 97 CheckCallAndRecord(False, 'reordering of inputs shouldn\'t trigger call') |
65 | 98 |
66 input_files = input_files[:1] | 99 input_files = input_files[:1] |
67 CheckCallAndRecord(True, 'removing file should trigger call') | 100 CheckCallAndRecord(True, 'removing file should trigger call', |
| 101 expected_changes='*Removed: %s' % input_file1.name, |
| 102 added_or_modified_only=False) |
68 | 103 |
69 input_files.append(input_file2.name) | 104 input_files.append(input_file1.name) |
70 CheckCallAndRecord(True, 'added input file should trigger call') | 105 CheckCallAndRecord(True, 'added input file should trigger call', |
| 106 expected_changes='*Added: %s' % input_file1.name, |
| 107 added_or_modified_only=True) |
71 | 108 |
72 input_strings[0] = input_strings[0] + ' a bit longer' | 109 input_strings[0] = input_strings[0] + ' a bit longer' |
73 CheckCallAndRecord(True, 'changed input string should trigger call') | 110 CheckCallAndRecord(True, 'changed input string should trigger call', |
| 111 expected_changes='*Input strings changed*', |
| 112 added_or_modified_only=False) |
74 | 113 |
75 input_strings = input_strings[::-1] | 114 input_strings = input_strings[::-1] |
76 CheckCallAndRecord(True, 'reordering of string inputs should trigger call') | 115 CheckCallAndRecord(True, 'reordering of string inputs should trigger call', |
| 116 expected_changes='*Input strings changed*') |
77 | 117 |
78 input_strings = input_strings[:1] | 118 input_strings = input_strings[:1] |
79 CheckCallAndRecord(True, 'removing a string should trigger call') | 119 CheckCallAndRecord(True, 'removing a string should trigger call') |
80 | 120 |
81 input_strings.append('a brand new string') | 121 input_strings.append('a brand new string') |
82 CheckCallAndRecord(True, 'added input string should trigger call') | 122 CheckCallAndRecord(True, 'added input string should trigger call') |
83 | 123 |
| 124 _WriteZipFile(input_file2.name, [('path/1.txt', '1')]) |
| 125 CheckCallAndRecord(True, 'added subpath should trigger call', |
| 126 expected_changes='*Modified: %s*Subpath added: %s' % ( |
| 127 input_file2.name, 'path/1.txt'), |
| 128 added_or_modified_only=True) |
| 129 _WriteZipFile(input_file2.name, [('path/1.txt', '2')]) |
| 130 CheckCallAndRecord(True, 'changed subpath should trigger call', |
| 131 expected_changes='*Modified: %s*Subpath modified: %s' % ( |
| 132 input_file2.name, 'path/1.txt'), |
| 133 added_or_modified_only=True) |
| 134 CheckCallAndRecord(False, 'should not call when nothing changed') |
| 135 |
| 136 _WriteZipFile(input_file2.name, []) |
| 137 CheckCallAndRecord(True, 'removed subpath should trigger call', |
| 138 expected_changes='*Modified: %s*Subpath removed: %s' % ( |
| 139 input_file2.name, 'path/1.txt'), |
| 140 added_or_modified_only=False) |
| 141 |
84 | 142 |
85 if __name__ == '__main__': | 143 if __name__ == '__main__': |
86 unittest.main() | 144 unittest.main() |
OLD | NEW |