test/jdk/java/net/httpclient/http2/java.net.http/java/net/http/internal/hpack/HuffmanTest.java
branchhttp-client-branch
changeset 56092 fd85b2bf2b0d
parent 56091 aedd6133e7a0
child 56093 22d94c4a3641
equal deleted inserted replaced
56091:aedd6133e7a0 56092:fd85b2bf2b0d
     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 java.net.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" +
       
    49      "       (  2)  |11111111|11111111|11111110|0010         fffffe2  [28]\n" +
       
    50      "       (  3)  |11111111|11111111|11111110|0011         fffffe3  [28]\n" +
       
    51      "       (  4)  |11111111|11111111|11111110|0100         fffffe4  [28]\n" +
       
    52      "       (  5)  |11111111|11111111|11111110|0101         fffffe5  [28]\n" +
       
    53      "       (  6)  |11111111|11111111|11111110|0110         fffffe6  [28]\n" +
       
    54      "       (  7)  |11111111|11111111|11111110|0111         fffffe7  [28]\n" +
       
    55      "       (  8)  |11111111|11111111|11111110|1000         fffffe8  [28]\n" +
       
    56      "       (  9)  |11111111|11111111|11101010               ffffea  [24]\n" +
       
    57      "       ( 10)  |11111111|11111111|11111111|111100      3ffffffc  [30]\n" +
       
    58      "       ( 11)  |11111111|11111111|11111110|1001         fffffe9  [28]\n" +
       
    59      "       ( 12)  |11111111|11111111|11111110|1010         fffffea  [28]\n" +
       
    60      "       ( 13)  |11111111|11111111|11111111|111101      3ffffffd  [30]\n" +
       
    61      "       ( 14)  |11111111|11111111|11111110|1011         fffffeb  [28]\n" +
       
    62      "       ( 15)  |11111111|11111111|11111110|1100         fffffec  [28]\n" +
       
    63      "       ( 16)  |11111111|11111111|11111110|1101         fffffed  [28]\n" +
       
    64      "       ( 17)  |11111111|11111111|11111110|1110         fffffee  [28]\n" +
       
    65      "       ( 18)  |11111111|11111111|11111110|1111         fffffef  [28]\n" +
       
    66      "       ( 19)  |11111111|11111111|11111111|0000         ffffff0  [28]\n" +
       
    67      "       ( 20)  |11111111|11111111|11111111|0001         ffffff1  [28]\n" +
       
    68      "       ( 21)  |11111111|11111111|11111111|0010         ffffff2  [28]\n" +
       
    69      "       ( 22)  |11111111|11111111|11111111|111110      3ffffffe  [30]\n" +
       
    70      "       ( 23)  |11111111|11111111|11111111|0011         ffffff3  [28]\n" +
       
    71      "       ( 24)  |11111111|11111111|11111111|0100         ffffff4  [28]\n" +
       
    72      "       ( 25)  |11111111|11111111|11111111|0101         ffffff5  [28]\n" +
       
    73      "       ( 26)  |11111111|11111111|11111111|0110         ffffff6  [28]\n" +
       
    74      "       ( 27)  |11111111|11111111|11111111|0111         ffffff7  [28]\n" +
       
    75      "       ( 28)  |11111111|11111111|11111111|1000         ffffff8  [28]\n" +
       
    76      "       ( 29)  |11111111|11111111|11111111|1001         ffffff9  [28]\n" +
       
    77      "       ( 30)  |11111111|11111111|11111111|1010         ffffffa  [28]\n" +
       
    78      "       ( 31)  |11111111|11111111|11111111|1011         ffffffb  [28]\n" +
       
    79      "   ' ' ( 32)  |010100                                       14  [ 6]\n" +
       
    80      "   '!' ( 33)  |11111110|00                                 3f8  [10]\n" +
       
    81      "  '\"' ( 34)  |11111110|01                                 3f9  [10]\n" +
       
    82      "   '#' ( 35)  |11111111|1010                               ffa  [12]\n" +
       
    83      "   '$' ( 36)  |11111111|11001                             1ff9  [13]\n" +
       
    84      "   '%' ( 37)  |010101                                       15  [ 6]\n" +
       
    85      "   '&' ( 38)  |11111000                                     f8  [ 8]\n" +
       
    86      "   ''' ( 39)  |11111111|010                                7fa  [11]\n" +
       
    87      "   '(' ( 40)  |11111110|10                                 3fa  [10]\n" +
       
    88      "   ')' ( 41)  |11111110|11                                 3fb  [10]\n" +
       
    89      "   '*' ( 42)  |11111001                                     f9  [ 8]\n" +
       
    90      "   '+' ( 43)  |11111111|011                                7fb  [11]\n" +
       
    91      "   ',' ( 44)  |11111010                                     fa  [ 8]\n" +
       
    92      "   '-' ( 45)  |010110                                       16  [ 6]\n" +
       
    93      "   '.' ( 46)  |010111                                       17  [ 6]\n" +
       
    94      "   '/' ( 47)  |011000                                       18  [ 6]\n" +
       
    95      "   '0' ( 48)  |00000                                         0  [ 5]\n" +
       
    96      "   '1' ( 49)  |00001                                         1  [ 5]\n" +
       
    97      "   '2' ( 50)  |00010                                         2  [ 5]\n" +
       
    98      "   '3' ( 51)  |011001                                       19  [ 6]\n" +
       
    99      "   '4' ( 52)  |011010                                       1a  [ 6]\n" +
       
   100      "   '5' ( 53)  |011011                                       1b  [ 6]\n" +
       
   101      "   '6' ( 54)  |011100                                       1c  [ 6]\n" +
       
   102      "   '7' ( 55)  |011101                                       1d  [ 6]\n" +
       
   103      "   '8' ( 56)  |011110                                       1e  [ 6]\n" +
       
   104      "   '9' ( 57)  |011111                                       1f  [ 6]\n" +
       
   105      "   ':' ( 58)  |1011100                                      5c  [ 7]\n" +
       
   106      "   ';' ( 59)  |11111011                                     fb  [ 8]\n" +
       
   107      "   '<' ( 60)  |11111111|1111100                           7ffc  [15]\n" +
       
   108      "   '=' ( 61)  |100000                                       20  [ 6]\n" +
       
   109      "   '>' ( 62)  |11111111|1011                               ffb  [12]\n" +
       
   110      "   '?' ( 63)  |11111111|00                                 3fc  [10]\n" +
       
   111      "   '@' ( 64)  |11111111|11010                             1ffa  [13]\n" +
       
   112      "   'A' ( 65)  |100001                                       21  [ 6]\n" +
       
   113      "   'B' ( 66)  |1011101                                      5d  [ 7]\n" +
       
   114      "   'C' ( 67)  |1011110                                      5e  [ 7]\n" +
       
   115      "   'D' ( 68)  |1011111                                      5f  [ 7]\n" +
       
   116      "   'E' ( 69)  |1100000                                      60  [ 7]\n" +
       
   117      "   'F' ( 70)  |1100001                                      61  [ 7]\n" +
       
   118      "   'G' ( 71)  |1100010                                      62  [ 7]\n" +
       
   119      "   'H' ( 72)  |1100011                                      63  [ 7]\n" +
       
   120      "   'I' ( 73)  |1100100                                      64  [ 7]\n" +
       
   121      "   'J' ( 74)  |1100101                                      65  [ 7]\n" +
       
   122      "   'K' ( 75)  |1100110                                      66  [ 7]\n" +
       
   123      "   'L' ( 76)  |1100111                                      67  [ 7]\n" +
       
   124      "   'M' ( 77)  |1101000                                      68  [ 7]\n" +
       
   125      "   'N' ( 78)  |1101001                                      69  [ 7]\n" +
       
   126      "   'O' ( 79)  |1101010                                      6a  [ 7]\n" +
       
   127      "   'P' ( 80)  |1101011                                      6b  [ 7]\n" +
       
   128      "   'Q' ( 81)  |1101100                                      6c  [ 7]\n" +
       
   129      "   'R' ( 82)  |1101101                                      6d  [ 7]\n" +
       
   130      "   'S' ( 83)  |1101110                                      6e  [ 7]\n" +
       
   131      "   'T' ( 84)  |1101111                                      6f  [ 7]\n" +
       
   132      "   'U' ( 85)  |1110000                                      70  [ 7]\n" +
       
   133      "   'V' ( 86)  |1110001                                      71  [ 7]\n" +
       
   134      "   'W' ( 87)  |1110010                                      72  [ 7]\n" +
       
   135      "   'X' ( 88)  |11111100                                     fc  [ 8]\n" +
       
   136      "   'Y' ( 89)  |1110011                                      73  [ 7]\n" +
       
   137      "   'Z' ( 90)  |11111101                                     fd  [ 8]\n" +
       
   138      "   '[' ( 91)  |11111111|11011                             1ffb  [13]\n" +
       
   139      "  '\\' ( 92)  |11111111|11111110|000                     7fff0  [19]\n" +
       
   140      "   ']' ( 93)  |11111111|11100                             1ffc  [13]\n" +
       
   141      "   '^' ( 94)  |11111111|111100                            3ffc  [14]\n" +
       
   142      "   '_' ( 95)  |100010                                       22  [ 6]\n" +
       
   143      "   '`' ( 96)  |11111111|1111101                           7ffd  [15]\n" +
       
   144      "   'a' ( 97)  |00011                                         3  [ 5]\n" +
       
   145      "   'b' ( 98)  |100011                                       23  [ 6]\n" +
       
   146      "   'c' ( 99)  |00100                                         4  [ 5]\n" +
       
   147      "   'd' (100)  |100100                                       24  [ 6]\n" +
       
   148      "   'e' (101)  |00101                                         5  [ 5]\n" +
       
   149      "   'f' (102)  |100101                                       25  [ 6]\n" +
       
   150      "   'g' (103)  |100110                                       26  [ 6]\n" +
       
   151      "   'h' (104)  |100111                                       27  [ 6]\n" +
       
   152      "   'i' (105)  |00110                                         6  [ 5]\n" +
       
   153      "   'j' (106)  |1110100                                      74  [ 7]\n" +
       
   154      "   'k' (107)  |1110101                                      75  [ 7]\n" +
       
   155      "   'l' (108)  |101000                                       28  [ 6]\n" +
       
   156      "   'm' (109)  |101001                                       29  [ 6]\n" +
       
   157      "   'n' (110)  |101010                                       2a  [ 6]\n" +
       
   158      "   'o' (111)  |00111                                         7  [ 5]\n" +
       
   159      "   'p' (112)  |101011                                       2b  [ 6]\n" +
       
   160      "   'q' (113)  |1110110                                      76  [ 7]\n" +
       
   161      "   'r' (114)  |101100                                       2c  [ 6]\n" +
       
   162      "   's' (115)  |01000                                         8  [ 5]\n" +
       
   163      "   't' (116)  |01001                                         9  [ 5]\n" +
       
   164      "   'u' (117)  |101101                                       2d  [ 6]\n" +
       
   165      "   'v' (118)  |1110111                                      77  [ 7]\n" +
       
   166      "   'w' (119)  |1111000                                      78  [ 7]\n" +
       
   167      "   'x' (120)  |1111001                                      79  [ 7]\n" +
       
   168      "   'y' (121)  |1111010                                      7a  [ 7]\n" +
       
   169      "   'z' (122)  |1111011                                      7b  [ 7]\n" +
       
   170      "   '{' (123)  |11111111|1111110                           7ffe  [15]\n" +
       
   171      "   '|' (124)  |11111111|100                                7fc  [11]\n" +
       
   172      "   '}' (125)  |11111111|111101                            3ffd  [14]\n" +
       
   173      "   '~' (126)  |11111111|11101                             1ffd  [13]\n" +
       
   174      "       (127)  |11111111|11111111|11111111|1100         ffffffc  [28]\n" +
       
   175      "       (128)  |11111111|11111110|0110                    fffe6  [20]\n" +
       
   176      "       (129)  |11111111|11111111|010010                 3fffd2  [22]\n" +
       
   177      "       (130)  |11111111|11111110|0111                    fffe7  [20]\n" +
       
   178      "       (131)  |11111111|11111110|1000                    fffe8  [20]\n" +
       
   179      "       (132)  |11111111|11111111|010011                 3fffd3  [22]\n" +
       
   180      "       (133)  |11111111|11111111|010100                 3fffd4  [22]\n" +
       
   181      "       (134)  |11111111|11111111|010101                 3fffd5  [22]\n" +
       
   182      "       (135)  |11111111|11111111|1011001                7fffd9  [23]\n" +
       
   183      "       (136)  |11111111|11111111|010110                 3fffd6  [22]\n" +
       
   184      "       (137)  |11111111|11111111|1011010                7fffda  [23]\n" +
       
   185      "       (138)  |11111111|11111111|1011011                7fffdb  [23]\n" +
       
   186      "       (139)  |11111111|11111111|1011100                7fffdc  [23]\n" +
       
   187      "       (140)  |11111111|11111111|1011101                7fffdd  [23]\n" +
       
   188      "       (141)  |11111111|11111111|1011110                7fffde  [23]\n" +
       
   189      "       (142)  |11111111|11111111|11101011               ffffeb  [24]\n" +
       
   190      "       (143)  |11111111|11111111|1011111                7fffdf  [23]\n" +
       
   191      "       (144)  |11111111|11111111|11101100               ffffec  [24]\n" +
       
   192      "       (145)  |11111111|11111111|11101101               ffffed  [24]\n" +
       
   193      "       (146)  |11111111|11111111|010111                 3fffd7  [22]\n" +
       
   194      "       (147)  |11111111|11111111|1100000                7fffe0  [23]\n" +
       
   195      "       (148)  |11111111|11111111|11101110               ffffee  [24]\n" +
       
   196      "       (149)  |11111111|11111111|1100001                7fffe1  [23]\n" +
       
   197      "       (150)  |11111111|11111111|1100010                7fffe2  [23]\n" +
       
   198      "       (151)  |11111111|11111111|1100011                7fffe3  [23]\n" +
       
   199      "       (152)  |11111111|11111111|1100100                7fffe4  [23]\n" +
       
   200      "       (153)  |11111111|11111110|11100                  1fffdc  [21]\n" +
       
   201      "       (154)  |11111111|11111111|011000                 3fffd8  [22]\n" +
       
   202      "       (155)  |11111111|11111111|1100101                7fffe5  [23]\n" +
       
   203      "       (156)  |11111111|11111111|011001                 3fffd9  [22]\n" +
       
   204      "       (157)  |11111111|11111111|1100110                7fffe6  [23]\n" +
       
   205      "       (158)  |11111111|11111111|1100111                7fffe7  [23]\n" +
       
   206      "       (159)  |11111111|11111111|11101111               ffffef  [24]\n" +
       
   207      "       (160)  |11111111|11111111|011010                 3fffda  [22]\n" +
       
   208      "       (161)  |11111111|11111110|11101                  1fffdd  [21]\n" +
       
   209      "       (162)  |11111111|11111110|1001                    fffe9  [20]\n" +
       
   210      "       (163)  |11111111|11111111|011011                 3fffdb  [22]\n" +
       
   211      "       (164)  |11111111|11111111|011100                 3fffdc  [22]\n" +
       
   212      "       (165)  |11111111|11111111|1101000                7fffe8  [23]\n" +
       
   213      "       (166)  |11111111|11111111|1101001                7fffe9  [23]\n" +
       
   214      "       (167)  |11111111|11111110|11110                  1fffde  [21]\n" +
       
   215      "       (168)  |11111111|11111111|1101010                7fffea  [23]\n" +
       
   216      "       (169)  |11111111|11111111|011101                 3fffdd  [22]\n" +
       
   217      "       (170)  |11111111|11111111|011110                 3fffde  [22]\n" +
       
   218      "       (171)  |11111111|11111111|11110000               fffff0  [24]\n" +
       
   219      "       (172)  |11111111|11111110|11111                  1fffdf  [21]\n" +
       
   220      "       (173)  |11111111|11111111|011111                 3fffdf  [22]\n" +
       
   221      "       (174)  |11111111|11111111|1101011                7fffeb  [23]\n" +
       
   222      "       (175)  |11111111|11111111|1101100                7fffec  [23]\n" +
       
   223      "       (176)  |11111111|11111111|00000                  1fffe0  [21]\n" +
       
   224      "       (177)  |11111111|11111111|00001                  1fffe1  [21]\n" +
       
   225      "       (178)  |11111111|11111111|100000                 3fffe0  [22]\n" +
       
   226      "       (179)  |11111111|11111111|00010                  1fffe2  [21]\n" +
       
   227      "       (180)  |11111111|11111111|1101101                7fffed  [23]\n" +
       
   228      "       (181)  |11111111|11111111|100001                 3fffe1  [22]\n" +
       
   229      "       (182)  |11111111|11111111|1101110                7fffee  [23]\n" +
       
   230      "       (183)  |11111111|11111111|1101111                7fffef  [23]\n" +
       
   231      "       (184)  |11111111|11111110|1010                    fffea  [20]\n" +
       
   232      "       (185)  |11111111|11111111|100010                 3fffe2  [22]\n" +
       
   233      "       (186)  |11111111|11111111|100011                 3fffe3  [22]\n" +
       
   234      "       (187)  |11111111|11111111|100100                 3fffe4  [22]\n" +
       
   235      "       (188)  |11111111|11111111|1110000                7ffff0  [23]\n" +
       
   236      "       (189)  |11111111|11111111|100101                 3fffe5  [22]\n" +
       
   237      "       (190)  |11111111|11111111|100110                 3fffe6  [22]\n" +
       
   238      "       (191)  |11111111|11111111|1110001                7ffff1  [23]\n" +
       
   239      "       (192)  |11111111|11111111|11111000|00           3ffffe0  [26]\n" +
       
   240      "       (193)  |11111111|11111111|11111000|01           3ffffe1  [26]\n" +
       
   241      "       (194)  |11111111|11111110|1011                    fffeb  [20]\n" +
       
   242      "       (195)  |11111111|11111110|001                     7fff1  [19]\n" +
       
   243      "       (196)  |11111111|11111111|100111                 3fffe7  [22]\n" +
       
   244      "       (197)  |11111111|11111111|1110010                7ffff2  [23]\n" +
       
   245      "       (198)  |11111111|11111111|101000                 3fffe8  [22]\n" +
       
   246      "       (199)  |11111111|11111111|11110110|0            1ffffec  [25]\n" +
       
   247      "       (200)  |11111111|11111111|11111000|10           3ffffe2  [26]\n" +
       
   248      "       (201)  |11111111|11111111|11111000|11           3ffffe3  [26]\n" +
       
   249      "       (202)  |11111111|11111111|11111001|00           3ffffe4  [26]\n" +
       
   250      "       (203)  |11111111|11111111|11111011|110          7ffffde  [27]\n" +
       
   251      "       (204)  |11111111|11111111|11111011|111          7ffffdf  [27]\n" +
       
   252      "       (205)  |11111111|11111111|11111001|01           3ffffe5  [26]\n" +
       
   253      "       (206)  |11111111|11111111|11110001               fffff1  [24]\n" +
       
   254      "       (207)  |11111111|11111111|11110110|1            1ffffed  [25]\n" +
       
   255      "       (208)  |11111111|11111110|010                     7fff2  [19]\n" +
       
   256      "       (209)  |11111111|11111111|00011                  1fffe3  [21]\n" +
       
   257      "       (210)  |11111111|11111111|11111001|10           3ffffe6  [26]\n" +
       
   258      "       (211)  |11111111|11111111|11111100|000          7ffffe0  [27]\n" +
       
   259      "       (212)  |11111111|11111111|11111100|001          7ffffe1  [27]\n" +
       
   260      "       (213)  |11111111|11111111|11111001|11           3ffffe7  [26]\n" +
       
   261      "       (214)  |11111111|11111111|11111100|010          7ffffe2  [27]\n" +
       
   262      "       (215)  |11111111|11111111|11110010               fffff2  [24]\n" +
       
   263      "       (216)  |11111111|11111111|00100                  1fffe4  [21]\n" +
       
   264      "       (217)  |11111111|11111111|00101                  1fffe5  [21]\n" +
       
   265      "       (218)  |11111111|11111111|11111010|00           3ffffe8  [26]\n" +
       
   266      "       (219)  |11111111|11111111|11111010|01           3ffffe9  [26]\n" +
       
   267      "       (220)  |11111111|11111111|11111111|1101         ffffffd  [28]\n" +
       
   268      "       (221)  |11111111|11111111|11111100|011          7ffffe3  [27]\n" +
       
   269      "       (222)  |11111111|11111111|11111100|100          7ffffe4  [27]\n" +
       
   270      "       (223)  |11111111|11111111|11111100|101          7ffffe5  [27]\n" +
       
   271      "       (224)  |11111111|11111110|1100                    fffec  [20]\n" +
       
   272      "       (225)  |11111111|11111111|11110011               fffff3  [24]\n" +
       
   273      "       (226)  |11111111|11111110|1101                    fffed  [20]\n" +
       
   274      "       (227)  |11111111|11111111|00110                  1fffe6  [21]\n" +
       
   275      "       (228)  |11111111|11111111|101001                 3fffe9  [22]\n" +
       
   276      "       (229)  |11111111|11111111|00111                  1fffe7  [21]\n" +
       
   277      "       (230)  |11111111|11111111|01000                  1fffe8  [21]\n" +
       
   278      "       (231)  |11111111|11111111|1110011                7ffff3  [23]\n" +
       
   279      "       (232)  |11111111|11111111|101010                 3fffea  [22]\n" +
       
   280      "       (233)  |11111111|11111111|101011                 3fffeb  [22]\n" +
       
   281      "       (234)  |11111111|11111111|11110111|0            1ffffee  [25]\n" +
       
   282      "       (235)  |11111111|11111111|11110111|1            1ffffef  [25]\n" +
       
   283      "       (236)  |11111111|11111111|11110100               fffff4  [24]\n" +
       
   284      "       (237)  |11111111|11111111|11110101               fffff5  [24]\n" +
       
   285      "       (238)  |11111111|11111111|11111010|10           3ffffea  [26]\n" +
       
   286      "       (239)  |11111111|11111111|1110100                7ffff4  [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,
       
   328                     parseInt(hex, 16), parseInt(len));
       
   329 
       
   330             StringBuilder actual = new StringBuilder();
       
   331             Huffman.Reader t = new Huffman.Reader();
       
   332             t.read(ByteBuffer.wrap(bytes), actual, false, true);
       
   333 
       
   334             // What has been read MUST represent a single symbol
       
   335             assertEquals(actual.length(), 1, "ascii: " + ascii);
       
   336 
       
   337             // It's a lot more visual to compare char as codes rather than
       
   338             // characters (as some of them might not be visible)
       
   339             assertEquals(actual.charAt(0), expected);
       
   340             i++;
       
   341         }
       
   342         assertEquals(i, 257); // 256 + EOS
       
   343     }
       
   344 
       
   345     //
       
   346     // https://tools.ietf.org/html/rfc7541#appendix-C.4.1
       
   347     //
       
   348     @Test
       
   349     public void read_1() {
       
   350         read("f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com");
       
   351     }
       
   352 
       
   353     @Test
       
   354     public void write_1() {
       
   355         write("www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff");
       
   356     }
       
   357 
       
   358     //
       
   359     // https://tools.ietf.org/html/rfc7541#appendix-C.4.2
       
   360     //
       
   361     @Test
       
   362     public void read_2() {
       
   363         read("a8eb 1064 9cbf", "no-cache");
       
   364     }
       
   365 
       
   366     @Test
       
   367     public void write_2() {
       
   368         write("no-cache", "a8eb 1064 9cbf");
       
   369     }
       
   370 
       
   371     //
       
   372     // https://tools.ietf.org/html/rfc7541#appendix-C.4.3
       
   373     //
       
   374     @Test
       
   375     public void read_3() {
       
   376         read("25a8 49e9 5ba9 7d7f", "custom-key");
       
   377     }
       
   378 
       
   379     @Test
       
   380     public void write_3() {
       
   381         write("custom-key", "25a8 49e9 5ba9 7d7f");
       
   382     }
       
   383 
       
   384     //
       
   385     // https://tools.ietf.org/html/rfc7541#appendix-C.4.3
       
   386     //
       
   387     @Test
       
   388     public void read_4() {
       
   389         read("25a8 49e9 5bb8 e8b4 bf", "custom-value");
       
   390     }
       
   391 
       
   392     @Test
       
   393     public void write_4() {
       
   394         write("custom-value", "25a8 49e9 5bb8 e8b4 bf");
       
   395     }
       
   396 
       
   397     //
       
   398     // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
       
   399     //
       
   400     @Test
       
   401     public void read_5() {
       
   402         read("6402", "302");
       
   403     }
       
   404 
       
   405     @Test
       
   406     public void write_5() {
       
   407         write("302", "6402");
       
   408     }
       
   409 
       
   410     //
       
   411     // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
       
   412     //
       
   413     @Test
       
   414     public void read_6() {
       
   415         read("aec3 771a 4b", "private");
       
   416     }
       
   417 
       
   418     @Test
       
   419     public void write_6() {
       
   420         write("private", "aec3 771a 4b");
       
   421     }
       
   422 
       
   423     //
       
   424     // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
       
   425     //
       
   426     @Test
       
   427     public void read_7() {
       
   428         read("d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff",
       
   429                 "Mon, 21 Oct 2013 20:13:21 GMT");
       
   430     }
       
   431 
       
   432     @Test
       
   433     public void write_7() {
       
   434         write("Mon, 21 Oct 2013 20:13:21 GMT",
       
   435                 "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff");
       
   436     }
       
   437 
       
   438     //
       
   439     // https://tools.ietf.org/html/rfc7541#appendix-C.6.1
       
   440     //
       
   441     @Test
       
   442     public void read_8() {
       
   443         read("9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3",
       
   444                 "https://www.example.com");
       
   445     }
       
   446 
       
   447     @Test
       
   448     public void write_8() {
       
   449         write("https://www.example.com",
       
   450                 "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3");
       
   451     }
       
   452 
       
   453     //
       
   454     // https://tools.ietf.org/html/rfc7541#appendix-C.6.2
       
   455     //
       
   456     @Test
       
   457     public void read_9() {
       
   458         read("640e ff", "307");
       
   459     }
       
   460 
       
   461     @Test
       
   462     public void write_9() {
       
   463         write("307", "640e ff");
       
   464     }
       
   465 
       
   466     //
       
   467     // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
       
   468     //
       
   469     @Test
       
   470     public void read_10() {
       
   471         read("d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff",
       
   472                 "Mon, 21 Oct 2013 20:13:22 GMT");
       
   473     }
       
   474 
       
   475     @Test
       
   476     public void write_10() {
       
   477         write("Mon, 21 Oct 2013 20:13:22 GMT",
       
   478                 "d07a be94 1054 d444 a820 0595 040b 8166 e084 a62d 1bff");
       
   479     }
       
   480 
       
   481     //
       
   482     // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
       
   483     //
       
   484     @Test
       
   485     public void read_11() {
       
   486         read("9bd9 ab", "gzip");
       
   487     }
       
   488 
       
   489     @Test
       
   490     public void write_11() {
       
   491         write("gzip", "9bd9 ab");
       
   492     }
       
   493 
       
   494     //
       
   495     // https://tools.ietf.org/html/rfc7541#appendix-C.6.3
       
   496     //
       
   497     @Test
       
   498     public void read_12() {
       
   499         read("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 " +
       
   500              "d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 " +
       
   501              "3160 65c0 03ed 4ee5 b106 3d50 07",
       
   502              "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1");
       
   503     }
       
   504 
       
   505     @Test
       
   506     public void test_trie_has_no_empty_nodes() {
       
   507         Huffman.Node root = Huffman.INSTANCE.getRoot();
       
   508         Stack<Huffman.Node> backlog = new Stack<>();
       
   509         backlog.push(root);
       
   510         while (!backlog.isEmpty()) {
       
   511             Huffman.Node n = backlog.pop();
       
   512             // The only type of nodes we couldn't possibly catch during
       
   513             // construction is an empty node: no children and no char
       
   514             if (n.left != null) {
       
   515                 backlog.push(n.left);
       
   516             }
       
   517             if (n.right != null) {
       
   518                 backlog.push(n.right);
       
   519             }
       
   520             assertFalse(!n.charIsSet && n.left == null && n.right == null,
       
   521                     "Empty node in the trie");
       
   522         }
       
   523     }
       
   524 
       
   525     @Test
       
   526     public void test_trie_has_257_nodes() {
       
   527         int count = 0;
       
   528         Huffman.Node root = Huffman.INSTANCE.getRoot();
       
   529         Stack<Huffman.Node> backlog = new Stack<>();
       
   530         backlog.push(root);
       
   531         while (!backlog.isEmpty()) {
       
   532             Huffman.Node n = backlog.pop();
       
   533             if (n.left != null) {
       
   534                 backlog.push(n.left);
       
   535             }
       
   536             if (n.right != null) {
       
   537                 backlog.push(n.right);
       
   538             }
       
   539             if (n.isLeaf()) {
       
   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();
       
   585         });
       
   586     }
       
   587 
       
   588     //
       
   589     // It's not very pretty, yes I know that
       
   590     //
       
   591     //      hex:
       
   592     //
       
   593     //      |31|30|...|N-1|...|01|00|
       
   594     //                  \        /
       
   595     //                  codeLength
       
   596     //
       
   597     //      hex <<= 32 - codeLength; (align to MSB):
       
   598     //
       
   599     //      |31|30|...|32-N|...|01|00|
       
   600     //        \        /
       
   601     //        codeLength
       
   602     //
       
   603     //      EOS:
       
   604     //
       
   605     //      |31|30|...|M-1|...|01|00|
       
   606     //                   \        /
       
   607     //                   eosLength
       
   608     //
       
   609     //      eos <<= 32 - eosLength; (align to MSB):
       
   610     //
       
   611     //      pad with MSBs of EOS:
       
   612     //
       
   613     //      |31|30|...|32-N|32-N-1|...|01|00|
       
   614     //                     |    32|...|
       
   615     //
       
   616     //      Finally, split into byte[]
       
   617     //
       
   618     private byte[] intToBytes(int eos, int eosLength, int hex, int codeLength) {
       
   619         hex <<= 32 - codeLength;
       
   620         eos >>= codeLength - (32 - eosLength);
       
   621         hex |= eos;
       
   622         int n = (int) Math.ceil(codeLength / 8.0);
       
   623         byte[] result = new byte[n];
       
   624         for (int i = 0; i < n; i++) {
       
   625             result[i] = (byte) (hex >> (32 - 8 * (i + 1)));
       
   626         }
       
   627         return result;
       
   628     }
       
   629 }