Skip to content

Commit 67231df

Browse files
committed
Merge branch 'master' into topic/GR-21836
2 parents 1326e2b + 7ae61e2 commit 67231df

File tree

63 files changed

+737
-569
lines changed

Some content is hidden

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

63 files changed

+737
-569
lines changed

ci.jsonnet

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{ "overlay": "d521478b3a031b5b55bb1b629650320cc9c9d425" }
1+
{ "overlay": "309437bc2ceea142484fb6568804b9d9e22949ac" }

graalpython/com.oracle.graal.python.benchmarks/python/harness.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import _io
4141
import os
4242
import sys
43+
import types
4344
from time import time
4445

4546

@@ -229,7 +230,7 @@ def get_bench_module(bench_file):
229230
return bench_module
230231

231232
else:
232-
bench_module = type(sys)(name, bench_file)
233+
bench_module = types.ModuleType(name, bench_file)
233234
with _io.FileIO(bench_file, "r") as f:
234235
bench_module.__file__ = bench_file
235236
bench_module.ccompile = ccompile
@@ -256,7 +257,10 @@ def run(self):
256257
args = self._call_attr(ATTR_PROCESS_ARGS, *self.bench_args)
257258
if args is None:
258259
# default args processor considers all args as ints
259-
args = list(map(int, self.bench_args))
260+
if sys.version_info.major < 3:
261+
args = list(map(lambda x: int(x.replace("_", "")), self.bench_args))
262+
else:
263+
args = list(map(int, self.bench_args))
260264

261265
print("### args = ", args)
262266
print(_HRULE)

graalpython/com.oracle.graal.python.benchmarks/python/meso/meteor3.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#
4242
# contributed by Daniel Nanz, 2008-08-21
4343
# 2to3
44+
from __future__ import print_function
4445
from bisect import bisect
4546
import time
4647

@@ -181,7 +182,7 @@ def main(n):
181182

182183
def measure(num):
183184
main(num)
184-
185+
185186

186187
def __benchmark__(num=2098):
187188
measure(num)

graalpython/com.oracle.graal.python.benchmarks/python/meso/richards3.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
# Translation from C++, Mario Wolczko
4646
# Outer loop added by Alex Jacoby
4747

48+
from __future__ import print_function
49+
4850
# Task IDs
4951
I_IDLE = 1
5052
I_WORK = 2

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/interop/InteropLibraryTest.java

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,24 @@
4040
*/
4141
package com.oracle.graal.python.test.interop;
4242

43-
import static org.junit.Assert.assertEquals;
43+
import org.junit.After;
44+
import org.junit.Before;
45+
import org.junit.Test;
4446
import static org.junit.Assert.assertFalse;
47+
import static org.junit.Assert.assertEquals;
4548
import static org.junit.Assert.assertTrue;
4649

4750
import org.graalvm.polyglot.Context;
4851
import org.graalvm.polyglot.Context.Builder;
4952
import org.graalvm.polyglot.Value;
50-
import org.junit.After;
51-
import org.junit.Before;
52-
import org.junit.Test;
53+
import org.graalvm.polyglot.proxy.ProxyArray;
5354

5455
import com.oracle.graal.python.test.PythonTests;
5556

