% HTTP/2 Campaign
# Frames expressed as binary str were generated using the solicit and hpack-rs
# Rust crates (https://github.com/mlalic/solicit, https://github.com/mlalic/hpack-rs)
# except Continuation Frames, Priority Frames and Push Promise Frames that we generated
# using Go x/net/http2 and x/net/http2/hpack modules.

+ Syntax check
= Configuring Scapy
~ http2 frame hpack build dissect data headers priority settings rststream pushpromise ping goaway winupdate continuation hpackhdrtable helpers

import scapy.config
scapy.config.conf.debug_dissector=True
import scapy.packet
import scapy.fields
import scapy.contrib.http2 as h2
import re
flags_bit_pattern = re.compile(r'''^\s+flags\s+=\s+\[.*['"]bit [0-9]+['"].*\]$''', re.M)
def expect_exception(e, c):
    try:
        eval(c)
        return False
    except e:
        return True

+ HTTP/2 UVarIntField Test Suite

= HTTP/2 UVarIntField.any2i
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 5)
expect_exception(AssertionError, 'f.any2i(None, None)')
assert f.any2i(None, 0) == 0
assert f.any2i(None, 3) == 3
assert f.any2i(None, 1<<5) == 1<<5
assert f.any2i(None, 1<<16) == 1<<16
f = h2.UVarIntField('value', 0, 8)
assert f.any2i(None, b'\x1E') == 30

= HTTP/2 UVarIntField.m2i on full byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 8)
assert f.m2i(None, b'\x00') == 0
assert f.m2i(None, b'\x03') == 3
assert f.m2i(None, b'\xFE') == 254
assert f.m2i(None, b'\xFF\x00') == 255
assert f.m2i(None, b'\xFF\xFF\x03') == 766 #0xFF + (0xFF ^ 0x80) + (3<<7

= HTTP/2 UVarIntField.m2i on partial byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 5)
assert f.m2i(None, (b'\x00', 3)) == 0
assert f.m2i(None, (b'\x03', 3)) == 3
assert f.m2i(None, (b'\x1e', 3)) == 30
assert f.m2i(None, (b'\x1f\x00', 3)) == 31
assert f.m2i(None, (b'\x1f\xe1\xff\x03', 3)) == 65536

= HTTP/2 UVarIntField.getfield on full byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 8)

r = f.getfield(None, b'\x00\x00')
assert r[0] == b'\x00'
assert r[1] == 0

r = f.getfield(None, b'\x03\x00')
assert r[0] == b'\x00'
assert r[1] == 3

r = f.getfield(None, b'\xFE\x00')
assert r[0] == b'\x00'
assert r[1] == 254

r = f.getfield(None, b'\xFF\x00\x00')
assert r[0] == b'\x00'
assert r[1] == 255

r = f.getfield(None, b'\xFF\xFF\x03\x00')
assert r[0] == b'\x00'
assert r[1] == 766

= HTTP/2 UVarIntField.getfield on partial byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 5)

r = f.getfield(None, (b'\x00\x00', 3))
assert r[0] == b'\x00'
assert r[1] == 0

r = f.getfield(None, (b'\x03\x00', 3))
assert r[0] == b'\x00'
assert r[1] == 3

r = f.getfield(None, (b'\x1e\x00', 3))
assert r[0] == b'\x00'
assert r[1] == 30

r = f.getfield(None, (b'\x1f\x00\x00', 3))
assert r[0] == b'\x00'
assert r[1] == 31

r = f.getfield(None, (b'\x1f\xe1\xff\x03\x00', 3))
assert r[0] == b'\x00'
assert r[1] == 65536

= HTTP/2 UVarIntField.i2m on full byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 8)
assert f.i2m(None, 0) == b'\x00'
assert f.i2m(None, 3) == b'\x03'
assert f.i2m(None, 254).lower() == b'\xfe'
assert f.i2m(None, 255).lower() == b'\xff\x00'
assert f.i2m(None, 766).lower() == b'\xff\xff\x03'

= HTTP/2 UVarIntField.i2m on partial byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 5)
assert f.i2m(None, 0) == b'\x00'
assert f.i2m(None, 3) == b'\x03'
assert f.i2m(None, 30).lower() == b'\x1e'
assert f.i2m(None, 31).lower() == b'\x1f\x00'
assert f.i2m(None, 65536).lower() == b'\x1f\xe1\xff\x03'

= HTTP/2 UVarIntField.addfield on full byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 8)

assert f.addfield(None, b'Toto', 0) == b'Toto\x00'
assert f.addfield(None, b'Toto', 3) == b'Toto\x03'
assert f.addfield(None, b'Toto', 254).lower() == b'toto\xfe'
assert f.addfield(None, b'Toto', 255).lower() == b'toto\xff\x00'
assert f.addfield(None, b'Toto', 766).lower() == b'toto\xff\xff\x03'

= HTTP/2 UVarIntField.addfield on partial byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 5)

assert f.addfield(None, (b'Toto', 3, 4), 0) == b'Toto\x80'
assert f.addfield(None, (b'Toto', 3, 4), 3) == b'Toto\x83'
assert f.addfield(None, (b'Toto', 3, 4), 30).lower() == b'toto\x9e'
assert f.addfield(None, (b'Toto', 3, 4), 31).lower() == b'toto\x9f\x00'
assert f.addfield(None, (b'Toto', 3, 4), 65536).lower() == b'toto\x9f\xe1\xff\x03'

= HTTP/2 UVarIntField.i2len on full byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 8)

assert f.i2len(None, 0) == 1
assert f.i2len(None, 3) == 1
assert f.i2len(None, 254) == 1
assert f.i2len(None, 255) == 2
assert f.i2len(None, 766) == 3

= HTTP/2 UVarIntField.i2len on partial byte
~ http2 frame field uvarintfield

f = h2.UVarIntField('value', 0, 5)

assert f.i2len(None, 0) == 1
assert f.i2len(None, 3) == 1
assert f.i2len(None, 30) == 1
assert f.i2len(None, 31) == 2
assert f.i2len(None, 65536) == 4

+ HTTP/2 FieldUVarLenField Test Suite

= HTTP/2 FieldUVarLenField.i2m without adjustment
~ http2 frame field fielduvarlenfield


f = h2.FieldUVarLenField('len', None, 8, length_of='data')
class TrivialPacket(Packet):
    name = 'Trivial Packet'
    fields_desc= [
        f,
        StrField('data', '')
    ]

assert f.i2m(TrivialPacket(data='a'*5), None) == b'\x05'
assert f.i2m(TrivialPacket(data='a'*255), None).lower() == b'\xff\x00'
assert f.i2m(TrivialPacket(data='a'), 2) == b'\x02'
assert f.i2m(None, 2) == b'\x02'
assert f.i2m(None, 0) == b'\x00'

= HTTP/2 FieldUVarLenField.i2m with adjustment
~ http2 frame field fielduvarlenfield

class TrivialPacket(Packet):
    name = 'Trivial Packet'
    fields_desc= [
        f,
        StrField('data', '')
    ]

f = h2.FieldUVarLenField('value', None, 8, length_of='data', adjust=lambda x: x-1)
assert f.i2m(TrivialPacket(data='a'*5), None) == b'\x04'
assert f.i2m(TrivialPacket(data='a'*255), None).lower() == b'\xfe'
#Adjustment does not affect non-None value!
assert f.i2m(TrivialPacket(data='a'*3), 2) == b'\x02'

+ HTTP/2 HPackZString Test Suite

= HTTP/2 HPackZString Compression
~ http2 hpack huffman

string = 'Test'
s = h2.HPackZString(string)
assert len(s) == 3
assert raw(s) == b"\xdeT'"
assert s.origin() == string

string = 'a'*65535
s = h2.HPackZString(string)
assert len(s) == 40960
assert raw(s) == (b'\x18\xc61\x8cc' * 8191) + b'\x18\xc61\x8c\x7f'
assert s.origin() == string

= HTTP/2 HPackZString Decompression
~ http2 hpack huffman

s = b"\xdeT'"
i, ibl = h2.HPackZString.huffman_conv2bitstring(s)
assert b'Test' == h2.HPackZString.huffman_decode(i, ibl)

s = (b'\x18\xc61\x8cc' * 8191) + b'\x18\xc61\x8c\x7f'
i, ibl = h2.HPackZString.huffman_conv2bitstring(s)
assert b'a'*65535 == h2.HPackZString.huffman_decode(i, ibl)

assert(
    expect_exception(h2.InvalidEncodingException,
    'h2.HPackZString.huffman_decode(*h2.HPackZString.huffman_conv2bitstring(b"\\xdeT"))')
)

+ HTTP/2 HPackStrLenField Test Suite

= HTTP/2 HPackStrLenField.m2i
~ http2 hpack field hpackstrlenfield

f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
class TrivialPacket(Packet):
    name = 'Trivial Packet'
    fields_desc = [
        IntField('type', None),
        IntField('len', None),
        f
    ]

s = f.m2i(TrivialPacket(type=0, len=4), b'Test')
assert isinstance(s, h2.HPackLiteralString)
assert s.origin() == 'Test'

