[3.6] bpo-30523, bpo-30764, bpo-30776: Sync regrtest from master (#2441) · python/cpython@35d2ca2

@@ -377,19 +377,19 @@ def parse_executed_tests(self, output):

377377

return list(match.group(1) for match in parser)

378378379379

def check_executed_tests(self, output, tests, skipped=(), failed=(),

380-

omitted=(), randomize=False, interrupted=False):

380+

env_changed=(), omitted=(),

381+

randomize=False, interrupted=False,

382+

fail_env_changed=False):

381383

if isinstance(tests, str):

382384

tests = [tests]

383385

if isinstance(skipped, str):

384386

skipped = [skipped]

385387

if isinstance(failed, str):

386388

failed = [failed]

389+

if isinstance(env_changed, str):

390+

env_changed = [env_changed]

387391

if isinstance(omitted, str):

388392

omitted = [omitted]

389-

ntest = len(tests)

390-

nskipped = len(skipped)

391-

nfailed = len(failed)

392-

nomitted = len(omitted)

393393394394

executed = self.parse_executed_tests(output)

395395

if randomize:

@@ -415,11 +415,17 @@ def list_regex(line_format, tests):

415415

regex = list_regex('%s test%s failed', failed)

416416

self.check_line(output, regex)

417417418+

if env_changed:

419+

regex = list_regex('%s test%s altered the execution environment',

420+

env_changed)

421+

self.check_line(output, regex)

422+418423

if omitted:

419424

regex = list_regex('%s test%s omitted', omitted)

420425

self.check_line(output, regex)

421426422-

good = ntest - nskipped - nfailed - nomitted

427+

good = (len(tests) - len(skipped) - len(failed)

428+

- len(omitted) - len(env_changed))

423429

if good:

424430

regex = r'%s test%s OK\.$' % (good, plural(good))

425431

if not skipped and not failed and good > 1:

@@ -429,10 +435,12 @@ def list_regex(line_format, tests):

429435

if interrupted:

430436

self.check_line(output, 'Test suite interrupted by signal SIGINT.')

431437432-

if nfailed:

438+

if failed:

433439

result = 'FAILURE'

434440

elif interrupted:

435441

result = 'INTERRUPTED'

442+

elif fail_env_changed and env_changed:

443+

result = 'ENV CHANGED'

436444

else:

437445

result = 'SUCCESS'

438446

self.check_line(output, 'Tests result: %s' % result)

@@ -604,7 +612,7 @@ def test_failing(self):

604612

test_failing = self.create_test('failing', code=code)

605613

tests = [test_ok, test_failing]

606614607-

output = self.run_tests(*tests, exitcode=1)

615+

output = self.run_tests(*tests, exitcode=2)

608616

self.check_executed_tests(output, tests, failed=test_failing)

609617610618

def test_resources(self):

@@ -703,7 +711,7 @@ def test_fromfile(self):

703711

def test_interrupted(self):

704712

code = TEST_INTERRUPTED

705713

test = self.create_test('sigint', code=code)

706-

output = self.run_tests(test, exitcode=1)

714+

output = self.run_tests(test, exitcode=130)

707715

self.check_executed_tests(output, test, omitted=test,

708716

interrupted=True)

709717

@@ -732,7 +740,7 @@ def test_slow_interrupted(self):

732740

args = ("--slowest", "-j2", test)

733741

else:

734742

args = ("--slowest", test)

735-

output = self.run_tests(*args, exitcode=1)

743+

output = self.run_tests(*args, exitcode=130)

736744

self.check_executed_tests(output, test,

737745

omitted=test, interrupted=True)

738746

@@ -772,9 +780,43 @@ def test_run(self):

772780

builtins.__dict__['RUN'] = 1

773781

