1# Copyright 2007 Google Inc. 2# 3# This program is free software; you can redistribute it and/or 4# modify it under the terms of the GNU General Public License 5# as published by the Free Software Foundation; either version 2 6# of the License, or (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program; if not, write to the Free Software Foundation, 15# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16"""Unit tests for passwd.py.""" 17 18__author__ = 'vasilios@google.com (Vasilios Hoffman)' 19 20import time 21import unittest 22 23from nss_cache import error 24from nss_cache.maps import group 25from nss_cache.maps import passwd 26 27 28class TestPasswdMap(unittest.TestCase): 29 """Tests for the PasswdMap class.""" 30 31 def setUp(self): 32 """Set some default avalible data for testing.""" 33 self._good_entry = passwd.PasswdMapEntry() 34 self._good_entry.name = 'foo' 35 self._good_entry.passwd = 'x' 36 self._good_entry.uid = 10 37 self._good_entry.gid = 10 38 self._good_entry.gecos = 'How Now Brown Cow' 39 self._good_entry.dir = '/home/foo' 40 self._good_entry.shell = '/bin/bash' 41 42 def testInit(self): 43 """Construct an empty or seeded PasswdMap.""" 44 self.assertEqual(passwd.PasswdMap, 45 type(passwd.PasswdMap()), 46 msg='failed to create emtpy PasswdMap') 47 pmap = passwd.PasswdMap([self._good_entry]) 48 self.assertEqual(self._good_entry, 49 pmap.PopItem(), 50 msg='failed to seed PasswdMap with list') 51 self.assertRaises(TypeError, passwd.PasswdMap, ['string']) 52 53 def testAdd(self): 54 """Add raises exceptions for objects it can't add or verify.""" 55 pmap = passwd.PasswdMap() 56 entry = self._good_entry 57 self.assertTrue(pmap.Add(entry), msg='failed to add new entry.') 58 59 self.assertEqual(1, len(pmap), msg='unexpected size for Map.') 60 61 ret_entry = pmap.PopItem() 62 self.assertEqual(ret_entry, entry, msg='failed to pop existing entry.') 63 64 gentry = group.GroupMapEntry() 65 gentry.name = 'foo' 66 gentry.gid = 10 67 self.assertRaises(TypeError, pmap.Add, gentry) 68 69 def testContains(self): 70 """Verify __contains__ works, and does a deep compare.""" 71 pentry_good = self._good_entry 72 pentry_like_good = passwd.PasswdMapEntry() 73 pentry_like_good.name = 'foo' # same Key(), but rest of attributes differ 74 pentry_bad = passwd.PasswdMapEntry() 75 pentry_bad.name = 'bar' 76 77 pmap = passwd.PasswdMap([pentry_good]) 78 79 self.assertTrue(pentry_good in pmap, msg='expected entry to be in map') 80 self.assertFalse(pentry_bad in pmap, 81 msg='did not expect entry to be in map') 82 self.assertFalse(pentry_like_good in pmap, 83 msg='__contains__ not doing a deep compare') 84 85 def testIterate(self): 86 """Check that we can iterate over PasswdMap.""" 87 pmap = passwd.PasswdMap() 88 pmap.Add(self._good_entry) 89 ret_entries = [] 90 for entry in pmap: 91 ret_entries.append(entry) 92 self.assertEqual(len(ret_entries), 1, msg='iterated over wrong count') 93 self.assertEqual(ret_entries[0], 94 self._good_entry, 95 msg='got the wrong entry back') 96 97 def testLen(self): 98 """Verify we have correctly overridden __len__ in MapEntry.""" 99 pmap = passwd.PasswdMap() 100 self.assertEqual(len(pmap), 0, msg='expected len(pmap) to be 0') 101 pmap.Add(self._good_entry) 102 self.assertEqual(len(pmap), 1, msg='expected len(pmap) to be 1') 103 104 def testExists(self): 105 """Verify Exists() checks for presence of MapEntry objects.""" 106 pmap = passwd.PasswdMap() 107 entry = self._good_entry 108 self.assertFalse(pmap.Exists(entry)) 109 pmap.Add(entry) 110 self.assertTrue(pmap.Exists(entry)) 111 112 def testMerge(self): 113 """Verify Merge() throws the right exceptions and correctly merges.""" 114 115 # Setup some MapEntry objects with distinct Key()s 116 pentry1 = self._good_entry 117 pentry2 = passwd.PasswdMapEntry() 118 pentry2.name = 'john' 119 pentry3 = passwd.PasswdMapEntry() 120 pentry3.name = 'jane' 121 122 # Setup some Map objects 123 pmap_big = passwd.PasswdMap([pentry1, pentry2]) 124 pmap_small = passwd.PasswdMap([pentry3]) 125 126 # Merge small into big 127 self.assertTrue(pmap_big.Merge(pmap_small), 128 msg='Merging small into big failed!') 129 self.assertTrue(pmap_big.Exists(pentry1), 130 msg='pentry1 not found in Map') 131 self.assertTrue(pmap_big.Exists(pentry2), 132 msg='pentry1 not found in Map') 133 self.assertTrue(pmap_big.Exists(pentry3), 134 msg='pentry1 not found in Map') 135 136 # A second merge should do nothing 137 self.assertFalse(pmap_big.Merge(pmap_small), 138 msg='Re-merging small into big succeeded.') 139 140 # An empty merge should do nothing 141 self.assertFalse(pmap_big.Merge(passwd.PasswdMap()), 142 msg='Empty Merge should have done nothing.') 143 144 # Merge a GroupMap should throw TypeError 145 gmap = group.GroupMap() 146 self.assertRaises(TypeError, pmap_big.Merge, gmap) 147 148 # Merge an older map should throw an UnsupportedMap 149 old_map = passwd.PasswdMap(modify_time=1) 150 new_map = passwd.PasswdMap(modify_time=2) 151 self.assertRaises(error.InvalidMerge, new_map.Merge, old_map) 152 old_map = passwd.PasswdMap(update_time=1) 153 new_map = passwd.PasswdMap(update_time=2) 154 self.assertRaises(error.InvalidMerge, new_map.Merge, old_map) 155 156 def testPopItem(self): 157 """Verify you can retrieve MapEntry with PopItem.""" 158 pmap = passwd.PasswdMap([self._good_entry]) 159 self.assertEqual(pmap.PopItem(), self._good_entry) 160 161 def testLastModificationTimestamp(self): 162 """Test setting/getting of timestamps on maps.""" 163 m = passwd.PasswdMap() 164 # we only work in whole-second resolution 165 now = int(time.time()) 166 167 m.SetModifyTimestamp(now) 168 self.assertEqual(now, m._last_modification_timestamp) 169 170 ts = m.GetModifyTimestamp() 171 self.assertEqual(now, ts) 172 173 174class TestPasswdMapEntry(unittest.TestCase): 175 """Tests for the PasswdMapEntry class.""" 176 177 def testInit(self): 178 """Construct empty and seeded PasswdMapEntry.""" 179 entry = passwd.PasswdMapEntry() 180 self.assertEqual(type(entry), 181 passwd.PasswdMapEntry, 182 msg='Could not create empty PasswdMapEntry') 183 seed = { 184 'name': 'foo', 185 'passwd': 'x', 186 'uid': 10, 187 'gid': 10, 188 'gecos': '', 189 'dir': '', 190 'shell': '' 191 } 192 entry = passwd.PasswdMapEntry(seed) 193 self.assertTrue(entry.Verify(), 194 msg='Could not verify seeded PasswdMapEntry') 195 self.assertEqual(entry.name, 196 'foo', 197 msg='Entry returned wrong value for name') 198 self.assertEqual(entry.passwd, 199 'x', 200 msg='Entry returned wrong value for passwd') 201 self.assertEqual(entry.uid, 202 10, 203 msg='Entry returned wrong value for uid') 204 self.assertEqual(entry.gid, 205 10, 206 msg='Entry returned wrong value for gid') 207 self.assertEqual(entry.gecos, 208 '', 209 msg='Entry returned wrong value for gecos') 210 self.assertEqual(entry.dir, 211 '', 212 msg='Entry returned wrong value for dir') 213 self.assertEqual(entry.shell, 214 '', 215 msg='Entry returned wrong value for shell') 216 217 def testAttributes(self): 218 """Test that we can get and set all expected attributes.""" 219 entry = passwd.PasswdMapEntry() 220 entry.name = 'foo' 221 self.assertEqual(entry.name, 'foo', msg='Could not set attribute: name') 222 entry.passwd = 'x' 223 self.assertEqual(entry.passwd, 224 'x', 225 msg='Could not set attribute: passwd') 226 entry.uid = 10 227 self.assertEqual(entry.uid, 10, msg='Could not set attribute: uid') 228 entry.gid = 10 229 self.assertEqual(entry.gid, 10, msg='Could not set attribute: gid') 230 entry.gecos = 'How Now Brown Cow' 231 self.assertEqual(entry.gecos, 232 'How Now Brown Cow', 233 msg='Could not set attribute: gecos') 234 entry.dir = '/home/foo' 235 self.assertEqual(entry.dir, 236 '/home/foo', 237 msg='Could not set attribute: dir') 238 entry.shell = '/bin/bash' 239 self.assertEqual(entry.shell, 240 '/bin/bash', 241 msg='Could not set attribute: shell') 242 243 def testEq(self): 244 """Verify we are doing a deep compare in __eq__.""" 245 246 # Setup some things to compare 247 entry_good = passwd.PasswdMapEntry({ 248 'name': 'foo', 249 'uid': 10, 250 'gid': 10 251 }) 252 entry_same_as_good = passwd.PasswdMapEntry({ 253 'name': 'foo', 254 'uid': 10, 255 'gid': 10 256 }) 257 entry_like_good = passwd.PasswdMapEntry() 258 entry_like_good.name = 'foo' # same Key(), but rest of attributes differ 259 entry_bad = passwd.PasswdMapEntry() 260 entry_bad.name = 'bar' 261 262 self.assertEqual(entry_good, 263 entry_good, 264 msg='entry_good not equal to itself') 265 self.assertEqual(entry_good, 266 entry_same_as_good, 267 msg='__eq__ not doing deep compare') 268 self.assertNotEqual(entry_good, 269 entry_like_good, 270 msg='__eq__ not doing deep compare') 271 self.assertNotEqual(entry_good, entry_bad, msg='unexpected equality') 272 273 def testVerify(self): 274 """Test that the object can verify it's attributes and itself.""" 275 entry = passwd.PasswdMapEntry() 276 277 # by leaving _KEY unset, we should bomb. 278 self.assertFalse(entry.Verify()) 279 280 def testKey(self): 281 """Key() should return the value of the 'name' attribute.""" 282 entry = passwd.PasswdMapEntry() 283 entry.name = 'foo' 284 self.assertEqual(entry.Key(), entry.name) 285 286 287if __name__ == '__main__': 288 unittest.main() 289