s = f.m2i(TrivialPacket(type=1, len=3), b"\xdeT'")
assert isinstance(s, h2.HPackZString)
assert s.origin() == 'Test'

= HTTP/2 HPackStrLenField.any2i
~ http2 hpack field hpackstrlenfield

f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
class TrivialPacket(Packet):
    name = 'Trivial Packet'
    fields_desc = [
        IntField('type', None),
        IntField('len', None),
        f
    ]

s = f.any2i(TrivialPacket(type=0, len=4), b'Test')
assert isinstance(s, h2.HPackLiteralString)
assert s.origin() == 'Test'

s = f.any2i(TrivialPacket(type=1, len=3), b"\xdeT'")
assert isinstance(s, h2.HPackZString)
assert s.origin() == 'Test'

s = h2.HPackLiteralString('Test')
s2 = f.any2i(TrivialPacket(type=0, len=4), s)
assert s.origin() == s2.origin()

s = h2.HPackZString('Test')
s2 = f.any2i(TrivialPacket(type=1, len=3), s)
assert s.origin() == s2.origin()

s = h2.HPackLiteralString('Test')
s2 = f.any2i(None, s)
assert s.origin() == s2.origin()

s = h2.HPackZString('Test')
s2 = f.any2i(None, s)
assert s.origin() == s2.origin()

# Verifies that one can fuzz
s = h2.HPackLiteralString('Test')
s2 = f.any2i(TrivialPacket(type=1, len=1), s)
assert s.origin() == s2.origin()

= HTTP/2 HPackStrLenField.i2m
~ http2 hpack field hpackstrlenfield

f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')

s = b'Test'
s2 = f.i2m(None, h2.HPackLiteralString(s))
assert s == s2

s = b'Test'
s2 = f.i2m(None, h2.HPackZString(s))
assert s2 == b"\xdeT'"

= HTTP/2 HPackStrLenField.addfield
~ http2 hpack field hpackstrlenfield

f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')

s = b'Test'
s2 = f.addfield(None, b'Toto', h2.HPackLiteralString(s))
assert b'Toto' + s == s2

s = b'Test'
s2 = f.addfield(None, b'Toto', h2.HPackZString(s))
assert s2 == b"Toto\xdeT'"

= HTTP/2 HPackStrLenField.getfield
~ http2 hpack field hpackstrlenfield

f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')
class TrivialPacket(Packet):
    name = 'Trivial Packet'
    fields_desc = [
        IntField('type', None),
        IntField('len', None),
        f
    ]

r = f.getfield(TrivialPacket(type=0, len=4), b'TestToto')
assert isinstance(r, tuple)
assert r[0] == b'Toto'
assert isinstance(r[1], h2.HPackLiteralString)
assert r[1].origin() == 'Test'

r = f.getfield(TrivialPacket(type=1, len=3), b"\xdeT'Toto")
assert isinstance(r, tuple)
assert r[0] == b'Toto'
assert isinstance(r[1], h2.HPackZString)
assert r[1].origin() == 'Test'

= HTTP/2 HPackStrLenField.i2h / i2repr
~ http2 hpack field hpackstrlenfield

f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')

s = b'Test'
assert f.i2h(None, h2.HPackLiteralString(s)) == 'HPackLiteralString(Test)'
assert f.i2repr(None, h2.HPackLiteralString(s)) == repr('HPackLiteralString(Test)')

assert f.i2h(None, h2.HPackZString(s)) == 'HPackZString(Test)'
assert f.i2repr(None, h2.HPackZString(s)) == repr('HPackZString(Test)')

= HTTP/2 HPackStrLenField.i2len
~ http2 hpack field hpackstrlenfield

f = h2.HPackStrLenField('data', h2.HPackLiteralString(''), length_from=lambda p: p.len, type_from='type')

s = b'Test'
assert f.i2len(None, h2.HPackLiteralString(s)) == 4
assert f.i2len(None, h2.HPackZString(s)) == 3

+ HTTP/2 HPackMagicBitField Test Suite
# Magic bits are not supposed to be modified and if they are anyway, they must
# be assigned the magic|default value only...

= HTTP/2 HPackMagicBitField.addfield
~ http2 hpack field hpackmagicbitfield

f = h2.HPackMagicBitField('value', 3, 2)
r = f.addfield(None, b'Toto', 3)
assert isinstance(r, tuple)
assert r[0] == b'Toto'
assert r[1] == 2
assert r[2] == 3

r = f.addfield(None, (b'Toto', 2, 1) , 3)
assert isinstance(r, tuple)
assert r[0] == b'Toto'
assert r[1] == 4
assert r[2] == 7

assert expect_exception(AssertionError, 'f.addfield(None, "toto", 2)')

= HTTP/2 HPackMagicBitField.getfield
~ http2 hpack field hpackmagicbitfield

f = h2.HPackMagicBitField('value', 3, 2)

r = f.getfield(None, b'\xc0')
assert isinstance(r, tuple)
assert len(r) == 2
assert isinstance(r[0], tuple)
assert len(r[0]) == 2
assert r[0][0] == b'\xc0'
assert r[0][1] == 2
assert r[1] == 3

r = f.getfield(None, (b'\x03', 6))
assert isinstance(r, tuple)
assert len(r) == 2
assert isinstance(r[0], bytes)
assert r[0] == b''
assert r[1] == 3

expect_exception(AssertionError, 'f.getfield(None, b"\\x80")')

= HTTP/2 HPackMagicBitField.h2i
~ http2 hpack field hpackmagicbitfield

f = h2.HPackMagicBitField('value', 3, 2)
assert f.h2i(None, 3) == 3
expect_exception(AssertionError, 'f.h2i(None, 2)')

= HTTP/2 HPackMagicBitField.m2i
~ http2 hpack field hpackmagicbitfield

f = h2.HPackMagicBitField('value', 3, 2)
assert f.m2i(None, 3) == 3
expect_exception(AssertionError, 'f.m2i(None, 2)')

= HTTP/2 HPackMagicBitField.i2m
~ http2 hpack field hpackmagicbitfield

f = h2.HPackMagicBitField('value', 3, 2)
assert f.i2m(None, 3) == 3
expect_exception(AssertionError, 'f.i2m(None, 2)')

= HTTP/2 HPackMagicBitField.any2i
~ http2 hpack field hpackmagicbitfield

f = h2.HPackMagicBitField('value', 3, 2)
assert f.any2i(None, 3) == 3
expect_exception(AssertionError, 'f.any2i(None, 2)')

+ HTTP/2 HPackHdrString Test Suite

= HTTP/2 Dissect HPackHdrString
~ http2 pack dissect hpackhdrstring

p = h2.HPackHdrString(b'\x04Test')
assert p.type == 0
assert p.len == 4
assert isinstance(p.getfieldval('data'), h2.HPackLiteralString)
assert p.getfieldval('data').origin() == 'Test'

p = h2.HPackHdrString(b"\x83\xdeT'")
assert p.type == 1
assert p.len == 3
assert isinstance(p.getfieldval('data'), h2.HPackZString)
assert p.getfieldval('data').origin() == 'Test'

= HTTP/2 Build HPackHdrString
~ http2 hpack build hpackhdrstring

p = h2.HPackHdrString(data=h2.HPackLiteralString('Test'))
assert raw(p) == b'\x04Test'

p = h2.HPackHdrString(data=h2.HPackZString('Test'))
assert raw(p) == b"\x83\xdeT'"

#Fuzzing-able tests
p = h2.HPackHdrString(type=1, len=3, data=h2.HPackLiteralString('Test'))
assert raw(p) == b'\x83Test'

+ HTTP/2 HPackIndexedHdr Test Suite

= HTTP/2 Dissect HPackIndexedHdr
~ http2 hpack dissect hpackindexedhdr

p = h2.HPackIndexedHdr(b'\x80')
assert p.magic == 1
assert p.index == 0

p = h2.HPackIndexedHdr(b'\xFF\x00')
assert p.magic == 1
assert p.index == 127

= HTTP/2 Build HPackIndexedHdr
~ http2 hpack build hpackindexedhdr

p = h2.HPackIndexedHdr(index=0)
assert raw(p) == b'\x80'

p = h2.HPackIndexedHdr(index=127)
assert raw(p) == b'\xFF\x00'

+ HTTP/2 HPackLitHdrFldWithIncrIndexing Test Suite

= HTTP/2 Dissect HPackLitHdrFldWithIncrIndexing without indexed name
~ http2 hpack dissect hpacklithdrfldwithincrindexing

p = h2.HPackLitHdrFldWithIncrIndexing(b'\x40\x04Test\x04Toto')
assert p.magic == 1
assert p.index == 0
assert isinstance(p.hdr_name, h2.HPackHdrString)
assert p.hdr_name.type == 0
assert p.hdr_name.len == 4
assert p.hdr_name.getfieldval('data').origin() == 'Test'
assert isinstance(p.hdr_value, h2.HPackHdrString)
assert p.hdr_value.type == 0
assert p.hdr_value.len == 4
assert p.hdr_value.getfieldval('data').origin() == 'Toto'

