comparison tests/run-tests.py @ 35450:e31773898197

run-tests: use context managers for file descriptors I've seen the following error a few times recently when running the tests with `yes | ./run-tests.py --local -j9 -i`: Errored test-add.t: Traceback (most recent call last): File "./run-tests.py", line 821, in run self.runTest() File "./run-tests.py", line 910, in runTest if self._result.addOutputMismatch(self, ret, out, self._refout): File "./run-tests.py", line 1774, in addOutputMismatch rename(test.errpath, test.path) File "./run-tests.py", line 571, in rename os.remove(src) WindowsError: [Error 32] The process cannot access the file because it is being used by another process: 'c:\\Users\\Matt\\projects\\hg\\tests\\test-add.t.err' This change doesn't fix the problem, but it seems like a simple enough improvement.
author Matt Harbison <matt_harbison@yahoo.com>
date Sun, 17 Dec 2017 14:06:49 -0500
parents 24528dba0e64
children 4f5596e5e311
comparison
equal deleted inserted replaced
35449:24528dba0e64 35450:e31773898197
899 self.fail('no result code from test') 899 self.fail('no result code from test')
900 elif out != self._refout: 900 elif out != self._refout:
901 # Diff generation may rely on written .err file. 901 # Diff generation may rely on written .err file.
902 if (ret != 0 or out != self._refout) and not self._skipped \ 902 if (ret != 0 or out != self._refout) and not self._skipped \
903 and not self._debug: 903 and not self._debug:
904 f = open(self.errpath, 'wb') 904 with open(self.errpath, 'wb') as f:
905 for line in out: 905 for line in out:
906 f.write(line) 906 f.write(line)
907 f.close()
908 907
909 # The result object handles diff calculation for us. 908 # The result object handles diff calculation for us.
910 if self._result.addOutputMismatch(self, ret, out, self._refout): 909 if self._result.addOutputMismatch(self, ret, out, self._refout):
911 # change was accepted, skip failing 910 # change was accepted, skip failing
912 return 911 return
939 # files are deleted 938 # files are deleted
940 shutil.rmtree(self._chgsockdir, True) 939 shutil.rmtree(self._chgsockdir, True)
941 940
942 if (self._ret != 0 or self._out != self._refout) and not self._skipped \ 941 if (self._ret != 0 or self._out != self._refout) and not self._skipped \
943 and not self._debug and self._out: 942 and not self._debug and self._out:
944 f = open(self.errpath, 'wb') 943 with open(self.errpath, 'wb') as f:
945 for line in self._out: 944 for line in self._out:
946 f.write(line) 945 f.write(line)
947 f.close()
948 946
949 vlog("# Ret was:", self._ret, '(%s)' % self.name) 947 vlog("# Ret was:", self._ret, '(%s)' % self.name)
950 948
951 def _run(self, env): 949 def _run(self, env):
952 # This should be implemented in child classes to run tests. 950 # This should be implemented in child classes to run tests.
1085 1083
1086 return env 1084 return env
1087 1085
1088 def _createhgrc(self, path): 1086 def _createhgrc(self, path):
1089 """Create an hgrc file for this test.""" 1087 """Create an hgrc file for this test."""
1090 hgrc = open(path, 'wb') 1088 with open(path, 'wb') as hgrc:
1091 hgrc.write(b'[ui]\n') 1089 hgrc.write(b'[ui]\n')
1092 hgrc.write(b'slash = True\n') 1090 hgrc.write(b'slash = True\n')
1093 hgrc.write(b'interactive = False\n') 1091 hgrc.write(b'interactive = False\n')
1094 hgrc.write(b'mergemarkers = detailed\n') 1092 hgrc.write(b'mergemarkers = detailed\n')
1095 hgrc.write(b'promptecho = True\n') 1093 hgrc.write(b'promptecho = True\n')
1096 hgrc.write(b'[defaults]\n') 1094 hgrc.write(b'[defaults]\n')
1097 hgrc.write(b'[devel]\n') 1095 hgrc.write(b'[devel]\n')
1098 hgrc.write(b'all-warnings = true\n') 1096 hgrc.write(b'all-warnings = true\n')
1099 hgrc.write(b'default-date = 0 0\n') 1097 hgrc.write(b'default-date = 0 0\n')
1100 hgrc.write(b'[largefiles]\n') 1098 hgrc.write(b'[largefiles]\n')
1101 hgrc.write(b'usercache = %s\n' % 1099 hgrc.write(b'usercache = %s\n' %
1102 (os.path.join(self._testtmp, b'.cache/largefiles'))) 1100 (os.path.join(self._testtmp, b'.cache/largefiles')))
1103 hgrc.write(b'[lfs]\n') 1101 hgrc.write(b'[lfs]\n')
1104 hgrc.write(b'usercache = %s\n' % 1102 hgrc.write(b'usercache = %s\n' %
1105 (os.path.join(self._testtmp, b'.cache/lfs'))) 1103 (os.path.join(self._testtmp, b'.cache/lfs')))
1106 hgrc.write(b'[web]\n') 1104 hgrc.write(b'[web]\n')
1107 hgrc.write(b'address = localhost\n') 1105 hgrc.write(b'address = localhost\n')
1108 hgrc.write(b'ipv6 = %s\n' % str(self._useipv6).encode('ascii')) 1106 hgrc.write(b'ipv6 = %s\n' % str(self._useipv6).encode('ascii'))
1109 1107
1110 for opt in self._extraconfigopts: 1108 for opt in self._extraconfigopts:
1111 section, key = opt.encode('utf-8').split(b'.', 1) 1109 section, key = opt.encode('utf-8').split(b'.', 1)
1112 assert b'=' in key, ('extra config opt %s must ' 1110 assert b'=' in key, ('extra config opt %s must '
1113 'have an = for assignment' % opt) 1111 'have an = for assignment' % opt)
1114 hgrc.write(b'[%s]\n%s\n' % (section, key)) 1112 hgrc.write(b'[%s]\n%s\n' % (section, key))
1115 hgrc.close()
1116 1113
1117 def fail(self, msg): 1114 def fail(self, msg):
1118 # unittest differentiates between errored and failed. 1115 # unittest differentiates between errored and failed.
1119 # Failed is denoted by AssertionError (by default at least). 1116 # Failed is denoted by AssertionError (by default at least).
1120 raise AssertionError(msg) 1117 raise AssertionError(msg)
1230 @property 1227 @property
1231 def refpath(self): 1228 def refpath(self):
1232 return os.path.join(self._testdir, self.bname) 1229 return os.path.join(self._testdir, self.bname)
1233 1230
1234 def _run(self, env): 1231 def _run(self, env):
1235 f = open(self.path, 'rb') 1232 with open(self.path, 'rb') as f:
1236 lines = f.readlines() 1233 lines = f.readlines()
1237 f.close()
1238 1234
1239 # .t file is both reference output and the test input, keep reference 1235 # .t file is both reference output and the test input, keep reference
1240 # output updated with the the test input. This avoids some race 1236 # output updated with the the test input. This avoids some race
1241 # conditions where the reference output does not match the actual test. 1237 # conditions where the reference output does not match the actual test.
1242 if self._refout is not None: 1238 if self._refout is not None:
1244 1240
1245 salt, script, after, expected = self._parsetest(lines) 1241 salt, script, after, expected = self._parsetest(lines)
1246 1242
1247 # Write out the generated script. 1243 # Write out the generated script.
1248 fname = b'%s.sh' % self._testtmp 1244 fname = b'%s.sh' % self._testtmp
1249 f = open(fname, 'wb') 1245 with open(fname, 'wb') as f:
1250 for l in script: 1246 for l in script:
1251 f.write(l) 1247 f.write(l)
1252 f.close()
1253 1248
1254 cmd = b'%s "%s"' % (self._shell, fname) 1249 cmd = b'%s "%s"' % (self._shell, fname)
1255 vlog("# Running", cmd) 1250 vlog("# Running", cmd)
1256 1251
1257 exitcode, output = self._runcommand(cmd, env) 1252 exitcode, output = self._runcommand(cmd, env)
1882 if self._retest and not os.path.exists(test.errpath): 1877 if self._retest and not os.path.exists(test.errpath):
1883 result.addIgnore(test, 'not retesting') 1878 result.addIgnore(test, 'not retesting')
1884 continue 1879 continue
1885 1880
1886 if self._keywords: 1881 if self._keywords:
1887 f = open(test.path, 'rb') 1882 with open(test.path, 'rb') as f:
1888 t = f.read().lower() + test.bname.lower() 1883 t = f.read().lower() + test.bname.lower()
1889 f.close()
1890 ignored = False 1884 ignored = False
1891 for k in self._keywords.lower().split(): 1885 for k in self._keywords.lower().split():
1892 if k not in t: 1886 if k not in t:
1893 result.addIgnore(test, "doesn't match keyword") 1887 result.addIgnore(test, "doesn't match keyword")
1894 ignored = True 1888 ignored = True
2820 os.remove(installerrs) 2814 os.remove(installerrs)
2821 except OSError as e: 2815 except OSError as e:
2822 if e.errno != errno.ENOENT: 2816 if e.errno != errno.ENOENT:
2823 raise 2817 raise
2824 else: 2818 else:
2825 f = open(installerrs, 'rb') 2819 with open(installerrs, 'rb') as f:
2826 for line in f: 2820 for line in f:
2827 if PYTHON3: 2821 if PYTHON3:
2828 sys.stdout.buffer.write(line) 2822 sys.stdout.buffer.write(line)
2829 else: 2823 else:
2830 sys.stdout.write(line) 2824 sys.stdout.write(line)
2831 f.close()
2832 sys.exit(1) 2825 sys.exit(1)
2833 os.chdir(self._testdir) 2826 os.chdir(self._testdir)
2834 2827
2835 self._usecorrectpython() 2828 self._usecorrectpython()
2836 2829
2837 if self.options.py3k_warnings and not self.options.anycoverage: 2830 if self.options.py3k_warnings and not self.options.anycoverage:
2838 vlog("# Updating hg command to enable Py3k Warnings switch") 2831 vlog("# Updating hg command to enable Py3k Warnings switch")
2839 f = open(os.path.join(self._bindir, 'hg'), 'rb') 2832 with open(os.path.join(self._bindir, 'hg'), 'rb') as f:
2840 lines = [line.rstrip() for line in f] 2833 lines = [line.rstrip() for line in f]
2841 lines[0] += ' -3' 2834 lines[0] += ' -3'
2842 f.close() 2835 with open(os.path.join(self._bindir, 'hg'), 'wb') as f:
2843 f = open(os.path.join(self._bindir, 'hg'), 'wb') 2836 for line in lines:
2844 for line in lines: 2837 f.write(line + '\n')
2845 f.write(line + '\n')
2846 f.close()
2847 2838
2848 hgbat = os.path.join(self._bindir, b'hg.bat') 2839 hgbat = os.path.join(self._bindir, b'hg.bat')
2849 if os.path.isfile(hgbat): 2840 if os.path.isfile(hgbat):
2850 # hg.bat expects to be put in bin/scripts while run-tests.py 2841 # hg.bat expects to be put in bin/scripts while run-tests.py
2851 # installation layout put it in bin/ directly. Fix it 2842 # installation layout put it in bin/ directly. Fix it
2852 f = open(hgbat, 'rb') 2843 with open(hgbat, 'rb') as f:
2853 data = f.read() 2844 data = f.read()
2854 f.close()
2855 if b'"%~dp0..\python" "%~dp0hg" %*' in data: 2845 if b'"%~dp0..\python" "%~dp0hg" %*' in data:
2856 data = data.replace(b'"%~dp0..\python" "%~dp0hg" %*', 2846 data = data.replace(b'"%~dp0..\python" "%~dp0hg" %*',
2857 b'"%~dp0python" "%~dp0hg" %*') 2847 b'"%~dp0python" "%~dp0hg" %*')
2858 f = open(hgbat, 'wb') 2848 with open(hgbat, 'wb') as f:
2859 f.write(data) 2849 f.write(data)
2860 f.close()
2861 else: 2850 else:
2862 print('WARNING: cannot fix hg.bat reference to python.exe') 2851 print('WARNING: cannot fix hg.bat reference to python.exe')
2863 2852
2864 if self.options.anycoverage: 2853 if self.options.anycoverage:
2865 custom = os.path.join(self._testdir, 'sitecustomize.py') 2854 custom = os.path.join(self._testdir, 'sitecustomize.py')