57+
import java.util.Arrays;
58+
import java.util.Iterator;
59+
import java.util.List;
60+
5661
public class InteropLibraryTest extends PythonTests {
5762
private Context context;
5863

@@ -137,4 +142,62 @@ public void testPListRemovable() {
137142
public void testIsNull() {
138143
assertTrue(v("None").isNull());
139144
}
145+
146+
@Test
147+
public void testForItemInLazyArray() {
148+
// @formatter:off
149+
Value collect = context.eval("python", ""
150+
+ "def iter (arr):\n"
151+
+ "\tcollect = []\n"
152+
+ "\tfor item in arr:\n"
153+
+ "\t\tcollect.append(item)\n"
154+
+ "\t\tcollect.append(item)\n"
155+
+ "\t\tcollect.append(item)\n"
156+
+ "\treturn collect\n"
157+
+ "iter\n"
158+
);
159+
// @formatter:on
160+
161+
final List<Integer> list = Arrays.asList(5, 7, 11, 13, 17, 23);
162+
163+
Value tripples = collect.execute(new LazyArray(list.iterator()));
164+
assertTrue("Array returned", tripples.hasArrayElements());
165+
assertEquals(list.size() * 3, tripples.getArraySize());
166+
}
167+
168+
private static final class LazyArray implements ProxyArray {
169+
170+
private final Iterator<?> it;
171+
private long at;
172+
173+
LazyArray(Iterator<?> it) {
174+
this.it = it;
175+
this.at = 0;
176+
}
177+
178+
@Override
179+
public Object get(long index) {
180+
if (index == at) {
181+
at++;
182+
return it.next();
183+
}
184+
return null;
185+
}
186+
187+
@Override
188+
public void set(long index, Value value) {
189+
throw new UnsupportedOperationException();
190+
}
191+
192+
@Override
193+
public boolean remove(long index) {
194+
throw new UnsupportedOperationException();
195+
}
196+
197+
@Override
198+
public long getSize() {
199+
return it.hasNext() ? at + 1 : at;
200+
}
201+
}
202+
140203
}

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

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,17 @@
4040
import csv
4141
import gzip
4242
import os
43+
import signal
4344
import re
4445
import html
46+
import time
4547
import subprocess
4648
from collections import defaultdict
4749
from json import dumps
4850
from multiprocessing import Pool, TimeoutError
4951
from pprint import pformat
5052

53+
5154
import argparse
5255
import sys
5356
from time import gmtime, strftime
@@ -125,29 +128,44 @@ def file_name(name, current_date_time):
125128
return '{}-{}{}'.format(name[:idx], current_date_time, name[idx:])
126129
return '{}-{}'.format(name, current_date_time)
127130

131+
def get_tail(output, count=15):
132+
lines = output.split("\n")
133+
start = max(0, len(lines) - count)
134+
return '\n'.join(lines[start:])
135+
136+
TIMEOUT = 60 * 20 # 20 mins per unittest wait time max ...
128137

129138
# ----------------------------------------------------------------------------------------------------------------------
130139
#
131140
# exec utils
132141
#
133142
# ----------------------------------------------------------------------------------------------------------------------
134-
def _run_cmd(cmd, capture_on_failure=True):
143+
def _run_cmd(cmd, timeout=TIMEOUT, capture_on_failure=True):
135144
if isinstance(cmd, str):
136145
cmd = cmd.split(" ")
137146
assert isinstance(cmd, (list, tuple))
138147

139-
log("[EXEC] cmd: {} ...".format(' '.join(cmd)))
140-
success = True
141-
output = None
148+
cmd_string = ' '.join(cmd)
149+
log("[EXEC] starting '{}' ...".format(cmd_string))
142150

151+
start_time = time.monotonic()
152+
# os.setsid is used to create a process group, to be able to call os.killpg upon timeout
153+
proc = subprocess.Popen(cmd, preexec_fn=os.setsid, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
143154
try:
144-
output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
145-
except subprocess.CalledProcessError as e:
146-
log("[ERR] Could not execute CMD. Reason: {}".format(e))
147-
if capture_on_failure:
148-
output = e.output
149-
150-
return success, output.decode("utf-8", "ignore")
155+
output = proc.communicate(timeout=timeout)[0]
156+
except subprocess.TimeoutExpired as e:
157+
delta = time.monotonic() - start_time
158+
os.killpg(proc.pid, signal.SIGKILL)
159+
output = proc.communicate()[0]
160+
msg = "TimeoutExpired: {:.3f}s".format(delta)
161+
tail = get_tail(output.decode('utf-8', 'ignore'))
162+
log("[ERR] timeout '{}' after {:.3f}s, killing process group {}, last lines of output:\n{}\n{}", cmd_string, delta, proc.pid, tail, HR)
163+
else:
164+
delta = time.monotonic() - start_time
165+
log("[EXEC] finished '{}' with exit code {} in {:.3f}s", cmd_string, proc.returncode, delta)
166+
msg = "Finished: {:.3f}s".format(delta)
167+
168+
return proc.returncode == 0, output.decode("utf-8", "ignore") + "\n" + msg
151169

152170

153171
def scp(results_file_path, destination_path, destination_name=None):
@@ -157,54 +175,42 @@ def scp(results_file_path, destination_path, destination_name=None):
157175
return _run_cmd(cmd)[0]
158176

159177

160-
def _run_unittest(test_path, with_cpython=False):
178+
def _run_unittest(test_path, timeout, with_cpython=False):
161179
if with_cpython:
162180
cmd = ["python3", test_path, "-v"]
163181
else:
164182
cmd = ["mx", "python3", "--python.CatchAllExceptions=true", test_path, "-v"]
165-
success, output = _run_cmd(cmd)
183+
output = _run_cmd(cmd, timeout)[1]
166184
output = '''
167185
##############################################################
168186
#### running: {}
169187
'''.format(test_path) + output
170-
return success, output
171-
188+
return output
172189

173-
TIMEOUT = 60 * 20 # 20 mins per unittest wait time max ...
174190

175191

176192
def run_unittests(unittests, timeout, with_cpython=False):
177193
assert isinstance(unittests, (list, tuple))
178194
num_unittests = len(unittests)
179195
log("[EXEC] running {} unittests ... ", num_unittests)
180196
log("[EXEC] timeout per unittest: {} seconds", timeout)
181-
results = []
182197

183-
pool = Pool()
198+
start_time = time.monotonic()
199+
pool = Pool(processes=(os.cpu_count() // 4) or 1) # to account for hyperthreading and some additional overhead
200+
201+
out = []
202+
def callback(result):
203+
out.append(result)
204+
log("[PROGRESS] {} / {}: \t {:.1f}%", len(out), num_unittests, len(out) * 100 / num_unittests)
205+
206+
# schedule all unittest runs
184207
for ut in unittests:
185-
results.append(pool.apply_async(_run_unittest, args=(ut, with_cpython)))
208+
pool.apply_async(_run_unittest, args=(ut, timeout, with_cpython), callback=callback)
209+
186210
pool.close()
187-
188-
log("[INFO] collect results ... ")
189-
out = []
190-
timed_out = []
191-
for i, res in enumerate(results):
192-
try:
193-
_, output = res.get(timeout)
194-
out.append(output)
195-
except TimeoutError:
196-
log("[ERR] timeout while getting results for {}, skipping!", unittests[i])
197-
timed_out.append(unittests[i])
198-
log("[PROGRESS] {} / {}: \t {}%", i+1, num_unittests, int(((i+1) * 100.0) / num_unittests))
199-
200-
if timed_out:
201-
log(HR)
202-
for t in timed_out:
203-
log("[TIMEOUT] skipped: {}", t)
204-
log(HR)
205-
log("[STATS] processed {} out of {} unittests", num_unittests - len(timed_out), num_unittests)
206-
pool.terminate()
207211
pool.join()
212+
pool.terminate()
213+
log("[STATS] processed {} unittests in {:.3f}s", num_unittests, time.monotonic() - start_time)
208214
return out
209215

210216

@@ -346,11 +352,12 @@ def process_output(output_lines):
346352
match = re.match(PTRN_ERROR, line)
347353
if match:
348354
error_message = (match.group('error'), match.group('message'))
349-
error_message_dict = error_messages[unittests[-1]]
350-
d = error_message_dict.get(error_message)
351-
if not d:
352-
d = 0
353-
error_message_dict[error_message] = d + 1
355+
if not error_message[0] == 'Directory' and not error_message[0] == 'Components':
356+
error_message_dict = error_messages[unittests[-1]]
357+
d = error_message_dict.get(error_message)
358+
if not d:
359+
d = 0
360+
error_message_dict[error_message] = d + 1
354361
continue
355362

356363
# extract java exceptions
@@ -521,6 +528,8 @@ def save_as_csv(report_path, unittests, error_messages, java_exceptions, stats,
521528
unittest_errmsg = error_messages[unittest]
522529
if not unittest_errmsg:
523530
unittest_errmsg = java_exceptions[unittest]
531+
if not unittest_errmsg:
532+
unittest_errmsg = {}
524533

525534
rows.append({
526535
Col.UNITTEST: unittest,
@@ -867,7 +876,7 @@ def main(prog, args):
867876
action="store_true")
868877
parser.add_argument("-l", "--limit", help="Limit the number of unittests to run.", default=None, type=int)
869878
parser.add_argument("-t", "--tests_path", help="Unittests path.", default=PATH_UNITTESTS)
870-
parser.add_argument("-T", "--timeout", help="Timeout per unittest run.", default=TIMEOUT, type=int)
879+
parser.add_argument("-T", "--timeout", help="Timeout per unittest run (seconds).", default=TIMEOUT, type=int)
871880
parser.add_argument("-o", "--only_tests", help="Run only these unittests (comma sep values).", default=None)
872881
parser.add_argument("-s", "--skip_tests", help="Run all unittests except (comma sep values)."
873882
"the only_tets option takes precedence", default=None)

0 commit comments

Comments
 (0)