1 /*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package jdk.incubator.http.internal.hpack;
24
25 import org.testng.annotations.Test;
26
27 import java.nio.ByteBuffer;
28 import java.util.Stack;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31
32 import static java.lang.Integer.parseInt;
33 import static org.testng.Assert.*;
34
35 public final class HuffmanTest {
36
37 //
38 // https://tools.ietf.org/html/rfc7541#appendix-B
39 //
40 private static final String SPEC =
41 // @formatter:off
42 " code as bits as hex len\n" +
43 " sym aligned to MSB aligned in\n" +
44 " to LSB bits\n" +
45 " ( 0) |11111111|11000 1ff8 [13]\n" +
46 " ( 1) |11111111|11111111|1011000 7fffd8 [23]\n" +
285 " (240) |11111111|11111111|11111010|11 3ffffeb [26]\n" +
286 " (241) |11111111|11111111|11111100|110 7ffffe6 [27]\n" +
287 " (242) |11111111|11111111|11111011|00 3ffffec [26]\n" +
288 " (243) |11111111|11111111|11111011|01 3ffffed [26]\n" +
289 " (244) |11111111|11111111|11111100|111 7ffffe7 [27]\n" +
290 " (245) |11111111|11111111|11111101|000 7ffffe8 [27]\n" +
291 " (246) |11111111|11111111|11111101|001 7ffffe9 [27]\n" +
292 " (247) |11111111|11111111|11111101|010 7ffffea [27]\n" +
293 " (248) |11111111|11111111|11111101|011 7ffffeb [27]\n" +
294 " (249) |11111111|11111111|11111111|1110 ffffffe [28]\n" +
295 " (250) |11111111|11111111|11111101|100 7ffffec [27]\n" +
296 " (251) |11111111|11111111|11111101|101 7ffffed [27]\n" +
297 " (252) |11111111|11111111|11111101|110 7ffffee [27]\n" +
298 " (253) |11111111|11111111|11111101|111 7ffffef [27]\n" +
299 " (254) |11111111|11111111|11111110|000 7fffff0 [27]\n" +
300 " (255) |11111111|11111111|11111011|10 3ffffee [26]\n" +
301 " EOS (256) |11111111|11111111|11111111|111111 3fffffff [30]";
302 // @formatter:on
303
304 @Test
305 public void read_table() {
306 Pattern line = Pattern.compile(
307 "\\(\\s*(?<ascii>\\d+)\\s*\\)\\s*(?<binary>(\\|(0|1)+)+)\\s*" +
308 "(?<hex>[0-9a-zA-Z]+)\\s*\\[\\s*(?<len>\\d+)\\s*\\]");
309 Matcher m = line.matcher(SPEC);
310 int i = 0;
311 while (m.find()) {
312 String ascii = m.group("ascii");
313 String binary = m.group("binary").replaceAll("\\|", "");
314 String hex = m.group("hex");
315 String len = m.group("len");
316
317 // Several sanity checks for the data read from the table, just to
318 // make sure what we read makes sense
319 assertEquals(parseInt(len), binary.length());
320 assertEquals(parseInt(binary, 2), parseInt(hex, 16));
321
322 int expected = parseInt(ascii);
323
324 // TODO: find actual eos, do not hardcode it!
325 byte[] bytes = intToBytes(0x3fffffff, 30,
538 count++;
539 }
540 }
541 assertEquals(count, 257);
542 }
543
544 @Test
545 public void cant_encode_outside_byte() {
546 TestHelper.Block<Object> coding =
547 () -> new Huffman.Writer()
548 .from(((char) 256) + "", 0, 1)
549 .write(ByteBuffer.allocate(1));
550 RuntimeException e =
551 TestHelper.assertVoidThrows(RuntimeException.class, coding);
552 TestHelper.assertExceptionMessageContains(e, "char");
553 }
554
555 private static void read(String hexdump, String decoded) {
556 ByteBuffer source = SpecHelper.toBytes(hexdump);
557 Appendable actual = new StringBuilder();
558 new Huffman.Reader().read(source, actual, true);
559 assertEquals(actual.toString(), decoded);
560 }
561
562 private static void write(String decoded, String hexdump) {
563 int n = Huffman.INSTANCE.lengthOf(decoded);
564 ByteBuffer destination = ByteBuffer.allocate(n); // Extra margin (1) to test having more bytes in the destination than needed is ok
565 Huffman.Writer writer = new Huffman.Writer();
566 BuffersTestingKit.forEachSplit(destination, byteBuffers -> {
567 writer.from(decoded, 0, decoded.length());
568 boolean written = false;
569 for (ByteBuffer b : byteBuffers) {
570 int pos = b.position();
571 written = writer.write(b);
572 b.position(pos);
573 }
574 assertTrue(written);
575 ByteBuffer concated = BuffersTestingKit.concat(byteBuffers);
576 String actual = SpecHelper.toHexdump(concated);
577 assertEquals(actual, hexdump);
578 writer.reset();
|
1 /*
2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package jdk.incubator.http.internal.hpack;
24
25 import org.testng.annotations.Test;
26
27 import java.io.IOException;
28 import java.io.UncheckedIOException;
29 import java.nio.ByteBuffer;
30 import java.util.Stack;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34 import static java.lang.Integer.parseInt;
35 import static org.testng.Assert.*;
36
37 public final class HuffmanTest {
38
39 //
40 // https://tools.ietf.org/html/rfc7541#appendix-B
41 //
42 private static final String SPEC =
43 // @formatter:off
44 " code as bits as hex len\n" +
45 " sym aligned to MSB aligned in\n" +
46 " to LSB bits\n" +
47 " ( 0) |11111111|11000 1ff8 [13]\n" +
48 " ( 1) |11111111|11111111|1011000 7fffd8 [23]\n" +
287 " (240) |11111111|11111111|11111010|11 3ffffeb [26]\n" +
288 " (241) |11111111|11111111|11111100|110 7ffffe6 [27]\n" +
289 " (242) |11111111|11111111|11111011|00 3ffffec [26]\n" +
290 " (243) |11111111|11111111|11111011|01 3ffffed [26]\n" +
291 " (244) |11111111|11111111|11111100|111 7ffffe7 [27]\n" +
292 " (245) |11111111|11111111|11111101|000 7ffffe8 [27]\n" +
293 " (246) |11111111|11111111|11111101|001 7ffffe9 [27]\n" +
294 " (247) |11111111|11111111|11111101|010 7ffffea [27]\n" +
295 " (248) |11111111|11111111|11111101|011 7ffffeb [27]\n" +
296 " (249) |11111111|11111111|11111111|1110 ffffffe [28]\n" +
297 " (250) |11111111|11111111|11111101|100 7ffffec [27]\n" +
298 " (251) |11111111|11111111|11111101|101 7ffffed [27]\n" +
299 " (252) |11111111|11111111|11111101|110 7ffffee [27]\n" +
300 " (253) |11111111|11111111|11111101|111 7ffffef [27]\n" +
301 " (254) |11111111|11111111|11111110|000 7fffff0 [27]\n" +
302 " (255) |11111111|11111111|11111011|10 3ffffee [26]\n" +
303 " EOS (256) |11111111|11111111|11111111|111111 3fffffff [30]";
304 // @formatter:on
305
306 @Test
307 public void read_table() throws IOException {
308 Pattern line = Pattern.compile(
309 "\\(\\s*(?<ascii>\\d+)\\s*\\)\\s*(?<binary>(\\|(0|1)+)+)\\s*" +
310 "(?<hex>[0-9a-zA-Z]+)\\s*\\[\\s*(?<len>\\d+)\\s*\\]");
311 Matcher m = line.matcher(SPEC);
312 int i = 0;
313 while (m.find()) {
314 String ascii = m.group("ascii");
315 String binary = m.group("binary").replaceAll("\\|", "");
316 String hex = m.group("hex");
317 String len = m.group("len");
318
319 // Several sanity checks for the data read from the table, just to
320 // make sure what we read makes sense
321 assertEquals(parseInt(len), binary.length());
322 assertEquals(parseInt(binary, 2), parseInt(hex, 16));
323
324 int expected = parseInt(ascii);
325
326 // TODO: find actual eos, do not hardcode it!
327 byte[] bytes = intToBytes(0x3fffffff, 30,
540 count++;
541 }
542 }
543 assertEquals(count, 257);
544 }
545
546 @Test
547 public void cant_encode_outside_byte() {
548 TestHelper.Block<Object> coding =
549 () -> new Huffman.Writer()
550 .from(((char) 256) + "", 0, 1)
551 .write(ByteBuffer.allocate(1));
552 RuntimeException e =
553 TestHelper.assertVoidThrows(RuntimeException.class, coding);
554 TestHelper.assertExceptionMessageContains(e, "char");
555 }
556
557 private static void read(String hexdump, String decoded) {
558 ByteBuffer source = SpecHelper.toBytes(hexdump);
559 Appendable actual = new StringBuilder();
560 try {
561 new Huffman.Reader().read(source, actual, true);
562 } catch (IOException e) {
563 throw new UncheckedIOException(e);
564 }
565 assertEquals(actual.toString(), decoded);
566 }
567
568 private static void write(String decoded, String hexdump) {
569 int n = Huffman.INSTANCE.lengthOf(decoded);
570 ByteBuffer destination = ByteBuffer.allocate(n); // Extra margin (1) to test having more bytes in the destination than needed is ok
571 Huffman.Writer writer = new Huffman.Writer();
572 BuffersTestingKit.forEachSplit(destination, byteBuffers -> {
573 writer.from(decoded, 0, decoded.length());
574 boolean written = false;
575 for (ByteBuffer b : byteBuffers) {
576 int pos = b.position();
577 written = writer.write(b);
578 b.position(pos);
579 }
580 assertTrue(written);
581 ByteBuffer concated = BuffersTestingKit.concat(byteBuffers);
582 String actual = SpecHelper.toHexdump(concated);
583 assertEquals(actual, hexdump);
584 writer.reset();
|