1 # Copyright (C) 2010 Chris Jerdonek (chris.jerdonek (at] gmail.com) 2 # 3 # Redistribution and use in source and binary forms, with or without 4 # modification, are permitted provided that the following conditions 5 # are met: 6 # 1. Redistributions of source code must retain the above copyright 7 # notice, this list of conditions and the following disclaimer. 8 # 2. Redistributions in binary form must reproduce the above copyright 9 # notice, this list of conditions and the following disclaimer in the 10 # documentation and/or other materials provided with the distribution. 11 # 12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 13 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 16 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 23 """Unit tests for filter.py.""" 24 25 import unittest 26 27 from filter import _CategoryFilter as CategoryFilter 28 from filter import validate_filter_rules 29 from filter import FilterConfiguration 30 31 # On Testing __eq__() and __ne__(): 32 # 33 # In the tests below, we deliberately do not use assertEquals() or 34 # assertNotEquals() to test __eq__() or __ne__(). We do this to be 35 # very explicit about what we are testing, especially in the case 36 # of assertNotEquals(). 37 # 38 # Part of the reason is that it is not immediately clear what 39 # expression the unittest module uses to assert "not equals" -- the 40 # negation of __eq__() or __ne__(), which are not necessarily 41 # equivalent expresions in Python. For example, from Python's "Data 42 # Model" documentation-- 43 # 44 # "There are no implied relationships among the comparison 45 # operators. The truth of x==y does not imply that x!=y is 46 # false. Accordingly, when defining __eq__(), one should 47 # also define __ne__() so that the operators will behave as 48 # expected." 49 # 50 # (from http://docs.python.org/reference/datamodel.html#object.__ne__ ) 51 52 class ValidateFilterRulesTest(unittest.TestCase): 53 54 """Tests validate_filter_rules() function.""" 55 56 def test_validate_filter_rules(self): 57 all_categories = ["tabs", "whitespace", "build/include"] 58 59 bad_rules = [ 60 "tabs", 61 "*tabs", 62 " tabs", 63 " +tabs", 64 "+whitespace/newline", 65 "+xxx", 66 ] 67 68 good_rules = [ 69 "+tabs", 70 "-tabs", 71 "+build" 72 ] 73 74 for rule in bad_rules: 75 self.assertRaises(ValueError, validate_filter_rules, 76 [rule], all_categories) 77 78 for rule in good_rules: 79 # This works: no error. 80 validate_filter_rules([rule], all_categories) 81 82 83 class CategoryFilterTest(unittest.TestCase): 84 85 """Tests CategoryFilter class.""" 86 87 def test_init(self): 88 """Test __init__ method.""" 89 # Test that the attributes are getting set correctly. 90 filter = CategoryFilter(["+"]) 91 self.assertEquals(["+"], filter._filter_rules) 92 93 def test_init_default_arguments(self): 94 """Test __init__ method default arguments.""" 95 filter = CategoryFilter() 96 self.assertEquals([], filter._filter_rules) 97 98 def test_str(self): 99 """Test __str__ "to string" operator.""" 100 filter = CategoryFilter(["+a", "-b"]) 101 self.assertEquals(str(filter), "+a,-b") 102 103 def test_eq(self): 104 """Test __eq__ equality function.""" 105 filter1 = CategoryFilter(["+a", "+b"]) 106 filter2 = CategoryFilter(["+a", "+b"]) 107 filter3 = CategoryFilter(["+b", "+a"]) 108 109 # See the notes at the top of this module about testing 110 # __eq__() and __ne__(). 111 self.assertTrue(filter1.__eq__(filter2)) 112 self.assertFalse(filter1.__eq__(filter3)) 113 114 def test_ne(self): 115 """Test __ne__ inequality function.""" 116 # By default, __ne__ always returns true on different objects. 117 # Thus, just check the distinguishing case to verify that the 118 # code defines __ne__. 119 # 120 # Also, see the notes at the top of this module about testing 121 # __eq__() and __ne__(). 122 self.assertFalse(CategoryFilter().__ne__(CategoryFilter())) 123 124 def test_should_check(self): 125 """Test should_check() method.""" 126 filter = CategoryFilter() 127 self.assertTrue(filter.should_check("everything")) 128 # Check a second time to exercise cache. 129 self.assertTrue(filter.should_check("everything")) 130 131 filter = CategoryFilter(["-"]) 132 self.assertFalse(filter.should_check("anything")) 133 # Check a second time to exercise cache. 134 self.assertFalse(filter.should_check("anything")) 135 136 filter = CategoryFilter(["-", "+ab"]) 137 self.assertTrue(filter.should_check("abc")) 138 self.assertFalse(filter.should_check("a")) 139 140 filter = CategoryFilter(["+", "-ab"]) 141 self.assertFalse(filter.should_check("abc")) 142 self.assertTrue(filter.should_check("a")) 143 144 145 class FilterConfigurationTest(unittest.TestCase): 146 147 """Tests FilterConfiguration class.""" 148 149 def _config(self, base_rules, path_specific, user_rules): 150 """Return a FilterConfiguration instance.""" 151 return FilterConfiguration(base_rules=base_rules, 152 path_specific=path_specific, 153 user_rules=user_rules) 154 155 def test_init(self): 156 """Test __init__ method.""" 157 # Test that the attributes are getting set correctly. 158 # We use parameter values that are different from the defaults. 159 base_rules = ["-"] 160 path_specific = [(["path"], ["+a"])] 161 user_rules = ["+"] 162 163 config = self._config(base_rules, path_specific, user_rules) 164 165 self.assertEquals(base_rules, config._base_rules) 166 self.assertEquals(path_specific, config._path_specific) 167 self.assertEquals(user_rules, config._user_rules) 168 169 def test_default_arguments(self): 170 # Test that the attributes are getting set correctly to the defaults. 171 config = FilterConfiguration() 172 173 self.assertEquals([], config._base_rules) 174 self.assertEquals([], config._path_specific) 175 self.assertEquals([], config._user_rules) 176 177 def test_eq(self): 178 """Test __eq__ method.""" 179 # See the notes at the top of this module about testing 180 # __eq__() and __ne__(). 181 self.assertTrue(FilterConfiguration().__eq__(FilterConfiguration())) 182 183 # Verify that a difference in any argument causes equality to fail. 184 config = FilterConfiguration() 185 186 # These parameter values are different from the defaults. 187 base_rules = ["-"] 188 path_specific = [(["path"], ["+a"])] 189 user_rules = ["+"] 190 191 self.assertFalse(config.__eq__(FilterConfiguration( 192 base_rules=base_rules))) 193 self.assertFalse(config.__eq__(FilterConfiguration( 194 path_specific=path_specific))) 195 self.assertFalse(config.__eq__(FilterConfiguration( 196 user_rules=user_rules))) 197 198 def test_ne(self): 199 """Test __ne__ method.""" 200 # By default, __ne__ always returns true on different objects. 201 # Thus, just check the distinguishing case to verify that the 202 # code defines __ne__. 203 # 204 # Also, see the notes at the top of this module about testing 205 # __eq__() and __ne__(). 206 self.assertFalse(FilterConfiguration().__ne__(FilterConfiguration())) 207 208 def test_base_rules(self): 209 """Test effect of base_rules on should_check().""" 210 base_rules = ["-b"] 211 path_specific = [] 212 user_rules = [] 213 214 config = self._config(base_rules, path_specific, user_rules) 215 216 self.assertTrue(config.should_check("a", "path")) 217 self.assertFalse(config.should_check("b", "path")) 218 219 def test_path_specific(self): 220 """Test effect of path_rules_specifier on should_check().""" 221 base_rules = ["-"] 222 path_specific = [(["path1"], ["+b"]), 223 (["path2"], ["+c"])] 224 user_rules = [] 225 226 config = self._config(base_rules, path_specific, user_rules) 227 228 self.assertFalse(config.should_check("c", "path1")) 229 self.assertTrue(config.should_check("c", "path2")) 230 # Test that first match takes precedence. 231 self.assertFalse(config.should_check("c", "path2/path1")) 232 233 def test_path_with_different_case(self): 234 """Test a path that differs only in case.""" 235 base_rules = ["-"] 236 path_specific = [(["Foo/"], ["+whitespace"])] 237 user_rules = [] 238 239 config = self._config(base_rules, path_specific, user_rules) 240 241 self.assertFalse(config.should_check("whitespace", "Fooo/bar.txt")) 242 self.assertTrue(config.should_check("whitespace", "Foo/bar.txt")) 243 # Test different case. 244 self.assertTrue(config.should_check("whitespace", "FOO/bar.txt")) 245 246 def test_user_rules(self): 247 """Test effect of user_rules on should_check().""" 248 base_rules = ["-"] 249 path_specific = [] 250 user_rules = ["+b"] 251 252 config = self._config(base_rules, path_specific, user_rules) 253 254 self.assertFalse(config.should_check("a", "path")) 255 self.assertTrue(config.should_check("b", "path")) 256 257