Skip to content

Commit 9c2af57

Browse files
committed
[GR-59893] Tagged tests for windows
PullRequest: graalpython/3577
2 parents 9a245a1 + 872e668 commit 9c2af57

File tree

339 files changed

+22616
-22393
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

339 files changed

+22616
-22393
lines changed

ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "overlay": "0f0411f4ace5b5c0f6ecdd5b787659e6adadc53c" }
1+
{ "overlay": "9b569abc4c15b4de648248809d31293b16f90182" }

graalpython/com.oracle.graal.python.test/src/runner.py

Lines changed: 103 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,14 @@
4242
import fnmatch
4343
import json
4444
import math
45-
import multiprocessing
4645
import os
4746
import pickle
4847
import platform
4948
import re
49+
import select
5050
import shlex
5151
import signal
52+
import socket
5253
import subprocess
5354
import sys
5455
import tempfile
@@ -205,7 +206,7 @@ def out_tell():
205206
try:
206207
return os.lseek(1, 0, os.SEEK_CUR)
207208
except OSError:
208-
return -1
209+
return 0
209210

210211

211212
T = typing.TypeVar('T')
@@ -303,7 +304,7 @@ def startTest(self, test):
303304
)
304305

305306

306-
class PipeResult(AbstractRemoteResult):
307+
class ConnectionResult(AbstractRemoteResult):
307308
def __init__(self, test_suite: 'TestSuite', conn):
308309
super().__init__(test_suite)
309310
self.conn = conn
@@ -435,7 +436,7 @@ def generate_mx_report(self, path: str):
435436
case _:
436437
status = 'FAILED'
437438
report_data.append({
438-
'name': str(result.test_id),
439+
'name': str(result.test_id).replace('\\', '/'),
439440
'status': status,
440441
'duration': result.duration,
441442
})
@@ -506,16 +507,18 @@ def write_tags(test_file: 'TestFile', tags: typing.Iterable['Tag']):
506507

507508

508509
def interrupt_process(process: subprocess.Popen):
509-
sig = signal.SIGINT if sys.platform != 'win32' else signal.CTRL_C_EVENT
510-
process.send_signal(sig)
510+
if hasattr(signal, 'SIGINT'):
511+
try:
512+
process.send_signal(signal.SIGINT)
513+
process.wait(3)
514+
return
515+
except (OSError, subprocess.TimeoutExpired):
516+
pass
517+
process.terminate()
511518
try:
512519
process.wait(3)
513520
except subprocess.TimeoutExpired:
514-
process.terminate()
515-
try:
516-
process.wait(3)
517-
except subprocess.TimeoutExpired:
518-
process.kill()
521+
process.kill()
519522

520523

521524
class ParallelTestRunner(TestRunner):
@@ -715,22 +718,18 @@ def get_test_to_blame(self):
715718

716719
def run_in_subprocess_and_watch(self):
717720
self.thread = threading.current_thread()
718-
# noinspection PyUnresolvedReferences
719-
use_pipe = sys.platform != 'win32' and (not IS_GRAALPY or __graalpython__.posix_module_backend() == 'native')
720-
with tempfile.TemporaryDirectory(prefix='graalpytest-') as tmp_dir:
721+
with (
722+
tempfile.TemporaryDirectory(prefix='graalpytest-') as tmp_dir,
723+
socket.create_server(('0.0.0.0', 0)) as server,
724+
):
721725
tmp_dir = Path(tmp_dir)
722726

723-
if use_pipe:
724-
pipe, child_pipe = multiprocessing.Pipe()
725-
else:
726-
result_file = tmp_dir / 'result'
727+
port = server.getsockname()[1]
728+
assert port
727729

