1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.james.mpt;
21
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.regex.Pattern;
27
28
29
30
31
32
33
34
35
36
37
38
39 public class ProtocolSession implements ProtocolInteractor {
40 private boolean continued = false;
41
42 private boolean continuationExpected = false;
43
44 private int maxSessionNumber;
45
46 protected List<ProtocolElement> testElements = new ArrayList<ProtocolElement>();
47
48 private Iterator elementsIterator;
49
50 private Session[] sessions;
51
52 private ProtocolElement nextTest;
53
54 private boolean continueAfterFailure = false;
55
56 public final boolean isContinueAfterFailure() {
57 return continueAfterFailure;
58 }
59
60 public final void setContinueAfterFailure(boolean continueAfterFailure) {
61 this.continueAfterFailure = continueAfterFailure;
62 }
63
64
65
66
67
68
69 public int getSessionCount() {
70 return maxSessionNumber + 1;
71 }
72
73
74
75
76
77
78
79
80
81
82 public void runSessions(Session[] sessions) throws Exception {
83 this.sessions = sessions;
84 elementsIterator = testElements.iterator();
85 while (elementsIterator.hasNext()) {
86 Object obj = elementsIterator.next();
87 if (obj instanceof ProtocolElement) {
88 ProtocolElement test = (ProtocolElement) obj;
89 test.testProtocol(sessions, continueAfterFailure);
90 }
91 }
92 }
93
94 public void doContinue() {
95 try {
96 if (continuationExpected) {
97 continued = true;
98 while (elementsIterator.hasNext()) {
99 Object obj = elementsIterator.next();
100 if (obj instanceof ProtocolElement) {
101 nextTest = (ProtocolElement) obj;
102
103 if (!nextTest.isClient()) {
104 break;
105 }
106 nextTest.testProtocol(sessions, continueAfterFailure);
107 }
108 }
109 if (!elementsIterator.hasNext()) {
110 nextTest = null;
111 }
112 } else {
113 throw new RuntimeException("Unexpected continuation");
114 }
115 } catch (Exception e) {
116 throw new RuntimeException(e);
117 }
118 }
119
120
121
122
123 public void CL(String clientLine) {
124 testElements.add(new ClientRequest(clientLine));
125 }
126
127
128
129
130 public void SL(String serverLine, String location) {
131 testElements.add(new ServerResponse(serverLine, location));
132 }
133
134
135
136
137 public void SUB(List<String> serverLines, String location) {
138 testElements
139 .add(new ServerUnorderedBlockResponse(serverLines, location));
140 }
141
142
143
144
145 public void CL(int sessionNumber, String clientLine) {
146 this.maxSessionNumber = Math.max(this.maxSessionNumber, sessionNumber);
147 testElements.add(new ClientRequest(sessionNumber, clientLine));
148 }
149
150
151
152
153 public void CONT(int sessionNumber) throws Exception {
154 this.maxSessionNumber = Math.max(this.maxSessionNumber, sessionNumber);
155 testElements.add(new ContinuationElement(sessionNumber));
156 }
157
158
159
160
161 public void SL(int sessionNumber, String serverLine, String location,
162 String lastClientMessage) {
163 this.maxSessionNumber = Math.max(this.maxSessionNumber, sessionNumber);
164 testElements.add(new ServerResponse(sessionNumber, serverLine,
165 location, lastClientMessage));
166 }
167
168
169
170
171 public void SUB(int sessionNumber, List<String> serverLines, String location,
172 String lastClientMessage) {
173 this.maxSessionNumber = Math.max(this.maxSessionNumber, sessionNumber);
174 testElements.add(new ServerUnorderedBlockResponse(sessionNumber,
175 serverLines, location, lastClientMessage));
176 }
177
178
179
180
181 private class ClientRequest implements ProtocolElement {
182 private int sessionNumber;
183
184 private String message;
185
186
187
188
189 public ClientRequest(String message) {
190 this(-1, message);
191 }
192
193
194
195
196
197
198
199 public ClientRequest(int sessionNumber, String message) {
200 this.sessionNumber = sessionNumber;
201 this.message = message;
202 }
203
204
205
206
207
208
209
210
211 public void testProtocol(Session[] sessions,
212 boolean continueAfterFailure) throws Exception {
213 if (sessionNumber < 0) {
214 for (int i = 0; i < sessions.length; i++) {
215 Session session = sessions[i];
216 writeMessage(session);
217 }
218 } else {
219 Session session = sessions[sessionNumber];
220 writeMessage(session);
221 }
222 }
223
224 private void writeMessage(Session session) throws Exception {
225 session.writeLine(message);
226 }
227
228 public boolean isClient() {
229 return true;
230 }
231
232
233
234
235
236
237
238
239 public String toString()
240 {
241 final String TAB = " ";
242
243 String retValue = "ClientRequest ( "
244 + "sessionNumber = " + this.sessionNumber + TAB
245 + "message = " + this.message + TAB
246 + " )";
247
248 return retValue;
249 }
250
251
252 }
253
254
255
256
257
258
259 private class ServerResponse implements ProtocolElement {
260 private String lastClientMessage;
261
262 private int sessionNumber;
263
264 private String expectedLine;
265
266 protected String location;
267
268
269
270
271
272
273
274
275
276
277 public ServerResponse(String expectedPattern, String location) {
278 this(-1, expectedPattern, location, null);
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292 public ServerResponse(int sessionNumber, String expectedPattern,
293 String location, String lastClientMessage) {
294 this.sessionNumber = sessionNumber;
295 this.expectedLine = expectedPattern;
296 this.location = location;
297 this.lastClientMessage = lastClientMessage;
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314 public void testProtocol(Session[] sessions,
315 boolean continueAfterFailure) throws Exception {
316 if (sessionNumber < 0) {
317 for (int i = 0; i < sessions.length; i++) {
318 Session session = sessions[i];
319 checkResponse(session, continueAfterFailure);
320 }
321 } else {
322 Session session = sessions[sessionNumber];
323 checkResponse(session, continueAfterFailure);
324 }
325 }
326
327 protected void checkResponse(Session session,
328 boolean continueAfterFailure) throws Exception {
329 String testLine = readLine(session);
330 if (!match(expectedLine, testLine)) {
331 String errMsg = "\nLocation: " + location + "\nLastClientMsg: "
332 + lastClientMessage + "\nExpected: '" + expectedLine
333 + "'\nActual : '" + testLine + "'";
334 if (continueAfterFailure) {
335 System.out.println(errMsg);
336 } else {
337 throw new InvalidServerResponseException(errMsg);
338 }
339 }
340 }
341
342
343
344
345
346
347
348
349
350
351
352 protected boolean match(String expected, String actual) {
353 final boolean result = Pattern.matches(expected, actual);
354 return result;
355 }
356
357
358
359
360
361
362
363 protected String readLine(Session session) throws Exception {
364 try {
365 return session.readLine();
366 } catch (IOException e) {
367 String errMsg = "\nLocation: " + location + "\nExpected: "
368 + expectedLine + "\nReason: Server Timeout.";
369 throw new InvalidServerResponseException(errMsg);
370 }
371 }
372
373 public boolean isClient() {
374 return false;
375 }
376
377
378
379
380
381
382
383
384 public String toString()
385 {
386 final String TAB = " ";
387
388 String result = "ServerResponse ( "
389 + "lastClientMessage = " + this.lastClientMessage + TAB
390 + "sessionNumber = " + this.sessionNumber + TAB
391 + "expectedLine = " + this.expectedLine + TAB
392 + "location = " + this.location + TAB
393 + " )";
394
395 return result;
396 }
397
398
399 }
400
401
402
403
404
405 private class ServerUnorderedBlockResponse extends ServerResponse {
406 private List<String> expectedLines = new ArrayList<String>();
407
408
409
410
411
412
413
414
415
416
417
418 public ServerUnorderedBlockResponse(List<String> expectedLines, String location) {
419 this(-1, expectedLines, location, null);
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435 public ServerUnorderedBlockResponse(int sessionNumber,
436 List<String> expectedLines, String location, String lastClientMessage) {
437 super(sessionNumber, "<Unordered Block>", location,
438 lastClientMessage);
439 this.expectedLines = expectedLines;
440 }
441
442
443
444
445
446
447
448
449
450
451
452
453 protected void checkResponse(Session session,
454 boolean continueAfterFailure) throws Exception {
455 List<String> testLines = new ArrayList<String>(expectedLines);
456 while (testLines.size() > 0) {
457 String actualLine = readLine(session);
458
459 boolean foundMatch = false;
460 for (int i = 0; i < testLines.size(); i++) {
461 String expected = (String) testLines.get(i);
462 if (match(expected, actualLine)) {
463 foundMatch = true;
464 testLines.remove(expected);
465 break;
466 }
467 }
468
469 if (!foundMatch) {
470 StringBuffer errMsg = new StringBuffer().append(
471 "\nLocation: ").append(location).append(
472 "\nExpected one of: ");
473 Iterator iter = expectedLines.iterator();
474 while (iter.hasNext()) {
475 errMsg.append("\n ");
476 errMsg.append(iter.next());
477 }
478 errMsg.append("\nActual: ").append(actualLine);
479 if (continueAfterFailure) {
480 System.out.println(errMsg.toString());
481 } else {
482 throw new InvalidServerResponseException(errMsg
483 .toString());
484 }
485 }
486 }
487 }
488
489
490
491
492
493
494
495
496 public String toString()
497 {
498 final String TAB = " ";
499
500 String result = "ServerUnorderedBlockResponse ( "
501 + "expectedLines = " + this.expectedLines + TAB
502 + " )";
503
504 return result;
505 }
506
507
508 }
509
510 private class ContinuationElement implements ProtocolElement {
511
512 private final int sessionNumber;
513
514 public ContinuationElement(final int sessionNumber) throws Exception {
515 this.sessionNumber = sessionNumber < 0 ? 0 : sessionNumber;
516 }
517
518 public void testProtocol(Session[] sessions,
519 boolean continueAfterFailure) throws Exception {
520 Session session = sessions[sessionNumber];
521 continuationExpected = true;
522 continued = false;
523 String testLine = session.readLine();
524 if (!"+".equals(testLine) || !continued) {
525 final String message = "Expected continuation";
526 if (continueAfterFailure) {
527 System.out.print(message);
528 } else {
529 throw new InvalidServerResponseException(message);
530 }
531 }
532 continuationExpected = false;
533 continued = false;
534
535 if (nextTest != null) {
536 nextTest.testProtocol(sessions, continueAfterFailure);
537 }
538 }
539
540 public boolean isClient() {
541 return false;
542 }
543
544
545
546
547
548
549
550
551 public String toString()
552 {
553 final String TAB = " ";
554
555 String result = "ContinuationElement ( "
556 + "sessionNumber = " + this.sessionNumber + TAB
557 + " )";
558
559 return result;
560 }
561
562
563 }
564
565
566
567
568
569
570
571 private interface ProtocolElement {
572
573
574
575
576
577
578
579 void testProtocol(Session[] sessions,
580 boolean continueAfterFailure) throws Exception;
581
582 boolean isClient();
583 }
584
585
586
587
588
589
590
591
592 public String toString()
593 {
594 final String TAB = " ";
595
596 String result = "ProtocolSession ( "
597 + "continued = " + this.continued + TAB
598 + "continuationExpected = " + this.continuationExpected + TAB
599 + "maxSessionNumber = " + this.maxSessionNumber + TAB
600 + "testElements = " + this.testElements + TAB
601 + "elementsIterator = " + this.elementsIterator + TAB
602 + "sessions = " + this.sessions + TAB
603 + "nextTest = " + this.nextTest + TAB
604 + "continueAfterFailure = " + this.continueAfterFailure + TAB
605 + " )";
606
607 return result;
608 }
609
610
611 }