= HTTP/2 Dissect HPackLitHdrFldWithIncrIndexing with indexed name
~ http2 hpack dissect hpacklithdrfldwithincrindexing

p = h2.HPackLitHdrFldWithIncrIndexing(b'\x41\x04Toto')
assert p.magic == 1
assert p.index == 1
assert p.hdr_name is None
assert isinstance(p.hdr_value, h2.HPackHdrString)
assert p.hdr_value.type == 0
assert p.hdr_value.len == 4
assert p.hdr_value.getfieldval('data').origin() == 'Toto'


= HTTP/2 Build HPackLitHdrFldWithIncrIndexing without indexed name
~ http2 hpack build hpacklithdrfldwithincrindexing

p = h2.HPackLitHdrFldWithIncrIndexing(
    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),
    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
)
assert raw(p) == b'\x40\x04Test\x04Toto'

= HTTP/2 Build HPackLitHdrFldWithIncrIndexing with indexed name
~ http2 hpack build hpacklithdrfldwithincrindexing

p = h2.HPackLitHdrFldWithIncrIndexing(
    index=1,
    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
)
assert raw(p) == b'\x41\x04Toto'

+ HTTP/2 HPackLitHdrFldWithoutIndexing Test Suite

= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : don't index and no index
~ http2 hpack dissect hpacklithdrfldwithoutindexing

p = h2.HPackLitHdrFldWithoutIndexing(b'\x00\x04Test\x04Toto')
assert p.magic == 0
assert p.never_index == 0
assert p.index == 0
assert isinstance(p.hdr_name, h2.HPackHdrString)
assert p.hdr_name.type == 0
assert p.hdr_name.len == 4
assert isinstance(p.hdr_name.getfieldval('data'), h2.HPackLiteralString)
assert p.hdr_name.getfieldval('data').origin() == 'Test'
assert isinstance(p.hdr_value, h2.HPackHdrString)
assert p.hdr_value.type == 0
assert p.hdr_value.len == 4
assert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString)
assert p.hdr_value.getfieldval('data').origin() == 'Toto'

= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : never index index and no index
~ http2 hpack dissect hpacklithdrfldwithoutindexing

p = h2.HPackLitHdrFldWithoutIndexing(b'\x10\x04Test\x04Toto')
assert p.magic == 0
assert p.never_index == 1
assert p.index == 0
assert isinstance(p.hdr_name, h2.HPackHdrString)
assert p.hdr_name.type == 0
assert p.hdr_name.len == 4
assert isinstance(p.hdr_name.getfieldval('data'), h2.HPackLiteralString)
assert p.hdr_name.getfieldval('data').origin() == 'Test'
assert isinstance(p.hdr_value, h2.HPackHdrString)
assert p.hdr_value.type == 0
assert p.hdr_value.len == 4
assert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString)
assert p.hdr_value.getfieldval('data').origin() == 'Toto'

= HTTP/2 Dissect HPackLitHdrFldWithoutIndexing : never index and indexed name
~ http2 hpack dissect hpacklithdrfldwithoutindexing

p = h2.HPackLitHdrFldWithoutIndexing(b'\x11\x04Toto')
assert p.magic == 0
assert p.never_index == 1
assert p.index == 1
assert p.hdr_name is None
assert isinstance(p.hdr_value, h2.HPackHdrString)
assert p.hdr_value.type == 0
assert p.hdr_value.len == 4
assert isinstance(p.hdr_value.getfieldval('data'), h2.HPackLiteralString)
assert p.hdr_value.getfieldval('data').origin() == 'Toto'

= HTTP/2 Build HPackLitHdrFldWithoutIndexing : don't index and no index
~ http2 hpack build hpacklithdrfldwithoutindexing

p = h2.HPackLitHdrFldWithoutIndexing(
    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),
    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
)
assert raw(p) == b'\x00\x04Test\x04Toto'

= HTTP/2 Build HPackLitHdrFldWithoutIndexing : never index index and no index
~ http2 hpack build hpacklithdrfldwithoutindexing

p = h2.HPackLitHdrFldWithoutIndexing(
    never_index=1,
    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('Test')),
    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
)
assert raw(p) == b'\x10\x04Test\x04Toto'

= HTTP/2 Build HPackLitHdrFldWithoutIndexing : never index and indexed name
~ http2 hpack build hpacklithdrfldwithoutindexing

p = h2.HPackLitHdrFldWithoutIndexing(
    never_index=1,
    index=1,
    hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString(b'Toto'))
)
assert raw(p) == b'\x11\x04Toto'

+ HTTP/2 HPackDynamicSizeUpdate Test Suite

= HTTP/2 Dissect HPackDynamicSizeUpdate
~ http2 hpack dissect hpackdynamicsizeupdate

p = h2.HPackDynamicSizeUpdate(b'\x25')
assert p.magic == 1
assert p.max_size == 5
p = h2.HPackDynamicSizeUpdate(b'\x3F\x00')
assert p.magic == 1
assert p.max_size == 31

= HTTP/2 Build HPackDynamicSizeUpdate
~ http2 hpack build hpackdynamicsizeupdate

p = h2.HPackDynamicSizeUpdate(max_size=5)
assert raw(p) == b'\x25'
p = h2.HPackDynamicSizeUpdate(max_size=31)
assert raw(p) == b'\x3F\x00'

+ HTTP/2 Data Frame Test Suite

= HTTP/2 Dissect Data Frame: Simple data frame
~ http2 frame dissect data

pkt = h2.H2Frame(b'\x00\x00\x04\x00\x00\x00\x00\x00\x01ABCD')
assert pkt.type == 0
assert pkt.len == 4
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2DataFrame)
assert pkt[h2.H2DataFrame]
assert pkt.payload.data == b'ABCD'
assert isinstance(pkt.payload.payload, scapy.packet.NoPayload)

= HTTP/2 Build Data Frame: Simple data frame
~ http2 frame build data

pkt = h2.H2Frame(stream_id = 1)/h2.H2DataFrame(data='ABCD')
assert raw(pkt) == b'\x00\x00\x04\x00\x00\x00\x00\x00\x01ABCD'
try:
    pkt.show2(dump=True)
    assert True
except Exception:
    assert False

= HTTP/2 Dissect Data Frame: Simple data frame with padding
~ http2 frame dissect data

pkt = h2.H2Frame(b'\x00\x00\r\x00\x08\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00') #Padded data frame
assert pkt.type == 0
assert pkt.len == 13
assert len(pkt.flags) ==  1
assert 'P' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2PaddedDataFrame)
assert pkt[h2.H2PaddedDataFrame]
assert pkt.payload.padlen == 8
assert pkt.payload.data == b'ABCD'
assert pkt.payload.padding == b'\x00'*8
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert isinstance(pkt.payload.payload, scapy.packet.NoPayload)

= HTTP/2 Build Data Frame: Simple data frame with padding
~ http2 frame build data

pkt = h2.H2Frame(flags = {'P'}, stream_id = 1)/h2.H2PaddedDataFrame(data='ABCD', padding=b'\x00'*8)
assert raw(pkt) == b'\x00\x00\r\x00\x08\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00'
try:
    pkt.show2(dump=True)
    assert True
except Exception:
    assert False

= HTTP/2 Dissect Data Frame: Simple data frame with padding and end stream flag
~ http2 frame dissect data

pkt = h2.H2Frame(b'\x00\x00\r\x00\t\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00') #Padded data frame with end stream flag
assert pkt.type == 0
assert pkt.len == 13
assert len(pkt.flags) == 2
assert 'P' in pkt.flags
assert 'ES' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2PaddedDataFrame)
assert pkt[h2.H2PaddedDataFrame]
assert pkt.payload.padlen == 8
assert pkt.payload.data == b'ABCD'
assert pkt.payload.padding == b'\x00'*8
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert isinstance(pkt.payload.payload, scapy.packet.NoPayload)

= HTTP/2 Build Data Frame: Simple data frame with padding and end stream flag
~ http2 frame build data

pkt = h2.H2Frame(flags = {'P', 'ES'}, stream_id=1)/h2.H2PaddedDataFrame(data='ABCD', padding=b'\x00'*8)
assert raw(pkt) == b'\x00\x00\r\x00\t\x00\x00\x00\x01\x08ABCD\x00\x00\x00\x00\x00\x00\x00\x00'
try:
    pkt.show2(dump=True)
    assert True
except Exception:
    assert False

+ HTTP/2 Headers Frame Test Suite

= HTTP/2 Dissect Headers Frame: Simple header frame
~ http2 frame dissect headers

