Changeset 391 for python/trunk/Lib/test/test_winreg.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Lib/test/test_winreg.py
r2 r391 2 2 # Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey 3 3 4 import os, sys, errno 5 import unittest 6 from test import test_support 7 threading = test_support.import_module("threading") 8 from platform import machine 9 10 # Do this first so test will be skipped if module doesn't exist 11 test_support.import_module('_winreg') 12 # Now import everything 4 13 from _winreg import * 5 import os, sys 6 import unittest 7 8 from test import test_support 9 10 test_key_name = "SOFTWARE\\Python Registry Test Key - Delete Me" 14 15 try: 16 REMOTE_NAME = sys.argv[sys.argv.index("--remote")+1] 17 except (IndexError, ValueError): 18 REMOTE_NAME = None 19 20 # tuple of (major, minor) 21 WIN_VER = sys.getwindowsversion()[:2] 22 # Some tests should only run on 64-bit architectures where WOW64 will be. 23 WIN64_MACHINE = True if machine() == "AMD64" else False 24 25 # Starting with Windows 7 and Windows Server 2008 R2, WOW64 no longer uses 26 # registry reflection and formerly reflected keys are shared instead. 27 # Windows 7 and Windows Server 2008 R2 are version 6.1. Due to this, some 28 # tests are only valid up until 6.1 29 HAS_REFLECTION = True if WIN_VER < (6, 1) else False 30 31 # Use a per-process key to prevent concurrent test runs (buildbot!) from 32 # stomping on each other. 33 test_key_base = "Python Test Key [%d] - Delete Me" % (os.getpid(),) 34 test_key_name = "SOFTWARE\\" + test_key_base 35 # On OS'es that support reflection we should test with a reflected key 36 test_reflect_key_name = "SOFTWARE\\Classes\\" + test_key_base 11 37 12 38 test_data = [ … … 30 56 ] 31 57 32 class WinregTests(unittest.TestCase): 33 remote_name = None 34 35 def WriteTestData(self, root_key): 58 class BaseWinregTests(unittest.TestCase): 59 60 def setUp(self): 61 # Make sure that the test key is absent when the test 62 # starts. 63 self.delete_tree(HKEY_CURRENT_USER, test_key_name) 64 65 def delete_tree(self, root, subkey): 66 try: 67 hkey = OpenKey(root, subkey, KEY_ALL_ACCESS) 68 except WindowsError: 69 # subkey does not exist 70 return 71 while True: 72 try: 73 subsubkey = EnumKey(hkey, 0) 74 except WindowsError: 75 # no more subkeys 76 break 77 self.delete_tree(hkey, subsubkey) 78 CloseKey(hkey) 79 DeleteKey(root, subkey) 80 81 def _write_test_data(self, root_key, CreateKey=CreateKey): 36 82 # Set the default value for this key. 37 83 SetValue(root_key, test_key_name, REG_SZ, "Default value") … … 46 92 # Check we wrote as many items as we thought. 47 93 nkeys, nvalues, since_mod = QueryInfoKey(key) 48 self.assertEqual s(nkeys, 1, "Not the correct number of sub keys")49 self.assertEqual s(nvalues, 1, "Not the correct number of values")94 self.assertEqual(nkeys, 1, "Not the correct number of sub keys") 95 self.assertEqual(nvalues, 1, "Not the correct number of values") 50 96 nkeys, nvalues, since_mod = QueryInfoKey(sub_key) 51 self.assertEqual s(nkeys, 0, "Not the correct number of sub keys")52 self.assertEqual s(nvalues, len(test_data),97 self.assertEqual(nkeys, 0, "Not the correct number of sub keys") 98 self.assertEqual(nvalues, len(test_data), 53 99 "Not the correct number of values") 54 100 # Close this key this way... … … 73 119 pass 74 120 75 def ReadTestData(self, root_key):121 def _read_test_data(self, root_key, OpenKey=OpenKey): 76 122 # Check we can get default value for this key. 77 123 val = QueryValue(root_key, test_key_name) 78 self.assertEqual s(val, "Default value",79 124 self.assertEqual(val, "Default value", 125 "Registry didn't give back the correct value") 80 126 81 127 key = OpenKey(root_key, test_key_name) … … 89 135 except EnvironmentError: 90 136 break 91 self.assert Equals(data in test_data, True,92 137 self.assertIn(data, test_data, 138 "Didn't read back the correct test data") 93 139 index = index + 1 94 self.assertEqual s(index, len(test_data),95 140 self.assertEqual(index, len(test_data), 141 "Didn't read the correct number of items") 96 142 # Check I can directly access each item 97 143 for value_name, value_data, value_type in test_data: 98 144 read_val, read_typ = QueryValueEx(sub_key, value_name) 99 self.assertEqual s(read_val, value_data,100 101 self.assertEqual s(read_typ, value_type,102 145 self.assertEqual(read_val, value_data, 146 "Could not directly read the value") 147 self.assertEqual(read_typ, value_type, 148 "Could not directly read the value") 103 149 sub_key.Close() 104 150 # Enumerate our main key. 105 151 read_val = EnumKey(key, 0) 106 self.assertEqual s(read_val, "sub_key", "Read subkey value wrong")152 self.assertEqual(read_val, "sub_key", "Read subkey value wrong") 107 153 try: 108 154 EnumKey(key, 1) … … 113 159 key.Close() 114 160 115 def DeleteTestData(self, root_key):161 def _delete_test_data(self, root_key): 116 162 key = OpenKey(root_key, test_key_name, 0, KEY_ALL_ACCESS) 117 163 sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS) … … 123 169 124 170 nkeys, nvalues, since_mod = QueryInfoKey(sub_key) 125 self.assertEqual s(nkeys, 0, "subkey not empty before delete")126 self.assertEqual s(nvalues, 0, "subkey not empty before delete")171 self.assertEqual(nkeys, 0, "subkey not empty before delete") 172 self.assertEqual(nvalues, 0, "subkey not empty before delete") 127 173 sub_key.Close() 128 174 DeleteKey(key, "sub_key") … … 143 189 pass 144 190 145 def TestAll(self, root_key): 146 self.WriteTestData(root_key) 147 self.ReadTestData(root_key) 148 self.DeleteTestData(root_key) 149 150 def testLocalMachineRegistryWorks(self): 151 self.TestAll(HKEY_CURRENT_USER) 152 153 def testConnectRegistryToLocalMachineWorks(self): 191 def _test_all(self, root_key): 192 self._write_test_data(root_key) 193 self._read_test_data(root_key) 194 self._delete_test_data(root_key) 195 196 class LocalWinregTests(BaseWinregTests): 197 198 def test_registry_works(self): 199 self._test_all(HKEY_CURRENT_USER) 200 201 def test_registry_works_extended_functions(self): 202 # Substitute the regular CreateKey and OpenKey calls with their 203 # extended counterparts. 204 # Note: DeleteKeyEx is not used here because it is platform dependent 205 cke = lambda key, sub_key: CreateKeyEx(key, sub_key, 0, KEY_ALL_ACCESS) 206 self._write_test_data(HKEY_CURRENT_USER, cke) 207 208 oke = lambda key, sub_key: OpenKeyEx(key, sub_key, 0, KEY_READ) 209 self._read_test_data(HKEY_CURRENT_USER, oke) 210 211 self._delete_test_data(HKEY_CURRENT_USER) 212 213 def test_connect_registry_to_local_machine_works(self): 154 214 # perform minimal ConnectRegistry test which just invokes it 155 215 h = ConnectRegistry(None, HKEY_LOCAL_MACHINE) 216 self.assertNotEqual(h.handle, 0) 156 217 h.Close() 157 158 def testRemoteMachineRegistryWorks(self): 159 if not self.remote_name: 160 return # remote machine name not specified 161 remote_key = ConnectRegistry(self.remote_name, HKEY_CURRENT_USER) 162 self.TestAll(remote_key) 163 164 def testExpandEnvironmentStrings(self): 218 self.assertEqual(h.handle, 0) 219 220 def test_inexistant_remote_registry(self): 221 connect = lambda: ConnectRegistry("abcdefghijkl", HKEY_CURRENT_USER) 222 self.assertRaises(WindowsError, connect) 223 224 def test_expand_environment_strings(self): 165 225 r = ExpandEnvironmentStrings(u"%windir%\\test") 166 226 self.assertEqual(type(r), unicode) 167 227 self.assertEqual(r, os.environ["windir"] + "\\test") 168 228 229 def test_context_manager(self): 230 # ensure that the handle is closed if an exception occurs 231 try: 232 with ConnectRegistry(None, HKEY_LOCAL_MACHINE) as h: 233 self.assertNotEqual(h.handle, 0) 234 raise WindowsError 235 except WindowsError: 236 self.assertEqual(h.handle, 0) 237 238 def test_changing_value(self): 239 # Issue2810: A race condition in 2.6 and 3.1 may cause 240 # EnumValue or QueryValue to raise "WindowsError: More data is 241 # available" 242 done = False 243 244 class VeryActiveThread(threading.Thread): 245 def run(self): 246 with CreateKey(HKEY_CURRENT_USER, test_key_name) as key: 247 use_short = True 248 long_string = 'x'*2000 249 while not done: 250 s = 'x' if use_short else long_string 251 use_short = not use_short 252 SetValue(key, 'changing_value', REG_SZ, s) 253 254 thread = VeryActiveThread() 255 thread.start() 256 try: 257 with CreateKey(HKEY_CURRENT_USER, 258 test_key_name+'\\changing_value') as key: 259 for _ in range(1000): 260 num_subkeys, num_values, t = QueryInfoKey(key) 261 for i in range(num_values): 262 name = EnumValue(key, i) 263 QueryValue(key, name[0]) 264 finally: 265 done = True 266 thread.join() 267 with OpenKey(HKEY_CURRENT_USER, test_key_name, 0, KEY_ALL_ACCESS) as key: 268 DeleteKey(key, 'changing_value') 269 DeleteKey(HKEY_CURRENT_USER, test_key_name) 270 271 def test_long_key(self): 272 # Issue2810, in 2.6 and 3.1 when the key name was exactly 256 273 # characters, EnumKey raised "WindowsError: More data is 274 # available" 275 name = 'x'*256 276 try: 277 with CreateKey(HKEY_CURRENT_USER, test_key_name) as key: 278 SetValue(key, name, REG_SZ, 'x') 279 num_subkeys, num_values, t = QueryInfoKey(key) 280 EnumKey(key, 0) 281 finally: 282 with OpenKey(HKEY_CURRENT_USER, test_key_name, 0, KEY_ALL_ACCESS) as key: 283 DeleteKey(key, name) 284 DeleteKey(HKEY_CURRENT_USER, test_key_name) 285 286 def test_dynamic_key(self): 287 # Issue2810, when the value is dynamically generated, these 288 # raise "WindowsError: More data is available" in 2.6 and 3.1 289 try: 290 EnumValue(HKEY_PERFORMANCE_DATA, 0) 291 except OSError as e: 292 if e.errno in (errno.EPERM, errno.EACCES): 293 self.skipTest("access denied to registry key " 294 "(are you running in a non-interactive session?)") 295 raise 296 QueryValueEx(HKEY_PERFORMANCE_DATA, None) 297 298 # Reflection requires XP x64/Vista at a minimum. XP doesn't have this stuff 299 # or DeleteKeyEx so make sure their use raises NotImplementedError 300 @unittest.skipUnless(WIN_VER < (5, 2), "Requires Windows XP") 301 def test_reflection_unsupported(self): 302 try: 303 with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck: 304 self.assertNotEqual(ck.handle, 0) 305 306 key = OpenKey(HKEY_CURRENT_USER, test_key_name) 307 self.assertNotEqual(key.handle, 0) 308 309 with self.assertRaises(NotImplementedError): 310 DisableReflectionKey(key) 311 with self.assertRaises(NotImplementedError): 312 EnableReflectionKey(key) 313 with self.assertRaises(NotImplementedError): 314 QueryReflectionKey(key) 315 with self.assertRaises(NotImplementedError): 316 DeleteKeyEx(HKEY_CURRENT_USER, test_key_name) 317 finally: 318 DeleteKey(HKEY_CURRENT_USER, test_key_name) 319 320 def test_setvalueex_value_range(self): 321 # Test for Issue #14420, accept proper ranges for SetValueEx. 322 # Py2Reg, which gets called by SetValueEx, was using PyLong_AsLong, 323 # thus raising OverflowError. The implementation now uses 324 # PyLong_AsUnsignedLong to match DWORD's size. 325 try: 326 with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck: 327 self.assertNotEqual(ck.handle, 0) 328 SetValueEx(ck, "test_name", None, REG_DWORD, 0x80000000) 329 finally: 330 DeleteKey(HKEY_CURRENT_USER, test_key_name) 331 332 def test_queryvalueex_return_value(self): 333 # Test for Issue #16759, return unsigned int from QueryValueEx. 334 # Reg2Py, which gets called by QueryValueEx, was returning a value 335 # generated by PyLong_FromLong. The implmentation now uses 336 # PyLong_FromUnsignedLong to match DWORD's size. 337 try: 338 with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck: 339 self.assertNotEqual(ck.handle, 0) 340 test_val = 0x80000000 341 SetValueEx(ck, "test_name", None, REG_DWORD, test_val) 342 ret_val, ret_type = QueryValueEx(ck, "test_name") 343 self.assertEqual(ret_type, REG_DWORD) 344 self.assertEqual(ret_val, test_val) 345 finally: 346 DeleteKey(HKEY_CURRENT_USER, test_key_name) 347 348 349 350 @unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests") 351 class RemoteWinregTests(BaseWinregTests): 352 353 def test_remote_registry_works(self): 354 remote_key = ConnectRegistry(REMOTE_NAME, HKEY_CURRENT_USER) 355 self._test_all(remote_key) 356 357 358 @unittest.skipUnless(WIN64_MACHINE, "x64 specific registry tests") 359 class Win64WinregTests(BaseWinregTests): 360 361 def test_reflection_functions(self): 362 # Test that we can call the query, enable, and disable functions 363 # on a key which isn't on the reflection list with no consequences. 364 with OpenKey(HKEY_LOCAL_MACHINE, "Software") as key: 365 # HKLM\Software is redirected but not reflected in all OSes 366 self.assertTrue(QueryReflectionKey(key)) 367 self.assertEqual(None, EnableReflectionKey(key)) 368 self.assertEqual(None, DisableReflectionKey(key)) 369 self.assertTrue(QueryReflectionKey(key)) 370 371 @unittest.skipUnless(HAS_REFLECTION, "OS doesn't support reflection") 372 def test_reflection(self): 373 # Test that we can create, open, and delete keys in the 32-bit 374 # area. Because we are doing this in a key which gets reflected, 375 # test the differences of 32 and 64-bit keys before and after the 376 # reflection occurs (ie. when the created key is closed). 377 try: 378 with CreateKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0, 379 KEY_ALL_ACCESS | KEY_WOW64_32KEY) as created_key: 380 self.assertNotEqual(created_key.handle, 0) 381 382 # The key should now be available in the 32-bit area 383 with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0, 384 KEY_ALL_ACCESS | KEY_WOW64_32KEY) as key: 385 self.assertNotEqual(key.handle, 0) 386 387 # Write a value to what currently is only in the 32-bit area 388 SetValueEx(created_key, "", 0, REG_SZ, "32KEY") 389 390 # The key is not reflected until created_key is closed. 391 # The 64-bit version of the key should not be available yet. 392 open_fail = lambda: OpenKey(HKEY_CURRENT_USER, 393 test_reflect_key_name, 0, 394 KEY_READ | KEY_WOW64_64KEY) 395 self.assertRaises(WindowsError, open_fail) 396 397 # Now explicitly open the 64-bit version of the key 398 with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0, 399 KEY_ALL_ACCESS | KEY_WOW64_64KEY) as key: 400 self.assertNotEqual(key.handle, 0) 401 # Make sure the original value we set is there 402 self.assertEqual("32KEY", QueryValue(key, "")) 403 # Set a new value, which will get reflected to 32-bit 404 SetValueEx(key, "", 0, REG_SZ, "64KEY") 405 406 # Reflection uses a "last-writer wins policy, so the value we set 407 # on the 64-bit key should be the same on 32-bit 408 with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0, 409 KEY_READ | KEY_WOW64_32KEY) as key: 410 self.assertEqual("64KEY", QueryValue(key, "")) 411 finally: 412 DeleteKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 413 KEY_WOW64_32KEY, 0) 414 415 @unittest.skipUnless(HAS_REFLECTION, "OS doesn't support reflection") 416 def test_disable_reflection(self): 417 # Make use of a key which gets redirected and reflected 418 try: 419 with CreateKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0, 420 KEY_ALL_ACCESS | KEY_WOW64_32KEY) as created_key: 421 # QueryReflectionKey returns whether or not the key is disabled 422 disabled = QueryReflectionKey(created_key) 423 self.assertEqual(type(disabled), bool) 424 # HKCU\Software\Classes is reflected by default 425 self.assertFalse(disabled) 426 427 DisableReflectionKey(created_key) 428 self.assertTrue(QueryReflectionKey(created_key)) 429 430 # The key is now closed and would normally be reflected to the 431 # 64-bit area, but let's make sure that didn't happen. 432 open_fail = lambda: OpenKeyEx(HKEY_CURRENT_USER, 433 test_reflect_key_name, 0, 434 KEY_READ | KEY_WOW64_64KEY) 435 self.assertRaises(WindowsError, open_fail) 436 437 # Make sure the 32-bit key is actually there 438 with OpenKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0, 439 KEY_READ | KEY_WOW64_32KEY) as key: 440 self.assertNotEqual(key.handle, 0) 441 finally: 442 DeleteKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 443 KEY_WOW64_32KEY, 0) 444 445 def test_exception_numbers(self): 446 with self.assertRaises(WindowsError) as ctx: 447 QueryValue(HKEY_CLASSES_ROOT, 'some_value_that_does_not_exist') 448 449 self.assertEqual(ctx.exception.errno, 2) 450 169 451 def test_main(): 170 test_support.run_unittest(WinregTests) 452 test_support.run_unittest(LocalWinregTests, RemoteWinregTests, 453 Win64WinregTests) 171 454 172 455 if __name__ == "__main__": 173 try: 174 WinregTests.remote_name = sys.argv[sys.argv.index("--remote")+1] 175 except (IndexError, ValueError): 456 if not REMOTE_NAME: 176 457 print "Remote registry calls can be tested using", 177 458 print "'test_winreg.py --remote \\\\machine_name'" 178 WinregTests.remote_name = None179 459 test_main()
Note:
See TracChangeset
for help on using the changeset viewer.