-
Notifications
You must be signed in to change notification settings - Fork 0
/
grade-lab5
executable file
·127 lines (112 loc) · 3.84 KB
/
grade-lab5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import re, sys
import random, string, time
from gradelib import *
def is_hex(s):
try:
int(s, 16)
return True
except ValueError:
return False
def send_term(line):
raise TerminateTest
sleep_set = [-1, -1, -1]
sleep_got = [-1, -1, -1]
def send_timer_commands(line, timer):
def qemu_write(st):
r.qemu.proc.stdin.write(st.encode("ascii"))
r.qemu.proc.stdin.flush()
global sleep_set
if sleep_set[0] < 0:
sleep_set[0] = random.randint(3, 7)
qemu_write(f"timer_stop\n");
qemu_write(f"timer_start {timer}\n")
time.sleep(sleep_set[0])
if sleep_set[1] < 0:
sleep_set[1] = random.randint(3, 7)
qemu_write(f"timer_start {timer}\n")
time.sleep(sleep_set[1])
qemu_write(f"timer_stop\n")
if sleep_set[2] < 0:
sleep_set[2] = random.randint(5, 10)
qemu_write(f"timer_start {timer}\n")
time.sleep(sleep_set[2])
qemu_write(f"timer_stop\n")
qemu_write(f"undef {timer}\n")
def change_execution_flow(out):
if is_hex(out):
sh = "%016x" % get_symbol_address("sched_halt")[0]
regs = out[:256] + sh[14:16] + sh[12:14] + sh[10:12] + sh[8:10] +\
sh[6:8] + sh[4:6] + sh[2:4] + sh[0:2] + out[272:]
r.gdb.update_regs(regs)
r.gdb.cont()
return 1
return 0
def view_regs_at_env_init(out):
if out.startswith("T"):
r.gdb.view_regs()
return 1
return 0
r = Runner(save("jos.out"),
add_breakpoint("env_init"),
add_gdb_command(view_regs_at_env_init),
add_gdb_command(change_execution_flow),
call_on_line(r'Type', lambda l: send_timer_commands(l, 'pit')),
call_on_line(r'Type', lambda l: send_timer_commands(l, 'hpet0')),
call_on_line(r'Type', lambda l: send_timer_commands(l, 'pm')),
call_on_line(r'K> undef pm', send_term))
@test(0, "running JOS")
def test_jos():
print(color("yellow", "Please, be patient. It takes from 10 to 60 seconds to run the tests."))
r.run_qemu()
def check_stop_without_start(line):
assert_equal(line, "Timer Error")
return 1
def check_stop_time(line, index):
i = 0
try:
i = int(line)
except:
raise AssertionError("String %s is not an integer\n" % line)
# FIXME: We really need to make measurement more reliable.
seconds = sleep_set[index]
if i != seconds and (i < seconds - 2 or i > seconds + 2):
assert_equal(i, seconds)
if sleep_got[index] < 0:
sleep_got[index] = i
# elif sleep_got[index] != i:
# assert_equal(sleep_got[index], i)
return 1
def check_start_after_start(line, timer):
assert_equal(line, "K> timer_start {}".format(timer))
return 1
@test(100, parent=test_jos)
def test_timer():
start = 0
stop = 0
l = r.qemu.output.splitlines()
checks = 0
for i in range(0, len(l)):
if l[i] == 'K> timer_stop':
if stop % 3 == 0:
checks += check_stop_without_start(l[i+1])
elif stop % 3 == 1:
checks += check_stop_time(l[i+1], 1)
elif stop % 3 == 2:
checks += check_stop_time(l[i+1], 2)
else:
raise AssertionError("Unknown timer_stop.\n")
stop += 1
elif l[i] == 'K> timer_start pit':
if start == 0: checks += check_start_after_start(l[i+1], 'pit')
start += 1
elif l[i] == 'K> timer_start hpet0':
if start == 3: checks += check_start_after_start(l[i+1], 'hpet0')
start += 1
elif l[i] == 'K> timer_start pm':
if start == 6: checks += check_start_after_start(l[i+1], 'pm')
start += 1
if checks != 12:
raise AssertionError("Executed only {} checks out 12. Check monitor commands timer_start/timer_stop.\n".format(checks))
run_tests()