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