python (3.11.7)

(root)/
lib/
python3.11/
test/
test_winreg.py
       1  # Test the windows specific win32reg module.
       2  # Only win32reg functions not hit here: FlushKey, LoadKey and SaveKey
       3  
       4  import os, sys, errno
       5  import unittest
       6  from test.support import import_helper
       7  import threading
       8  from platform import machine, win32_edition
       9  
      10  # Do this first so test will be skipped if module doesn't exist
      11  import_helper.import_module('winreg', required_on=['win'])
      12  # Now import everything
      13  from winreg import *
      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
      37  
      38  test_data = [
      39      ("Int Value",     45,                                      REG_DWORD),
      40      ("Qword Value",   0x1122334455667788,                      REG_QWORD),
      41      ("String Val",    "A string value",                        REG_SZ),
      42      ("StringExpand",  "The path is %path%",                    REG_EXPAND_SZ),
      43      ("Multi-string",  ["Lots", "of", "string", "values"],      REG_MULTI_SZ),
      44      ("Multi-nul",     ["", "", "", ""],                        REG_MULTI_SZ),
      45      ("Raw Data",      b"binary\x00data",                       REG_BINARY),
      46      ("Big String",    "x"*(2**14-1),                           REG_SZ),
      47      ("Big Binary",    b"x"*(2**14),                            REG_BINARY),
      48      # Two and three kanjis, meaning: "Japan" and "Japanese".
      49      ("Japanese 日本", "日本語", REG_SZ),
      50  ]
      51  
      52  class ESC[4;38;5;81mBaseWinregTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      53  
      54      def setUp(self):
      55          # Make sure that the test key is absent when the test
      56          # starts.
      57          self.delete_tree(HKEY_CURRENT_USER, test_key_name)
      58  
      59      def delete_tree(self, root, subkey):
      60          try:
      61              hkey = OpenKey(root, subkey, 0, KEY_ALL_ACCESS)
      62          except OSError:
      63              # subkey does not exist
      64              return
      65          while True:
      66              try:
      67                  subsubkey = EnumKey(hkey, 0)
      68              except OSError:
      69                  # no more subkeys
      70                  break
      71              self.delete_tree(hkey, subsubkey)
      72          CloseKey(hkey)
      73          DeleteKey(root, subkey)
      74  
      75      def _write_test_data(self, root_key, subkeystr="sub_key",
      76                           CreateKey=CreateKey):
      77          # Set the default value for this key.
      78          SetValue(root_key, test_key_name, REG_SZ, "Default value")
      79          key = CreateKey(root_key, test_key_name)
      80          self.assertTrue(key.handle != 0)
      81          # Create a sub-key
      82          sub_key = CreateKey(key, subkeystr)
      83          # Give the sub-key some named values
      84  
      85          for value_name, value_data, value_type in test_data:
      86              SetValueEx(sub_key, value_name, 0, value_type, value_data)
      87  
      88          # Check we wrote as many items as we thought.
      89          nkeys, nvalues, since_mod = QueryInfoKey(key)
      90          self.assertEqual(nkeys, 1, "Not the correct number of sub keys")
      91          self.assertEqual(nvalues, 1, "Not the correct number of values")
      92          nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
      93          self.assertEqual(nkeys, 0, "Not the correct number of sub keys")
      94          self.assertEqual(nvalues, len(test_data),
      95                           "Not the correct number of values")
      96          # Close this key this way...
      97          # (but before we do, copy the key as an integer - this allows
      98          # us to test that the key really gets closed).
      99          int_sub_key = int(sub_key)
     100          CloseKey(sub_key)
     101          try:
     102              QueryInfoKey(int_sub_key)
     103              self.fail("It appears the CloseKey() function does "
     104                        "not close the actual key!")
     105          except OSError:
     106              pass
     107          # ... and close that key that way :-)
     108          int_key = int(key)
     109          key.Close()
     110          try:
     111              QueryInfoKey(int_key)
     112              self.fail("It appears the key.Close() function "
     113                        "does not close the actual key!")
     114          except OSError:
     115              pass
     116      def _read_test_data(self, root_key, subkeystr="sub_key", OpenKey=OpenKey):
     117          # Check we can get default value for this key.
     118          val = QueryValue(root_key, test_key_name)
     119          self.assertEqual(val, "Default value",
     120                           "Registry didn't give back the correct value")
     121  
     122          key = OpenKey(root_key, test_key_name)
     123          # Read the sub-keys
     124          with OpenKey(key, subkeystr) as sub_key:
     125              # Check I can enumerate over the values.
     126              index = 0
     127              while 1:
     128                  try:
     129                      data = EnumValue(sub_key, index)
     130                  except OSError:
     131                      break
     132                  self.assertEqual(data in test_data, True,
     133                                   "Didn't read back the correct test data")
     134                  index = index + 1
     135              self.assertEqual(index, len(test_data),
     136                               "Didn't read the correct number of items")
     137              # Check I can directly access each item
     138              for value_name, value_data, value_type in test_data:
     139                  read_val, read_typ = QueryValueEx(sub_key, value_name)
     140                  self.assertEqual(read_val, value_data,
     141                                   "Could not directly read the value")
     142                  self.assertEqual(read_typ, value_type,
     143                                   "Could not directly read the value")
     144          sub_key.Close()
     145          # Enumerate our main key.
     146          read_val = EnumKey(key, 0)
     147          self.assertEqual(read_val, subkeystr, "Read subkey value wrong")
     148          try:
     149              EnumKey(key, 1)
     150              self.fail("Was able to get a second key when I only have one!")
     151          except OSError:
     152              pass
     153  
     154          key.Close()
     155  
     156      def _delete_test_data(self, root_key, subkeystr="sub_key"):
     157          key = OpenKey(root_key, test_key_name, 0, KEY_ALL_ACCESS)
     158          sub_key = OpenKey(key, subkeystr, 0, KEY_ALL_ACCESS)
     159          # It is not necessary to delete the values before deleting
     160          # the key (although subkeys must not exist).  We delete them
     161          # manually just to prove we can :-)
     162          for value_name, value_data, value_type in test_data:
     163              DeleteValue(sub_key, value_name)
     164  
     165          nkeys, nvalues, since_mod = QueryInfoKey(sub_key)
     166          self.assertEqual(nkeys, 0, "subkey not empty before delete")
     167          self.assertEqual(nvalues, 0, "subkey not empty before delete")
     168          sub_key.Close()
     169          DeleteKey(key, subkeystr)
     170  
     171          try:
     172              # Shouldn't be able to delete it twice!
     173              DeleteKey(key, subkeystr)
     174              self.fail("Deleting the key twice succeeded")
     175          except OSError:
     176              pass
     177          key.Close()
     178          DeleteKey(root_key, test_key_name)
     179          # Opening should now fail!
     180          try:
     181              key = OpenKey(root_key, test_key_name)
     182              self.fail("Could open the non-existent key")
     183          except OSError: # Use this error name this time
     184              pass
     185  
     186      def _test_all(self, root_key, subkeystr="sub_key"):
     187          self._write_test_data(root_key, subkeystr)
     188          self._read_test_data(root_key, subkeystr)
     189          self._delete_test_data(root_key, subkeystr)
     190  
     191      def _test_named_args(self, key, sub_key):
     192          with CreateKeyEx(key=key, sub_key=sub_key, reserved=0,
     193                           access=KEY_ALL_ACCESS) as ckey:
     194              self.assertTrue(ckey.handle != 0)
     195  
     196          with OpenKeyEx(key=key, sub_key=sub_key, reserved=0,
     197                         access=KEY_ALL_ACCESS) as okey:
     198              self.assertTrue(okey.handle != 0)
     199  
     200  
     201  class ESC[4;38;5;81mLocalWinregTests(ESC[4;38;5;149mBaseWinregTests):
     202  
     203      def test_registry_works(self):
     204          self._test_all(HKEY_CURRENT_USER)
     205          self._test_all(HKEY_CURRENT_USER, "日本-subkey")
     206  
     207      def test_registry_works_extended_functions(self):
     208          # Substitute the regular CreateKey and OpenKey calls with their
     209          # extended counterparts.
     210          # Note: DeleteKeyEx is not used here because it is platform dependent
     211          cke = lambda key, sub_key: CreateKeyEx(key, sub_key, 0, KEY_ALL_ACCESS)
     212          self._write_test_data(HKEY_CURRENT_USER, CreateKey=cke)
     213  
     214          oke = lambda key, sub_key: OpenKeyEx(key, sub_key, 0, KEY_READ)
     215          self._read_test_data(HKEY_CURRENT_USER, OpenKey=oke)
     216  
     217          self._delete_test_data(HKEY_CURRENT_USER)
     218  
     219      def test_named_arguments(self):
     220          self._test_named_args(HKEY_CURRENT_USER, test_key_name)
     221          # Use the regular DeleteKey to clean up
     222          # DeleteKeyEx takes named args and is tested separately
     223          DeleteKey(HKEY_CURRENT_USER, test_key_name)
     224  
     225      def test_connect_registry_to_local_machine_works(self):
     226          # perform minimal ConnectRegistry test which just invokes it
     227          h = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
     228          self.assertNotEqual(h.handle, 0)
     229          h.Close()
     230          self.assertEqual(h.handle, 0)
     231  
     232      def test_nonexistent_remote_registry(self):
     233          connect = lambda: ConnectRegistry("abcdefghijkl", HKEY_CURRENT_USER)
     234          self.assertRaises(OSError, connect)
     235  
     236      def testExpandEnvironmentStrings(self):
     237          r = ExpandEnvironmentStrings("%windir%\\test")
     238          self.assertEqual(type(r), str)
     239          self.assertEqual(r, os.environ["windir"] + "\\test")
     240  
     241      def test_context_manager(self):
     242          # ensure that the handle is closed if an exception occurs
     243          try:
     244              with ConnectRegistry(None, HKEY_LOCAL_MACHINE) as h:
     245                  self.assertNotEqual(h.handle, 0)
     246                  raise OSError
     247          except OSError:
     248              self.assertEqual(h.handle, 0)
     249  
     250      def test_changing_value(self):
     251          # Issue2810: A race condition in 2.6 and 3.1 may cause
     252          # EnumValue or QueryValue to raise "WindowsError: More data is
     253          # available"
     254          done = False
     255  
     256          class ESC[4;38;5;81mVeryActiveThread(ESC[4;38;5;149mthreadingESC[4;38;5;149m.ESC[4;38;5;149mThread):
     257              def run(self):
     258                  with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
     259                      use_short = True
     260                      long_string = 'x'*2000
     261                      while not done:
     262                          s = 'x' if use_short else long_string
     263                          use_short = not use_short
     264                          SetValue(key, 'changing_value', REG_SZ, s)
     265  
     266          thread = VeryActiveThread()
     267          thread.start()
     268          try:
     269              with CreateKey(HKEY_CURRENT_USER,
     270                             test_key_name+'\\changing_value') as key:
     271                  for _ in range(1000):
     272                      num_subkeys, num_values, t = QueryInfoKey(key)
     273                      for i in range(num_values):
     274                          name = EnumValue(key, i)
     275                          QueryValue(key, name[0])
     276          finally:
     277              done = True
     278              thread.join()
     279              DeleteKey(HKEY_CURRENT_USER, test_key_name+'\\changing_value')
     280              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     281  
     282      def test_long_key(self):
     283          # Issue2810, in 2.6 and 3.1 when the key name was exactly 256
     284          # characters, EnumKey raised "WindowsError: More data is
     285          # available"
     286          name = 'x'*256
     287          try:
     288              with CreateKey(HKEY_CURRENT_USER, test_key_name) as key:
     289                  SetValue(key, name, REG_SZ, 'x')
     290                  num_subkeys, num_values, t = QueryInfoKey(key)
     291                  EnumKey(key, 0)
     292          finally:
     293              DeleteKey(HKEY_CURRENT_USER, '\\'.join((test_key_name, name)))
     294              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     295  
     296      def test_dynamic_key(self):
     297          # Issue2810, when the value is dynamically generated, these
     298          # raise "WindowsError: More data is available" in 2.6 and 3.1
     299          try:
     300              EnumValue(HKEY_PERFORMANCE_DATA, 0)
     301          except OSError as e:
     302              if e.errno in (errno.EPERM, errno.EACCES):
     303                  self.skipTest("access denied to registry key "
     304                                "(are you running in a non-interactive session?)")
     305              raise
     306          QueryValueEx(HKEY_PERFORMANCE_DATA, "")
     307  
     308      # Reflection requires XP x64/Vista at a minimum. XP doesn't have this stuff
     309      # or DeleteKeyEx so make sure their use raises NotImplementedError
     310      @unittest.skipUnless(WIN_VER < (5, 2), "Requires Windows XP")
     311      def test_reflection_unsupported(self):
     312          try:
     313              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     314                  self.assertNotEqual(ck.handle, 0)
     315  
     316              key = OpenKey(HKEY_CURRENT_USER, test_key_name)
     317              self.assertNotEqual(key.handle, 0)
     318  
     319              with self.assertRaises(NotImplementedError):
     320                  DisableReflectionKey(key)
     321              with self.assertRaises(NotImplementedError):
     322                  EnableReflectionKey(key)
     323              with self.assertRaises(NotImplementedError):
     324                  QueryReflectionKey(key)
     325              with self.assertRaises(NotImplementedError):
     326                  DeleteKeyEx(HKEY_CURRENT_USER, test_key_name)
     327          finally:
     328              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     329  
     330      def test_setvalueex_value_range(self):
     331          # Test for Issue #14420, accept proper ranges for SetValueEx.
     332          # Py2Reg, which gets called by SetValueEx, was using PyLong_AsLong,
     333          # thus raising OverflowError. The implementation now uses
     334          # PyLong_AsUnsignedLong to match DWORD's size.
     335          try:
     336              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     337                  self.assertNotEqual(ck.handle, 0)
     338                  SetValueEx(ck, "test_name", None, REG_DWORD, 0x80000000)
     339          finally:
     340              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     341  
     342      def test_setvalueex_negative_one_check(self):
     343          # Test for Issue #43984, check -1 was not set by SetValueEx.
     344          # Py2Reg, which gets called by SetValueEx, wasn't checking return
     345          # value by PyLong_AsUnsignedLong, thus setting -1 as value in the registry.
     346          # The implementation now checks PyLong_AsUnsignedLong return value to assure
     347          # the value set was not -1.
     348          try:
     349              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     350                  with self.assertRaises(OverflowError):
     351                      SetValueEx(ck, "test_name_dword", None, REG_DWORD, -1)
     352                      SetValueEx(ck, "test_name_qword", None, REG_QWORD, -1)
     353                  self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_dword")
     354                  self.assertRaises(FileNotFoundError, QueryValueEx, ck, "test_name_qword")
     355  
     356          finally:
     357              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     358  
     359      def test_queryvalueex_return_value(self):
     360          # Test for Issue #16759, return unsigned int from QueryValueEx.
     361          # Reg2Py, which gets called by QueryValueEx, was returning a value
     362          # generated by PyLong_FromLong. The implementation now uses
     363          # PyLong_FromUnsignedLong to match DWORD's size.
     364          try:
     365              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     366                  self.assertNotEqual(ck.handle, 0)
     367                  test_val = 0x80000000
     368                  SetValueEx(ck, "test_name", None, REG_DWORD, test_val)
     369                  ret_val, ret_type = QueryValueEx(ck, "test_name")
     370                  self.assertEqual(ret_type, REG_DWORD)
     371                  self.assertEqual(ret_val, test_val)
     372          finally:
     373              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     374  
     375      def test_setvalueex_crash_with_none_arg(self):
     376          # Test for Issue #21151, segfault when None is passed to SetValueEx
     377          try:
     378              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     379                  self.assertNotEqual(ck.handle, 0)
     380                  test_val = None
     381                  SetValueEx(ck, "test_name", 0, REG_BINARY, test_val)
     382                  ret_val, ret_type = QueryValueEx(ck, "test_name")
     383                  self.assertEqual(ret_type, REG_BINARY)
     384                  self.assertEqual(ret_val, test_val)
     385          finally:
     386              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     387  
     388      def test_read_string_containing_null(self):
     389          # Test for issue 25778: REG_SZ should not contain null characters
     390          try:
     391              with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
     392                  self.assertNotEqual(ck.handle, 0)
     393                  test_val = "A string\x00 with a null"
     394                  SetValueEx(ck, "test_name", 0, REG_SZ, test_val)
     395                  ret_val, ret_type = QueryValueEx(ck, "test_name")
     396                  self.assertEqual(ret_type, REG_SZ)
     397                  self.assertEqual(ret_val, "A string")
     398          finally:
     399              DeleteKey(HKEY_CURRENT_USER, test_key_name)
     400  
     401  
     402  @unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests")
     403  class ESC[4;38;5;81mRemoteWinregTests(ESC[4;38;5;149mBaseWinregTests):
     404  
     405      def test_remote_registry_works(self):
     406          remote_key = ConnectRegistry(REMOTE_NAME, HKEY_CURRENT_USER)
     407          self._test_all(remote_key)
     408  
     409  
     410  @unittest.skipUnless(WIN64_MACHINE, "x64 specific registry tests")
     411  class ESC[4;38;5;81mWin64WinregTests(ESC[4;38;5;149mBaseWinregTests):
     412  
     413      def test_named_arguments(self):
     414          self._test_named_args(HKEY_CURRENT_USER, test_key_name)
     415          # Clean up and also exercise the named arguments
     416          DeleteKeyEx(key=HKEY_CURRENT_USER, sub_key=test_key_name,
     417                      access=KEY_ALL_ACCESS, reserved=0)
     418  
     419      @unittest.skipIf(win32_edition() in ('WindowsCoreHeadless', 'IoTEdgeOS'), "APIs not available on WindowsCoreHeadless")
     420      def test_reflection_functions(self):
     421          # Test that we can call the query, enable, and disable functions
     422          # on a key which isn't on the reflection list with no consequences.
     423          with OpenKey(HKEY_LOCAL_MACHINE, "Software") as key:
     424              # HKLM\Software is redirected but not reflected in all OSes
     425              self.assertTrue(QueryReflectionKey(key))
     426              self.assertIsNone(EnableReflectionKey(key))
     427              self.assertIsNone(DisableReflectionKey(key))
     428              self.assertTrue(QueryReflectionKey(key))
     429  
     430      @unittest.skipUnless(HAS_REFLECTION, "OS doesn't support reflection")
     431      def test_reflection(self):
     432          # Test that we can create, open, and delete keys in the 32-bit
     433          # area. Because we are doing this in a key which gets reflected,
     434          # test the differences of 32 and 64-bit keys before and after the
     435          # reflection occurs (ie. when the created key is closed).
     436          try:
     437              with CreateKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     438                               KEY_ALL_ACCESS | KEY_WOW64_32KEY) as created_key:
     439                  self.assertNotEqual(created_key.handle, 0)
     440  
     441                  # The key should now be available in the 32-bit area
     442                  with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     443                               KEY_ALL_ACCESS | KEY_WOW64_32KEY) as key:
     444                      self.assertNotEqual(key.handle, 0)
     445  
     446                  # Write a value to what currently is only in the 32-bit area
     447                  SetValueEx(created_key, "", 0, REG_SZ, "32KEY")
     448  
     449                  # The key is not reflected until created_key is closed.
     450                  # The 64-bit version of the key should not be available yet.
     451                  open_fail = lambda: OpenKey(HKEY_CURRENT_USER,
     452                                              test_reflect_key_name, 0,
     453                                              KEY_READ | KEY_WOW64_64KEY)
     454                  self.assertRaises(OSError, open_fail)
     455  
     456              # Now explicitly open the 64-bit version of the key
     457              with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     458                           KEY_ALL_ACCESS | KEY_WOW64_64KEY) as key:
     459                  self.assertNotEqual(key.handle, 0)
     460                  # Make sure the original value we set is there
     461                  self.assertEqual("32KEY", QueryValue(key, ""))
     462                  # Set a new value, which will get reflected to 32-bit
     463                  SetValueEx(key, "", 0, REG_SZ, "64KEY")
     464  
     465              # Reflection uses a "last-writer wins policy, so the value we set
     466              # on the 64-bit key should be the same on 32-bit
     467              with OpenKey(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     468                           KEY_READ | KEY_WOW64_32KEY) as key:
     469                  self.assertEqual("64KEY", QueryValue(key, ""))
     470          finally:
     471              DeleteKeyEx(HKEY_CURRENT_USER, test_reflect_key_name,
     472                          KEY_WOW64_32KEY, 0)
     473  
     474      @unittest.skipUnless(HAS_REFLECTION, "OS doesn't support reflection")
     475      def test_disable_reflection(self):
     476          # Make use of a key which gets redirected and reflected
     477          try:
     478              with CreateKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     479                               KEY_ALL_ACCESS | KEY_WOW64_32KEY) as created_key:
     480                  # QueryReflectionKey returns whether or not the key is disabled
     481                  disabled = QueryReflectionKey(created_key)
     482                  self.assertEqual(type(disabled), bool)
     483                  # HKCU\Software\Classes is reflected by default
     484                  self.assertFalse(disabled)
     485  
     486                  DisableReflectionKey(created_key)
     487                  self.assertTrue(QueryReflectionKey(created_key))
     488  
     489              # The key is now closed and would normally be reflected to the
     490              # 64-bit area, but let's make sure that didn't happen.
     491              open_fail = lambda: OpenKeyEx(HKEY_CURRENT_USER,
     492                                            test_reflect_key_name, 0,
     493                                            KEY_READ | KEY_WOW64_64KEY)
     494              self.assertRaises(OSError, open_fail)
     495  
     496              # Make sure the 32-bit key is actually there
     497              with OpenKeyEx(HKEY_CURRENT_USER, test_reflect_key_name, 0,
     498                             KEY_READ | KEY_WOW64_32KEY) as key:
     499                  self.assertNotEqual(key.handle, 0)
     500          finally:
     501              DeleteKeyEx(HKEY_CURRENT_USER, test_reflect_key_name,
     502                          KEY_WOW64_32KEY, 0)
     503  
     504      def test_exception_numbers(self):
     505          with self.assertRaises(FileNotFoundError) as ctx:
     506              QueryValue(HKEY_CLASSES_ROOT, 'some_value_that_does_not_exist')
     507  
     508  
     509  if __name__ == "__main__":
     510      if not REMOTE_NAME:
     511          print("Remote registry calls can be tested using",
     512                "'test_winreg.py --remote \\\\machine_name'")
     513      unittest.main()