More PRESUBMIT checks.

Checks for:
- No iostream includes in headers
- No use of FRIEND_TEST for gtest
- Verifies that all C/C++ code passes cpplint.py check.
- Verifies that BUG= is present in commit message
- Verifies that TEST= is present in commit message

For more details, see Chrome's PRESUBMIT.py at
http://src.chromium.org/viewvc/chrome/trunk/src/PRESUBMIT.py?revision=113979&view=markup
and the canned checks at
http://src.chromium.org/viewvc/chrome/trunk/tools/depot_tools/presubmit_canned_checks.py?view=markup

BUG=
TEST=

Review URL: https://webrtc-codereview.appspot.com/317011

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1737 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 33bdab3..56c8d5b 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -23,8 +23,91 @@
   }
   return license_header
 
+def _CheckNoIOStreamInHeaders(input_api, output_api):
+  """Checks to make sure no .h files include <iostream>."""
+  files = []
+  pattern = input_api.re.compile(r'^#include\s*<iostream>',
+                                 input_api.re.MULTILINE)
+  for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
+    if not f.LocalPath().endswith('.h'):
+      continue
+    contents = input_api.ReadFile(f)
+    if pattern.search(contents):
+      files.append(f)
+
+  if len(files):
+    return [ output_api.PresubmitError(
+        'Do not #include <iostream> in header files, since it inserts static ' +
+        'initialization into every file including the header. Instead, ' +
+        '#include <ostream>. See http://crbug.com/94794',
+        files) ]
+  return []
+
+def _CheckNoFRIEND_TEST(input_api, output_api):
+  """Make sure that gtest's FRIEND_TEST() macro is not used, the
+  FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be
+  used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes."""
+  problems = []
+
+  file_filter = lambda f: f.LocalPath().endswith(('.cc', '.h'))
+  for f in input_api.AffectedFiles(file_filter=file_filter):
+    for line_num, line in f.ChangedContents():
+      if 'FRIEND_TEST(' in line:
+        problems.append('    %s:%d' % (f.LocalPath(), line_num))
+
+  if not problems:
+    return []
+  return [output_api.PresubmitPromptWarning('WebRTC\'s code should not use '
+      'gtest\'s FRIEND_TEST() macro. Include testsupport/gtest_prod_util.h and '
+      'use FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems))]
+
+def _CheckNewFilesLintClean(input_api, output_api, source_file_filter=None):
+  """Checks that all NEW '.cc' and '.h' files pass cpplint.py.
+  This check is based on _CheckChangeLintsClean in
+  depot_tools/presubmit_canned_checks.py but has less filters and only checks
+  added files."""
+  result = []
+
+  # Initialize cpplint.
+  import cpplint
+  # Access to a protected member _XX of a client class
+  # pylint: disable=W0212
+  cpplint._cpplint_state.ResetErrorCounts()
+
+  # Justifications for each filter:
+  #
+  # - build/header_guard  : WebRTC coding style says they should be prefixed
+  #                         with WEBRTC_, which is not possible to configure in
+  #                         cpplint.py.
+  cpplint._SetFilters('-build/header_guard')
+
+  # Use the strictest verbosity level for cpplint.py (level 1) which is the
+  # default when running cpplint.py from command line.
+  # To make it possible to work with not-yet-converted code, we're only applying
+  # it to new (or moved/renamed) files.
+  verbosity_level = 1
+  files = []
+  for f in input_api.AffectedSourceFiles(source_file_filter):
+    # Note that moved/renamed files also count as added for svn.
+    if (f.Action() == 'A'):
+      files.append(f.AbsoluteLocalPath())
+  for file_name in files:
+    cpplint.ProcessFile(file_name, verbosity_level)
+
+  if cpplint._cpplint_state.error_count > 0:
+    if input_api.is_committing:
+      # TODO(kjellander): Change back to PresubmitError below when we're
+      # confident with the lint settings.
+      res_type = output_api.PresubmitPromptWarning
+    else:
+      res_type = output_api.PresubmitPromptWarning
+    result = [res_type('Changelist failed cpplint.py check.')]
+
+  return result
+
 def _CommonChecks(input_api, output_api):
   """Checks common to both upload and commit."""
+  # TODO(kjellander): Use presubmit_canned_checks.PanProjectChecks too.
   results = []
   results.extend(input_api.canned_checks.CheckLongLines(
       input_api, output_api))
@@ -34,8 +117,11 @@
       input_api, output_api))
   results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
       input_api, output_api))
+  results.extend(_CheckNewFilesLintClean(input_api, output_api))
   results.extend(input_api.canned_checks.CheckLicense(
       input_api, output_api, _LicenseHeader(input_api)))
+  results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
+  results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
   return results
 
 def CheckChangeOnUpload(input_api, output_api):
@@ -51,4 +137,8 @@
       input_api, output_api))
   results.extend(input_api.canned_checks.CheckChangeHasDescription(
       input_api, output_api))
+  results.extend(input_api.canned_checks.CheckChangeHasBugField(
+      input_api, output_api))
+  results.extend(input_api.canned_checks.CheckChangeHasTestField(
+      input_api, output_api))
   return results