1#!/usr/bin/env python3 2# Copyright 2016 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16"""Unittests for the config module.""" 17 18import os 19import shutil 20import sys 21import tempfile 22import unittest 23 24_path = os.path.realpath(__file__ + '/../..') 25if sys.path[0] != _path: 26 sys.path.insert(0, _path) 27del _path 28 29# We have to import our local modules after the sys.path tweak. We can't use 30# relative imports because this is an executable program, not a module. 31# pylint: disable=wrong-import-position 32import rh.hooks 33import rh.config 34 35 36class PreUploadConfigTests(unittest.TestCase): 37 """Tests for the PreUploadConfig class.""" 38 39 def testMissing(self): 40 """Instantiating a non-existent config file should be fine.""" 41 rh.config.PreUploadConfig() 42 43 44class FileTestCase(unittest.TestCase): 45 """Helper class for tests cases to setup configuration files.""" 46 47 def setUp(self): 48 self.tempdir = tempfile.mkdtemp() 49 50 def tearDown(self): 51 shutil.rmtree(self.tempdir) 52 53 def _write_config(self, data, filename='temp.cfg'): 54 """Helper to write out a config file for testing. 55 56 Returns: 57 Path to the file where the configuration was written. 58 """ 59 path = os.path.join(self.tempdir, filename) 60 with open(path, 'w') as fp: 61 fp.write(data) 62 return path 63 64 def _write_local_config(self, data): 65 """Helper to write out a local config file for testing.""" 66 return self._write_config( 67 data, filename=rh.config.LocalPreUploadFile.FILENAME) 68 69 def _write_global_config(self, data): 70 """Helper to write out a global config file for testing.""" 71 return self._write_config( 72 data, filename=rh.config.GlobalPreUploadFile.FILENAME) 73 74 75class PreUploadFileTests(FileTestCase): 76 """Tests for the PreUploadFile class.""" 77 78 def testEmpty(self): 79 """Instantiating an empty config file should be fine.""" 80 path = self._write_config('') 81 rh.config.PreUploadFile(path) 82 83 def testValid(self): 84 """Verify a fully valid file works.""" 85 path = self._write_config("""# This be a comment me matey. 86[Hook Scripts] 87name = script --with "some args" 88 89[Builtin Hooks] 90cpplint = true 91 92[Builtin Hooks Options] 93cpplint = --some 'more args' 94 95[Options] 96ignore_merged_commits = true 97""") 98 rh.config.PreUploadFile(path) 99 100 def testUnknownSection(self): 101 """Reject unknown sections.""" 102 path = self._write_config('[BOOGA]') 103 self.assertRaises(rh.config.ValidationError, rh.config.PreUploadFile, 104 path) 105 106 def testUnknownBuiltin(self): 107 """Reject unknown builtin hooks.""" 108 path = self._write_config('[Builtin Hooks]\nbooga = borg!') 109 self.assertRaises(rh.config.ValidationError, rh.config.PreUploadFile, 110 path) 111 112 def testEmptyCustomHook(self): 113 """Reject empty custom hooks.""" 114 path = self._write_config('[Hook Scripts]\nbooga = \t \n') 115 self.assertRaises(rh.config.ValidationError, rh.config.PreUploadFile, 116 path) 117 118 def testInvalidIni(self): 119 """Reject invalid ini files.""" 120 path = self._write_config('[Hook Scripts]\n =') 121 self.assertRaises(rh.config.ValidationError, rh.config.PreUploadFile, 122 path) 123 124 def testInvalidString(self): 125 """Catch invalid string quoting.""" 126 path = self._write_config("""[Hook Scripts] 127name = script --'bad-quotes 128""") 129 self.assertRaises(rh.config.ValidationError, rh.config.PreUploadFile, 130 path) 131 132 133class LocalPreUploadFileTests(FileTestCase): 134 """Test for the LocalPreUploadFile class.""" 135 136 def testInvalidSectionConfig(self): 137 """Reject local config that uses invalid sections.""" 138 path = self._write_config("""[Builtin Hooks Exclude Paths] 139cpplint = external/ 'test directory' ^vendor/(?!google/) 140""") 141 self.assertRaises(rh.config.ValidationError, 142 rh.config.LocalPreUploadFile, 143 path) 144 145 146class PreUploadSettingsTests(FileTestCase): 147 """Tests for the PreUploadSettings class.""" 148 149 def testGlobalConfigs(self): 150 """Verify global configs stack properly.""" 151 self._write_global_config("""[Builtin Hooks] 152commit_msg_bug_field = true 153commit_msg_changeid_field = true 154commit_msg_test_field = false""") 155 self._write_local_config("""[Builtin Hooks] 156commit_msg_bug_field = false 157commit_msg_test_field = true""") 158 config = rh.config.PreUploadSettings(paths=(self.tempdir,), 159 global_paths=(self.tempdir,)) 160 self.assertEqual(config.builtin_hooks, 161 ['commit_msg_changeid_field', 'commit_msg_test_field']) 162 163 def testGlobalExcludeScope(self): 164 """Verify exclude scope is valid for global config.""" 165 self._write_global_config("""[Builtin Hooks Exclude Paths] 166cpplint = external/ 'test directory' ^vendor/(?!google/) 167""") 168 rh.config.PreUploadSettings(global_paths=(self.tempdir,)) 169 170 171if __name__ == '__main__': 172 unittest.main() 173