KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > test > ProtocolSession


1 /***********************************************************************
2  * Copyright (c) 2000-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.test;
19
20 import org.apache.oro.text.perl.Perl5Util;
21
22 import java.io.BufferedReader JavaDoc;
23 import java.io.PrintWriter JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28
29 /**
30  * A protocol session which can be run against a reader and writer, which checks
31  * the server response against the expected values.
32  * TODO make ProtocolSession itself be a permissible ProtocolElement,
33  * so that we can nest and reuse sessions.
34  *
35  * @version $Revision: 1.4.2.3 $
36  */

37 public class ProtocolSession
38 {
39     protected List JavaDoc testElements = new ArrayList JavaDoc();
40     private static final Perl5Util perl = new Perl5Util();
41
42     /**
43      * Executes the ProtocolSession in real time against the reader and writer
44      * supplied, writing client requests and reading server responses in the order
45      * that they appear in the test elements.
46      * If an exception occurs, no more test elements are executed.
47      * @param out The client requests are written to here.
48      * @param in The server responses are read from here.
49      */

50     public void runLiveSession( PrintWriter JavaDoc out, BufferedReader JavaDoc in ) throws Exception JavaDoc
51     {
52         for ( Iterator JavaDoc iter = testElements.iterator(); iter.hasNext(); ) {
53             Object JavaDoc obj = iter.next();
54             if ( obj instanceof ProtocolElement ) {
55                 ProtocolElement test = ( ProtocolElement ) obj;
56                 test.testProtocol( out, in );
57             }
58         }
59     }
60
61     /**
62      * Write an entire client session to the specified PrintWriter. Server
63      * responses are not collected, but clients may collect themfor later
64      * testing with {@link #testResponse}.
65      * @param out The client requests are written to here.
66      */

67     public void writeClient( PrintWriter JavaDoc out ) throws Exception JavaDoc
68     {
69         Iterator JavaDoc iterator = testElements.iterator();
70         while ( iterator.hasNext() ) {
71             ProtocolElement element = (ProtocolElement) iterator.next();
72             if ( element instanceof ClientRequest ) {
73                 element.testProtocol( out, null );
74             }
75         }
76     }
77
78     /**
79      * Reads Server responses from the supplied Buffered reader, ensuring that
80      * they match the expected responses for the protocol session. This permits
81      * clients to run a session asynchronously, by first writing the client requests
82      * with {@link #writeClient} and later testing the responses.
83      * @param in The server responses are read from here.
84      */

85     public void testResponse( BufferedReader JavaDoc in ) throws Exception JavaDoc
86     {
87         Iterator JavaDoc iterator = testElements.iterator();
88         while ( iterator.hasNext() ) {
89             ProtocolElement element = (ProtocolElement) iterator.next();
90             if ( element instanceof ServerResponse ) {
91                 element.testProtocol( null, in );
92             }
93         }
94     }
95
96     /**
97      * adds a new Client request line to the test elements
98      */

99     public void CL( String JavaDoc clientLine )
100     {
101         testElements.add( new ClientRequest( clientLine ) );
102     }
103
104     /**
105      * adds a new Server Response line to the test elements, with the specified location.
106      */

107     public void SL( String JavaDoc serverLine, String JavaDoc location )
108     {
109         testElements.add( new ServerResponse( serverLine, location ) );
110     }
111
112     /**
113      * adds a new Server Unordered Block to the test elements.
114      */

115     public void SUB( List JavaDoc serverLines, String JavaDoc location )
116     {
117         testElements.add( new ServerUnorderedBlockResponse( serverLines, location ) );
118     }
119
120     /**
121      * Adds a ProtocolElement to the test elements.
122      */

123     public void addProtocolElement( ProtocolElement element )
124     {
125         testElements.add( element );
126     }
127
128     /**
129      * A client request, which write the specified message to a Writer.
130      */

131     private class ClientRequest implements ProtocolElement
132     {
133         private String JavaDoc message;
134
135         /**
136          * Initialises the ClientRequest with the supplied message.
137          */

138         public ClientRequest( String JavaDoc message )
139         {
140             this.message = message;
141         }
142
143         /**
144          * Writes the request message to the PrintWriter.
145          */

146         public void testProtocol( PrintWriter JavaDoc out, BufferedReader JavaDoc in )
147         {
148             out.write( message );
149             out.write( '\r' );
150             out.write( '\n' );
151             out.flush();
152         }
153     }
154
155     /**
156      * Represents a single-line server response, which reads a line
157      * from a reader, and compares it with the defined regular expression
158      * definition of this line.
159      */

160     private class ServerResponse implements ProtocolElement
161     {
162         private String JavaDoc expectedLine;
163         protected String JavaDoc location;
164
165         /**
166          * Sets up a server response.
167          * @param expectedPattern A Perl regular expression pattern used to test
168          * the line recieved.
169          * @param location A descriptive value to use in error messages.
170          */

171         public ServerResponse( String JavaDoc expectedPattern, String JavaDoc location )
172         {
173             this.expectedLine = expectedPattern;
174             this.location = location;
175         }
176
177         /**
178          * Reads a line from the supplied reader, and tests that it matches
179          * the expected regular expression.
180          * @param out Is ignored.
181          * @param in The server response is read from here.
182          * @throws InvalidServerResponseException If the actual server response didn't
183          * match the regular expression expected.
184          */

185         public void testProtocol( PrintWriter JavaDoc out, BufferedReader JavaDoc in )
186                 throws InvalidServerResponseException
187         {
188             String JavaDoc testLine = readLine( in );
189             if ( ! match( expectedLine, testLine ) ) {
190                 String JavaDoc errMsg = "\nLocation: " + location +
191                         "\nExcpected: " + expectedLine +
192                         "\nActual : " + testLine;
193                 throw new InvalidServerResponseException( errMsg );
194             }
195         }
196
197         /**
198          * A convenience method which returns true if the actual string
199          * matches the expected regular expression.
200          * @param expected The regular expression used for matching.
201          * @param actual The actual message to match.
202          * @return <code>true</code> if the actual matches the expected.
203          */

204         protected boolean match( String JavaDoc expected, String JavaDoc actual )
205         {
206             String JavaDoc pattern = "m/" + expected + "/";
207             return perl.match( pattern, actual );
208         }
209
210         /**
211          * Grabs a line from the server and throws an error message if it
212          * doesn't work out
213          * @param in BufferedReader for getting the server response
214          * @return String of the line from the server
215          */

216         protected String JavaDoc readLine( BufferedReader JavaDoc in )
217                 throws InvalidServerResponseException
218         {
219             try {
220                 return in.readLine();
221             }
222             catch ( IOException JavaDoc e ) {
223                 String JavaDoc errMsg = "\nLocation: " + location +
224                         "\nExpected: " + expectedLine +
225                         "\nReason: Server Timeout.";
226                 throw new InvalidServerResponseException( errMsg );
227             }
228         }
229     }
230
231     /**
232      * Represents a set of lines which must be recieved from the server,
233      * in a non-specified order.
234      */

235     private class ServerUnorderedBlockResponse extends ServerResponse
236     {
237         private List JavaDoc expectedLines = new ArrayList JavaDoc();
238
239         /**
240          * Sets up a ServerUnorderedBlockResponse with the list of expected lines.
241          * @param expectedLines A list containing a reqular expression for each
242          * expected line.
243          * @param location A descriptive location string for error messages.
244          */

245         public ServerUnorderedBlockResponse( List JavaDoc expectedLines, String JavaDoc location )
246         {
247             super( "<Unordered Block>", location );
248             this.expectedLines = expectedLines;
249         }
250
251         /**
252          * Reads lines from the server response and matches them against the
253          * list of expected regular expressions. Each regular expression in the
254          * expected list must be matched by only one server response line.
255          * @param out Is ignored.
256          * @param in Server responses are read from here.
257          * @throws InvalidServerResponseException If a line is encountered which doesn't
258          * match one of the expected lines.
259          */

260         public void testProtocol( PrintWriter JavaDoc out, BufferedReader JavaDoc in )
261                 throws InvalidServerResponseException
262         {
263             List JavaDoc testLines = new ArrayList JavaDoc( expectedLines );
264             while ( testLines.size() > 0 )
265             {
266                 String JavaDoc actualLine = readLine( in );
267                 boolean foundMatch = false;
268
269                 for ( int i = 0; i < testLines.size(); i++ )
270                 {
271                     String JavaDoc expected = (String JavaDoc)testLines.get( i );
272                     if ( match( expected, actualLine ))
273                     {
274                         foundMatch = true;
275                         testLines.remove( expected );
276                         break;
277                     }
278                 }
279
280                 if (! foundMatch )
281                 {
282                     StringBuffer JavaDoc errMsg = new StringBuffer JavaDoc()
283                         .append( "\nLocation: " )
284                         .append( location )
285                         .append( "\nExpected one of: " );
286                     Iterator JavaDoc iter = expectedLines.iterator();
287                     while ( iter.hasNext() ) {
288                         errMsg.append( "\n " );
289                         errMsg.append( iter.next() );
290                     }
291                     errMsg.append("\nActual: " )
292                           .append( actualLine );
293
294                     throw new InvalidServerResponseException( errMsg.toString() );
295                 }
296             }
297         }
298     }
299
300     /**
301      * Represents a generic protocol element, which may write requests to the server,
302      * read responses from the server, or both. Implementations should test the server
303      * response against an expected response, and throw an exception on mismatch.
304      */

305     interface ProtocolElement
306     {
307         /**
308          * Executes the ProtocolElement against the supplied read and writer.
309          * @param out Client requests are written to here.
310          * @param in Server responses are read from here.
311          * @throws InvalidServerResponseException If the actual server response
312          * doesn't match the one expected.
313          */

314         void testProtocol( PrintWriter JavaDoc out, BufferedReader JavaDoc in )
315                 throws InvalidServerResponseException;
316     }
317
318     /**
319      * An exception which is thrown when the actual response from a server
320      * is different from that expected.
321      */

322     public class InvalidServerResponseException extends Exception JavaDoc
323     {
324         public InvalidServerResponseException( String JavaDoc message )
325         {
326             super( message );
327         }
328     }
329
330 }
331
Popular Tags