Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/test/test_winreg.py

    r2 r391  
    22# Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey
    33
     4import os, sys, errno
     5import unittest
     6from test import test_support
     7threading = test_support.import_module("threading")
     8from platform import machine
     9
     10# Do this first so test will be skipped if module doesn't exist
     11test_support.import_module('_winreg')
     12# Now import everything
    413from _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
     15try:
     16    REMOTE_NAME = sys.argv[sys.argv.index("--remote")+1]
     17except (IndexError, ValueError):
     18    REMOTE_NAME = None
     19
     20# tuple of (major, minor)
     21WIN_VER = sys.getwindowsversion()[:2]
     22# Some tests should only run on 64-bit architectures where WOW64 will be.
     23WIN64_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
     29HAS_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.
     33test_key_base = "Python Test Key [%d] - Delete Me" % (os.getpid(),)
     34test_key_name = "SOFTWARE\\" + test_key_base
     35# On OS'es that support reflection we should test with a reflected key
     36test_reflect_key_name = "SOFTWARE\\Classes\\" + test_key_base
    1137
    1238test_data = [
     
    3056    ]
    3157
    32 class WinregTests(unittest.TestCase):
    33     remote_name = None
    34 
    35     def WriteTestData(self, root_key):
     58class 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):
    3682        # Set the default value for this key.
    3783        SetValue(root_key, test_key_name, REG_SZ, "Default value")
     
    4692        # Check we wrote as many items as we thought.
    4793        nkeys, nvalues, since_mod = QueryInfoKey(key)
    48         self.assertEquals(nkeys, 1, "Not the correct number of sub keys")
    49         self.assertEquals(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")
    5096        nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
    51         self.assertEquals(nkeys, 0, "Not the correct number of sub keys")
    52         self.assertEquals(nvalues, len(test_data),
     97        self.assertEqual(nkeys, 0, "Not the correct number of sub keys")
     98        self.assertEqual(nvalues, len(test_data),
    5399                          "Not the correct number of values")
    54100        # Close this key this way...
     
    73119            pass
    74120
    75     def ReadTestData(self, root_key):
     121    def _read_test_data(self, root_key, OpenKey=OpenKey):
    76122        # Check we can get default value for this key.
    77123        val = QueryValue(root_key, test_key_name)
    78         self.assertEquals(val, "Default value",
    79                           "Registry didn't give back the correct value")
     124        self.assertEqual(val, "Default value",
     125                         "Registry didn't give back the correct value")
    80126
    81127        key = OpenKey(root_key, test_key_name)
     
    89135                except EnvironmentError:
    90136                    break
    91                 self.assertEquals(data in test_data, True,
    92                                   "Didn't read back the correct test data")
     137                self.assertIn(data, test_data,
     138                              "Didn't read back the correct test data")
    93139                index = index + 1
    94             self.assertEquals(index, len(test_data),
    95                               "Didn't read the correct number of items")
     140            self.assertEqual(index, len(test_data),
     141                             "Didn't read the correct number of items")
    96142            # Check I can directly access each item
    97143            for value_name, value_data, value_type in test_data:
    98144                read_val, read_typ = QueryValueEx(sub_key, value_name)
    99                 self.assertEquals(read_val, value_data,
    100                                   "Could not directly read the value")
    101                 self.assertEquals(read_typ, value_type,
    102                                   "Could not directly read the value")
     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")
    103149        sub_key.Close()
    104150        # Enumerate our main key.
    105151        read_val = EnumKey(key, 0)
    106         self.assertEquals(read_val, "sub_key", "Read subkey value wrong")
     152        self.assertEqual(read_val, "sub_key", "Read subkey value wrong")
    107153        try:
    108154            EnumKey(key, 1)
     
    113159        key.Close()
    114160
    115     def DeleteTestData(self, root_key):
     161    def _delete_test_data(self, root_key):
    116162        key = OpenKey(root_key, test_key_name, 0, KEY_ALL_ACCESS)
    117163        sub_key = OpenKey(key, "sub_key", 0, KEY_ALL_ACCESS)
     
    123169
    124170        nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
    125         self.assertEquals(nkeys, 0, "subkey not empty before delete")
    126         self.assertEquals(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")
    127173        sub_key.Close()
    128174        DeleteKey(key, "sub_key")
     
    143189            pass
    144190
    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
     196class 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):
    154214        # perform minimal ConnectRegistry test which just invokes it
    155215        h = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
     216        self.assertNotEqual(h.handle, 0)
    156217        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):
    165225        r = ExpandEnvironmentStrings(u"%windir%\\test")
    166226        self.assertEqual(type(r), unicode)
    167227        self.assertEqual(r, os.environ["windir"] + "\\test")
    168228
     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")
     351class 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")
     359class 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
    169451def test_main():
    170     test_support.run_unittest(WinregTests)
     452    test_support.run_unittest(LocalWinregTests, RemoteWinregTests,
     453                              Win64WinregTests)
    171454
    172455if __name__ == "__main__":
    173     try:
    174         WinregTests.remote_name = sys.argv[sys.argv.index("--remote")+1]
    175     except (IndexError, ValueError):
     456    if not REMOTE_NAME:
    176457        print "Remote registry calls can be tested using",
    177458        print "'test_winreg.py --remote \\\\machine_name'"
    178         WinregTests.remote_name = None
    179459    test_main()
Note: See TracChangeset for help on using the changeset viewer.