View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.compress.harmony.pack200;
20  
21  import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertFalse;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  
28  import java.io.ByteArrayInputStream;
29  import java.io.EOFException;
30  import java.io.IOException;
31  import java.util.stream.IntStream;
32  import java.util.stream.Stream;
33  
34  import org.junit.jupiter.api.Test;
35  import org.junit.jupiter.params.ParameterizedTest;
36  import org.junit.jupiter.params.provider.Arguments;
37  import org.junit.jupiter.params.provider.MethodSource;
38  
39  /**
40   */
41  class CodecTest {
42  
43      static Stream<Arguments> bCodings() {
44          return IntStream.rangeClosed(1, 5).mapToObj(Arguments::of);
45      }
46  
47      static Stream<Arguments> codecFamily() {
48          return Stream.of(Arguments.of((Object) CanonicalCodecFamilies.nonDeltaUnsignedCodecs1),
49                  Arguments.of((Object) CanonicalCodecFamilies.nonDeltaUnsignedCodecs2), Arguments.of((Object) CanonicalCodecFamilies.nonDeltaUnsignedCodecs3),
50                  Arguments.of((Object) CanonicalCodecFamilies.nonDeltaUnsignedCodecs4), Arguments.of((Object) CanonicalCodecFamilies.nonDeltaUnsignedCodecs5),
51                  Arguments.of((Object) CanonicalCodecFamilies.deltaUnsignedCodecs1), Arguments.of((Object) CanonicalCodecFamilies.deltaUnsignedCodecs2),
52                  Arguments.of((Object) CanonicalCodecFamilies.deltaUnsignedCodecs3), Arguments.of((Object) CanonicalCodecFamilies.deltaUnsignedCodecs4),
53                  Arguments.of((Object) CanonicalCodecFamilies.deltaUnsignedCodecs5), Arguments.of((Object) CanonicalCodecFamilies.nonDeltaSignedCodecs1),
54                  Arguments.of((Object) CanonicalCodecFamilies.nonDeltaSignedCodecs2), Arguments.of((Object) CanonicalCodecFamilies.nonDeltaDoubleSignedCodecs1),
55                  Arguments.of((Object) CanonicalCodecFamilies.deltaSignedCodecs1), Arguments.of((Object) CanonicalCodecFamilies.deltaSignedCodecs2),
56                  Arguments.of((Object) CanonicalCodecFamilies.deltaSignedCodecs3), Arguments.of((Object) CanonicalCodecFamilies.deltaSignedCodecs4),
57                  Arguments.of((Object) CanonicalCodecFamilies.deltaSignedCodecs5), Arguments.of((Object) CanonicalCodecFamilies.deltaDoubleSignedCodecs1));
58      }
59  
60      static Stream<Arguments> hCodings() {
61          return IntStream.range(0, 256).mapToObj(Arguments::of);
62      }
63  
64      private long decode(final Codec codec, final byte[] data, final long value, final long last) throws IOException, Pack200Exception {
65          final ByteArrayInputStream in = new ByteArrayInputStream(data);
66          assertEquals(value, codec.decode(in, last));
67          assertEquals(-1, in.read());
68          return value;
69      }
70  
71      private void decodeFail(final Codec codec, final byte[] data) {
72          assertThrowsExactly(EOFException.class, () -> decode(codec, data, 0, 0), "Should have detected an EOFException");
73      }
74  
75      @ParameterizedTest
76      @MethodSource("bCodings")
77      void testBCodings(final int i) {
78          if (i == 5) {
79              assertThrows(IllegalArgumentException.class, () -> new BHSDCodec(i, 256));
80          } else {
81              assertDoesNotThrow(() -> new BHSDCodec(i, 256));
82          }
83      }
84  
85      @Test
86      void testByte1() throws Exception {
87          for (int i = 0; i < 255; i++) {
88              decode(Codec.BYTE1, new byte[] { (byte) i }, i, 0);
89          }
90      }
91  
92      @Test
93      void testByte1Delta() throws Exception {
94          final Codec BYTE1D = new BHSDCodec(1, 256, 0, 1);
95          long last = 0;
96          for (int i = 1; i < 255; i++) {
97              last = decode(BYTE1D, new byte[] { (byte) 1 }, i, last);
98          }
99      }
100 
101     @Test
102     void testByte1DeltaException() throws Exception {
103         final Codec BYTE1D = new BHSDCodec(1, 256, 0, 1);
104         assertThrows(Pack200Exception.class, () -> BYTE1D.decode(new ByteArrayInputStream(new byte[] { (byte) 1 })),
105                 "Decoding with a delta stream and not passing a last value should throw an exception");
106     }
107 
108     @Test
109     void testByte1Signed() throws Exception {
110         final Codec BYTE1S2 = new BHSDCodec(1, 256, 2);
111         decode(BYTE1S2, new byte[] { 0 }, 0, 0);
112         decode(BYTE1S2, new byte[] { 1 }, 1, 0);
113         decode(BYTE1S2, new byte[] { 2 }, 2, 0);
114         decode(BYTE1S2, new byte[] { 3 }, -1, 0);
115         decode(BYTE1S2, new byte[] { 4 }, 3, 0);
116         decode(BYTE1S2, new byte[] { 5 }, 4, 0);
117         decode(BYTE1S2, new byte[] { 6 }, 5, 0);
118         decode(BYTE1S2, new byte[] { 7 }, -2, 0);
119         decode(BYTE1S2, new byte[] { 8 }, 6, 0);
120         decode(BYTE1S2, new byte[] { 9 }, 7, 0);
121         decode(BYTE1S2, new byte[] { 10 }, 8, 0);
122         decode(BYTE1S2, new byte[] { 11 }, -3, 0);
123     }
124 
125     @Test
126     void testCardinality() {
127         final BHSDCodec byte1 = Codec.BYTE1;
128         assertEquals(256, byte1.cardinality());
129         assertEquals(0, byte1.smallest());
130         assertEquals(255, byte1.largest());
131         assertFalse(byte1.encodes(-257));
132         assertFalse(byte1.encodes(-256));
133         assertFalse(byte1.encodes(-255));
134         assertFalse(byte1.encodes(-129));
135         assertFalse(byte1.encodes(-128));
136         assertFalse(byte1.encodes(-127));
137         assertFalse(byte1.encodes(-1));
138         assertTrue(byte1.encodes(0));
139         assertTrue(byte1.encodes(1));
140         assertTrue(byte1.encodes(255));
141         assertFalse(byte1.encodes(256));
142         final BHSDCodec byte1s = new BHSDCodec(1, 256, 1);
143         assertEquals(256, byte1s.cardinality());
144         assertEquals(-128, byte1s.smallest());
145         assertEquals(127, byte1s.largest());
146         assertFalse(byte1s.encodes(-257));
147         assertFalse(byte1s.encodes(-256));
148         assertFalse(byte1s.encodes(-255));
149         assertFalse(byte1s.encodes(-129));
150         assertTrue(byte1s.encodes(-128));
151         assertTrue(byte1s.encodes(-127));
152         assertTrue(byte1s.encodes(-1));
153         assertTrue(byte1s.encodes(0));
154         assertTrue(byte1s.encodes(1));
155         assertTrue(byte1s.encodes(127));
156         assertFalse(byte1s.encodes(128));
157         assertFalse(byte1s.encodes(129));
158         assertFalse(byte1s.encodes(255));
159         assertFalse(byte1s.encodes(256));
160         final BHSDCodec byte2s = new BHSDCodec(1, 256, 2);
161         assertEquals(256, byte2s.cardinality());
162         assertEquals(-64, byte2s.smallest());
163         assertEquals(191, byte2s.largest());
164         assertFalse(byte2s.encodes(-257));
165         assertFalse(byte2s.encodes(-256));
166         assertFalse(byte2s.encodes(-255));
167         assertFalse(byte2s.encodes(-129));
168         assertFalse(byte2s.encodes(-128));
169         assertFalse(byte2s.encodes(-127));
170         assertFalse(byte2s.encodes(-65));
171         assertTrue(byte2s.encodes(-64));
172         assertTrue(byte2s.encodes(-64));
173         assertTrue(byte2s.encodes(-1));
174         assertTrue(byte2s.encodes(0));
175         assertTrue(byte2s.encodes(1));
176         assertTrue(byte2s.encodes(127));
177         assertTrue(byte2s.encodes(128));
178         assertTrue(byte2s.encodes(191));
179         assertFalse(byte2s.encodes(192));
180         assertFalse(byte2s.encodes(256));
181     }
182 
183     @ParameterizedTest
184     @MethodSource("codecFamily")
185     void testCodecFamilies(final BHSDCodec[] family) {
186         for (int i = 1; i < family.length; i++) {
187             final BHSDCodec previous = family[i - 1];
188             final BHSDCodec codec = family[i];
189             assertTrue(codec.largest() >= previous.largest());
190             assertTrue(codec.smallest() <= previous.smallest());
191         }
192     }
193 
194     @Test
195     void testCodecToString() {
196         assertEquals("(1,256)", Codec.BYTE1.toString());
197         assertEquals("(3,128)", Codec.CHAR3.toString());
198         assertEquals("(5,4)", Codec.BCI5.toString());
199         assertEquals("(5,4,2)", Codec.BRANCH5.toString());
200         assertEquals("(5,64)", Codec.UNSIGNED5.toString());
201         assertEquals("(5,64,1)", Codec.SIGNED5.toString());
202         assertEquals("(5,64,0,1)", Codec.UDELTA5.toString());
203         assertEquals("(5,64,1,1)", Codec.DELTA5.toString());
204         assertEquals("(5,64,2,1)", Codec.MDELTA5.toString());
205         assertEquals("(5,64)", Codec.UNSIGNED5.toString());
206         assertEquals("(5,64,1)", Codec.SIGNED5.toString());
207         assertEquals("(5,64,1,1)", Codec.DELTA5.toString());
208         assertEquals("(5,64,2,1)", Codec.MDELTA5.toString());
209     }
210 
211     @ParameterizedTest
212     @MethodSource("hCodings")
213     void testInvalidHCodings(final int i) {
214         assertThrows(IllegalArgumentException.class, () -> new BHSDCodec(1, i), "b=1 -> h=256");
215     }
216 
217     @Test
218     void testUnsigned5() throws Exception {
219         decode(Codec.UNSIGNED5, new byte[] { 1 }, 1, 0);
220         decode(Codec.UNSIGNED5, new byte[] { (byte) 191 }, 191, 0);
221         decode(Codec.UNSIGNED5, new byte[] { (byte) 192, 0 }, 192, 0);
222         decode(Codec.UNSIGNED5, new byte[] { (byte) 193, 0 }, 193, 0);
223         decode(Codec.UNSIGNED5, new byte[] { (byte) 255, 0 }, 255, 0);
224         decode(Codec.UNSIGNED5, new byte[] { (byte) 192, 1 }, 256, 0);
225         decode(Codec.UNSIGNED5, new byte[] { (byte) 192, 5 }, 512, 0);
226         decode(Codec.UNSIGNED5, new byte[] { (byte) 192, 13 }, 1024, 0);
227         decode(Codec.UNSIGNED5, new byte[] { (byte) 192, 29 }, 2048, 0);
228         decode(Codec.UNSIGNED5, new byte[] { (byte) 255, (byte) 191 }, 12479, 0);
229 
230         decode(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192, 0 }, 12480, 0);
231         decode(Codec.UNSIGNED5, new byte[] { (byte) 255, (byte) 255, (byte) 191 }, 798911, 0);
232         decode(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192, (byte) 192, 0 }, 798912, 0);
233         decode(Codec.UNSIGNED5, new byte[] { (byte) 255, (byte) 255, (byte) 255, (byte) 191 }, 51130559, 0);
234         decode(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192, (byte) 192, (byte) 192, 0 }, 51130560, 0);
235         decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192 });
236         decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192 });
237         decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192, (byte) 192 });
238         decodeFail(Codec.UNSIGNED5, new byte[] { (byte) 192, (byte) 192, (byte) 192, (byte) 192 });
239     }
240 }