pkt = h2.H2Frame(b'\x00\x00\x0e\x01\x00\x00\x00\x00\x01\x88\x0f\x10\ntext/plain') #Header frame
assert pkt.type == 1
assert pkt.len == 14
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2HeadersFrame)
assert pkt[h2.H2HeadersFrame]
hf = pkt[h2.H2HeadersFrame]
assert len(hf.hdrs) == 2
assert isinstance(hf.hdrs[0], h2.HPackIndexedHdr)
assert hf.hdrs[0].magic == 1
assert hf.hdrs[0].index == 8
assert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing)
assert hf.hdrs[1].magic == 0
assert hf.hdrs[1].never_index == 0
assert hf.hdrs[1].index == 31
assert hf.hdrs[1].hdr_name is None
assert expect_exception(AttributeError, 'hf.hdrs[1].non_existant')
assert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString)
s = hf.hdrs[1].hdr_value
assert s.type == 0
assert s.len == 10
assert s.getfieldval('data').origin() == 'text/plain'
assert isinstance(hf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Headers Frame: Simple header frame
~ http2 frame build headers

p = h2.H2Frame(stream_id=1)/h2.H2HeadersFrame(hdrs=[
        h2.HPackIndexedHdr(index=8),
        h2.HPackLitHdrFldWithoutIndexing(
            index=31,
            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))
        )
    ]
)
assert raw(p) == b'\x00\x00\x0e\x01\x00\x00\x00\x00\x01\x88\x0f\x10\ntext/plain'

= HTTP/2 Dissect Headers Frame: Header frame with padding
~ http2 frame dissect headers

pkt = h2.H2Frame(b'\x00\x00\x17\x01\x08\x00\x00\x00\x01\x08\x88\x0f\x10\ntext/plain\x00\x00\x00\x00\x00\x00\x00\x00') #Header frame with padding
assert pkt.type == 1
assert pkt.len == 23
assert len(pkt.flags) == 1
assert 'P' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2PaddedHeadersFrame)
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert pkt[h2.H2PaddedHeadersFrame]
hf = pkt[h2.H2PaddedHeadersFrame]
assert hf.padlen == 8
assert hf.padding == b'\x00' * 8
assert len(hf.hdrs) == 2
assert isinstance(hf.hdrs[0], h2.HPackIndexedHdr)
assert hf.hdrs[0].magic == 1
assert hf.hdrs[0].index == 8
assert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing)
assert hf.hdrs[1].magic == 0
assert hf.hdrs[1].never_index == 0
assert hf.hdrs[1].index == 31
assert hf.hdrs[1].hdr_name is None
assert expect_exception(AttributeError, 'hf.hdrs[1].non_existant')
assert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString)
s = hf.hdrs[1].hdr_value
assert s.type == 0
assert s.len == 10
assert s.getfieldval('data').origin() == 'text/plain'
assert isinstance(hf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Headers Frame: Header frame with padding
~ http2 frame build headers

p = h2.H2Frame(flags={'P'}, stream_id=1)/h2.H2PaddedHeadersFrame(
    hdrs=[
        h2.HPackIndexedHdr(index=8),
        h2.HPackLitHdrFldWithoutIndexing(
            index=31,
            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))
        )
    ],
    padding=b'\x00'*8,
)
assert raw(p) == b'\x00\x00\x17\x01\x08\x00\x00\x00\x01\x08\x88\x0f\x10\ntext/plain\x00\x00\x00\x00\x00\x00\x00\x00'

= HTTP/2 Dissect Headers Frame: Header frame with priority
~ http2 frame dissect headers

pkt = h2.H2Frame(b'\x00\x00\x13\x01 \x00\x00\x00\x01\x00\x00\x00\x02d\x88\x0f\x10\ntext/plain') #Header frame with priority
assert pkt.type == 1
assert pkt.len == 19
assert len(pkt.flags) == 1
assert '+' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2PriorityHeadersFrame)
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert pkt[h2.H2PriorityHeadersFrame]
hf = pkt[h2.H2PriorityHeadersFrame]
assert hf.exclusive == 0
assert hf.stream_dependency == 2
assert hf.weight == 100
assert len(hf.hdrs) == 2
assert isinstance(hf.hdrs[0], h2.HPackIndexedHdr)
assert hf.hdrs[0].magic == 1
assert hf.hdrs[0].index == 8
assert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing)
assert hf.hdrs[1].magic == 0
assert hf.hdrs[1].never_index == 0
assert hf.hdrs[1].index == 31
assert hf.hdrs[1].hdr_name is None
assert expect_exception(AttributeError, 'hf.hdrs[1].non_existant')
assert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString)
s = hf.hdrs[1].hdr_value
assert s.type == 0
assert s.len == 10
assert s.getfieldval('data').origin() == 'text/plain'
assert isinstance(hf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Headers Frame: Header frame with priority
~ http2 frame build headers

p = h2.H2Frame(flags={'+'}, stream_id=1)/h2.H2PriorityHeadersFrame(
    exclusive=0,
    stream_dependency=2,
    weight=100,
    hdrs=[
        h2.HPackIndexedHdr(index=8),
        h2.HPackLitHdrFldWithoutIndexing(
            index=31,
            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))
        )
    ]
)
assert raw(p) == b'\x00\x00\x13\x01 \x00\x00\x00\x01\x00\x00\x00\x02d\x88\x0f\x10\ntext/plain'

= HTTP/2 Dissect Headers Frame: Header frame with priority and padding and flags
~ http2 frame dissect headers

pkt = h2.H2Frame(b'\x00\x00\x1c\x01-\x00\x00\x00\x01\x08\x00\x00\x00\x02d\x88\x0f\x10\ntext/plain\x00\x00\x00\x00\x00\x00\x00\x00') #Header frame with priority and padding and flags ES|EH
assert pkt.type == 1
assert pkt.len == 28
assert len(pkt.flags) == 4
assert '+' in pkt.flags
assert 'P' in pkt.flags
assert 'ES' in pkt.flags
assert 'EH' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2PaddedPriorityHeadersFrame)
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert pkt[h2.H2PaddedPriorityHeadersFrame]
hf = pkt[h2.H2PaddedPriorityHeadersFrame]
assert hf.padlen == 8
assert hf.padding == b'\x00' * 8
assert hf.exclusive == 0
assert hf.stream_dependency == 2
assert hf.weight == 100
assert len(hf.hdrs) == 2
assert isinstance(hf.hdrs[0], h2.HPackIndexedHdr)
assert hf.hdrs[0].magic == 1
assert hf.hdrs[0].index == 8
assert isinstance(hf.hdrs[1], h2.HPackLitHdrFldWithoutIndexing)
assert hf.hdrs[1].magic == 0
assert hf.hdrs[1].never_index == 0
assert hf.hdrs[1].index == 31
assert hf.hdrs[1].hdr_name is None
assert expect_exception(AttributeError, 'hf.hdrs[1].non_existant')
assert isinstance(hf.hdrs[1].hdr_value, h2.HPackHdrString)
s = hf.hdrs[1].hdr_value
assert s.type == 0
assert s.len == 10
assert s.getfieldval('data').origin() == 'text/plain'
assert isinstance(hf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Headers Frame: Header frame with priority and padding and flags
~ http2 frame build headers

p = h2.H2Frame(flags={'P', '+', 'ES', 'EH'}, stream_id=1)/h2.H2PaddedPriorityHeadersFrame(
    exclusive=0,
    stream_dependency=2,
    weight=100,
    padding=b'\x00'*8,
    hdrs=[
        h2.HPackIndexedHdr(index=8),
        h2.HPackLitHdrFldWithoutIndexing(
            index=31,
            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('text/plain'))
        )
    ]
)

+ HTTP/2 Priority Frame Test Suite

= HTTP/2 Dissect Priority Frame
~ http2 frame dissect priority

pkt = h2.H2Frame(b'\x00\x00\x05\x02\x00\x00\x00\x00\x03\x80\x00\x00\x01d')
assert pkt.type == 2
assert pkt.len == 5
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 3
assert isinstance(pkt.payload, h2.H2PriorityFrame)
assert pkt[h2.H2PriorityFrame]
pp = pkt[h2.H2PriorityFrame]
assert pp.stream_dependency == 1
assert pp.exclusive == 1
assert pp.weight == 100

= HTTP/2 Build Priority Frame
~ http2 frame build priority

p = h2.H2Frame(stream_id=3)/h2.H2PriorityFrame(
    exclusive=1,
    stream_dependency=1,
    weight=100
)
assert raw(p) == b'\x00\x00\x05\x02\x00\x00\x00\x00\x03\x80\x00\x00\x01d'

+ HTTP/2 Reset Stream Frame Test Suite

= HTTP/2 Dissect Reset Stream Frame: Protocol Error
~ http2 frame dissect rststream

pkt = h2.H2Frame(b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01') #Reset stream with protocol error
assert pkt.type == 3
assert pkt.len == 4
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2ResetFrame)
assert pkt[h2.H2ResetFrame]
rf = pkt[h2.H2ResetFrame]
assert rf.error == 1
assert isinstance(rf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Reset Stream Frame: Protocol Error
~ http2 frame build rststream

p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error='Protocol error')
assert raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01'

p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error=1)
assert raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x00\x00\x01'

= HTTP/2 Dissect Reset Stream Frame: Raw 123456 error
~ http2 frame dissect rststream

pkt = h2.H2Frame(b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x01\xe2@') #Reset stream with raw error
assert pkt.type == 3
assert pkt.len == 4
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2ResetFrame)
assert pkt[h2.H2ResetFrame]
rf = pkt[h2.H2ResetFrame]
assert rf.error == 123456
assert isinstance(rf.payload, scapy.packet.NoPayload)