""")

774782

test = self.create_test('forever', code=code)

775-

output = self.run_tests('--forever', test, exitcode=1)

783+

output = self.run_tests('--forever', test, exitcode=2)

776784

self.check_executed_tests(output, [test]*3, failed=test)

777785786+

def check_leak(self, code, what):

787+

test = self.create_test('huntrleaks', code=code)

788+789+

filename = 'reflog.txt'

790+

self.addCleanup(support.unlink, filename)

791+

output = self.run_tests('--huntrleaks', '3:3:', test,

792+

exitcode=2,

793+

stderr=subprocess.STDOUT)

794+

self.check_executed_tests(output, [test], failed=test)

795+796+

line = 'beginning 6 repetitions\n123456\n......\n'

797+

self.check_line(output, re.escape(line))

798+799+

line2 = '%s leaked [1, 1, 1] %s, sum=3\n' % (test, what)

800+

self.assertIn(line2, output)

801+802+

with open(filename) as fp:

803+

reflog = fp.read()

804+

self.assertIn(line2, reflog)

805+806+

@unittest.skipUnless(Py_DEBUG, 'need a debug build')

807+

def test_huntrleaks(self):

808+

# test --huntrleaks

809+

code = textwrap.dedent("""

810+

import unittest

811+812+

GLOBAL_LIST = []

813+814+

class RefLeakTest(unittest.TestCase):

815+

def test_leak(self):

816+

GLOBAL_LIST.append(object())

817+

""")

818+

self.check_leak(code, 'references')

819+778820

@unittest.skipUnless(Py_DEBUG, 'need a debug build')

779821

def test_huntrleaks_fd_leak(self):

780822

# test --huntrleaks for file descriptor leak

@@ -799,24 +841,7 @@ def test_leak(self):

799841

fd = os.open(__file__, os.O_RDONLY)

800842

# bug: never cloes the file descriptor

801843

""")

802-

test = self.create_test('huntrleaks', code=code)

803-804-

filename = 'reflog.txt'

805-

self.addCleanup(support.unlink, filename)

806-

output = self.run_tests('--huntrleaks', '3:3:', test,

807-

exitcode=1,

808-

stderr=subprocess.STDOUT)

809-

self.check_executed_tests(output, [test], failed=test)

810-811-

line = 'beginning 6 repetitions\n123456\n......\n'

812-

self.check_line(output, re.escape(line))

813-814-

line2 = '%s leaked [1, 1, 1] file descriptors, sum=3\n' % test

815-

self.assertIn(line2, output)

816-817-

with open(filename) as fp:

818-

reflog = fp.read()

819-

self.assertIn(line2, reflog)

844+

self.check_leak(code, 'file descriptors')

820845821846

def test_list_tests(self):

822847

# test --list-tests

@@ -837,19 +862,28 @@ def test_method2(self):

837862

pass

838863

""")

839864

testname = self.create_test(code=code)

865+866+

# Test --list-cases

840867

all_methods = ['%s.Tests.test_method1' % testname,

841868

'%s.Tests.test_method2' % testname]

842869

output = self.run_tests('--list-cases', testname)

843870

self.assertEqual(output.splitlines(), all_methods)

844871872+

# Test --list-cases with --match

873+

all_methods = ['%s.Tests.test_method1' % testname]

874+

output = self.run_tests('--list-cases',

875+

'-m', 'test_method1',

876+

testname)

877+

self.assertEqual(output.splitlines(), all_methods)

878+845879

def test_crashed(self):

846880

# Any code which causes a crash

847881

code = 'import faulthandler; faulthandler._sigsegv()'

848882

crash_test = self.create_test(name="crash", code=code)

849883

ok_test = self.create_test(name="ok")

850884851885

tests = [crash_test, ok_test]

852-

output = self.run_tests("-j2", *tests, exitcode=1)

886+

output = self.run_tests("-j2", *tests, exitcode=2)

853887

self.check_executed_tests(output, tests, failed=crash_test,

854888

randomize=True)

855889

@@ -898,6 +932,25 @@ def test_method4(self):

898932

subset = ['test_method1', 'test_method3']

899933

self.assertEqual(methods, subset)

900934935+

def test_env_changed(self):

936+

code = textwrap.dedent("""

937+

import unittest

938+939+

class Tests(unittest.TestCase):

940+

def test_env_changed(self):

941+

open("env_changed", "w").close()

942+

""")

943+

testname = self.create_test(code=code)

944+945+

# don't fail by default

946+

output = self.run_tests(testname)

947+

self.check_executed_tests(output, [testname], env_changed=testname)

948+949+

# fail with --fail-env-changed

950+

output = self.run_tests("--fail-env-changed", testname, exitcode=3)

951+

self.check_executed_tests(output, [testname], env_changed=testname,

952+

fail_env_changed=True)

953+901954902955

if __name__ == '__main__':

903956

unittest.main()