728730
while self.remaining_test_ids and not self.stop_event.is_set():
729731
last_remaining_count = len(self.remaining_test_ids)
730-
with (
731-
open(tmp_dir / 'out', 'w+') as self.out_file,
732-
open(tmp_dir / 'tests', 'w+') as tests_file,
733-
):
732+
with open(tmp_dir / 'out', 'w+') as self.out_file:
734733
self.last_out_pos = 0
735734
self.last_started_time = time.time()
736735
cmd = [
@@ -739,69 +738,54 @@ def run_in_subprocess_and_watch(self):
739738
*self.runner.subprocess_args,
740739
__file__,
741740
'worker',
742-
'--tests-file', str(tests_file.name),
741+
'--port', str(port),
743742
]
744-
if use_pipe:
745-
cmd += ['--pipe-fd', str(child_pipe.fileno())]
746-
else:
747-
cmd += ['--result-file', str(result_file)]
748743
if self.runner.failfast:
749744
cmd.append('--failfast')
750-
# We communicate the tests through a temp file to avoid running into too long commandlines on windows
751-
tests_file.seek(0)
752-
tests_file.truncate()
753-
tests_file.write('\n'.join(map(str, self.remaining_test_ids)))
754-
tests_file.flush()
755-
popen_kwargs: dict = dict(
756-
stdout=self.out_file,
757-
stderr=self.out_file,
758-
)
759-
if use_pipe:
760-
popen_kwargs.update(pass_fds=[child_pipe.fileno()])
761-
self.process = subprocess.Popen(cmd, **popen_kwargs)
762-
763-
timed_out = None
764-
765-
if use_pipe:
766-
while self.process.poll() is None:
767-
while pipe.poll(0.1):
768-
self.process_event(pipe.recv())
769-
if self.stop_event.is_set():
770-
interrupt_process(self.process)
771-
break
772-
if self.last_started_test_id:
773-
last_started_test = self.tests_by_id.get(self.last_started_test_id)
774-
timeout = (
775-
last_started_test.test_file.test_config.per_test_timeout
776-
or self.runner.default_test_timeout
777-
)
778-
else:
779-
timeout = self.runner.default_test_timeout
780-
timeout *= self.runner.timeout_factor
781-
if time.time() - self.last_started_time >= timeout:
782-
interrupt_process(self.process)
783-
timed_out = timeout
784-
# Drain the pipe
785-
while pipe.poll(0.1):
786-
pipe.recv()
787-
break
745+
self.process = subprocess.Popen(cmd, stdout=self.out_file, stderr=self.out_file)
746+
747+
server.settimeout(600.0)
748+
with server.accept()[0] as sock:
749+
conn = Connection(sock)
750+
751+
conn.send([TestSpecifier(t.test_file, t.test_name) for t in self.remaining_test_ids])
752+
753+
timed_out = None
754+
788755
try:
789-
self.process.wait(self.runner.default_test_timeout)
790-
except subprocess.TimeoutExpired:
791-
log("Warning: Worker didn't shutdown in a timely manner, interrupting it")
792-
interrupt_process(self.process)
756+
while True:
757+
while conn.poll(0.1):
758+
event = conn.recv()
759+
self.process_event(event)
760+
if self.stop_event.is_set():
761+
interrupt_process(self.process)
762+
break
763+
if self.last_started_test_id:
764+
last_started_test = self.tests_by_id.get(self.last_started_test_id)
765+
timeout = (
766+
last_started_test.test_file.test_config.per_test_timeout
767+
or self.runner.default_test_timeout
768+
)
769+
else:
770+
timeout = self.runner.default_test_timeout
771+
timeout *= self.runner.timeout_factor
772+
if time.time() - self.last_started_time >= timeout:
773+
interrupt_process(self.process)
774+
timed_out = timeout
775+
break
776+
except (ConnectionClosed, OSError):
777+
# The socket closed or got connection reset, that's normal if the worker exitted or crashed
778+
pass
779+
try:
780+
self.process.wait(self.runner.default_test_timeout)
781+
except subprocess.TimeoutExpired:
782+
log("Warning: Worker didn't shutdown in a timely manner, interrupting it")
783+
interrupt_process(self.process)
793784

794785
returncode = self.process.wait()
795786

796787
if self.stop_event.is_set():
797788
return
798-
if use_pipe:
799-
while pipe.poll(0.1):
800-
self.process_event(pipe.recv())
801-
else:
802-
with open(result_file, 'rb') as f:
803-
for file_event in pickle.load(f):
804-
self.process_event(file_event)
805789

806790
if returncode != 0 or timed_out is not None:
807791
self.out_file.seek(self.last_out_pos)
@@ -1215,32 +1199,51 @@ def loadTestsFromModule(self, module, *, pattern=None):
12151199
return test_suite
12161200

12171201