= HTTP/2 Dissect Reset Stream Frame: Raw 123456 error
~ http2 frame dissect rststream

p = h2.H2Frame(stream_id=1)/h2.H2ResetFrame(error=123456)
assert raw(p) == b'\x00\x00\x04\x03\x00\x00\x00\x00\x01\x00\x01\xe2@'

+ HTTP/2 Settings Frame Test Suite

= HTTP/2 Dissect Settings Frame: Settings Frame
~ http2 frame dissect settings

pkt = h2.H2Frame(b'\x00\x00$\x04\x00\x00\x00\x00\x00\x00\x01\x07[\xcd\x15\x00\x02\x00\x00\x00\x01\x00\x03\x00\x00\x00{\x00\x04\x00\x12\xd6\x87\x00\x05\x00\x01\xe2@\x00\x06\x00\x00\x00{') #Settings frame
assert pkt.type == 4
assert pkt.len == 36
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 0
assert isinstance(pkt.payload, h2.H2SettingsFrame)
assert pkt[h2.H2SettingsFrame]
sf = pkt[h2.H2SettingsFrame]
assert len(sf.settings) == 6
assert isinstance(sf.settings[0], h2.H2Setting)
assert sf.settings[0].id == 1
assert sf.settings[0].value == 123456789
assert isinstance(sf.settings[1], h2.H2Setting)
assert sf.settings[1].id == 2
assert sf.settings[1].value == 1
assert isinstance(sf.settings[2], h2.H2Setting)
assert sf.settings[2].id == 3
assert sf.settings[2].value == 123
assert isinstance(sf.settings[3], h2.H2Setting)
assert sf.settings[3].id == 4
assert sf.settings[3].value == 1234567
assert isinstance(sf.settings[4], h2.H2Setting)
assert sf.settings[4].id == 5
assert sf.settings[4].value == 123456
assert isinstance(sf.settings[5], h2.H2Setting)
assert sf.settings[5].id == 6
assert sf.settings[5].value == 123
assert isinstance(sf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Settings Frame: Settings Frame
~ http2 frame build settings

p = h2.H2Frame()/h2.H2SettingsFrame(settings=[
        h2.H2Setting(id='Header table size',value=123456789),
        h2.H2Setting(id='Enable push', value=1),
        h2.H2Setting(id='Max concurrent streams', value=123),
        h2.H2Setting(id='Initial window size', value=1234567),
        h2.H2Setting(id='Max frame size', value=123456),
        h2.H2Setting(id='Max header list size', value=123)
    ]
)
assert raw(p) == b'\x00\x00$\x04\x00\x00\x00\x00\x00\x00\x01\x07[\xcd\x15\x00\x02\x00\x00\x00\x01\x00\x03\x00\x00\x00{\x00\x04\x00\x12\xd6\x87\x00\x05\x00\x01\xe2@\x00\x06\x00\x00\x00{'

= HTTP/2 Dissect Settings Frame: Incomplete Settings Frame
~ http2 frame dissect settings

#We use here the decode('hex') method because null-bytes are rejected by eval()
assert expect_exception(AssertionError, 'h2.H2Frame(bytes_hex("0000240400000000000001075bcd1500020000000100030000007b00040012d68700050001e2400006000000"))')

= HTTP/2 Dissect Settings Frame: Settings Frame acknowledgement
~ http2 frame dissect settings

pkt = h2.H2Frame(b'\x00\x00\x00\x04\x01\x00\x00\x00\x00') #Settings frame w/ ack flag
assert pkt.type == 4
assert pkt.len == 0
assert len(pkt.flags) == 1
assert 'A' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 0
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert isinstance(pkt.payload, scapy.packet.NoPayload)

= HTTP/2 Build Settings Frame: Settings Frame acknowledgement
~ http2 frame build settings

p = h2.H2Frame(type=h2.H2SettingsFrame.type_id, flags={'A'})
assert raw(p) == b'\x00\x00\x00\x04\x01\x00\x00\x00\x00'

+ HTTP/2 Push Promise Frame Test Suite

= HTTP/2 Dissect Push Promise Frame: no flag & headers with compression and hdr_name
~ http2 frame dissect pushpromise

pkt = h2.H2Frame(b'\x00\x00\x15\x05\x00\x00\x00\x00\x01\x00\x00\x00\x03@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me')
assert pkt.type == 5
assert pkt.len == 21
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2PushPromiseFrame)
assert pkt[h2.H2PushPromiseFrame]
pf = pkt[h2.H2PushPromiseFrame]
assert pf.reserved == 0
assert pf.stream_id == 3
assert len(pf.hdrs) == 1
assert isinstance(pf.payload, scapy.packet.NoPayload)
hdr = pf.hdrs[0]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.type == 1
assert hdr.hdr_name.len == 12
assert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.type == 0
assert hdr.hdr_value.len == 2
assert hdr.hdr_value.getfieldval('data').origin() == 'Me'

= HTTP/2 Build Push Promise Frame: no flag & headers with compression and hdr_name
~ http2 frame build pushpromise

p = h2.H2Frame(stream_id=1)/h2.H2PushPromiseFrame(stream_id=3,hdrs=[
    h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me')),
    )
])
assert raw(p) == b'\x00\x00\x15\x05\x00\x00\x00\x00\x01\x00\x00\x00\x03@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me'

= HTTP/2 Dissect Push Promise Frame: with padding, the flag END_Header & headers with compression and hdr_name
~ http2 frame dissect pushpromise

pkt = h2.H2Frame(b'\x00\x00\x1e\x05\x0c\x00\x00\x00\x01\x08\x00\x00\x00\x03@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me\x00\x00\x00\x00\x00\x00\x00\x00')
assert pkt.type == 5
assert pkt.len == 30
assert len(pkt.flags) == 2
assert 'P' in pkt.flags
assert 'EH' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert isinstance(pkt.payload, h2.H2PaddedPushPromiseFrame)
assert pkt[h2.H2PaddedPushPromiseFrame]
pf = pkt[h2.H2PaddedPushPromiseFrame]
assert pf.padlen == 8
assert pf.padding == b'\x00'*8
assert pf.stream_id == 3
assert len(pf.hdrs) == 1
hdr = pf.hdrs[0]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.type == 1
assert hdr.hdr_name.len == 12
assert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.type == 0
assert hdr.hdr_value.len == 2
assert hdr.hdr_value.getfieldval('data').origin() == 'Me'

= HTTP/2 Build Push Promise Frame: with padding, the flag END_Header & headers with compression and hdr_name
~ http2 frame build pushpromise

p = h2.H2Frame(flags={'P', 'EH'}, stream_id=1)/h2.H2PaddedPushPromiseFrame(
    stream_id=3,
    hdrs=[
        h2.HPackLitHdrFldWithIncrIndexing(
            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),
            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))
        )
    ],
    padding=b'\x00'*8
)
assert raw(p) == b'\x00\x00\x1e\x05\x0c\x00\x00\x00\x01\x08\x00\x00\x00\x03@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me\x00\x00\x00\x00\x00\x00\x00\x00'

+ HTTP/2 Ping Frame Test Suite

= HTTP/2 Dissect Ping Frame: Ping frame
~ http2 frame dissect ping

