View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.asn1.ber ;
18  
19  
20  import junit.framework.TestCase;
21  import org.apache.asn1.codec.DecoderException;
22  import org.apache.asn1.codec.binary.BinaryCodec;
23  import org.apache.asn1.codec.stateful.DecoderCallback;
24  import org.apache.asn1.codec.stateful.DecoderMonitor;
25  import org.apache.asn1.codec.stateful.StatefulDecoder;
26  import org.apache.commons.lang.exception.ExceptionUtils;
27  
28  import java.nio.ByteBuffer;
29  import java.util.ArrayList;
30  import java.util.Stack;
31  
32  
33  /***
34   * Tests the BER decoder.
35   *
36   * @author <a href="mailto:dev@directory.apache.org">
37   * Apache Directory Project</a>
38   * @version $Rev: 158144 $
39   */
40  public abstract class AbstractDecoderTestCase extends TestCase 
41      implements BERDecoderCallback, DecoderMonitor
42  {
43      /*** list of encountered TLV's as we recieve completed decode callbacks */
44      protected ArrayList tlvList = new ArrayList() ;
45      /*** the decoder that is constructed every time */
46      protected BERDecoder decoder = null ;
47      /*** value accumulator */
48      ByteBuffer buf = ByteBuffer.allocate(11111) ;
49      
50  
51      /*
52       * @see TestCase#setUp()
53       */
54      protected void setUp() throws Exception
55      {
56          super.setUp() ;
57          decoder = new BERDecoder() ;
58          decoder.setCallback( this ) ;
59          decoder.setDecoderMonitor( this ) ;
60      }
61  
62      
63      /*
64       * @see TestCase#tearDown()
65       */
66      protected void tearDown() throws Exception
67      {
68          super.tearDown() ;
69          tlvList.clear() ;
70          decoder = null ;
71      }
72  
73      
74      /***
75       * Constructor for BERDecoderTest.
76       * @param arg0
77       */
78      public AbstractDecoderTestCase( String arg0 )
79      {
80          super( arg0 ) ;
81      }
82      
83      
84      /***
85       * Fragments an array of bytes into multiple arrays 'attempting' to keep 
86       * them the same size however the last fragment will be an array 
87       * bites.length%size which may or may not be of the requested fragment size.
88       * However it will never be greater.  Use this method to break appart TLV 
89       * byte arrays to feed them into the decoder for testing.
90       * 
91       * @param bites the bites to fragment
92       * @param size the maximum size of a fragment
93       * @return the array of byte[] fragments
94       */
95      public byte[][] fragment( byte[] bites, int size )
96      {
97          byte[][] fragments = null ;
98          
99          if ( size <= 0 )
100         {    
101             throw new IllegalArgumentException( 
102                     "fragment size should be 1 or more but was " + size ) ;
103         }
104         
105         int wholeFrags = bites.length/size ;
106         int partialFragSize = bites.length % size ; 
107 
108         /*
109          * Allocate what we need depending on the size of our remainder
110          */
111         if ( partialFragSize == 0 ) 
112         {
113             fragments = new byte[wholeFrags][] ;
114         }
115         else
116         {
117             fragments = new byte[wholeFrags+1][] ;
118             fragments[wholeFrags] = new byte[partialFragSize] ;
119         }
120         
121         for ( int ii = 0; ii < wholeFrags; ii++ )
122         {
123             fragments[ii] = new byte[size] ;
124             System.arraycopy( bites, ii * size, fragments[ii], 0, size ) ;
125         }
126         
127         if ( partialFragSize != 0 )
128         {
129             int srcPos = wholeFrags * size ;
130             byte[] src = fragments[wholeFrags] ;
131             System.arraycopy( bites, srcPos, src, 0, partialFragSize ) ;
132         }
133         
134         return fragments ;
135     }
136     
137     
138     /***
139      * Fragments a byte buffer into multiple buffer 'attempting' to keep 
140      * them the same size however the last fragment will be an array 
141      * bites.length%size which may or may not be of the requested fragment size.
142      * However it will never be greater.  Use this method to break appart TLV 
143      * bytes to feed them into the decoder for testing.
144      * 
145      * @param bites the bites to fragment
146      * @param size the maximum size of a fragment
147      * @return the buffer fragment
148      */
149     public ByteBuffer[] fragment( ByteBuffer bites, int size )
150     {
151         bites = bites.duplicate() ;
152         ByteBuffer[] fragments = null ;
153         
154         if ( size <= 0 )
155         {    
156             throw new IllegalArgumentException( 
157                     "fragment size should be 1 or more but was " + size ) ;
158         }
159         
160         int wholeFrags = bites.remaining()/size ;
161         int partialFragSize = bites.remaining() % size ; 
162 
163         /*
164          * Allocate what we need depending on the size of our remainder
165          */
166         if ( partialFragSize == 0 ) 
167         {
168             fragments = new ByteBuffer[wholeFrags] ;
169         }
170         else
171         {
172             fragments = new ByteBuffer[wholeFrags+1] ;
173             fragments[wholeFrags] = ByteBuffer.allocate( partialFragSize ) ;
174         }
175         
176         for ( int ii = 0; ii < wholeFrags; ii++ )
177         {
178             fragments[ii] = ( ByteBuffer ) bites.slice().limit( size ) ;
179             bites.position( bites.position() + size ) ;
180         }
181         
182         if ( partialFragSize != 0 )
183         {
184             fragments[wholeFrags].put( bites ) ;
185             fragments[wholeFrags].flip() ;
186         }
187         
188         return fragments ;
189     }
190     
191     
192     /***
193      * BER decodes a string of 0's and 1's.
194      * 
195      * @param bitString a string of ascii 0's and 1's
196      * @return a copy of the decoded tuple or the partially decoded current tlv
197      * @throws DecoderException if there are errors while decoding.
198      */
199     public Tuple decode( String bitString ) throws DecoderException
200     {
201         byte [] bites = BinaryCodec.fromAscii( bitString.getBytes() ) ;
202         ByteBuffer buf = ByteBuffer.wrap( bites ) ;
203         int lastSize = tlvList.size() ;
204         decoder.decode( buf ) ;
205         
206         if ( tlvList.isEmpty() || tlvList.size() == lastSize )
207         {
208             return decoder.getCurrentTuple() ;
209         }
210         
211         return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
212     }
213 
214     
215     /***
216      * BER decodes a single byte.
217      * 
218      * @param bite a single byte to decode
219      * @return a copy of the decoded tuple or the partially decoded current tlv
220      * @throws DecoderException if there are errors while decoding.
221      */
222     public Tuple decode( byte bite ) throws DecoderException
223     {
224         byte [] bites = { bite } ;
225         ByteBuffer buf = ByteBuffer.wrap( bites ) ;
226         int lastSize = tlvList.size() ;
227         decoder.decode( buf ) ;
228         
229         if ( tlvList.isEmpty() || tlvList.size() == lastSize )
230         {
231             return decoder.getCurrentTuple() ;
232         }
233         
234         return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
235     }
236 
237     
238     /***
239      * BER decodes a byte buffer.
240      * 
241      * @param bites a byte buffer to decode
242      * @return a copy of the decoded tuple or the partially decoded current tlv
243      * @throws DecoderException if there are errors while decoding.
244      */
245     public Tuple decode( ByteBuffer bites ) throws DecoderException
246     {
247         int lastSize = tlvList.size() ;
248         decoder.decode( bites ) ;
249         
250         if ( tlvList.isEmpty() || tlvList.size() == lastSize )
251         {
252             return decoder.getCurrentTuple() ;
253         }
254         
255         return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
256     }
257 
258     
259     /***
260      * First BER encodes then BER decodes a Tuple.
261      * 
262      * @param tlv a tuple to encode then decode
263      * @return a copy of the decoded tuple or the partially decoded current tlv
264      * @throws DecoderException if there are errors while decoding
265      */
266     public Tuple decode( Tuple tlv, ByteBuffer value ) throws DecoderException
267     {
268         ArrayList list = new ArrayList() ;
269         list.add( value ) ;
270         ByteBuffer buf = tlv.toEncodedBuffer( list ) ;
271         int lastSize = tlvList.size() ;
272         decoder.decode( buf ) ;
273         
274         if ( tlvList.isEmpty() || tlvList.size() == lastSize )
275         {
276             Stack stack = decoder.getTupleStack() ;
277             
278             if ( stack.isEmpty() )
279             {    
280                 return decoder.getCurrentTuple() ;
281             }
282             else
283             {
284                 return ( Tuple ) stack.peek() ;
285             }
286         }
287         
288         return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
289     }
290 
291     
292     /***
293      * First BER encodes then BER decodes a train of Tuples.
294      * 
295      * @param tlvs a tuple array to encode then decode
296      * @return a copy of the decoded tuple or the partially decoded current tlv
297      * @throws DecoderException if there are errors while decoding
298      */
299     public Tuple decode( Tuple[] tlvs, ByteBuffer[] values ) 
300         throws DecoderException
301     {
302         int lastSize = tlvList.size() ;
303 
304         for ( int ii = 0; ii < tlvs.length; ii++ )
305         {
306             decode( tlvs[ii], values[ii] ) ;
307         }
308         
309         if ( tlvList.isEmpty() || tlvList.size() == lastSize )
310         {
311             return decoder.getCurrentTuple() ;
312         }
313         
314         return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
315     }
316     
317     public Tuple decode( byte[] pdu ) throws DecoderException
318     {
319         decode( ByteBuffer.wrap( pdu ) ) ;
320         return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
321     }
322 
323     /* (non-Javadoc)
324      * @see org.apache.asn1.ber.BERDecoderCallback#tagDecoded(
325      * org.apache.asn1.ber.Tuple)
326      */
327     public void tagDecoded( Tuple tlv )
328     {
329         assertTrue( decoder.getCurrentTuple().equals( tlv ) ) ;
330         assertEquals( BERDecoderState.TAG, decoder.getState() ) ;
331     }
332 
333 
334     /* (non-Javadoc)
335      * @see org.apache.asn1.ber.BERDecoderCallback#lengthDecoded(
336      * org.apache.asn1.ber.Tuple)
337      */
338     public void lengthDecoded( Tuple tlv )
339     {
340         assertTrue( decoder.getCurrentTuple().equals( tlv ) ) ;
341         assertEquals( BERDecoderState.LENGTH, decoder.getState() ) ;
342         buf.clear() ;
343     }
344 
345     
346     /* (non-Javadoc)
347      * @see org.apache.asn1.ber.BERDecoderCallback#partialValueDecoded(
348      * org.apache.asn1.ber.Tuple)
349      */
350     public void partialValueDecoded( Tuple tlv )
351     {
352         buf.put( tlv.valueChunk ) ;
353     }
354     
355 
356     /* (non-Javadoc)
357      * @see org.apache.asn1.codec.stateful.DecoderCallback#decodeOccurred(
358      * org.apache.asn1.codec.stateful.StatefulDecoder, java.lang.Object)
359      */
360     public void decodeOccurred( StatefulDecoder decoder, Object decoded )
361     {
362         Tuple t = ( Tuple ) decoded ;
363         tlvList.add( t.clone() ) ;
364         assertEquals( BERDecoderState.VALUE, this.decoder.getState() ) ;
365         buf.flip() ;
366     }
367     
368     
369     /* (non-Javadoc)
370      * @see org.apache.asn1.codec.stateful.DecoderMonitor#callbackOccured(
371      * org.apache.asn1.codec.stateful.StatefulDecoder,
372      * org.apache.asn1.codec.stateful.DecoderCallback, java.lang.Object)
373      */
374     public void callbackOccured( StatefulDecoder decoder, DecoderCallback cb,
375 								 Object decoded )
376     {
377         assertEquals( this, cb ) ;
378         assertEquals( this.decoder, decoder ) ;
379         Tuple t = ( Tuple ) decoded ;
380         assertNotNull( t ) ;
381         if ( t.isPrimitive )
382         {    
383             assertTrue( this.decoder.getCurrentTuple().equals( decoded ) ) ;
384         }
385     }
386 
387     
388     /* (non-Javadoc)
389      * @see org.apache.asn1.codec.stateful.DecoderMonitor#callbackSet(
390      * org.apache.asn1.codec.stateful.StatefulDecoder,
391      * org.apache.asn1.codec.stateful.DecoderCallback,
392      * org.apache.asn1.codec.stateful.DecoderCallback)
393      */
394     public void callbackSet( StatefulDecoder decoder, DecoderCallback oldcb,
395 							 DecoderCallback newcb )
396     {
397         assertEquals( this, newcb ) ;
398     }
399 
400 
401     /* (non-Javadoc)
402      * @see org.apache.asn1.codec.stateful.DecoderMonitor#error(
403      * org.apache.asn1.codec.stateful.StatefulDecoder, java.lang.Exception)
404      */
405     public void error( StatefulDecoder decoder, Exception exception )
406     {
407         fail( ExceptionUtils.getFullStackTrace( exception ) ) ;
408     }
409 
410     
411     /* (non-Javadoc)
412      * @see org.apache.asn1.codec.stateful.DecoderMonitor#fatalError(
413      * org.apache.asn1.codec.stateful.StatefulDecoder, java.lang.Exception)
414      */
415     public void fatalError( StatefulDecoder decoder, Exception exception )
416     {
417         fail( ExceptionUtils.getFullStackTrace( exception ) ) ;
418     }
419 
420     
421     /* (non-Javadoc)
422      * @see org.apache.asn1.codec.stateful.DecoderMonitor#monitorSet(
423      * org.apache.asn1.codec.stateful.StatefulDecoder,
424      * org.apache.asn1.codec.stateful.DecoderMonitor)
425      */
426     public void monitorSet( StatefulDecoder decoder, DecoderMonitor oldmon )
427     {
428         assertEquals( this, oldmon ) ;
429     }
430 
431     
432     /* (non-Javadoc)
433      * @see org.apache.asn1.codec.stateful.DecoderMonitor#warning(
434      * org.apache.asn1.codec.stateful.StatefulDecoder, java.lang.Exception)
435      */
436     public void warning( StatefulDecoder decoder, Exception exception )
437     {
438         assertNotNull( exception ) ;
439     }
440 }