1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174

media / PRESUBMIT_test.py [blame]

#!/usr/bin/env python
# Copyright 2014 The Chromium Authors
# 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)

class NoV4L2AggregateInitializationTest(unittest.TestCase):

  def testValid(self):
    self._testChange(['struct v4l2_format_ format;'], 0)

  def testInvalid(self):
    self._testChange(['struct v4l2_format format = {};'], 1)
    self._testChange(['  struct v4l2_format format = {};'], 1)
    self._testChange(['  struct std::vector<v4l2_format> format[] = {};'], 1)
    self._testChange(['  struct std::vector<v4l2_format> format[] = {{}};'], 1)

  def _testChange(self, content, expected_warnings):
    mock_input_api = MockInputApi()
    mock_input_api.files.append(MockFile('test.cc', content))
    results = PRESUBMIT._CheckForNoV4L2AggregateInitialization(mock_input_api,
                                                               MockOutputApi())
    if expected_warnings:
      self.assertEqual(1, len(results))
      self.assertEqual(expected_warnings, len(results[0].items))
    else:
      self.assertEqual(0, len(results))


if __name__ == '__main__':
  unittest.main()