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 file,
3
# You can obtain one at http://mozilla.org/MPL/2.0/.
8
from tempfile import NamedTemporaryFile
10
from mozbuild.compilation.warnings import CompilerWarning
11
from mozbuild.compilation.warnings import WarningsCollector
12
from mozbuild.compilation.warnings import WarningsDatabase
16
('foobar.cpp:123:10: warning: you messed up [-Wfoo]',
17
'foobar.cpp', 123, 10, 'you messed up', '-Wfoo')
21
("C:/mozilla-central/test/foo.cpp(793) : warning C4244: 'return' : "
22
"conversion from 'double' to 'uint32_t', possible loss of data",
23
'C:/mozilla-central/test/foo.cpp', 793, 'C4244',
24
"'return' : conversion from 'double' to 'uint32_t', possible loss of "
34
w['filename'] = '/foo/bar/baz.cpp'
35
w['line'] = CURRENT_LINE
37
w['message'] = 'This is irrelevant'
43
class TestCompilerWarning(unittest.TestCase):
44
def test_equivalence(self):
45
w1 = CompilerWarning()
46
w2 = CompilerWarning()
50
# Empty warnings should be equal.
51
self.assertEqual(w1, w2)
56
self.assertEqual(len(s), 1)
58
w1['filename'] = '/foo.c'
59
w2['filename'] = '/bar.c'
61
self.assertNotEqual(w1, w2)
67
self.assertEqual(len(s), 2)
69
w1['filename'] = '/foo.c'
73
w2['filename'] = '/foo.c'
77
self.assertEqual(w1, w2)
79
class TestWarningsParsing(unittest.TestCase):
80
def test_clang_parsing(self):
81
for source, filename, line, column, message, flag in CLANG_TESTS:
82
collector = WarningsCollector(resolve_files=False)
83
warning = collector.process_line(source)
85
self.assertIsNotNone(warning)
87
self.assertEqual(warning['filename'], filename)
88
self.assertEqual(warning['line'], line)
89
self.assertEqual(warning['column'], column)
90
self.assertEqual(warning['message'], message)
91
self.assertEqual(warning['flag'], flag)
93
def test_msvc_parsing(self):
94
for source, filename, line, flag, message in MSVC_TESTS:
95
collector = WarningsCollector(resolve_files=False)
96
warning = collector.process_line(source)
98
self.assertIsNotNone(warning)
100
self.assertEqual(warning['filename'], filename)
101
self.assertEqual(warning['line'], line)
102
self.assertEqual(warning['flag'], flag)
103
self.assertEqual(warning['message'], message)
105
class TestWarningsDatabase(unittest.TestCase):
106
def test_basic(self):
107
db = WarningsDatabase()
109
self.assertEqual(len(db), 0)
112
db.insert(get_warning(), compute_hash=False)
114
self.assertEqual(len(db), 10)
117
self.assertEqual(len(warnings), 10)
119
def test_hashing(self):
120
"""Ensure that hashing files on insert works."""
121
db = WarningsDatabase()
123
temp = NamedTemporaryFile()
124
temp.write('x' * 100)
127
w = CompilerWarning()
128
w['filename'] = temp.name
131
w['message'] = 'foo bar'
136
w['filename'] = 'DOES_NOT_EXIST'
138
with self.assertRaises(Exception):
141
def test_pruning(self):
142
"""Ensure old warnings are removed from database appropriately."""
143
db = WarningsDatabase()
146
for i in xrange(1, 21):
147
temp = NamedTemporaryFile()
148
temp.write('x' * (100 * i))
151
# Keep reference so it doesn't get GC'd and deleted.
152
source_files.append(temp)
154
w = CompilerWarning()
155
w['filename'] = temp.name
158
w['message'] = 'irrelevant'
162
self.assertEqual(len(db), 20)
164
# If we change a source file, inserting a new warning should nuke the
166
source_files[0].write('extra')
167
source_files[0].flush()
169
w = CompilerWarning()
170
w['filename'] = source_files[0].name
173
w['message'] = 'replaced'
177
self.assertEqual(len(db), 20)
179
warnings = list(db.warnings_for_file(source_files[0].name))
180
self.assertEqual(len(warnings), 1)
181
self.assertEqual(warnings[0]['column'], w['column'])
183
# If we delete the source file, calling prune should call the warnings
185
old_filename = source_files[0].name
188
self.assertFalse(os.path.exists(old_filename))
191
self.assertEqual(len(db), 19)