1   package org.apache.jcs.auxiliary.disk.block;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  
24  import junit.framework.TestCase;
25  
26  /***
27   * Test for the disk acces layer of the Block Disk Cache.
28   * <p>
29   * @author Aaron Smuts
30   */
31  public class BlockDiskUnitTest
32      extends TestCase
33  {
34      private File rafDir;
35  
36      /***
37       * Creates the base directory
38       */
39      public BlockDiskUnitTest()
40      {
41          String rootDirName = "target/test-sandbox/block";
42          this.rafDir = new File( rootDirName );
43          this.rafDir.mkdirs();
44      }
45  
46      /***
47       * Test writing an element within a single block size.
48       * <p>
49       * @throws Exception
50       */
51      public void testWriteSingleBlockElement()
52          throws Exception
53      {
54          // SETUP
55          String fileName = "testWriteSingleBlockElement";
56          File file = new File( rafDir, fileName + ".data" );
57          file.delete();
58          BlockDisk disk = new BlockDisk( file );
59  
60          // DO WORK
61          int bytes = 1 * 1024;
62          int[] blocks = disk.write( new byte[bytes] );
63  
64          // VERIFY
65          System.out.println( "testWriteSingleBlockElement " + disk );
66          assertEquals( "Wrong number of blocks recorded.", 1, disk.getNumberOfBlocks() );
67          assertEquals( "Wrong number of blocks returned.", 1, blocks.length );
68          assertEquals( "Wrong block returned.", 0, blocks[0] );
69      }
70  
71      /***
72       * Test writing and reading an element within a single block size.
73       * <p>
74       * @throws Exception
75       */
76      public void testWriteAndReadSingleBlockElement()
77          throws Exception
78      {
79          // SETUP
80          String fileName = "testWriteAndReadSingleBlockElement";
81          File file = new File( rafDir, fileName + ".data" );
82          file.delete();
83          BlockDisk disk = new BlockDisk( file );
84  
85          // DO WORK
86          int bytes = 1 * 1024;
87          int[] blocks = disk.write( new byte[bytes] );
88  
89          byte[] result = (byte[]) disk.read( blocks );
90  
91          // VERIFY
92          assertEquals( "Wrong item retured.", new byte[bytes].length, result.length );
93      }
94  
95      /***
96       * Test writing two elements that each fit within a single block size.
97       * <p>
98       * @throws Exception
99       */
100     public void testWriteTwoSingleBlockElements()
101         throws Exception
102     {
103         // SETUP
104         String fileName = "testWriteSingleBlockElement";
105         File file = new File( rafDir, fileName + ".data" );
106         file.delete();
107         BlockDisk disk = new BlockDisk( file );
108 
109         // DO WORK
110         int bytes = 1 * 1024;
111         int[] blocks1 = disk.write( new byte[bytes] );
112         int[] blocks2 = disk.write( new byte[bytes] );
113 
114         // VERIFY
115         assertEquals( "Wrong number of blocks recorded.", 2, disk.getNumberOfBlocks() );
116         assertEquals( "Wrong number of blocks returned.", 1, blocks1.length );
117         assertEquals( "Wrong block returned.", 0, blocks1[0] );
118         assertEquals( "Wrong number of blocks returned.", 1, blocks2.length );
119         assertEquals( "Wrong block returned.", 1, blocks2[0] );
120     }
121 
122     /***
123      * Verify that it says we need two blocks if the total size will fit.
124      * <p>
125      * @throws Exception
126      */
127     public void testCalculateBlocksNeededDouble()
128         throws Exception
129     {
130         // SETUP
131         String fileName = "testCalculateBlocksNeededDouble";
132         File file = new File( rafDir, fileName + ".data" );
133         file.delete();
134         BlockDisk disk = new BlockDisk( file );
135 
136         // DO WORK
137         int result = disk.calculateTheNumberOfBlocksNeeded( new byte[disk.getBlockSizeBytes() * 2
138             - ( 2 * BlockDisk.HEADER_SIZE_BYTES )] );
139 
140         // Verify
141         assertEquals( "Wrong number of blocks", 2, result );
142     }
143 
144     /***
145      * Test writing an element that takes two blocks.
146      * <p>
147      * @throws Exception
148      */
149     public void testWriteDoubleBlockElement()
150         throws Exception
151     {
152         // SETUP
153         String fileName = "testWriteDoubleBlockElement";
154         File file = new File( rafDir, fileName + ".data" );
155         BlockDisk disk = new BlockDisk( file );
156 
157         // DO WORK
158         // byte arrays encur 27 bytes of serialization overhead.
159         int bytes = getBytesForBlocksOfByteArrays( disk.getBlockSizeBytes(), 2 );
160         int[] blocks = disk.write( new byte[bytes] );
161 
162         // VERIFY
163         System.out.println( "testWriteDoubleBlockElement " + disk );
164         assertEquals( "Wrong number of blocks recorded.", 2, disk.getNumberOfBlocks() );
165         assertEquals( "Wrong number of blocks returned.", 2, blocks.length );
166         assertEquals( "Wrong block returned.", 0, blocks[0] );
167     }
168 
169     /***
170      * Test writing and reading elements that do not fit within a single block.
171      * <p>
172      * @throws Exception
173      */
174     public void testWriteAndReadMultipleMultiBlockElement()
175         throws Exception
176     {
177         // SETUP
178         String fileName = "testWriteAndReadSingleBlockElement";
179         File file = new File( rafDir, fileName + ".data" );
180         file.delete();
181         BlockDisk disk = new BlockDisk( file );
182 
183         // DO WORK
184         int numBlocksPerElement = 4;
185         int bytes = getBytesForBlocksOfByteArrays( disk.getBlockSizeBytes(), numBlocksPerElement );
186 
187         int numElements = 100;
188         for ( int i = 0; i < numElements; i++ )
189         {
190             int[] blocks = disk.write( new byte[bytes] );
191             byte[] result = (byte[]) disk.read( blocks );
192 
193             // VERIFY
194             assertEquals( "Wrong item retured.", new byte[bytes].length, result.length );
195             assertEquals( "Wrong number of blocks returned.", numBlocksPerElement, blocks.length );
196         }
197         System.out.println( "testWriteAndReadMultipleMultiBlockElement " + disk );
198     }
199 
200     /***
201      * Test writing and reading elements that do not fit within a single block.
202      * <p>
203      * @throws Exception
204      */
205     public void testWriteAndReadMultipleMultiBlockElement_setSize()
206         throws Exception
207     {
208         // SETUP
209         String fileName = "testWriteAndReadSingleBlockElement";
210         File file = new File( rafDir, fileName + ".data" );
211         file.delete();
212         int blockSizeBytes = 1024;
213         BlockDisk disk = new BlockDisk( file, blockSizeBytes );
214 
215         // DO WORK
216         int numBlocksPerElement = 4;
217         int bytes = getBytesForBlocksOfByteArrays( disk.getBlockSizeBytes(), numBlocksPerElement );
218 
219         int numElements = 100;
220         for ( int i = 0; i < numElements; i++ )
221         {
222             int[] blocks = disk.write( new byte[bytes] );
223             byte[] result = (byte[]) disk.read( blocks );
224 
225             // VERIFY
226             assertEquals( "Wrong item retured.", new byte[bytes].length, result.length );
227             assertEquals( "Wrong number of blocks returned.", numBlocksPerElement, blocks.length );
228         }
229         System.out.println( "testWriteAndReadMultipleMultiBlockElement_setSize " + disk );
230         assertEquals( "Wrong number of elements.", numBlocksPerElement * numElements, disk.getNumberOfBlocks() );
231     }
232 
233     /***
234      * Used to get the size for byte arrays that will take up the number of blocks specified.
235      * <p>
236      * @param blockSize
237      * @param numBlocks
238      * @return num bytes.
239      */
240     private int getBytesForBlocksOfByteArrays( int blockSize, int numBlocks )
241     {
242         // byte arrays encur some bytes of serialization overhead.
243         return blockSize * numBlocks - ( numBlocks * BlockDisk.HEADER_SIZE_BYTES ) - ( numBlocks * 14 );
244     }
245 }