Skip to content

Commit 1690eed

Browse files
committed
remove unused logs and trim long logs
1 parent 29e95f2 commit 1690eed

File tree

1 file changed

+86
-31
lines changed

1 file changed

+86
-31
lines changed

judge/testing.py

+86-31
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import zipfile
33
import os
44
import shutil
5+
import shlex
56
import subprocess
67
from os.path import isdir, join, exists, dirname
78
from django.core.files.storage import FileSystemStorage
@@ -52,9 +53,8 @@ def make_file_executable(file_path):
5253
def run_command_with_timeout(command: list, timeout: float) -> int:
5354
try:
5455
# Use the 'sudo' command to execute the given command with elevated privileges.
55-
result = subprocess.run(["/usr/bin/python3"] + command, capture_output=False, text=True, check=True, timeout=timeout)
56-
print("Command output:")
57-
print(result.stdout)
56+
result = subprocess.run(["/usr/bin/python3"] + command, capture_output=True, text=True, check=True, timeout=timeout)
57+
# print("Command output:\n", result.stdout)
5858
return TestResult.Succeed
5959
except subprocess.TimeoutExpired:
6060
print(f'program timeout after {timeout} seconds')
@@ -180,13 +180,55 @@ def __init__(self, submission: Submission):
180180
print(f"substitude {codepath} with user implemented")
181181
wfp.write(filecontent)
182182

183+
def remove_all_logs(self):
184+
log_path = join(self.sub_dirpath, 'logs')
185+
for filename in os.listdir(log_path):
186+
if filename.startswith("testcase"):
187+
file_path = join(log_path, filename)
188+
os.remove(file_path)
189+
190+
def remove_redudant_logs(self, failed_indexes: list):
191+
log_path = join(self.sub_dirpath, 'logs')
192+
ignore_files = [f"testcase{idx}.log" for idx in failed_indexes]
193+
ignore_files.append("results.json")
194+
for filename in os.listdir(log_path):
195+
if filename in ignore_files:
196+
continue
197+
file_path = join(log_path, filename)
198+
os.remove(file_path)
199+
200+
def trim_logs(self, failed_indexes: list):
201+
log_path = join(self.sub_dirpath, 'logs')
202+
max_lines = 1000
203+
for idx in failed_indexes:
204+
file_path = join(log_path, f"testcase{idx}.log")
205+
temp_file_path = file_path + ".trimmed"
206+
escaped_file_path = shlex.quote(file_path)
207+
tail_command = f"tail -n {max_lines} {escaped_file_path} > {shlex.quote(temp_file_path)}"
208+
os.system(tail_command)
209+
210+
with open(temp_file_path, 'r') as temp_file:
211+
content = temp_file.read()
212+
213+
if os.path.getsize(file_path) > os.path.getsize(temp_file_path):
214+
with open(temp_file_path, 'w') as temp_file:
215+
temp_file.write("log file is too long, only show the last 1000 lines:\n")
216+
temp_file.write(content)
217+
218+
os.remove(file_path)
219+
os.rename(temp_file_path, file_path)
220+
221+
183222
def judge(self) -> bool:
184223
# return True if grade is 100
185224
tester_path = join(self.sub_dirpath, TESTER_NAME)
186225
if not exists(tester_path):
187226
raise Exception("running submission: tester {} not exists".format(tester_path))
188227
print(f"running {tester_path}")
189228
res = run_command_with_timeout([tester_path, "--log", "--json"], self.sub.problem.timeout)
229+
230+
if res != TestResult.Succeed:
231+
self.remove_all_logs()
190232
if res == TestResult.Timeout:
191233
self.sub.result = JudgeStatus.PROGRAM_TIMEOUT
192234
self.sub.save()
@@ -198,39 +240,51 @@ def judge(self) -> bool:
198240
if not exists(log_path):
199241
raise Exception(f"logs path {log_path} not exists")
200242
failed_info = []
243+
failed_indexes: list
244+
201245
with open(join(log_path, "results.json")) as fp:
202246
res = json.load(fp)
203247
grade = res['grade']
204248
self.sub.grade = res['grade']
205-
for idx in res['failed']:
206-
log_fp = open(join(log_path, f"testcase{idx}.log"), "r")
207-
testcase_fp = open(join(self.sub_dirpath, TESTCASE_NAME), "r")
208-
testcase_json_data = json.load(testcase_fp)
209-
# notice the index here, logical index starts from 1
210-
if "config" in testcase_json_data:
211-
# global config
212-
config = testcase_json_data["config"]
213-
else:
214-
cur_data = testcase_json_data["testcases"][idx-1]
215-
if "config" in cur_data:
216-
# specific config for testcase
217-
config = cur_data["config"]
249+
250+
if grade == 0 or grade == 100:
251+
self.remove_all_logs()
252+
else:
253+
# clean and trim
254+
failed_indexes = res['failed']
255+
self.remove_redudant_logs(failed_indexes)
256+
self.trim_logs(failed_indexes)
257+
258+
for idx in res['failed']:
259+
log_fp = open(join(log_path, f"testcase{idx}.log"), "r")
260+
testcase_fp = open(join(self.sub_dirpath, TESTCASE_NAME), "r")
261+
testcase_json_data = json.load(testcase_fp)
262+
# notice the index here, logical index starts from 1
263+
if "config" in testcase_json_data:
264+
# global config
265+
config = testcase_json_data["config"]
218266
else:
219-
# no config
220-
config = None
221-
displayed_test = {
222-
"input": testcase_json_data["testcases"][idx-1]["input"],
223-
"expected_output":testcase_json_data["testcases"][idx-1]["output"],
224-
}
225-
# config, "testcase"
226-
failed_info.append({
227-
"config": config,
228-
"testcase_index": idx,
229-
"testcase": displayed_test,
230-
"log": log_fp.read()
231-
})
232-
log_fp.close()
233-
testcase_fp.close()
267+
cur_data = testcase_json_data["testcases"][idx-1]
268+
if "config" in cur_data:
269+
# specific config for testcase
270+
config = cur_data["config"]
271+
else:
272+
# no config
273+
config = None
274+
displayed_test = {
275+
"input": testcase_json_data["testcases"][idx-1]["input"],
276+
"expected_output":testcase_json_data["testcases"][idx-1]["output"],
277+
}
278+
# config, "testcase"
279+
failed_info.append({
280+
"config": config,
281+
"testcase_index": idx,
282+
"testcase": displayed_test,
283+
"log": log_fp.read()
284+
})
285+
log_fp.close()
286+
testcase_fp.close()
287+
234288
self.sub.failed_info = failed_info
235289
if grade == 0:
236290
self.sub.result = JudgeStatus.ALL_FAILED
@@ -239,6 +293,7 @@ def judge(self) -> bool:
239293
else:
240294
self.sub.result = JudgeStatus.SOME_PASSED
241295
self.sub.save()
296+
242297
if grade == 100:
243298
return True
244299
return False

0 commit comments

Comments
 (0)