forked from oleander/The-Pub-Simulation
/
Door.jr~
218 lines (155 loc) · 5.34 KB
/
Door.jr~
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
import edu.ucdavis.jr.*;
import java.util.*;
import java.util.ArrayList;
public class Door {
private ArrayList<Person> entrants;
private boolean isLocked;
private cap void() returnOkCap;
public op boolean add(Person p);
public op ArrayList<Person> lock(cap void() returnOkCap);
public op void leave(Person p);
public Door() {
entrants = new ArrayList<Person>();
isLocked = false;
Global.door = this;
}
private process doorProcess {
startLoop();
System.out.println("Door process exits ...");
}
// I added this as a seperate method to be able to override stupid warnings
@SuppressWarnings("unchecked")
private void startLoop()
{
while(true)
{
inni ArrayList<Person> lock(cap void() returnOkCap)
{
isLocked = true;
this.returnOkCap = returnOkCap;
return new ArrayList<Person>(entrants); // This adds stupid warning
}
[] boolean add(Person p)
{
if(isLocked)
{
return false;
}
addPersonToList(p);
return true;
}
[] void leave(Person p)
{
removePersonFromList(p);
if(isLocked && entrants.size() == 1)
{
// Ok, only landlord should be left, lets notift him
send returnOkCap();
}
if(isLocked && entrants.size() == 0)
{
// Ok, now even landlord left, lets exit gracfully
break;
}
}
}
}
@SuppressWarnings("unchecked")
private void addPersonToList(Person p)
{
entrants.add(p); // This darn command adds stupid warning
}
@SuppressWarnings("unchecked")
private void removePersonFromList(Person p)
{
entrants.remove(p); // This darn command adds stupid warning
}
/***************************************************
TESTING CODE BELOW
***************************************************/
public static void main(String[] args) {
allDoorTests();
}
public static void allDoorTests()
{
testOnePersonEnters();
testOnePersonLeaving();
testDoor();
System.out.println("Door tests passed.");
}
// This test is starting other threads
public static void testOnePersonEnters()
{
Door d = new Door();
asserts(d.entrants.size() == 0, "Door should start empty");
Person p = new Person(true);
JR.nap(10);
asserts(d.entrants.get(0) == p, "Person p should be in list");
asserts(d.entrants.size() == 1, "Should only be 1 person in list");
}
// This test is starting other threads
public static void testOnePersonLeaving()
{
Door d = new Door();
Person p = new TestPerson();
JR.nap(10);
p.leaveBar();
JR.nap(10);
asserts(d.entrants.size() == 0, "Everyone should have exited.");
}
// This test runs in a two threads (test+Doorprocess) and only emulates a person
// What is good with this test is that it doesn't depend on Person
// This test tests most behavior
public static void testDoor()
{
Door d = new Door();
Person p1 = new TestPerson(); //fakeperson
asserts(d.add(p1), "Door should start open"); // try enter door
asserts(d.entrants.size() == 1, "Should only be 1 person in list");
Person p2 = new TestPerson(); // another entrant
d.add(p2);
asserts(d.entrants.size() == 2, "Two should 've entered");
asserts(d.entrants.contains(p1), "p1 should be in list");
asserts(d.entrants.contains(p2), "p2 should be in list");
Person landlord = new TestPerson(); // this emulates Landlord (auto-enters)
op void returnCap(); // The landlords replyChannel
ArrayList<Person> list = d.lock(returnCap);
asserts(list != d.entrants, "Should not be reference to entrants!");
asserts(list.equals(d.entrants), "Should however be equal to entrants!");
Person p3 = new TestPerson(); // this one will emulate door-rejected customer
asserts(!d.add(p3), "Door is locked, p3 should be rejected");
asserts(d.entrants.size() == 3, "Nobody should've entered yet since it was locked (2persons + landlord is in)");
// Now let p1 leave
d.leave(p1);
asserts(d.entrants.size() == 2, "only 1 + landlord should be left");
asserts(d.entrants.contains(p2), "p2 should be left");
JR.nap(10);
// make sure we haven't got reply yet
inni void returnCap()
{
asserts(false, "The closing signal is sent too early!");
}
[] else { /* landing here is good :) */ }
// Now let p2 leave
d.leave(p2);
asserts(d.entrants.size() == 1, "Only landlord should be in!");
asserts(d.entrants.contains(landlord), "Only landlord should be in");
JR.nap(10);
// make sure we HAVE got reply now
inni void returnCap()
{ /* landing here is good :) */ }
[] else {
asserts(false, "The closing signal was not sent!");
}
d.leave(landlord);
asserts(d.entrants.isEmpty(), "Everyone should've leaved");
}
public static void asserts(boolean b, String s)
{
if(!b)
{
System.out.println("DoorAssert failed: " + s);
System.exit(1);
}
}
}