mirror of
https://git.nju.edu.cn/oslab2023/oslab.git
synced 2024-06-13 04:44:31 +08:00
218 lines
5.0 KiB
Python
Executable File
218 lines
5.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import os
|
|
import re
|
|
import subprocess
|
|
from gradelib import *
|
|
|
|
STOPS = [stop_on_line(".*failed.*"),
|
|
stop_on_line(".*Abort @.*")]
|
|
|
|
r = Runner(save("qemu.out"))
|
|
|
|
@test(10, "childtest")
|
|
def test_child():
|
|
s = r"""
|
|
$ childtest 1 10 25
|
|
^(parent|child) sleep\.\.\.
|
|
^(parent|child) sleep\.\.\.
|
|
child exit @ 0
|
|
$ childtest 1 25 10
|
|
^(parent|child) sleep\.\.\.
|
|
^(parent|child) sleep\.\.\.
|
|
child exit @ 0
|
|
$ echo OK
|
|
OK
|
|
"""
|
|
script, exps, isregs = parse_script(s)
|
|
r.run_qemu(*STOPS, shell_script(script))
|
|
r.match(*exps, isregs=isregs, continued=True)
|
|
|
|
@test(10, "forkfork")
|
|
def test_forkfork():
|
|
s = """
|
|
$ forkfork
|
|
forkfork start
|
|
forkfork passed!
|
|
$ echo OK
|
|
OK
|
|
"""
|
|
script, exps, isregs = parse_script(s)
|
|
r.run_qemu(*STOPS, shell_script(script))
|
|
r.match(*exps, isregs=isregs, continued=True)
|
|
|
|
@test(10, "multiadd")
|
|
def test_multiadd():
|
|
s = """
|
|
$ multiadd
|
|
multiadd start.
|
|
ans = 289377997.
|
|
multiadd passed!
|
|
$ echo OK
|
|
OK
|
|
"""
|
|
script, exps, isregs = parse_script(s)
|
|
r.run_qemu(*STOPS, shell_script(script))
|
|
r.match(*exps, isregs=isregs, continued=True)
|
|
|
|
@test(10, "waittest")
|
|
def test_wait():
|
|
s = """
|
|
$ waittest
|
|
waittest start.
|
|
...
|
|
waittest passed!
|
|
$ echo OK
|
|
OK
|
|
"""
|
|
script, exps, isregs = parse_script(s)
|
|
r.run_qemu(*STOPS, shell_script(script))
|
|
r.match(*exps, isregs=isregs, continued=True)
|
|
|
|
@test(20, "pingpong")
|
|
def test_pingpong():
|
|
s = """
|
|
$ pingpong 114514 1919810
|
|
pingpong start
|
|
ping: pid=2, i=0, x=114514
|
|
pong: pid=3, i=0, x=1919810
|
|
ping: pid=2, i=1, x=114514
|
|
pong: pid=3, i=1, x=1919810
|
|
ping: pid=2, i=2, x=114514
|
|
pong: pid=3, i=2, x=1919810
|
|
ping: pid=2, i=3, x=114514
|
|
pong: pid=3, i=3, x=1919810
|
|
ping: pid=2, i=4, x=114514
|
|
pong: pid=3, i=4, x=1919810
|
|
ping: pid=2, i=5, x=114514
|
|
pong: pid=3, i=5, x=1919810
|
|
ping: pid=2, i=6, x=114514
|
|
pong: pid=3, i=6, x=1919810
|
|
ping: pid=2, i=7, x=114514
|
|
pong: pid=3, i=7, x=1919810
|
|
$ echo OK
|
|
OK
|
|
"""
|
|
script, exps, isregs = parse_script(s)
|
|
r.run_qemu(*STOPS, shell_script(script))
|
|
r.match(*exps, isregs=isregs, continued=True)
|
|
|
|
@test(20, "producer")
|
|
def test_producer():
|
|
curr_buf, MAXBUF = 0, 32
|
|
curr_line, MAXLINE = 0, 300
|
|
fail = False
|
|
producer_times = [0, 0, 0, 0]
|
|
customer_times = [0, 0]
|
|
|
|
def handle(line: str):
|
|
if line.startswith("producer"):
|
|
handle_producer(line)
|
|
elif line.startswith("consumer"):
|
|
handle_customer(line)
|
|
else:
|
|
set_fail(line)
|
|
|
|
def handle_producer(line):
|
|
nonlocal curr_buf, curr_line
|
|
no_str = line[9:10]
|
|
if not no_str.isdigit():
|
|
set_fail(line)
|
|
no = int(no_str)
|
|
if no < 0 or no > 3:
|
|
set_fail(line)
|
|
if curr_buf >= MAXBUF:
|
|
set_fail(line)
|
|
curr_buf += 1
|
|
curr_line += 1
|
|
producer_times[no] += 1
|
|
if curr_line >= MAXLINE:
|
|
raise TerminateTest
|
|
|
|
def handle_customer(line):
|
|
nonlocal curr_buf, curr_line
|
|
no_str = line[9:10]
|
|
if not no_str.isdigit():
|
|
set_fail(line)
|
|
no = int(no_str)
|
|
if no < 0 or no > 1:
|
|
set_fail(line)
|
|
if curr_buf < 0:
|
|
set_fail(line)
|
|
curr_buf -= 1
|
|
curr_line += 1
|
|
customer_times[no] += 1
|
|
if curr_line >= MAXLINE:
|
|
raise TerminateTest
|
|
|
|
def set_fail(_):
|
|
nonlocal fail
|
|
fail = True
|
|
raise TerminateTest
|
|
|
|
r.run_qemu(call_on_line(".*failed.*", set_fail),
|
|
call_on_line(".*Abort @.*", set_fail),
|
|
call_on_line(r"(^producer \d: produce$)|(^consumer \d: consume$)", handle),
|
|
shell_script(['producer']))
|
|
assert not fail
|
|
assert 0 not in producer_times
|
|
assert 0 not in customer_times
|
|
|
|
@test(20, "philosopher")
|
|
def test_philosopher():
|
|
chops = [1, 1, 1, 1, 1]
|
|
times = [0, 0, 0, 0, 0]
|
|
curr_line, MAXLINE = 0, 300
|
|
fail = False
|
|
|
|
def handle(line: str):
|
|
if line.endswith("start eating."):
|
|
handle_eat(line)
|
|
elif line.endswith("end eating."):
|
|
handle_think(line)
|
|
else:
|
|
set_fail(line)
|
|
|
|
def handle_eat(line: str):
|
|
nonlocal curr_line
|
|
no_str = line[12:13]
|
|
if not no_str.isdigit():
|
|
set_fail(line)
|
|
no = int(no_str)
|
|
if no < 0 or no > 4 or chops[no] == 0 or chops[(no + 1) % 5] == 0:
|
|
set_fail(line)
|
|
chops[no] = 0
|
|
chops[(no + 1) % 5] = 0
|
|
times[no] += 1
|
|
curr_line += 1
|
|
if curr_line >= MAXLINE:
|
|
raise TerminateTest
|
|
|
|
def handle_think(line: str):
|
|
nonlocal curr_line
|
|
no_str = line[12:13]
|
|
if not no_str.isdigit():
|
|
set_fail(line)
|
|
no = int(no_str)
|
|
if no < 0 or no > 4 or chops[no] == 1 or chops[(no + 1) % 5] == 1:
|
|
set_fail(line)
|
|
chops[no] = 1
|
|
chops[(no + 1) % 5] = 1
|
|
curr_line += 1
|
|
if curr_line >= MAXLINE:
|
|
raise TerminateTest
|
|
|
|
def set_fail(_):
|
|
nonlocal fail
|
|
fail = True
|
|
raise TerminateTest
|
|
|
|
r.run_qemu(call_on_line(".*failed.*", set_fail),
|
|
call_on_line(".*Abort @.*", set_fail),
|
|
call_on_line(r"(^philosopher \d start eating\.$)|(^philosopher \d end eating\.$)", handle),
|
|
shell_script(['philosopher']))
|
|
assert not fail
|
|
assert 0 not in times
|
|
|
|
run_tests()
|