#!/usr/bin/perl -w
$| = 1;
my
$data
;
my
$string
;
my
$s
;
my
$s1
;
ok( UBInt16(
"foo"
)->parse(
"\x01\x02"
) == 258,
"Primitive: Parse: UBInt16"
);
ok( ULInt16(
"foo"
)->parse(
"\x01\x02"
) == 513,
"Primitive: Parse: ULInt16"
);
ok( UBInt16(
"foo"
)->build(31337) eq
'zi'
,
"Primitive: Build: UBInt16"
);
ok( SBInt16(
"foo"
)->build(-31337) eq
"\x85\x97"
,
"Primitive: Build: SBInt16"
);
ok( SLInt16(
"foo"
)->build(-31337) eq
"\x97\x85"
,
"Primitive: Build: SLInt16"
);
ok( BFloat32(
"foo"
)->build(5) eq
"\x40\xa0\0\0"
,
"Primitive: Build: BFloat32"
);
ok( LFloat32(
"foo"
)->build(5) eq
"\0\0\xa0\x40"
,
"Primitive: Build: LFloat32"
);
ok( BFloat32(
"foo"
)->parse(
"\x40\xa0\0\0"
) == 5,
"Primitive: Parse: BFloat32"
);
ok( LFloat64(
"foo"
)->build(5) eq
"\0\0\0\0\0\0\x14\x40"
,
"Primitive: Build: LFloat64"
);
ok( LFloat64(
"foo"
)->parse(
"\0\0\0\0\0\0\x14\x40"
) == 5,
"Primitive: Build: LFloat64"
);
$s
= Struct(
"foo"
,
UBInt8(
"a"
),
SLInt16(
"b"
)
);
$data
= {
a
=> 7,
b
=> 256};
$string
=
"\x07\x00\x01"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Struct: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Struct: Build: Rebuild1"
);
$data
->{b} = 5000;
ok(
$s
->build(
$data
) eq
"\x07\x88\x13"
,
"Struct: Build: Rebuild2"
);
$s
= Struct(
"foo"
,
UBInt8(
"a"
),
UBInt16(
"b"
),
Struct(
"bar"
,
UBInt8(
"a"
),
UBInt16(
"b"
),
)
);
$data
= {
a
=>65,
b
=>16962,
bar
=>{
a
=>97,
b
=> 25186}};
$string
=
"ABBabb"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Nested Struct: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Nested Struct: Build: Rebuild1"
);
$s
= Sequence(
"foo"
,
UBInt8(
"a"
),
UBInt16(
"b"
)
);
$data
= [97, 25186];
$string
=
"abb"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Sequence: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Sequence: Build: Rebuild1"
);
ok(
$s
->build([1,2]) eq
"\x01\x00\x02"
,
"Sequence: Build: correct"
);
$s
= Sequence(
"foo"
,
UBInt8(
"a"
),
UBInt16(
"b"
),
Sequence(
"bar"
,
UBInt8(
"a"
),
UBInt16(
"b"
),
)
);
$data
= [65, 16962, [97, 25186]];
$string
=
"ABBabb"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Nested Sequence: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Nested Sequence: Build: correct"
);
$s
= Array(4, UBInt8(
"foo"
));
$data
=
$s
->parse(
"\x01\x02\x03\x04"
);
is_deeply(
$s
->parse(
"\x01\x02\x03\x04"
), [1..4],
"StrictRepeater: Parse: correct elements1"
);
eval
{
$data
=
$s
->parse(
"\x01\x02\x03"
) };
ok( $@ ,
"StrictRepeater: Parse: Die on too few elements"
);
is_deeply(
$s
->parse(
"\x01\x02\x03\x04\x05"
), [1..4],
"StrictRepeater: Parse: correct elements2"
);
ok(
$s
->build([5,6,7,8]) eq
"\x05\x06\x07\x08"
,
"StrictRepeater: Build: normal build"
);
eval
{
$s
->build([5,6,7,8,9]) };
ok( $@,
"StrictRepeater: Build: dies on too many elements"
);
$s
= Array(5, Array(2, UBInt8(
"foo"
)));
$data
= [[97,97], [98,98], [99,99], [100,100], [101,101]];
$string
=
"aabbccddee"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Nested StrictRepeater: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Nested StrictRepeater: Build: correct"
);
$s
= Struct(
"foo"
,
Padding(2),
Flag(
"myflag"
),
Padding(5),
);
$data
= {
myflag
=> 1};
$string
=
"\x00\x00\x01\x00\x00\x00\x00\x00"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Struct with Padding, Flag: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Struct with Padding, Flag: Build: correct"
);
$s
= BitStruct(
"foo"
,
Padding(2),
Flag(
"myflag"
),
Padding(5),
);
$data
= {
myflag
=> 1};
$string
=
"\x20"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"BitStruct with Padding, Flag: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"BitStruct with Padding, Flag: Build: correct"
);
$s
= BitStruct(
"foo"
,
BitField(
"a"
, 3),
Flag(
"b"
),
Padding(3),
Nibble(
"c"
),
BitField(
"d"
, 5),
);
$data
= {
a
=>7,
b
=>0,
c
=>8,
d
=>31};
$string
=
"\xe1\x1f"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"BitStruct: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"BitStruct: Build: correct"
);
$s
= BitStruct(
"foo"
,
BitField(
"a"
, 3),
Flag(
"b"
),
Padding(3),
Nibble(
"c"
),
Struct(
"bar"
,
Nibble(
"d"
),
Bit(
"e"
),
)
);
$data
= {
a
=>7,
b
=>0,
c
=>8,
bar
=>{
d
=>15,
e
=>1 } };
$string
=
"\xe1\x1f"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Nested BitStruct: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Nested BitStruct: Build: correct"
);
$s
= BitStruct(
"foo"
,
BitField(
"a"
, 3),
Flag(
"b"
),
Byte(
"c"
),
);
$data
= {
a
=>7,
b
=>0,
c
=>59 };
$string
=
"\xe3\xb0"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"BitStruct with Byte: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"BitStruct with Byte: Build: correct"
);
$s
= Enum(Byte(
"protocol"
),
TCP
=> 6,
UDP
=> 17,
);
ok(
$s
->parse(
"\x06"
) eq
'TCP'
,
"Enum: correct1"
);
ok(
$s
->parse(
"\x11"
) eq
'UDP'
,
"Enum: correct1"
);
eval
{
$s
->parse(
"\x12"
) };
ok( $@,
"Enum: dies on undeclared value with default"
);
ok(
$s
->build(
"TCP"
) eq
"\x06"
,
"Enum: build 1"
);
ok(
$s
->build(
"UDP"
) eq
"\x11"
,
"Enum: build 2"
);
$s
= Enum(Byte(
"protocol"
),
TCP
=> 6,
UDP
=> 17,
_default_
=>
blah
=> 99,
);
ok(
$s
->parse(
"\x11"
) eq
'UDP'
,
"Enum with default: correct1"
);
ok(
$s
->parse(
"\x12"
) eq
'blah'
,
"Enum with default: correct2"
);
ok(
$s
->build(
"TCP"
) eq
"\x06"
,
"Enum with default: build 1"
);
ok(
$s
->build(
"blah"
) eq
"\x63"
,
"Enum with default: build default"
);
$s
= Enum(Byte(
"protocol"
),
TCP
=> 6,
UDP
=> 17,
_default_
=>
$DefaultPass
,
);
ok(
$s
->parse(
"\x11"
) eq
'UDP'
,
"Enum with pass: correct1"
);
ok(
$s
->parse(
"\x12"
) == 18,
"Enum with pass: correct2"
);
ok(
$s
->parse(
"\xff"
) == 255,
"Enum with pass: correct3"
);
ok(
$s
->build(
"TCP"
) eq
"\x06"
,
"Enum with pass: build 1"
);
ok(
$s
->build(18) eq
"\x12"
,
"Enum with pass: build 2"
);
ok(
$s
->build(255) eq
"\xff"
,
"Enum with pass: build 3"
);
ok( OneOf(UBInt8(
"foo"
), [4,5,6,7])->parse(
"\x05"
) == 5,
"OneOf: Parse: passing"
);
eval
{ OneOf(UBInt8(
"foo"
), [4,5,6,7])->parse(
"\x08"
) };
ok( $@,
"OneOf: Parse: blocking"
);
ok( OneOf(UBInt8(
"foo"
), [4,5,6,7])->build(5) eq
"\x05"
,
"OneOf: Build: passing"
);
eval
{ OneOf(UBInt8(
"foo"
), [4,5,6,7])->build(8) };
ok( $@,
"OneOf: Build: blocking"
);
ok( NoneOf(UBInt8(
"foo"
), [4,5,6,7])->parse(
"\x08"
) == 8,
"NoneOf: Parse: passing"
);
eval
{ NoneOf(UBInt8(
"foo"
), [4,5,6,7])->parse(
"\x06"
) };
ok( $@,
"NoneOf: Parse: blocking"
);
ok( NoneOf(UBInt8(
"foo"
), [4,5,6,7])->build(8) eq
"\x08"
,
"NoneOf: Build: passing"
);
eval
{ NoneOf(UBInt8(
"foo"
), [4,5,6,7])->build(6) };
ok( $@,
"NoneOf: Build: blocking"
);
$s
= Struct(
"foo"
,
Byte(
"length"
),
Field(
"data"
,
sub
{
$_
->ctx->{
length
} }),
);
$data
= {
data
=>
'ABC'
,
length
=> 3};
$string
=
"\x03ABC"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"MetaField: Parse: correct1"
);
ok(
$s
->build(
$data
) eq
$string
,
"MetaField: Build: correct1"
);
$data
= {
data
=>
'ABCD'
,
length
=> 4};
$string
=
"\x04ABCD"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"MetaField: Parse: correct2"
);
ok(
$s
->build(
$data
) eq
$string
,
"MetaField: Build: correct2"
);
ok( Field(
"foo"
, 3)->parse(
"ABCD"
) eq
"ABC"
,
"Field: Parse: route to StaticField"
);
ok( Field(
"foo"
,
sub
{
return
3})->parse(
"ABCD"
) eq
"ABC"
,
"Field: Parse: route to MetaField"
);
$s
= Struct(
"foo"
,
Byte(
"length"
),
Array(
sub
{
$_
->ctx->{
length
}}, UBInt16(
"data"
)),
);
$data
= {
length
=> 3,
data
=> [1,2,3]};
$string
=
"\x03\x00\x01\x00\x02\x00\x03"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"MetaRepeater: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"MetaRepeater: Build: correct"
);
$s
= RepeatUntil(
sub
{
$_
->obj eq
"\x00"
}, Field(
"data"
, 1));
$data
= [
split
(
''
,
"abcdef\x00"
) ];
$string
=
"abcdef\x00this is another string"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"RepeatUntil: Parse: correct"
);
$string
=
"abcdef\x00"
;
ok(
$s
->build(
$data
) eq
$string
,
"RepeatUntil: Build: correct"
);
$s
= Struct(
"foo"
,
Enum(Byte(
"type"
),
INT1
=> 1,
INT2
=> 2,
INT4
=> 3,
STRING
=> 4,
),
Switch(
"data"
,
sub
{
$_
->ctx->{type} },
{
"INT1"
=> UBInt8(
"spam"
),
"INT2"
=> UBInt16(
"spam"
),
"INT4"
=> UBInt32(
"spam"
),
"STRING"
=> String(
"spam"
, 6),
}
)
);
$data
= {
type
=>
'INT1'
,
data
=> 18};
$string
=
"\x01\x12"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch: Parse: correct1"
);
ok(
$s
->build(
$data
) eq
$string
,
"Switch: Build: correct1"
);
$data
= {
type
=>
'INT2'
,
data
=> 4660};
$string
=
"\x02\x12\x34"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch: Parse: correct2"
);
ok(
$s
->build(
$data
) eq
$string
,
"Switch: Build: correct2"
);
$data
= {
type
=>
'INT4'
,
data
=> 305419896};
$string
=
"\x03\x12\x34\x56\x78"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch: Parse: correct3"
);
ok(
$s
->build(
$data
) eq
$string
,
"Switch: Build: correct3"
);
$data
= {
type
=>
'STRING'
,
data
=>
'abcdef'
};
$string
=
"\x04abcdef"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch: Parse: correct4"
);
ok(
$s
->build(
$data
) eq
$string
,
"Switch: Build: correct4"
);
$s
= Struct(
"foo"
,
Byte(
"type"
),
Switch(
"data"
,
sub
{
$_
->ctx->{type} },
{
1
=> UBInt8(
"spam"
),
2
=> UBInt16(
"spam"
),
},
default
=> UBInt8(
"spam"
)
)
);
$data
= {
type
=> 1,
data
=> 255};
$string
=
"\x01\xff"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch with default: Parse: correct1"
);
ok(
$s
->build(
$data
) eq
$string
,
"Switch with default: Build: correct1"
);
$data
= {
type
=> 2,
data
=> 65535};
$string
=
"\x02\xff\xff"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch with default: Parse: correct2"
);
ok(
$s
->build(
$data
) eq
$string
,
"Switch with default: Build: correct2"
);
$data
= {
type
=> 3,
data
=> 255};
$string
=
"\x03\xff\xff"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch with default: Parse: correct3"
);
ok(
$s
->build(
$data
) eq
"\x03\xff"
,
"Switch with default: Build: correct3"
);
$s
= Struct(
"foo"
,
Byte(
"type"
),
Switch(
"data"
,
sub
{
$_
->ctx->{type} },
{
1
=> UBInt8(
"spam"
),
2
=> UBInt16(
"spam"
),
},
default
=>
$DefaultPass
,
)
);
$data
= {
type
=> 1,
data
=> 255};
$string
=
"\x01\xff"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch with pass: Parse: correct1"
);
ok(
$s
->build(
$data
) eq
$string
,
"Switch with pass: Build: correct1"
);
$data
= {
type
=> 2,
data
=> 65535};
$string
=
"\x02\xff\xff"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch with pass: Parse: correct2"
);
ok(
$s
->build(
$data
) eq
$string
,
"Switch with pass: Build: correct2"
);
$data
= {
type
=> 3,
data
=>
undef
};
$string
=
"\x03\xff\xff"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Switch with pass: Parse: correct3"
);
ok(
$s
->build(
$data
) eq
"\x03"
,
"Switch with pass: Build: correct3"
);
$s
= Struct(
"foo"
,
Pointer(
sub
{ 4 }, Byte(
"data1"
)),
Pointer(
sub
{ 7 }, Byte(
"data2"
)),
);
$data
= {
data1
=> 1,
data2
=> 2};
$string
=
"\x00\x00\x00\x00\x01\x00\x00\x02"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Pointer: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Pointer: Build: Empty"
);
$s
= Struct(
"foo"
,
Byte(
"padding_length"
),
Padding(
sub
{
$_
->ctx->{padding_length} } ),
Byte(
"relative_offset"
),
Anchor(
"absolute_position"
),
Pointer(
sub
{
$_
->ctx->{absolute_position} +
$_
->ctx->{relative_offset} }, Byte(
"data"
)),
);
$data
= {
relative_offset
=>3,
absolute_position
=>7,
data
=>255,
padding_length
=>5};
$string
=
"\x05\x00\x00\x00\x00\x00\x03\x00\x00\x00\xff"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Pointer n Anchor: Parse: Correct"
);
ok((
$s
->build(
$data
) eq
$string
),
"Pointer n Anchor: Build: Correct"
);
$s
= Struct(
"foo"
,
Byte(
"padding_length"
),
Padding(
sub
{
$_
->ctx->{padding_length} } ),
Byte(
"relative_offset"
),
Pointer(
sub
{
$_
->stream->
tell
+
$_
->ctx->{relative_offset} }, Byte(
"data"
)),
);
$data
= {
relative_offset
=>3,
data
=>255,
padding_length
=>5};
$string
=
"\x05\x00\x00\x00\x00\x00\x03\x00\x00\x00\xff"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Pointer n Anchor: Parse: Correct"
);
ok((
$s
->build(
$data
) eq
$string
),
"Pointer n Anchor: Build: Correct"
);
ok(( String(
"foo"
, 5)->parse(
"hello"
) eq
"hello"
),
"String: Parse: Simple"
);
$s
= String(
"foo"
, 10,
padchar
=>
"X"
,
paddir
=>
"right"
);
ok((
$s
->parse(
"helloXXXXX"
) eq
'hello'
),
"Padded String: Parse: Simple"
);
ok((
$s
->build(
"hello"
) eq
'helloXXXXX'
),
"Padded String: Build: Simple"
);
$s
= PascalString(
"foo"
);
ok((
$s
->parse(
"\x05hello"
) eq
'hello'
),
"PascalString: Parse: Simple"
);
ok((
$s
->build(
"hello world"
) eq
"\x0bhello world"
),
"PascalString: Build: Simple"
);
$s
= PascalString(
"foo"
, \
&UBInt16
);
ok((
$s
->parse(
"\x00\x05hello"
) eq
'hello'
),
"PascalString: Parse: With cutsom length type"
);
ok((
$s
->build(
"hello"
) eq
"\x00\x05hello"
),
"PascalString: Build: With cutsom length type"
);
$s
= CString(
"foo"
);
ok((
$s
->parse(
"hello\x00"
) eq
'hello'
),
"CString: Parse: Simple"
);
ok((
$s
->build(
"hello"
) eq
"hello\x00"
),
"CString: Build: Simple"
);
$s
= CString(
"foo"
,
terminators
=>
"XYZ"
);
ok((
$s
->parse(
"helloX"
) eq
'hello'
),
"CString: Parse: custom terminator1"
);
ok((
$s
->parse(
"helloY"
) eq
'hello'
),
"CString: Parse: custom terminator2"
);
ok((
$s
->parse(
"helloZ"
) eq
'hello'
),
"CString: Parse: custom terminator3"
);
ok((
$s
->build(
"hello"
) eq
"helloX"
),
"CString: Build: custom terminator"
);
$s
= Struct(
"foo"
,
UBInt8(
"width"
),
UBInt8(
"height"
),
Value(
"total_pixels"
,
sub
{
$_
->ctx->{width} *
$_
->ctx->{height}}),
);
is_deeply(
$s
->parse(
"\x05\x05"
), {
width
=> 5,
height
=> 5,
total_pixels
=> 25 },
"Value: Parse: Simple"
);
$data
= {
width
=> 5,
height
=> 5 };
ok((
$s
->build(
$data
) eq
"\x05\x05"
),
"Value: Parse: Ignored"
);
is_deeply(
$data
, {
width
=> 5,
height
=> 5,
total_pixels
=> 25 },
"Value: Parse: Added to hash"
);
$s
= Struct(
"foo"
,
Flag(
"has_options"
),
If(
sub
{
$_
->ctx->{has_options} },
Bytes(
"options"
, 5)
)
);
is_deeply(
$s
->parse(
"\x01hello"
), {
options
=>
'hello'
,
has_options
=> 1 },
"If: Parse: True"
);
is_deeply(
$s
->parse(
"\x00hello"
), {
options
=>
undef
,
has_options
=> 0 },
"If: Parse: False"
);
ok((
$s
->build({
options
=>
undef
,
has_options
=> 0 }) eq
"\0"
),
"If: Build: False"
);
ok((
$s
->build({
options
=>
'hello'
,
has_options
=> 1 }) eq
"\x01hello"
),
"If: Build: True"
);
$s
= Struct(
"foo"
,
Flag(
"long_options"
),
IfThenElse(
"options"
,
sub
{
$_
->ctx->{long_options} },
Bytes(
"Long Options"
, 5),
Bytes(
"Short Options"
, 3),
),
);
is_deeply(
$s
->parse(
"\x01hello"
), {
options
=>
'hello'
,
long_options
=> 1 },
"IfThenElse: Parse: True"
);
is_deeply(
$s
->parse(
"\x00hello"
), {
options
=>
'hel'
,
long_options
=> 0 },
"IfThenElse: Parse: False"
);
ok((
$s
->build({
options
=>
'hel'
,
long_options
=> 0 }) eq
"\0hel"
),
"IfThenElse: Build: False"
);
ok((
$s
->build({
options
=>
'hello'
,
long_options
=> 1 }) eq
"\x01hello"
),
"IfThenElse: Build: True"
);
$s
= Struct(
"foo"
,
Flag(
"has_next"
),
If(
sub
{
$_
->ctx->{has_next} }, LazyBound(
"next"
,
sub
{
$s
})),
);
$data
= {
has_next
=> 1,
next
=> {
has_next
=> 1,
next
=> {
has_next
=> 1,
next
=> {
has_next
=> 0,
next
=>
undef
} } } };
$string
=
"\x01\x01\x01\x00"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"LazyBound: Parse: Correct"
);
ok((
$s
->build(
$data
) eq
$string
),
"LazyBound: Build: Correct"
);
$s
= Struct(
"foo"
,
Byte(
"a"
),
Peek(Byte(
"b"
)),
Byte(
"c"
),
);
is_deeply(
$s
->parse(
"\x01\x02"
), {
a
=>1,
b
=>2,
c
=>2},
"Peek: Parse: Simple"
);
ok((
$s
->build({
a
=>1,
b
=>222,
c
=>2}) eq
"\x01\x02"
),
"Peek: Build: Ignored"
);
$s
= Struct(
"foo"
,
Byte(
"a"
),
Peek(Byte(
"b"
), 3),
UBInt16(
"c"
),
Byte(
"d"
),
Byte(
"e"
),
);
$string
=
"\x01\xaa\xbb\x03\x04"
;
$data
= {
a
=>1,
c
=>43707,
d
=>3,
e
=>4};
is_deeply(
$s
->parse(
$string
), {
%$data
,
b
=>4},
"Far Peek: Parse: Simple"
);
ok((
$s
->build(
$data
) eq
$string
),
"Far Peek: Build: Ignored"
);
$s
= Const(Bytes(
"magic"
, 6),
"FOOBAR"
);
ok((
$s
->parse(
"FOOBAR"
) eq
"FOOBAR"
),
"Const: Parse: OK"
);
eval
{
$s
->parse(
"FOOBAX"
) };
ok( $@,
"Const: Parse: Dies"
);
ok((
$s
->build(
"FOOBAR"
) eq
"FOOBAR"
),
"Const: Build: OK"
);
eval
{
$s
->build(
"FOOBAX"
) };
ok( $@,
"Const: Build: Dies"
);
$s
= Terminator();
ok(( not
defined
$s
->parse(
""
)),
"Terminator: Parse: ok"
);
eval
{
$s
->parse(
"x"
) };
ok( $@,
"Terminator: Parse: dies"
);
ok((
$s
->build({}) eq
""
),
"Terminator: Build: Empty"
);
$s
= Struct(
"foo"
,
Byte(
"a"
),
Alias(
"b"
,
"a"
),
);
is_deeply(
$s
->parse(
"\x03"
), {
a
=>3,
b
=>3},
"Alias: Parse: Simple"
);
$data
= {
a
=>3};
ok((
$s
->build(
$data
) eq
"\x03"
),
"Alias: Build: OK"
);
is_deeply(
$data
, {
a
=>3,
b
=>3},
"Alias: Build: Add value"
);
$data
= {
a
=>3,
b
=>5};
ok((
$s
->build(
$data
) eq
"\x03"
),
"Alias: Build: Ignore b"
);
$s
= Union(
"foo"
,
UBInt32(
"a"
),
UBInt16(
"b"
)
);
is_deeply(
$s
->parse(
"\xaa\xbb\xcc\xdd"
), {
a
=> 2864434397,
b
=> 43707 },
"Union: Parse: Simple"
);
ok((
$s
->build( {
a
=> 2864434397 } ) eq
"\xaa\xbb\xcc\xdd"
),
"Union: Build: a"
);
ok((
$s
->build( {
b
=> 43707 } ) eq
"\xaa\xbb\0\0"
),
"Union: Build: b"
);
$s
= Struct(
"foo"
, Aligned(Byte(
"bbb"
), 8), Byte(
"aaa"
));
$data
= {
bbb
=> 99,
aaa
=>5 };
$string
=
"c\0\0\0\0\0\0\0\5"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Aligned: Parse: Correct"
);
ok((
$s
->build(
$data
) eq
$string
),
"Aligned: Build: Correct"
);
$s
= Bitwise(Struct(
"foo"
,
Padding(2),
Flag(
"myflag"
),
Padding(5),
));
$data
= {
myflag
=> 1};
$string
=
"\x20"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"Bitwise eq BitStruct: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"Bitwise eq BitStruct: Build: correct"
);
$s
= Struct(
"foo1"
,
Byte(
"a"
),
Select(
Const(Byte(
"b1"
), 4),
Const(Byte(
"b2"
), 2),
),
Byte(
"c"
),
);
$s1
= Struct(
"foo1"
,
Byte(
"a"
),
Select(
Const(Byte(
"b1"
), 4),
Const(Byte(
"b2"
), 2),
$DefaultPass
,
),
Byte(
"c"
),
);
$string
=
"\3\4\xb0"
;
$data
= {
a
=>3,
b1
=>4,
c
=>176};
is_deeply(
$s
->parse(
$string
),
$data
,
"Select: Parse: OK1"
);
ok(
$s
->build(
$data
) eq
$string
,
"Select: Build: OK1"
);
is_deeply(
$s1
->parse(
$string
),
$data
,
"Select with Pass: Parse: OK1"
);
ok(
$s1
->build(
$data
) eq
$string
,
"Select with Pass: Build: OK1"
);
$string
=
"\3\2\xb0"
;
$data
= {
a
=>3,
b2
=>2,
c
=>176};
is_deeply(
$s
->parse(
$string
),
$data
,
"Select: Parse: OK2"
);
ok(
$s
->build(
$data
) eq
$string
,
"Select: Build: OK2"
);
is_deeply(
$s1
->parse(
$string
),
$data
,
"Select with Pass: Parse: OK2"
);
ok(
$s1
->build(
$data
) eq
$string
,
"Select with Pass: Build: OK2"
);
$string
=
"\3\3\xb0"
;
$data
= {
a
=>3,
b2
=>3,
c
=>176};
eval
{
$s
->parse(
$string
) };
ok( $@,
"Select: Parse: Failed"
);
eval
{
$s
->build(
$data
) };
ok( $@,
"Select: Build: Failed"
);
$data
= {
a
=>3,
c
=>3};
is_deeply(
$s1
->parse(
$string
),
$data
,
"Select with Pass: Parse: Pass"
);
ok(
$s1
->build(
$data
) eq
"\3\3"
,
"Select with Pass: Build: Pass"
);
$s
= FlagsEnum(ULInt16(
"characteristics"
),
RELOCS_STRIPPED
=> 0x0001,
EXECUTABLE_IMAGE
=> 0x0002,
LINE_NUMS_STRIPPED
=> 0x0004,
LOCAL_SYMS_STRIPPED
=> 0x0008,
AGGRESSIVE_WS_TRIM
=> 0x0010,
LARGE_ADDRESS_AWARE
=> 0x0020,
MACHINE_16BIT
=> 0x0040,
BYTES_REVERSED_LO
=> 0x0080,
MACHINE_32BIT
=> 0x0100,
DEBUG_STRIPPED
=> 0x0200,
REMOVABLE_RUN_FROM_SWAP
=> 0x0400,
SYSTEM
=> 0x1000,
DLL
=> 0x2000,
UNIPROCESSOR_ONLY
=> 0x4000,
BIG_ENDIAN_MACHINE
=> 0x8000,
);
$data
= {};
$string
=
"\0\0"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"FlagsEnum: Parse: Empty"
);
ok(
$s
->build(
$data
) eq
$string
,
"FlagsEnum: Build: Empty"
);
$data
= {
EXECUTABLE_IMAGE
=> 1,
REMOVABLE_RUN_FROM_SWAP
=>1};
$string
=
"\2\4"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"FlagsEnum: Parse: Pass"
);
ok(
$s
->build(
$data
) eq
$string
,
"FlagsEnum: Build: Pass"
);
$string
=
"PNG"
;
$s
= Magic(
$string
);
ok(
$s
->build({ }) eq
$string
,
"Magic: Build: Pass"
);
eval
{
$s
->parse(
$string
) };
ok( (not $@),
"Magic: Parse: OK"
);
eval
{
$s
->parse(
"PXNG"
) };
ok( $@,
"Magic: Parse: Dies"
);
$s
= ReversedBitStruct(
"foo"
,
BitField(
"a"
, 3),
Flag(
"b"
),
Byte(
"c"
),
);
$data
= {
a
=>7,
b
=>0,
c
=>236 };
$string
=
pack
"B*"
,
"0111011100000011"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"ReversedBitStruct: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"ReversedBitStruct: Build: correct"
);
$s
= ReversedBitStruct(
"foo"
,
BitField(
"a"
, 3),
Flag(
"b"
),
ReversedBitField(
"c"
, 8),
);
$data
= {
a
=>7,
b
=>0,
c
=>236 };
$string
=
pack
"B*"
,
"1100011100001110"
;
is_deeply(
$s
->parse(
$string
),
$data
,
"ReversedBitStruct with ReversedBitField: Parse: correct"
);
ok(
$s
->build(
$data
) eq
$string
,
"ReversedBitStruct with ReversedBitField: Build: correct"
);
done_testing();