KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > hssf > record > TestSSTRecord


1
2 /* ====================================================================
3    Copyright 2002-2004 Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You 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 implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 ==================================================================== */

17         
18
19 package org.apache.poi.hssf.record;
20
21 import junit.framework.TestCase;
22 import org.apache.poi.hssf.usermodel.HSSFSheet;
23 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
24 import org.apache.poi.util.HexRead;
25 import org.apache.poi.util.LittleEndian;
26 import org.apache.poi.util.LittleEndianConsts;
27 import org.apache.poi.util.TempFile;
28
29 import java.io.*;
30 import java.util.Arrays JavaDoc;
31 import java.util.Iterator JavaDoc;
32
33 /**
34  * @author Marc Johnson (mjohnson at apache dot org)
35  * @author Glen Stampoultzis (glens at apache.org)
36  */

37
38 public class TestSSTRecord
39         extends TestCase
40 {
41     private String JavaDoc _test_file_path;
42     private static final String JavaDoc _test_file_path_property = "HSSF.testdata.path";
43
44     /**
45      * Creates new TestSSTRecord
46      *
47      * @param name
48      */

49
50     public TestSSTRecord( String JavaDoc name )
51     {
52         super( name );
53         _test_file_path = System.getProperty( _test_file_path_property );
54     }
55
56     /**
57      * test processContinueRecord
58      *
59      * @exception IOException
60      */

61
62     public void testProcessContinueRecord()
63             throws IOException
64     {
65         byte[] testdata = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord" );
66         byte[] input = new byte[testdata.length - 4];
67
68         System.arraycopy( testdata, 4, input, 0, input.length );
69         SSTRecord record =
70                 new SSTRecord( LittleEndian.getShort( testdata, 0 ),
71                         LittleEndian.getShort( testdata, 2 ), input );
72         byte[] continueRecord = HexRead.readData( _test_file_path + File.separator + "BigSSTRecordCR" );
73
74         input = new byte[continueRecord.length - 4];
75         System.arraycopy( continueRecord, 4, input, 0, input.length );
76         record.processContinueRecord( input );
77         assertEquals( 1464, record.getNumStrings() );
78         assertEquals( 688, record.getNumUniqueStrings() );
79         assertEquals( 688, record.countStrings() );
80         byte[] ser_output = record.serialize();
81         int offset = 0;
82         short type = LittleEndian.getShort( ser_output, offset );
83
84         offset += LittleEndianConsts.SHORT_SIZE;
85         short length = LittleEndian.getShort( ser_output, offset );
86
87         offset += LittleEndianConsts.SHORT_SIZE;
88         byte[] recordData = new byte[length];
89
90         System.arraycopy( ser_output, offset, recordData, 0, length );
91         offset += length;
92         SSTRecord testRecord = new SSTRecord( type, length, recordData );
93
94         assertEquals( ContinueRecord.sid,
95                 LittleEndian.getShort( ser_output, offset ) );
96         offset += LittleEndianConsts.SHORT_SIZE;
97         length = LittleEndian.getShort( ser_output, offset );
98         offset += LittleEndianConsts.SHORT_SIZE;
99         byte[] cr = new byte[length];
100
101         System.arraycopy( ser_output, offset, cr, 0, length );
102         offset += length;
103         assertEquals( offset, ser_output.length );
104         testRecord.processContinueRecord( cr );
105         assertEquals( record, testRecord );
106
107         // testing based on new bug report
108
testdata = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord2" );
109         input = new byte[testdata.length - 4];
110         System.arraycopy( testdata, 4, input, 0, input.length );
111         record = new SSTRecord( LittleEndian.getShort( testdata, 0 ),
112                 LittleEndian.getShort( testdata, 2 ), input );
113         byte[] continueRecord1 = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord2CR1" );
114
115         input = new byte[continueRecord1.length - 4];
116         System.arraycopy( continueRecord1, 4, input, 0, input.length );
117         record.processContinueRecord( input );
118         byte[] continueRecord2 = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord2CR2" );
119
120         input = new byte[continueRecord2.length - 4];
121         System.arraycopy( continueRecord2, 4, input, 0, input.length );
122         record.processContinueRecord( input );
123         byte[] continueRecord3 = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord2CR3" );
124
125         input = new byte[continueRecord3.length - 4];
126         System.arraycopy( continueRecord3, 4, input, 0, input.length );
127         record.processContinueRecord( input );
128         byte[] continueRecord4 = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord2CR4" );
129
130         input = new byte[continueRecord4.length - 4];
131         System.arraycopy( continueRecord4, 4, input, 0, input.length );
132         record.processContinueRecord( input );
133         byte[] continueRecord5 = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord2CR5" );
134
135         input = new byte[continueRecord5.length - 4];
136         System.arraycopy( continueRecord5, 4, input, 0, input.length );
137         record.processContinueRecord( input );
138         byte[] continueRecord6 = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord2CR6" );
139
140         input = new byte[continueRecord6.length - 4];
141         System.arraycopy( continueRecord6, 4, input, 0, input.length );
142         record.processContinueRecord( input );
143         byte[] continueRecord7 = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord2CR7" );
144
145         input = new byte[continueRecord7.length - 4];
146         System.arraycopy( continueRecord7, 4, input, 0, input.length );
147         record.processContinueRecord( input );
148         assertEquals( 158642, record.getNumStrings() );
149         assertEquals( 5249, record.getNumUniqueStrings() );
150         assertEquals( 5249, record.countStrings() );
151         ser_output = record.serialize();
152         offset = 0;
153         type = LittleEndian.getShort( ser_output, offset );
154         offset += LittleEndianConsts.SHORT_SIZE;
155         length = LittleEndian.getShort( ser_output, offset );
156         offset += LittleEndianConsts.SHORT_SIZE;
157         recordData = new byte[length];
158         System.arraycopy( ser_output, offset, recordData, 0, length );
159         offset += length;
160         testRecord = new SSTRecord( type, length, recordData );
161         for ( int count = 0; count < 7; count++ )
162         {
163             assertEquals( ContinueRecord.sid,
164                     LittleEndian.getShort( ser_output, offset ) );
165             offset += LittleEndianConsts.SHORT_SIZE;
166             length = LittleEndian.getShort( ser_output, offset );
167             offset += LittleEndianConsts.SHORT_SIZE;
168             cr = new byte[length];
169             System.arraycopy( ser_output, offset, cr, 0, length );
170             testRecord.processContinueRecord( cr );
171             offset += length;
172         }
173         assertEquals( offset, ser_output.length );
174         assertEquals( record, testRecord );
175         assertEquals( record.countStrings(), testRecord.countStrings() );
176     }
177
178     /**
179      * Test capability of handling mondo big strings
180      *
181      * @exception IOException
182      */

183
184     public void testHugeStrings()
185             throws IOException
186     {
187         SSTRecord record = new SSTRecord();
188         byte[][] bstrings =
189                 {
190                     new byte[9000], new byte[7433], new byte[9002],
191                     new byte[16998]
192                 };
193         String JavaDoc[] strings = new String JavaDoc[bstrings.length];
194         int total_length = 0;
195
196         for ( int k = 0; k < bstrings.length; k++ )
197         {
198             Arrays.fill( bstrings[k], (byte) ( 'a' + k ) );
199             strings[k] = new String JavaDoc( bstrings[k] );
200             record.addString( strings[k] );
201             total_length += 3 + bstrings[k].length;
202         }
203
204         // add overhead of SST record
205
total_length += 8;
206
207         // add overhead of broken strings
208
total_length += 4;
209
210         // add overhead of six records
211
total_length += ( 6 * 4 );
212         byte[] content = new byte[record.getRecordSize()];
213
214         record.serialize( 0, content );
215         assertEquals( total_length, content.length );
216         for ( int index = 0; index != content.length; )
217         {
218             short record_type = LittleEndian.getShort( content, index );
219
220             index += LittleEndianConsts.SHORT_SIZE;
221             short record_length = LittleEndian.getShort( content, index );
222
223             index += LittleEndianConsts.SHORT_SIZE;
224             byte[] data = new byte[record_length];
225
226             System.arraycopy( content, index, data, 0, record_length );
227             index += record_length;
228             if ( record_type == SSTRecord.sid )
229             {
230                 record = new SSTRecord( record_type, record_length, data );
231             }
232             else
233             {
234                 record.processContinueRecord( data );
235             }
236         }
237         assertEquals( strings.length, record.getNumStrings() );
238         assertEquals( strings.length, record.getNumUniqueStrings() );
239         assertEquals( strings.length, record.countStrings() );
240         for ( int k = 0; k < strings.length; k++ )
241         {
242             assertEquals( strings[k], record.getString( k ) );
243         }
244         record = new SSTRecord();
245         bstrings[1] = new byte[bstrings[1].length - 1];
246         for ( int k = 0; k < bstrings.length; k++ )
247         {
248             if ( ( bstrings[k].length % 2 ) == 1 )
249             {
250                 Arrays.fill( bstrings[k], (byte) ( 'a' + k ) );
251                 strings[k] = new String JavaDoc( bstrings[k] );
252             }
253             else
254             {
255                 char[] data = new char[bstrings[k].length / 2];
256
257                 Arrays.fill( data, (char) ( '\u2122' + k ) );
258                 strings[k] = new String JavaDoc( data );
259             }
260             record.addString( strings[k] );
261         }
262         content = new byte[record.getRecordSize()];
263         record.serialize( 0, content );
264         total_length--;
265         assertEquals( total_length, content.length );
266         for ( int index = 0; index != content.length; )
267         {
268             short record_type = LittleEndian.getShort( content, index );
269
270             index += LittleEndianConsts.SHORT_SIZE;
271             short record_length = LittleEndian.getShort( content, index );
272
273             index += LittleEndianConsts.SHORT_SIZE;
274             byte[] data = new byte[record_length];
275
276             System.arraycopy( content, index, data, 0, record_length );
277             index += record_length;
278             if ( record_type == SSTRecord.sid )
279             {
280                 record = new SSTRecord( record_type, record_length, data );
281             }
282             else
283             {
284                 record.processContinueRecord( data );
285             }
286         }
287         assertEquals( strings.length, record.getNumStrings() );
288         assertEquals( strings.length, record.getNumUniqueStrings() );
289         assertEquals( strings.length, record.countStrings() );
290         for ( int k = 0; k < strings.length; k++ )
291         {
292             assertEquals( strings[k], record.getString( k ) );
293         }
294     }
295
296     /**
297      * test SSTRecord boundary conditions
298      *
299      * @exception IOException
300      */

301     public void testSSTRecordBug()
302             throws IOException
303     {
304
305         // create an SSTRecord and write a certain pattern of strings
306
// to it ... then serialize it and verify the content
307
SSTRecord record = new SSTRecord();
308
309         // the record will start with two integers, then this string
310
// ... that will eat up 16 of the 8224 bytes that the record
311
// can hold
312
record.addString( "Hello" );
313
314         // now we have an additional 8208 bytes, which is an exact
315
// multiple of 16 bytes
316
long testvalue = 1000000000000L;
317
318         for ( int k = 0; k < 2000; k++ )
319         {
320             record.addString( String.valueOf( testvalue++ ) );
321         }
322         byte[] content = new byte[record.getRecordSize()];
323
324         record.serialize( 0, content );
325         assertEquals( (byte) 13, content[4 + 8228] );
326         assertEquals( (byte) 13, content[4 + 8228 * 2] );
327         assertEquals( (byte) 13, content[4 + 8228 * 3] );
328     }
329
330     /**
331      * test simple addString
332      */

333     public void testSimpleAddString()
334     {
335         SSTRecord record = new SSTRecord();
336         String JavaDoc s1 = "Hello world";
337
338         // \u2122 is the encoding of the trademark symbol ...
339
String JavaDoc s2 = "Hello world\u2122";
340
341         assertEquals( 0, record.addString( s1 ) );
342         assertEquals( s1, record.getString( 0 ) );
343         assertEquals( 1, record.countStrings() );
344         assertEquals( 1, record.getNumStrings() );
345         assertEquals( 1, record.getNumUniqueStrings() );
346         assertEquals( 0, record.addString( s1 ) );
347         assertEquals( s1, record.getString( 0 ) );
348         assertEquals( 1, record.countStrings() );
349         assertEquals( 2, record.getNumStrings() );
350         assertEquals( 1, record.getNumUniqueStrings() );
351         assertEquals( 1, record.addString( s2 ) );
352         assertEquals( s2, record.getString( 1 ) );
353         assertEquals( 2, record.countStrings() );
354         assertEquals( 3, record.getNumStrings() );
355         assertEquals( 2, record.getNumUniqueStrings() );
356         Iterator JavaDoc iter = record.getStrings();
357
358         while ( iter.hasNext() )
359         {
360             UnicodeString ucs = (UnicodeString) iter.next();
361
362             if ( ucs.getString().equals( s1 ) )
363             {
364                 assertEquals( (byte) 0, ucs.getOptionFlags() );
365             }
366             else if ( ucs.getString().equals( s2 ) )
367             {
368                 assertEquals( (byte) 1, ucs.getOptionFlags() );
369             }
370             else
371             {
372                 fail( "cannot match string: " + ucs.getString() );
373             }
374         }
375     }
376
377     /**
378      * test reader constructor
379      *
380      * @exception IOException
381      */

382
383     public void testReaderConstructor()
384             throws IOException
385     {
386         byte[] testdata = HexRead.readData( _test_file_path + File.separator + "BigSSTRecord" );
387         byte[] input = new byte[testdata.length - 4];
388
389         System.arraycopy( testdata, 4, input, 0, input.length );
390         SSTRecord record = new SSTRecord( LittleEndian.getShort( testdata, 0 ),
391                 LittleEndian.getShort( testdata, 2 ),
392                 input );
393
394         assertEquals( 1464, record.getNumStrings() );
395         assertEquals( 688, record.getNumUniqueStrings() );
396         assertEquals( 492, record.countStrings() );
397 //jmh assertEquals( 1, record.getDeserializer().getContinuationExpectedChars() );
398
assertEquals( "Consolidated B-24J Liberator The Dragon & His Tai",
399                 record.getDeserializer().getUnfinishedString() );
400 // assertEquals( 52, record.getDeserializer().getTotalLength() );
401
// assertEquals( 3, record.getDeserializer().getStringDataOffset() );
402
assertTrue( !record.getDeserializer().isWideChar() );
403     }
404
405     /**
406      * test simple constructor
407      */

408
409     public void testSimpleConstructor()
410     {
411         SSTRecord record = new SSTRecord();
412
413         assertEquals( 0, record.getNumStrings() );
414         assertEquals( 0, record.getNumUniqueStrings() );
415         assertEquals( 0, record.countStrings() );
416         assertEquals( 0, record.getDeserializer().getContinuationCharsRead() );
417         assertEquals( "", record.getDeserializer().getUnfinishedString() );
418 // assertEquals( 0, record.getDeserializer().getTotalLength() );
419
// assertEquals( 0, record.getDeserializer().getStringDataOffset() );
420
assertTrue( !record.getDeserializer().isWideChar() );
421         byte[] output = record.serialize();
422         byte[] expected =
423                 {
424                     (byte) record.getSid(), (byte) ( record.getSid() >> 8 ),
425                     (byte) 8, (byte) 0, (byte) 0, (byte) 0, (byte) 0,
426                     (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0
427                 };
428
429         assertEquals( expected.length, output.length );
430         for ( int k = 0; k < expected.length; k++ )
431         {
432             assertEquals( String.valueOf( k ), expected[k], output[k] );
433         }
434     }
435
436     /**
437      * main method to run the unit tests
438      *
439      * @param ignored_args
440      */

441
442     public static void main( String JavaDoc[] ignored_args )
443     {
444         System.out.println( "Testing hssf.record.SSTRecord functionality" );
445         junit.textui.TestRunner.run( TestSSTRecord.class );
446     }
447
448     /**
449      * Tests that workbooks with rich text that duplicates a non rich text cell can be read and written.
450      */

451     public void testReadWriteDuplicatedRichText1()
452             throws Exception JavaDoc
453     {
454         File file = new File( _test_file_path + File.separator + "duprich1.xls" );
455         InputStream stream = new FileInputStream( file );
456         HSSFWorkbook wb = new HSSFWorkbook( stream );
457         stream.close();
458         HSSFSheet sheet = wb.getSheetAt( 1 );
459         assertEquals( "01/05 (Wed) ", sheet.getRow( 0 ).getCell( (short) 8 ).getStringCellValue() );
460         assertEquals( "01/05 (Wed)", sheet.getRow( 1 ).getCell( (short) 8 ).getStringCellValue() );
461
462         file = TempFile.createTempFile( "testout", "xls" );
463         FileOutputStream outStream = new FileOutputStream( file );
464         wb.write( outStream );
465         outStream.close();
466         file.delete();
467
468         // test the second file.
469
file = new File( _test_file_path + File.separator + "duprich2.xls" );
470         stream = new FileInputStream( file );
471         wb = new HSSFWorkbook( stream );
472         stream.close();
473         sheet = wb.getSheetAt( 0 );
474         int row = 0;
475         assertEquals( "Testing ", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() );
476         assertEquals( "rich", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() );
477         assertEquals( "text", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() );
478         assertEquals( "strings", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() );
479         assertEquals( "Testing ", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() );
480         assertEquals( "Testing", sheet.getRow( row++ ).getCell( (short) 0 ).getStringCellValue() );
481
482 // file = new File("/tryme.xls");
483
file = TempFile.createTempFile( "testout", ".xls" );
484         outStream = new FileOutputStream( file );
485         wb.write( outStream );
486         outStream.close();
487         file.delete();
488     }
489
490 }
491
Popular Tags