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.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.io.ByteArrayInputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.util.stream.IntStream;
28  import java.util.stream.Stream;
29  
30  import org.junit.jupiter.api.Test;
31  import org.junit.jupiter.params.ParameterizedTest;
32  import org.junit.jupiter.params.provider.Arguments;
33  import org.junit.jupiter.params.provider.MethodSource;
34  
35  /**
36   */
37  class CodecEncodingTest {
38  
39      static Stream<Arguments> arbitraryCodec() {
40          return Stream.of(Arguments.of("(1,256)", new byte[] { 0x00, (byte) 0xFF }), Arguments.of("(5,128,2,1)", new byte[] { 0x25, (byte) 0x7F }),
41                  Arguments.of("(2,128,1,1)", new byte[] { 0x0B, (byte) 0x7F }));
42      }
43  
44      // These are the canonical encodings specified by the Pack200 spec
45      static Stream<Arguments> canonicalEncodings() {
46          return Stream.of(Arguments.of(1, "(1,256)"), Arguments.of(2, "(1,256,1)"), Arguments.of(3, "(1,256,0,1)"), Arguments.of(4, "(1,256,1,1)"),
47                  Arguments.of(5, "(2,256)"), Arguments.of(6, "(2,256,1)"), Arguments.of(7, "(2,256,0,1)"), Arguments.of(8, "(2,256,1,1)"),
48                  Arguments.of(9, "(3,256)"), Arguments.of(10, "(3,256,1)"), Arguments.of(11, "(3,256,0,1)"), Arguments.of(12, "(3,256,1,1)"),
49                  Arguments.of(13, "(4,256)"), Arguments.of(14, "(4,256,1)"), Arguments.of(15, "(4,256,0,1)"), Arguments.of(16, "(4,256,1,1)"),
50                  Arguments.of(17, "(5,4)"), Arguments.of(18, "(5,4,1)"), Arguments.of(19, "(5,4,2)"), Arguments.of(20, "(5,16)"), Arguments.of(21, "(5,16,1)"),
51                  Arguments.of(22, "(5,16,2)"), Arguments.of(23, "(5,32)"), Arguments.of(24, "(5,32,1)"), Arguments.of(25, "(5,32,2)"),
52                  Arguments.of(26, "(5,64)"), Arguments.of(27, "(5,64,1)"), Arguments.of(28, "(5,64,2)"), Arguments.of(29, "(5,128)"),
53                  Arguments.of(30, "(5,128,1)"), Arguments.of(31, "(5,128,2)"), Arguments.of(32, "(5,4,0,1)"), Arguments.of(33, "(5,4,1,1)"),
54                  Arguments.of(34, "(5,4,2,1)"), Arguments.of(35, "(5,16,0,1)"), Arguments.of(36, "(5,16,1,1)"), Arguments.of(37, "(5,16,2,1)"),
55                  Arguments.of(38, "(5,32,0,1)"), Arguments.of(39, "(5,32,1,1)"), Arguments.of(40, "(5,32,2,1)"), Arguments.of(41, "(5,64,0,1)"),
56                  Arguments.of(42, "(5,64,1,1)"), Arguments.of(43, "(5,64,2,1)"), Arguments.of(44, "(5,128,0,1)"), Arguments.of(45, "(5,128,1,1)"),
57                  Arguments.of(46, "(5,128,2,1)"), Arguments.of(47, "(2,192)"), Arguments.of(48, "(2,224)"), Arguments.of(49, "(2,240)"),
58                  Arguments.of(50, "(2,248)"), Arguments.of(51, "(2,252)"), Arguments.of(52, "(2,8,0,1)"), Arguments.of(53, "(2,8,1,1)"),
59                  Arguments.of(54, "(2,16,0,1)"), Arguments.of(55, "(2,16,1,1)"), Arguments.of(56, "(2,32,0,1)"), Arguments.of(57, "(2,32,1,1)"),
60                  Arguments.of(58, "(2,64,0,1)"), Arguments.of(59, "(2,64,1,1)"), Arguments.of(60, "(2,128,0,1)"), Arguments.of(61, "(2,128,1,1)"),
61                  Arguments.of(62, "(2,192,0,1)"), Arguments.of(63, "(2,192,1,1)"), Arguments.of(64, "(2,224,0,1)"), Arguments.of(65, "(2,224,1,1)"),
62                  Arguments.of(66, "(2,240,0,1)"), Arguments.of(67, "(2,240,1,1)"), Arguments.of(68, "(2,248,0,1)"), Arguments.of(69, "(2,248,1,1)"),
63                  Arguments.of(70, "(3,192)"), Arguments.of(71, "(3,224)"), Arguments.of(72, "(3,240)"), Arguments.of(73, "(3,248)"), Arguments.of(74, "(3,252)"),
64                  Arguments.of(75, "(3,8,0,1)"), Arguments.of(76, "(3,8,1,1)"), Arguments.of(77, "(3,16,0,1)"), Arguments.of(78, "(3,16,1,1)"),
65                  Arguments.of(79, "(3,32,0,1)"), Arguments.of(80, "(3,32,1,1)"), Arguments.of(81, "(3,64,0,1)"), Arguments.of(82, "(3,64,1,1)"),
66                  Arguments.of(83, "(3,128,0,1)"), Arguments.of(84, "(3,128,1,1)"), Arguments.of(85, "(3,192,0,1)"), Arguments.of(86, "(3,192,1,1)"),
67                  Arguments.of(87, "(3,224,0,1)"), Arguments.of(88, "(3,224,1,1)"), Arguments.of(89, "(3,240,0,1)"), Arguments.of(90, "(3,240,1,1)"),
68                  Arguments.of(91, "(3,248,0,1)"), Arguments.of(92, "(3,248,1,1)"), Arguments.of(93, "(4,192)"), Arguments.of(94, "(4,224)"),
69                  Arguments.of(95, "(4,240)"), Arguments.of(96, "(4,248)"), Arguments.of(97, "(4,252)"), Arguments.of(98, "(4,8,0,1)"),
70                  Arguments.of(99, "(4,8,1,1)"), Arguments.of(100, "(4,16,0,1)"), Arguments.of(101, "(4,16,1,1)"), Arguments.of(102, "(4,32,0,1)"),
71                  Arguments.of(103, "(4,32,1,1)"), Arguments.of(104, "(4,64,0,1)"), Arguments.of(105, "(4,64,1,1)"), Arguments.of(106, "(4,128,0,1)"),
72                  Arguments.of(107, "(4,128,1,1)"), Arguments.of(108, "(4,192,0,1)"), Arguments.of(109, "(4,192,1,1)"), Arguments.of(110, "(4,224,0,1)"),
73                  Arguments.of(111, "(4,224,1,1)"), Arguments.of(112, "(4,240,0,1)"), Arguments.of(113, "(4,240,1,1)"), Arguments.of(114, "(4,248,0,1)"),
74                  Arguments.of(115, "(4,248,1,1)"));
75      }
76  
77      // Test canonical codecs
78      static Stream<Arguments> canonicalGetSpecifier() {
79          return IntStream.range(1, 115).mapToObj(Arguments::of);
80      }
81  
82      static Stream<Arguments> specifier() {
83          return Stream.of(Arguments.of(new BHSDCodec(2, 125, 0, 1)), Arguments.of(new BHSDCodec(3, 125, 2, 1)), Arguments.of(new BHSDCodec(4, 125)),
84                  Arguments.of(new BHSDCodec(5, 125, 2, 0)), Arguments.of(new BHSDCodec(3, 5, 2, 1)));
85      }
86  
87      @ParameterizedTest
88      @MethodSource("arbitraryCodec")
89      void testArbitraryCodec(final String expected, final byte[] bytes) throws IOException, Pack200Exception {
90          assertEquals(expected, CodecEncoding.getCodec(116, new ByteArrayInputStream(bytes), null).toString());
91      }
92  
93      @ParameterizedTest
94      @MethodSource("canonicalEncodings")
95      void testCanonicalEncodings(final int i, final String expectedCodec) throws IOException, Pack200Exception {
96          assertEquals(expectedCodec, CodecEncoding.getCodec(i, null, null).toString());
97      }
98  
99      @ParameterizedTest
100     @MethodSource("canonicalGetSpecifier")
101     void testCanonicalGetSpecifier(final int i) throws Pack200Exception, IOException {
102         assertEquals(i, CodecEncoding.getSpecifier(CodecEncoding.getCodec(i, null, null), null)[0]);
103     }
104 
105     @Test
106     void testDefaultCodec() throws Pack200Exception, IOException {
107         final Codec defaultCodec = new BHSDCodec(2, 16, 0, 0);
108         assertEquals(defaultCodec, CodecEncoding.getCodec(0, null, defaultCodec));
109     }
110 
111     @Test
112     void testGetSpeciferForPopulationCodec() throws IOException, Pack200Exception {
113         final PopulationCodec populationCodec = new PopulationCodec(Codec.BYTE1, Codec.CHAR3, Codec.UNSIGNED5);
114         final int[] specifiers = CodecEncoding.getSpecifier(populationCodec, null);
115         assertTrue(specifiers[0] > 140);
116         assertTrue(specifiers[0] < 189);
117         final byte[] bytes = new byte[specifiers.length - 1];
118         for (int i = 0; i < bytes.length; i++) {
119             bytes[i] = (byte) specifiers[i + 1];
120         }
121         final InputStream in = new ByteArrayInputStream(bytes);
122         final PopulationCodec populationCodec2 = (PopulationCodec) CodecEncoding.getCodec(specifiers[0], in, null);
123         assertEquals(populationCodec.getFavouredCodec(), populationCodec2.getFavouredCodec());
124         assertEquals(populationCodec.getTokenCodec(), populationCodec2.getTokenCodec());
125         assertEquals(populationCodec.getUnfavouredCodec(), populationCodec2.getUnfavouredCodec());
126     }
127 
128     @Test
129     void testGetSpeciferForRunCodec() throws Pack200Exception, IOException {
130         RunCodec runCodec = new RunCodec(25, Codec.DELTA5, Codec.BYTE1);
131         int[] specifiers = CodecEncoding.getSpecifier(runCodec, null);
132         assertTrue(specifiers[0] > 116);
133         assertTrue(specifiers[0] < 141);
134         byte[] bytes = new byte[specifiers.length - 1];
135         for (int i = 0; i < bytes.length; i++) {
136             bytes[i] = (byte) specifiers[i + 1];
137         }
138         InputStream in = new ByteArrayInputStream(bytes);
139         RunCodec runCodec2 = (RunCodec) CodecEncoding.getCodec(specifiers[0], in, null);
140         assertEquals(runCodec.getK(), runCodec2.getK());
141         assertEquals(runCodec.getACodec(), runCodec2.getACodec());
142         assertEquals(runCodec.getBCodec(), runCodec2.getBCodec());
143 
144         // One codec is the same as the default
145         runCodec = new RunCodec(4096, Codec.DELTA5, Codec.BYTE1);
146         specifiers = CodecEncoding.getSpecifier(runCodec, Codec.DELTA5);
147         assertTrue(specifiers[0] > 116);
148         assertTrue(specifiers[0] < 141);
149         bytes = new byte[specifiers.length - 1];
150         for (int i = 0; i < bytes.length; i++) {
151             bytes[i] = (byte) specifiers[i + 1];
152         }
153         in = new ByteArrayInputStream(bytes);
154         runCodec2 = (RunCodec) CodecEncoding.getCodec(specifiers[0], in, Codec.DELTA5);
155         assertEquals(runCodec.getK(), runCodec2.getK());
156         assertEquals(runCodec.getACodec(), runCodec2.getACodec());
157         assertEquals(runCodec.getBCodec(), runCodec2.getBCodec());
158 
159         // Nested run codecs
160         runCodec = new RunCodec(64, Codec.SIGNED5, new RunCodec(25, Codec.UDELTA5, Codec.DELTA5));
161         specifiers = CodecEncoding.getSpecifier(runCodec, null);
162         assertTrue(specifiers[0] > 116);
163         assertTrue(specifiers[0] < 141);
164         bytes = new byte[specifiers.length - 1];
165         for (int i = 0; i < bytes.length; i++) {
166             bytes[i] = (byte) specifiers[i + 1];
167         }
168         in = new ByteArrayInputStream(bytes);
169         runCodec2 = (RunCodec) CodecEncoding.getCodec(specifiers[0], in, null);
170         assertEquals(runCodec.getK(), runCodec2.getK());
171         assertEquals(runCodec.getACodec(), runCodec2.getACodec());
172         RunCodec bCodec = (RunCodec) runCodec.getBCodec();
173         RunCodec bCodec2 = (RunCodec) runCodec2.getBCodec();
174         assertEquals(bCodec.getK(), bCodec2.getK());
175         assertEquals(bCodec.getACodec(), bCodec2.getACodec());
176         assertEquals(bCodec.getBCodec(), bCodec2.getBCodec());
177 
178         // Nested with one the same as the default
179         runCodec = new RunCodec(64, Codec.SIGNED5, new RunCodec(25, Codec.UDELTA5, Codec.DELTA5));
180         specifiers = CodecEncoding.getSpecifier(runCodec, Codec.UDELTA5);
181         assertTrue(specifiers[0] > 116);
182         assertTrue(specifiers[0] < 141);
183         bytes = new byte[specifiers.length - 1];
184         for (int i = 0; i < bytes.length; i++) {
185             bytes[i] = (byte) specifiers[i + 1];
186         }
187         in = new ByteArrayInputStream(bytes);
188         runCodec2 = (RunCodec) CodecEncoding.getCodec(specifiers[0], in, Codec.UDELTA5);
189         assertEquals(runCodec.getK(), runCodec2.getK());
190         assertEquals(runCodec.getACodec(), runCodec2.getACodec());
191         bCodec = (RunCodec) runCodec.getBCodec();
192         bCodec2 = (RunCodec) runCodec2.getBCodec();
193         assertEquals(bCodec.getK(), bCodec2.getK());
194         assertEquals(bCodec.getACodec(), bCodec2.getACodec());
195         assertEquals(bCodec.getBCodec(), bCodec2.getBCodec());
196     }
197 
198     @ParameterizedTest
199     @MethodSource("specifier")
200     void testGetSpecifier(final Codec c1) throws IOException, Pack200Exception {
201         final int[] specifiers = CodecEncoding.getSpecifier(c1, null);
202         assertEquals(3, specifiers.length);
203         assertEquals(116, specifiers[0]);
204         final byte[] bytes = { (byte) specifiers[1], (byte) specifiers[2] };
205         final InputStream in = new ByteArrayInputStream(bytes);
206         assertEquals(c1, CodecEncoding.getCodec(116, in, null));
207     }
208 
209 }