Skip to content

Commit c18f8d0

Browse files
authored
Read and print tests output as UTF-8 in run_tests.py (#303)
The tests output is written as UTF-8, but run_tests.py read it with the locale's encoding. On Windows (cp1252) a non-ASCII character crashed the reader thread with a UnicodeDecodeError, and the run ended with "Timeout: output is frozen." instead of the test results. - Open all files as UTF-8, matching how UnitTesting writes them. - Reconfigure stdout to UTF-8, since it uses cp1252 when piped on Windows and printing the output would fail next. - Make the reader thread a daemon, so that an error in the main thread doesn't leave the process hanging.
1 parent dbfa72c commit c18f8d0

1 file changed

Lines changed: 13 additions & 7 deletions

File tree

‎actions/run-tests/run_tests.py‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,15 @@ def create_schedule(package, output_file, default_schedule):
5858
schedule = []
5959

6060
try:
61-
with open(SCHEDULE_FILE_PATH, "r") as f:
61+
with open(SCHEDULE_FILE_PATH, "r", encoding="utf-8") as f:
6262
schedule = json.load(f)
6363
except Exception:
6464
pass
6565

6666
if not any(s["package"] == package for s in schedule):
6767
schedule.append(default_schedule)
6868

69-
with open(SCHEDULE_FILE_PATH, "w") as f:
69+
with open(SCHEDULE_FILE_PATH, "w", encoding="utf-8") as f:
7070
f.write(json.dumps(schedule, ensure_ascii=False, indent=True))
7171

7272

@@ -135,7 +135,9 @@ def check_is_success(result):
135135
lock = threading.Lock()
136136

137137
def reader():
138-
with open(path, "r") as f:
138+
# The output is written as UTF-8. A read can end in the middle of a character, which is replaced until the
139+
# incomplete line is read again.
140+
with open(path, "r", encoding="utf-8", errors="replace") as f:
139141
while not done:
140142
offset = f.tell()
141143
line = f.readline()
@@ -149,7 +151,8 @@ def reader():
149151
time.sleep(0.2)
150152

151153
# run the reader in thread to avoid blocking
152-
t = threading.Thread(target=reader)
154+
# A daemon thread, so that an error in the main thread doesn't leave the process hanging.
155+
t = threading.Thread(target=reader, daemon=True)
153156
t.start()
154157
last_update_time = time.time()
155158

@@ -193,10 +196,10 @@ def restore_coverage_report(report_file):
193196
source_path, name = os.path.split(report_file)
194197
dest_path = os.getcwd()
195198
dest_file = os.path.join(dest_path, name)
196-
with open(report_file, "r") as f:
199+
with open(report_file, "r", encoding="utf-8") as f:
197200
txt = f.read()
198201
txt = txt.replace(source_path, dest_path)
199-
with open(dest_file, "w") as f:
202+
with open(dest_file, "w", encoding="utf-8") as f:
200203
f.write(txt)
201204
print(f"UnitTesting: Restored {dest_file}")
202205

@@ -235,7 +238,7 @@ def main(default_schedule_info):
235238

236239
# print errors recorded by ST
237240
if os.path.isfile(log_file):
238-
with open(log_file) as f:
241+
with open(log_file, encoding="utf-8", errors="replace") as f:
239242
print(f.read())
240243

241244
kill_sublime_text()
@@ -260,6 +263,9 @@ def main(default_schedule_info):
260263

261264

262265
if __name__ == "__main__":
266+
# The tests output is UTF-8, while stdout uses the locale's encoding when it's a pipe, e.g. cp1252 on Windows.
267+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
268+
263269
parser = optparse.OptionParser()
264270
parser.add_option("--syntax-test", action="store_true")
265271
parser.add_option("--syntax-compatibility", action="store_true")

0 commit comments

Comments
 (0)