1202+
class ConnectionClosed(Exception):
1203+
pass
1204+
1205+
1206+
class Connection:
1207+
def __init__(self, sock):
1208+
self.socket = sock
1209+
1210+
def send(self, obj):
1211+
data = pickle.dumps(obj)
1212+
header = len(data).to_bytes(8, byteorder='big')
1213+
self.socket.sendall(header)
1214+
self.socket.sendall(data)
1215+
1216+
def _recv(self, size):
1217+
data = b''
1218+
while len(data) < size:
1219+
read = self.socket.recv(size - len(data))
1220+
if not read:
1221+
return data
1222+
data += read
1223+
return data
1224+
1225+
def recv(self):
1226+
size = int.from_bytes(self._recv(8), byteorder='big')
1227+
if not size:
1228+
raise ConnectionClosed
1229+
data = self._recv(size)
1230+
return pickle.loads(data)
1231+
1232+
def poll(self, timeout=None):
1233+
rlist, wlist, xlist = select.select([self.socket], [], [], timeout)
1234+
return bool(rlist)
1235+
1236+
12181237
def main_worker(args):
1219-
tests = []
1220-
with open(args.tests_file) as f:
1221-
for line in f:
1222-
tests.append(TestSpecifier.from_str(line.strip()))
1223-
1224-
data = []
1225-
if args.pipe_fd:
1226-
import multiprocessing.connection
1227-
conn = multiprocessing.connection.Connection(args.pipe_fd)
1228-
1229-
def result_factory(suite):
1230-
return PipeResult(suite, conn)
1231-
else:
1232-
def result_factory(suite):
1233-
return SimpleResult(suite, data)
1238+
with socket.create_connection(('localhost', args.port)) as sock:
1239+
conn = Connection(sock)
12341240

1235-
for test_suite in collect(tests, no_excludes=True):
1236-
result = result_factory(test_suite)
1237-
result.failfast = args.failfast
1238-
test_suite.run(result)
1241+
tests = conn.recv()
12391242

1240-
if args.result_file:
1241-
with open(args.result_file, 'wb') as f:
1242-
# noinspection PyTypeChecker
1243-
pickle.dump(data, f)
1243+
for test_suite in collect(tests, no_excludes=True):
1244+
result = ConnectionResult(test_suite, conn)
1245+
result.failfast = args.failfast
1246+
test_suite.run(result)
12441247

12451248

12461249
def main_merge_tags(args):
@@ -1393,10 +1396,7 @@ def main():
13931396
# worker command declaration
13941397
worker_parser = subparsers.add_parser('worker', help="Internal command for subprocess workers")
13951398
worker_parser.set_defaults(main=main_worker)
1396-
group = worker_parser.add_mutually_exclusive_group()
1397-
group.add_argument('--pipe-fd', type=int)
1398-
group.add_argument('--result-file', type=Path)
1399-
worker_parser.add_argument('--tests-file', type=Path, required=True)
1399+
worker_parser.add_argument('--port', type=int)
14001400
worker_parser.add_argument('--failfast', action='store_true')
14011401

14021402
# merge-tags-from-report command declaration

graalpython/com.oracle.graal.python.test/src/tests/conftest.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ run_top_level_functions = true
33

44
[[test_rules]]
55
selector = ['standalone/*']
6-
per_test_timeout = 1800
6+
per_test_timeout = 2400
77
partial_splits_individual_tests = true
88

99
[[test_rules]]

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_functions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ def forgiving_set_item(args):
316316
resultspec="i",
317317
)
318318

319-
if not RUNS_ON_LLVM:
319+
if sys.implementation.name != 'graalpy' or __graalpython__.posix_module_backend() != 'java':
320320
__PyObject_AsFileDescriptor_FD0 = open(1, buffering=0, mode="wb")
321321
__PyObject_AsFileDescriptor_FD1 = open("%s/As_FileDescriptor_Testfile" % DIR, buffering=0, mode="wb")
322322
test_PyObject_AsFileDescriptor = CPyExtFunction(
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
test.test_abstract_numbers.TestNumbers.test_complex @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64
2-
test.test_abstract_numbers.TestNumbers.test_float @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64
3-
test.test_abstract_numbers.TestNumbers.test_int @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64
1+
test.test_abstract_numbers.TestNumbers.test_complex @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64
2+
test.test_abstract_numbers.TestNumbers.test_float @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64
3+
test.test_abstract_numbers.TestNumbers.test_int @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64

0 commit comments

Comments
 (0)