pkt = h2.H2Frame(b'\x00\x00\x08\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@') #Ping frame with payload
assert pkt.type == 6
assert pkt.len == 8
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 0
assert isinstance(pkt.payload, h2.H2PingFrame)
assert pkt[h2.H2PingFrame]
pf = pkt[h2.H2PingFrame]
assert pf.opaque == 123456
assert isinstance(pf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Ping Frame: Ping frame
~ http2 frame build ping

p = h2.H2Frame()/h2.H2PingFrame(opaque=123456)
assert raw(p) == b'\x00\x00\x08\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@'

= HTTP/2 Dissect Ping Frame: Pong frame
~ http2 frame dissect ping

pkt = h2.H2Frame(b'\x00\x00\x08\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@') #Pong frame
assert pkt.type == 6
assert pkt.len == 8
assert len(pkt.flags) == 1
assert 'A' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 0
assert isinstance(pkt.payload, h2.H2PingFrame)
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert pkt[h2.H2PingFrame]
pf = pkt[h2.H2PingFrame]
assert pf.opaque == 123456
assert isinstance(pf.payload, scapy.packet.NoPayload)

= HTTP/2 Dissect Ping Frame: Pong frame
~ http2 frame dissect ping

p = h2.H2Frame(flags={'A'})/h2.H2PingFrame(opaque=123456)
assert raw(p) == b'\x00\x00\x08\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xe2@'

+ HTTP/2 Go Away Frame Test Suite

= HTTP/2 Dissect Go Away Frame: No error
~ http2 frame dissect goaway

pkt = h2.H2Frame(b'\x00\x00\x08\x07\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00') #Go Away for no particular reason :)
assert pkt.type == 7
assert pkt.len == 8
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 0
assert isinstance(pkt.payload, h2.H2GoAwayFrame)
assert pkt[h2.H2GoAwayFrame]
gf = pkt[h2.H2GoAwayFrame]
assert gf.reserved == 0
assert gf.last_stream_id == 1
assert gf.error == 0
assert len(gf.additional_data) == 0
assert isinstance(gf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Go Away Frame: No error
~ http2 frame build goaway

p = h2.H2Frame()/h2.H2GoAwayFrame(last_stream_id=1, error='No error')
assert raw(p) == b'\x00\x00\x08\x07\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00'

= HTTP/2 Dissect Go Away Frame: Arbitrary error with additional data
~ http2 frame dissect goaway

pkt = h2.H2Frame(b'\x00\x00\x10\x07\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\xe2@\x00\x00\x00\x00\x00\x00\x00\x00') #Go Away with debug data
assert pkt.type == 7
assert pkt.len == 16
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 0
assert isinstance(pkt.payload, h2.H2GoAwayFrame)
assert pkt[h2.H2GoAwayFrame]
gf = pkt[h2.H2GoAwayFrame]
assert gf.reserved == 0
assert gf.last_stream_id == 2
assert gf.error == 123456
assert gf.additional_data == 8*b'\x00'
assert isinstance(gf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Go Away Frame: Arbitrary error with additional data
~ http2 frame build goaway

p = h2.H2Frame()/h2.H2GoAwayFrame(
    last_stream_id=2,
    error=123456,
    additional_data=b'\x00'*8
)
assert raw(p) == b'\x00\x00\x10\x07\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\xe2@\x00\x00\x00\x00\x00\x00\x00\x00'

+ HTTP/2 Window Update Frame Test Suite

= HTTP/2 Dissect Window Update Frame: global
~ http2 frame dissect winupdate

pkt = h2.H2Frame(b'\x00\x00\x04\x08\x00\x00\x00\x00\x00\x00\x01\xe2@') #Window update with increment for connection
assert pkt.type == 8
assert pkt.len == 4
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 0
assert isinstance(pkt.payload, h2.H2WindowUpdateFrame)
assert pkt[h2.H2WindowUpdateFrame]
wf = pkt[h2.H2WindowUpdateFrame]
assert wf.reserved == 0
assert wf.win_size_incr == 123456
assert isinstance(wf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Window Update Frame: global
~ http2 frame build winupdate

p = h2.H2Frame()/h2.H2WindowUpdateFrame(win_size_incr=123456)
assert raw(p) == b'\x00\x00\x04\x08\x00\x00\x00\x00\x00\x00\x01\xe2@'

= HTTP/2 Dissect Window Update Frame: a stream
~ http2 frame dissect winupdate

pkt = h2.H2Frame(b'\x00\x00\x04\x08\x00\x00\x00\x00\x01\x00\x01\xe2@') #Window update with increment for a stream
assert pkt.type == 8
assert pkt.len == 4
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2WindowUpdateFrame)
assert pkt[h2.H2WindowUpdateFrame]
wf = pkt[h2.H2WindowUpdateFrame]
assert wf.reserved == 0
assert wf.win_size_incr == 123456
assert isinstance(wf.payload, scapy.packet.NoPayload)

= HTTP/2 Build Window Update Frame: a stream
~ http2 frame build winupdate

p = h2.H2Frame(stream_id=1)/h2.H2WindowUpdateFrame(win_size_incr=123456)
assert raw(p) == b'\x00\x00\x04\x08\x00\x00\x00\x00\x01\x00\x01\xe2@'

+ HTTP/2 Continuation Frame Test Suite

= HTTP/2 Dissect Continuation Frame: no flag & headers with compression and hdr_name
~ http2 frame dissect continuation

pkt = h2.H2Frame(b'\x00\x00\x11\t\x00\x00\x00\x00\x01@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me')
assert pkt.type == 9
assert pkt.len == 17
assert len(pkt.flags) == 0
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert isinstance(pkt.payload, h2.H2ContinuationFrame)
assert pkt[h2.H2ContinuationFrame]
hf = pkt[h2.H2ContinuationFrame]
assert len(hf.hdrs) == 1
assert isinstance(hf.payload, scapy.packet.NoPayload)
hdr = hf.hdrs[0]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.type == 1
assert hdr.hdr_name.len == 12
assert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.type == 0
assert hdr.hdr_value.len == 2
assert hdr.hdr_value.getfieldval('data').origin() == 'Me'

= HTTP/2 Build Continuation Frame: no flag & headers with compression and hdr_name
~ http2 frame build continuation

p = h2.H2Frame(stream_id=1)/h2.H2ContinuationFrame(
    hdrs=[
        h2.HPackLitHdrFldWithIncrIndexing(
            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),
            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))
        )
    ]
)
assert raw(p) == b'\x00\x00\x11\t\x00\x00\x00\x00\x01@\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me'

= HTTP/2 Dissect Continuation Frame: flag END_Header & headers with compression, sensitive flag and hdr_name
~ http2 frame dissect continuation

pkt = h2.H2Frame(b'\x00\x00\x11\t\x04\x00\x00\x00\x01\x10\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me')
assert pkt.type == 9
assert pkt.len == 17
assert len(pkt.flags) == 1
assert 'EH' in pkt.flags
assert pkt.reserved == 0
assert pkt.stream_id == 1
assert flags_bit_pattern.search(pkt.show(dump=True)) is None
assert isinstance(pkt.payload, h2.H2ContinuationFrame)
assert pkt[h2.H2ContinuationFrame]
hf = pkt[h2.H2ContinuationFrame]
assert len(hf.hdrs) == 1
assert isinstance(hf.payload, scapy.packet.NoPayload)
hdr = hf.hdrs[0]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.type == 1
assert hdr.hdr_name.len == 12
assert hdr.hdr_name.getfieldval('data').origin() == 'X-Requested-With'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.type == 0
assert hdr.hdr_value.len == 2
assert hdr.hdr_value.getfieldval('data').origin() == 'Me'

= HTTP/2 Build Continuation Frame: flag END_Header & headers with compression, sensitive flag and hdr_name
~ http2 frame build continuation

p = h2.H2Frame(flags={'EH'}, stream_id=1)/h2.H2ContinuationFrame(
    hdrs=[
        h2.HPackLitHdrFldWithoutIndexing(
            never_index=1,
            hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Requested-With')),
            hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))
        )
    ]
)
assert raw(p) == b'\x00\x00\x11\t\x04\x00\x00\x00\x01\x10\x8c\xfc[i{ZT$\xb2-\xc8\xc9\x9f\x02Me'

+ HTTP/2 HPackHdrTable Test Suite

= HTTP/2 HPackHdrEntry Tests
~ http2 hpack hpackhdrtable

n = 'X-Requested-With'
v = 'Me'
h = h2.HPackHdrEntry(n, v)
assert len(h) == 32 + len(n) + len(v)
assert h.name() == n.lower()
assert h.value() == v
assert str(h) == '{}: {}'.format(n.lower(), v)

n = ':status'
v = '200'
h = h2.HPackHdrEntry(n, v)
assert len(h) == 32 + len(n) + len(v)
assert h.name() == n.lower()
assert h.value() == v
assert str(h) == '{} {}'.format(n.lower(), v)

= HTTP/2 HPackHdrTable : Querying Static Entries
~ http2 hpack hpackhdrtable

# In RFC7541, the table is 1-based
assert expect_exception(KeyError, 'h2.HPackHdrTable()[0]')

h = h2.HPackHdrTable()
assert h[1].name() == ':authority'
assert h[7].name() == ':scheme'
assert h[7].value() == 'https'
assert str(h[14]) == ':status 500'
assert str(h[16]) == 'accept-encoding: gzip, deflate'

assert expect_exception(KeyError, 'h2.HPackHdrTable()[h2.HPackHdrTable._static_entries_last_idx+1]')

= HTTP/2 HPackHdrTable : Addind Dynamic Entries without overflowing the table
~ http2 hpack hpackhdrtable

tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
hdr = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString('PHPSESSID=abcdef0123456789'))
)
tbl.register(hdr)

tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString('JSESSID=abcdef0123456789'))
)
tbl.register([hdr,hdr2])

tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
hdr3 = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString('Test=abcdef0123456789'))
)
frm = h2.H2Frame(stream_id=1)/h2.H2HeadersFrame(hdrs=[hdr, hdr2, hdr3])
tbl.register(frm)


= HTTP/2 HPackHdrTable : Querying Dynamic Entries
~ http2 hpack hpackhdrtable

tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)
hdrv = 'PHPSESSID=abcdef0123456789'
hdr = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
)
tbl.register(hdr)

hdrv2 = 'JSESSID=abcdef0123456789'
hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))
)
tbl.register(hdr2)

hdr3 = h2.HPackLitHdrFldWithIncrIndexing(
    index=0,
    hdr_name=h2.HPackHdrString(data=h2.HPackLiteralString('x-requested-by')),
    hdr_value=h2.HPackHdrString(data=h2.HPackZString('me'))
)
tbl.register(hdr3)

assert tbl.get_idx_by_name('x-requested-by') == h2.HPackHdrTable._static_entries_last_idx+1
assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv2
assert tbl[h2.HPackHdrTable._static_entries_last_idx+3].value() == hdrv

= HTTP/2 HPackHdrTable : Addind already registered Dynamic Entries without overflowing the table
~ http2 hpack hpackhdrtable

