Clean up histogram'd media enum max values.
This adds a PRESUBMIT test to src/media/ which enforces the following when using UMA_HISTOGRAM_ENUMERATION:
- The max enum value should be suffixed with 'MAX' or 'Max' (and it should be equal to the largest valid entry ever logged).
- One should be added to that max value when used in the UMA_HISTOGRAM_ENUMERATION macro.
To handle past misuses of UMA_HISTOGRAM_ENUMERATION for non-enums a comment of '// IGNORE_PRESUBMIT_UMA_MAX' was added to silence the presubmit check.
BUG=165553
TBR=danakj
Review URL: https://codereview.chromium.org/148553003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254209 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/media/PRESUBMIT_test.py b/media/PRESUBMIT_test.py
new file mode 100644
index 0000000..f537a6d
--- /dev/null
+++ b/media/PRESUBMIT_test.py
@@ -0,0 +1,150 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import os
+import re
+import unittest
+
+import PRESUBMIT
+
+class MockInputApi(object):
+ def __init__(self):
+ self.re = re
+ self.os_path = os.path
+ self.files = []
+ self.is_committing = False
+
+ def AffectedFiles(self):
+ return self.files
+
+ def AffectedSourceFiles(self, fn):
+ # we'll just pretend everything is a source file for the sake of simplicity
+ return self.files
+
+ def ReadFile(self, f):
+ return f.NewContents()
+
+
+class MockOutputApi(object):
+ class PresubmitResult(object):
+ def __init__(self, message, items=None, long_text=''):
+ self.message = message
+ self.items = items
+ self.long_text = long_text
+
+ class PresubmitError(PresubmitResult):
+ def __init__(self, message, items, long_text=''):
+ MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
+ self.type = 'error'
+
+ class PresubmitPromptWarning(PresubmitResult):
+ def __init__(self, message, items, long_text=''):
+ MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
+ self.type = 'warning'
+
+ class PresubmitNotifyResult(PresubmitResult):
+ def __init__(self, message, items, long_text=''):
+ MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
+ self.type = 'notify'
+
+ class PresubmitPromptOrNotify(PresubmitResult):
+ def __init__(self, message, items, long_text=''):
+ MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
+ self.type = 'promptOrNotify'
+
+
+class MockFile(object):
+ def __init__(self, local_path, new_contents):
+ self._local_path = local_path
+ self._new_contents = new_contents
+ self._changed_contents = [(i + 1, l) for i, l in enumerate(new_contents)]
+
+ def ChangedContents(self):
+ return self._changed_contents
+
+ def NewContents(self):
+ return self._new_contents
+
+ def LocalPath(self):
+ return self._local_path
+
+
+class MockChange(object):
+ def __init__(self, changed_files):
+ self._changed_files = changed_files
+
+ def LocalPaths(self):
+ return self._changed_files
+
+
+class HistogramOffByOneTest(unittest.TestCase):
+
+ # Take an input and make sure the problems found equals the expectation.
+ def simpleCheck(self, contents, expected_errors):
+ input_api = MockInputApi()
+ input_api.files.append(MockFile('test.cc', contents))
+ results = PRESUBMIT._CheckForHistogramOffByOne(input_api, MockOutputApi())
+ if expected_errors:
+ self.assertEqual(1, len(results))
+ self.assertEqual(expected_errors, len(results[0].items))
+ else:
+ self.assertEqual(0, len(results))
+
+ def testValid(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFooMax + 1);', 0)
+
+ def testValidComments(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", /*...*/ kFoo, /*...*/'
+ 'kFooMax + 1);', 0)
+
+ def testValidMultiLine(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test",\n'
+ ' kFoo,\n'
+ ' kFooMax + 1);', 0)
+
+ def testValidMultiLineComments(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", // This is the name\n'
+ ' kFoo, /* The value */\n'
+ ' kFooMax + 1 /* The max */ );',
+ 0)
+
+ def testNoPlusOne(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFooMax);', 1)
+
+ def testInvalidWithIgnore(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFooMax); '
+ '// PRESUBMIT_IGNORE_UMA_MAX', 0)
+
+ def testNoMax(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFoo + 1);', 1)
+
+ def testNoMaxNoPlusOne(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFoo);', 1)
+
+ def testMultipleErrors(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFoo);\n'
+ 'printf("hello, world!");\n'
+ 'UMA_HISTOGRAM_ENUMERATION("test", kBar, kBarMax);', 2)
+
+ def testValidAndInvalid(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFoo);\n'
+ 'UMA_HISTOGRAM_ENUMERATION("test", kFoo, kFooMax + 1);'
+ 'UMA_HISTOGRAM_ENUMERATION("test", kBar, kBarMax);', 2)
+
+ def testInvalidMultiLine(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test",\n'
+ ' kFoo,\n'
+ ' kFooMax + 2);', 1)
+
+ def testInvalidComments(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", /*...*/, val, /*...*/,'
+ 'Max);\n', 1)
+
+ def testInvalidMultiLineComments(self):
+ self.simpleCheck('UMA_HISTOGRAM_ENUMERATION("test", // This is the name\n'
+ ' kFoo, /* The value */\n'
+ ' kFooMax + 2 /* The max */ );',
+ 1)
+
+if __name__ == '__main__':
+ unittest.main()