pre-upload: add COMMIT-QUEUE.ini parse check
BUG=chromium:655381
TEST=None
Change-Id: I17aa70eeb519dde79e7c17266e86e3ed0a0f87f9
Reviewed-on: https://chromium-review.googlesource.com/435579
Commit-Ready: Aviv Keshet <akeshet@chromium.org>
Tested-by: Aviv Keshet <akeshet@chromium.org>
Reviewed-by: Prathmesh Prabhu <pprabhu@chromium.org>
diff --git a/pre-upload.py b/pre-upload.py
index be40f96..734b626 100755
--- a/pre-upload.py
+++ b/pre-upload.py
@@ -20,6 +20,7 @@
import re
import sys
import stat
+import StringIO
from errors import (VerifyException, HookFailure, PrintErrorForProject,
PrintErrorsForCommit)
@@ -31,6 +32,7 @@
sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), '..', '..'))
from chromite.lib import commandline
+from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import git
from chromite.lib import osutils
@@ -1229,6 +1231,28 @@
return HookFailure(msg)
+def _check_cq_ini_well_formed(_project, commit):
+ """Check that any modified COMMIT-QUEUE.ini files are well formed."""
+ pattern = '.*' + constants.CQ_CONFIG_FILENAME
+ files = _filter_files(_get_affected_files(commit), (pattern,))
+
+ # TODO(akeshet): Check not only that the file is parseable, but that all the
+ # pre-cq configs it requests are existing ones.
+ for f in files:
+ try:
+ parser = ConfigParser.SafeConfigParser()
+ # Prior to python3, ConfigParser has no read_string method, so we must
+ # pass it either a file path or file like object. And we must use
+ # _get_file_content to fetch file contents to ensure we are examining the
+ # commit diff, rather than whatever's on disk.
+ contents = _get_file_content(f, commit)
+ parser.readfp(StringIO.StringIO(contents))
+ except ConfigParser.Error as e:
+ msg = ('Unable to parse COMMIT-QUEUE.ini file at %s due to %s.' %
+ (f, e))
+ return HookFailure(msg)
+
+
def _run_project_hook_script(script, project, commit):
"""Runs a project hook script.
@@ -1313,6 +1337,8 @@
# A list of hooks that are not project-specific
_COMMON_HOOKS = [
+ _check_cq_ini_well_formed,
+ _check_cros_license,
_check_ebuild_eapi,
_check_ebuild_keywords,
_check_ebuild_licenses,
@@ -1320,12 +1346,11 @@
_check_for_uprev,
_check_gofmt,
_check_layout_conf,
- _check_cros_license,
_check_no_long_lines,
_check_no_stray_whitespace,
_check_no_tabs,
- _check_tabbed_indents,
_check_portage_make_use_var,
+ _check_tabbed_indents,
]
diff --git a/pre-upload_unittest.py b/pre-upload_unittest.py
index c8efbc1..44b47fd 100755
--- a/pre-upload_unittest.py
+++ b/pre-upload_unittest.py
@@ -202,6 +202,46 @@
self.assertFalse(failure)
+class CheckConfigParsing(cros_test_lib.MockTestCase):
+ """Tests _check_cq_ini_well_formed."""
+
+ def setUp(self):
+ self.file_mock = self.PatchObject(pre_upload, '_get_affected_files')
+ self.content_mock = self.PatchObject(pre_upload, '_get_file_content')
+
+ def testIgnoreIrrelevantFile(self):
+ self.file_mock.return_value = ['unrelated_file.ini']
+ self.content_mock.return_value = '^$malformed gibberish^^&'
+ self.assertEqual(pre_upload._check_cq_ini_well_formed('PROJECT', 'COMMIT'),
+ None)
+
+ def testWellformedFile(self):
+ self.file_mock.return_value = ['COMMIT-QUEUE.ini']
+ self.content_mock.return_value = """#
+# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Per-project Commit Queue settings.
+# Documentation: http://goo.gl/4rZhAx
+
+[GENERAL]
+
+# Stages to ignore in the commit queue. If these steps break, your CL will be
+# submitted anyway. Use with caution.
+# The files in here currently only get tested via internal canaries.
+ignored-stages: UNitTest HWTest VMTest UploadPrebuilts Archive"""
+
+ self.assertEqual(pre_upload._check_cq_ini_well_formed('PROJECT', 'COMMIT'),
+ None)
+
+ def testMalformedFile(self):
+ self.file_mock.return_value = ['COMMIT-QUEUE.ini']
+ self.content_mock.return_value = '^$malformed gibberish^^&'
+ m = pre_upload._check_cq_ini_well_formed('PROJECT', 'COMMIT')
+ self.assertTrue(isinstance(m, pre_upload.HookFailure))
+
+
class CheckPortageMakeUseVar(cros_test_lib.MockTestCase):
"""Tests for _check_portage_make_use_var."""