tbl = h2.HPackHdrTable(dynamic_table_max_size=1<<32, dynamic_table_cap_size=1<<32)

assert len(tbl) == 0

hdrv = 'PHPSESSID=abcdef0123456789'
hdr = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
)
tbl.register(hdr)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv

hdr2v = 'JSESSID=abcdef0123456789'
hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdr2v))
)
tbl.register(hdr2)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdr2v

l = len(tbl)
tbl.register(hdr)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv
assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdr2v
assert tbl[h2.HPackHdrTable._static_entries_last_idx+3].value() == hdrv

= HTTP/2 HPackHdrTable : Addind Dynamic Entries and overflowing the table
~ http2 hpack hpackhdrtable

tbl = h2.HPackHdrTable(dynamic_table_max_size=80, dynamic_table_cap_size=80)
hdrv = 'PHPSESSID=abcdef0123456789'
hdr = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
)
tbl.register(hdr)
assert len(tbl) <= 80
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv

hdrv2 = 'JSESSID=abcdef0123456789'
hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))
)
tbl.register(hdr2)
assert len(tbl) <= 80
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
try:
    tbl[h2.HPackHdrTable._static_entries_last_idx+2]
    ret = False
except Exception:
    ret = True

assert ret


= HTTP/2 HPackHdrTable : Resizing
~ http2 hpack hpackhdrtable

tbl = h2.HPackHdrTable()
hdrv = 'PHPSESSID=abcdef0123456789'
hdr = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
)
tbl.register(hdr)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv

hdrv2 = 'JSESSID=abcdef0123456789'
hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))
)
tbl.register(hdr2)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv

#Resizing to a value higher than cap (default:4096)
try:
    tbl.resize(8192)
    ret = False
except AssertionError:
    ret = True

assert ret
#Resizing to a lower value by that is not small enough to cause eviction
tbl.resize(1024)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv
#Resizing to a higher value but thatt is lower than cap
tbl.resize(2048)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv
#Resizing to a lower value that causes eviction
tbl.resize(80)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
try:
    tbl[h2.HPackHdrTable._static_entries_last_idx+2]
    ret = False
except Exception:
    ret = True

assert ret

= HTTP/2 HPackHdrTable : Recapping
~ http2 hpack hpackhdrtable

tbl = h2.HPackHdrTable()
hdrv = 'PHPSESSID=abcdef0123456789'
hdr = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv))
)
tbl.register(hdr)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv

hdrv2 = 'JSESSID=abcdef0123456789'
hdr2 = h2.HPackLitHdrFldWithIncrIndexing(
    index=32,
    hdr_value=h2.HPackHdrString(data=h2.HPackZString(hdrv2))
)
tbl.register(hdr2)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv

#Recapping to a higher value
tbl.recap(8192)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv

#Recapping to a low value but without causing eviction
tbl.recap(1024)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
assert tbl[h2.HPackHdrTable._static_entries_last_idx+2].value() == hdrv

#Recapping to a low value that causes evictiontbl.recap(1024)
tbl.recap(80)
assert tbl[h2.HPackHdrTable._static_entries_last_idx+1].value() == hdrv2
try:
    tbl[h2.HPackHdrTable._static_entries_last_idx+2]
    ret = False
except Exception:
    ret = True

assert ret

= HTTP/2 HPackHdrTable : Generating Textual Representation
~ http2 hpack hpackhdrtable helpers

h = h2.HPackHdrTable()
h.register(h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
))

hdrs_lst = [
    h2.HPackIndexedHdr(index=2), #Method Get
    h2.HPackLitHdrFldWithIncrIndexing(
        index=h.get_idx_by_name(':path'),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('/index.php'))
    ),
    h2.HPackIndexedHdr(index=7), #Scheme HTTPS
    h2.HPackIndexedHdr(index=h2.HPackHdrTable._static_entries_last_idx+2),
    h2.HPackLitHdrFldWithIncrIndexing(
        index=58,
        hdr_value=h2.HPackHdrString(data=h2.HPackZString('Mozilla/5.0 Generated by hand'))
    ),
    h2.HPackLitHdrFldWithoutIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generated-By')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('Me'))
    )
]

p = h2.H2Frame(stream_id = 1)/h2.H2HeadersFrame(hdrs=hdrs_lst)

expected_output = ''':method GET
:path /index.php
:scheme https
x-generation-date: 2016-08-11
user-agent: Mozilla/5.0 Generated by hand
X-Generated-By: Me'''

assert h.gen_txt_repr(p) == expected_output

= HTTP/2 HPackHdrTable : Parsing Textual Representation
~ http2 hpack hpackhdrtable helpers

body = b'login=titi&passwd=toto'
hdrs = ''':method POST
:path /login.php
:scheme https
content-type: application/x-www-form-urlencoded
content-length: {}
user-agent: Mozilla/5.0 Generated by hand
x-generated-by: Me
x-generation-date: 2016-08-11
x-generation-software: scapy
'''.format(len(body))

h = h2.HPackHdrTable()
h.register(h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
))
seq = h.parse_txt_hdrs(
    hdrs,
    stream_id=1,
    body=body,
    should_index=lambda name: name in ['user-agent', 'x-generation-software'],
    is_sensitive=lambda name, value: name in ['x-generated-by', ':path']
)
assert isinstance(seq, h2.H2Seq)
assert len(seq.frames) == 2
p = seq.frames[0]
assert isinstance(p, h2.H2Frame)
assert p.type == 1
assert len(p.flags) == 1
assert 'EH' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2HeadersFrame)
hdrs_frm = p[h2.H2HeadersFrame]
assert len(p.hdrs) == 9
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 3
hdr = p.hdrs[1]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 1
assert hdr.index in [4, 5]
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(/login.php)'
hdr = p.hdrs[2]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 7
hdr = p.hdrs[3]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 31
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'
hdr = p.hdrs[4]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 28
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(22)'
hdr = p.hdrs[5]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 58
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'
hdr = p.hdrs[6]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generated-by)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(Me)'
hdr = p.hdrs[7]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 63
hdr = p.hdrs[8]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generation-software)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(scapy)'

p = seq.frames[1]
assert isinstance(p, h2.H2Frame)
assert p.type == 0
assert len(p.flags) == 1
assert 'ES' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2DataFrame)
pay = p[h2.H2DataFrame]
assert pay.data == body

# now with bytes
h = h2.HPackHdrTable()
h.register(h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
))
seq = h.parse_txt_hdrs(
    hdrs.encode(),
    stream_id=1,
    body=body,
    should_index=lambda name: name in ['user-agent', 'x-generation-software'],
    is_sensitive=lambda name, value: name in ['x-generated-by', ':path']
)
assert isinstance(seq, h2.H2Seq)
assert len(seq.frames) == 2
p = seq.frames[0]
assert isinstance(p, h2.H2Frame)
assert p.type == 1
assert len(p.flags) == 1
assert 'EH' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2HeadersFrame)
hdrs_frm = p[h2.H2HeadersFrame]
assert len(p.hdrs) == 9
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 3
hdr = p.hdrs[1]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 1
assert hdr.index in [4, 5]
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(/login.php)'
hdr = p.hdrs[2]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 7
hdr = p.hdrs[3]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 31
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'
hdr = p.hdrs[4]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 28
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(22)'
hdr = p.hdrs[5]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 58
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'
hdr = p.hdrs[6]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generated-by)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(Me)'
hdr = p.hdrs[7]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 63
hdr = p.hdrs[8]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generation-software)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(scapy)'

p = seq.frames[1]
assert isinstance(p, h2.H2Frame)
assert p.type == 0
assert len(p.flags) == 1
assert 'ES' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2DataFrame)
pay = p[h2.H2DataFrame]
assert pay.data == body

= HTTP/2 HPackHdrTable : Parsing Textual Representation without body
~ http2 hpack hpackhdrtable helpers

hdrs = b''':method POST
:path /login.php
:scheme https
user-agent: Mozilla/5.0 Generated by hand
x-generated-by: Me
x-generation-date: 2016-08-11
'''

h = h2.HPackHdrTable()
h.register(h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
))

# Without body
seq = h.parse_txt_hdrs(hdrs, stream_id=1)
assert isinstance(seq, h2.H2Seq)
#This is the first major difference with the first test
assert len(seq.frames) == 1
p = seq.frames[0]
assert isinstance(p, h2.H2Frame)
assert p.type == 1
assert len(p.flags) == 2
assert 'EH' in p.flags
#This is the second major difference with the first test
assert 'ES' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2HeadersFrame)
hdrs_frm = p[h2.H2HeadersFrame]
assert len(p.hdrs) == 6
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 3
hdr = p.hdrs[1]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index in [4, 5]
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(/login.php)'
hdr = p.hdrs[2]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 7
hdr = p.hdrs[3]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 58
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'
hdr = p.hdrs[4]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generated-by)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(Me)'
hdr = p.hdrs[5]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 62


= HTTP/2 HPackHdrTable : Parsing Textual Representation with too small max frame
~ http2 hpack hpackhdrtable helpers

body = b'login=titi&passwd=toto'
hdrs = ''':method POST
:path /login.php
:scheme https
content-type: application/x-www-form-urlencoded
content-length: {}
user-agent: Mozilla/5.0 Generated by hand
x-generated-by: Me
x-generation-date: 2016-08-11
x-long-header: {}
'''.format(len(body), 'a'*5000).encode()

h = h2.HPackHdrTable()
h.register(h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
))

#x-long-header is too long to fit in any frames (whose default max size is 4096)
expect_exception(Exception, "seq = h.parse_txt_hdrs('''{}''', stream_id=1".format(hdrs))

= HTTP/2 HPackHdrTable : Parsing Textual Representation with very large header and a large authorized frame size
~ http2 hpack hpackhdrtable helpers

body = b'login=titi&passwd=toto'
hdrs = ''':method POST
:path /login.php
:scheme https
content-type: application/x-www-form-urlencoded
content-length: {}
user-agent: Mozilla/5.0 Generated by hand
x-generated-by: Me
x-generation-date: 2016-08-11
x-long-header: {}
'''.format(len(body), 'a'*5000).encode()

h = h2.HPackHdrTable()
h.register(h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
))

# Now trying to parse it with a max frame size large enough for x-long-header to
# fit in a frame
seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192)
assert isinstance(seq, h2.H2Seq)
assert len(seq.frames) == 1
p = seq.frames[0]
assert isinstance(p, h2.H2Frame)
assert p.type == 1
assert len(p.flags) == 2
assert 'EH' in p.flags
assert 'ES' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2HeadersFrame)
hdrs_frm = p[h2.H2HeadersFrame]
assert len(p.hdrs) == 9
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 3
hdr = p.hdrs[1]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index in [4, 5]
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(/login.php)'
hdr = p.hdrs[2]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 7
hdr = p.hdrs[3]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 31
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'
hdr = p.hdrs[4]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 28
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(22)'
hdr = p.hdrs[5]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 58
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'
hdr = p.hdrs[6]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generated-by)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(Me)'
hdr = p.hdrs[7]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 62
hdr = p.hdrs[8]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-long-header)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000)

= HTTP/2 HPackHdrTable : Parsing Textual Representation with two very large headers and a large authorized frame size
~ http2 hpack hpackhdrtable helpers

body = b'login=titi&passwd=toto'
hdrs = ''':method POST
:path /login.php
:scheme https
content-type: application/x-www-form-urlencoded
content-length: {}
user-agent: Mozilla/5.0 Generated by hand
x-generated-by: Me
x-generation-date: 2016-08-11
x-long-header: {}
x-long-header: {}
'''.format(len(body), 'a'*5000, 'b'*5000).encode()

h = h2.HPackHdrTable()
h.register(h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
))

# Now trying to parse it with a max frame size large enough for x-long-header to
# fit in a frame but a maximum header fragment size that is not large enough to
# store two x-long-header
seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192)
assert isinstance(seq, h2.H2Seq)
assert len(seq.frames) == 2
p = seq.frames[0]
assert isinstance(p, h2.H2Frame)
assert p.type == 1
assert len(p.flags) == 1
assert 'ES' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2HeadersFrame)
hdrs_frm = p[h2.H2HeadersFrame]
assert len(p.hdrs) == 9
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 3
hdr = p.hdrs[1]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index in [4, 5]
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(/login.php)'
hdr = p.hdrs[2]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 7
hdr = p.hdrs[3]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 31
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'
hdr = p.hdrs[4]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 28
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(22)'
hdr = p.hdrs[5]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 58
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'
hdr = p.hdrs[6]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generated-by)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(Me)'
hdr = p.hdrs[7]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 62
hdr = p.hdrs[8]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-long-header)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000)
p = seq.frames[1]
assert isinstance(p, h2.H2Frame)
assert p.type == 9
assert len(p.flags) == 1
assert 'EH' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2ContinuationFrame)
hdrs_frm = p[h2.H2ContinuationFrame]
assert len(p.hdrs) == 1
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-long-header)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString({})'.format('b'*5000)

= HTTP/2 HPackHdrTable : Parsing Textual Representation with two very large headers, a large authorized frame size and a "small" max header list size
~ http2 hpack hpackhdrtable helpers

body = b'login=titi&passwd=toto'
hdrs = ''':method POST
:path /login.php
:scheme https
content-type: application/x-www-form-urlencoded
content-length: {}
user-agent: Mozilla/5.0 Generated by hand
x-generated-by: Me
x-generation-date: 2016-08-11
x-long-header: {}
x-long-header: {}
'''.format(len(body), 'a'*5000, 'b'*5000).encode()

h = h2.HPackHdrTable()
h.register(h2.HPackLitHdrFldWithIncrIndexing(
        hdr_name=h2.HPackHdrString(data=h2.HPackZString('X-Generation-Date')),
        hdr_value=h2.HPackHdrString(data=h2.HPackLiteralString('2016-08-11'))
))

# Now trying to parse it with a max frame size large enough for x-long-header to
# fit in a frame but and a max header list size that is large enough to fit one
# but not two
seq = h.parse_txt_hdrs(hdrs, stream_id=1, max_frm_sz=8192, max_hdr_lst_sz=5050)
assert isinstance(seq, h2.H2Seq)
assert len(seq.frames) == 3
p = seq.frames[0]
assert isinstance(p, h2.H2Frame)
assert p.type == 1
assert len(p.flags) == 1
assert 'ES' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2HeadersFrame)
hdrs_frm = p[h2.H2HeadersFrame]
assert len(p.hdrs) == 8
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 3
hdr = p.hdrs[1]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index in [4, 5]
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(/login.php)'
hdr = p.hdrs[2]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 7
hdr = p.hdrs[3]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 31
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'
hdr = p.hdrs[4]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 28
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(22)'
hdr = p.hdrs[5]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 58
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'
hdr = p.hdrs[6]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generated-by)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(Me)'
hdr = p.hdrs[7]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 62
p = seq.frames[1]
assert isinstance(p, h2.H2Frame)
assert p.type == 9
assert len(p.flags) == 0
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2ContinuationFrame)
hdrs_frm = p[h2.H2ContinuationFrame]
assert len(p.hdrs) == 1
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-long-header)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString({})'.format('a'*5000)
p = seq.frames[2]
assert isinstance(p, h2.H2Frame)
assert p.type == 9
assert len(p.flags) == 1
assert 'EH' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2ContinuationFrame)
hdrs_frm = p[h2.H2ContinuationFrame]
assert len(p.hdrs) == 1
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-long-header)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString({})'.format('b'*5000)

= HTTP/2 HPackHdrTable : Parsing Textual Representation with sensitive headers and non-indexable ones
~ http2 hpack hpackhdrtable helpers

hdrs = ''':method POST
:path /login.php
:scheme https
content-type: application/x-www-form-urlencoded
content-length: {}
user-agent: Mozilla/5.0 Generated by hand
x-generated-by: Me
x-generation-date: 2016-08-11
'''.format(len(body)).encode()

h = h2.HPackHdrTable()
seq = h.parse_txt_hdrs(hdrs, stream_id=1, body=body, is_sensitive=lambda n,v: n in ['x-generation-date'], should_index=lambda x: x != 'x-generated-by')
assert isinstance(seq, h2.H2Seq)
assert len(seq.frames) == 2
p = seq.frames[0]
assert isinstance(p, h2.H2Frame)
assert p.type == 1
assert len(p.flags) == 1
assert 'EH' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2HeadersFrame)
hdrs_frm = p[h2.H2HeadersFrame]
assert len(p.hdrs) == 8
hdr = p.hdrs[0]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 3
hdr = p.hdrs[1]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index in [4, 5]
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(/login.php)'
hdr = p.hdrs[2]
assert isinstance(hdr, h2.HPackIndexedHdr)
assert hdr.magic == 1
assert hdr.index == 7
hdr = p.hdrs[3]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 31
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(application/x-www-form-urlencoded)'
hdr = p.hdrs[4]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 28
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(22)'
hdr = p.hdrs[5]
assert isinstance(hdr, h2.HPackLitHdrFldWithIncrIndexing)
assert hdr.magic == 1
assert hdr.index == 58
assert hdr.hdr_name is None
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(Mozilla/5.0 Generated by hand)'
hdr = p.hdrs[6]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 0
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generated-by)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackLiteralString(Me)'
hdr = p.hdrs[7]
assert isinstance(hdr, h2.HPackLitHdrFldWithoutIndexing)
assert hdr.magic == 0
assert hdr.never_index == 1
assert hdr.index == 0
assert isinstance(hdr.hdr_name, h2.HPackHdrString)
assert hdr.hdr_name.data == 'HPackZString(x-generation-date)'
assert isinstance(hdr.hdr_value, h2.HPackHdrString)
assert hdr.hdr_value.data == 'HPackZString(2016-08-11)'
p = seq.frames[1]
assert isinstance(p, h2.H2Frame)
assert p.type == 0
assert len(p.flags) == 1
assert 'ES' in p.flags
assert p.stream_id == 1
assert isinstance(p.payload, h2.H2DataFrame)
pay = p[h2.H2DataFrame]
assert pay.data == body
