Affix
view release on metacpan or search on metacpan
t/012_enum.t view on Meta::CPAN
{
package Other::Scope;
use Affix;
use Test2::Tools::Affix qw[ok is];
sub run_test {
Affix::typedef( ScopedEnum => Affix::Enum( [ [ SCOPED_A => 99 ] ] ) );
ok defined &SCOPED_A, 'Constant exported to Other::Scope';
is SCOPED_A(), 99, 'Constant value correct in Other::Scope';
}
}
subtest 'Namespace Isolation' => sub {
Other::Scope::run_test();
ok !defined &SCOPED_A, 'Constant NOT leaked to main package';
};
subtest 'Bitwise Shift' => sub {
my $e = Enum [ [ BIT_0 => '1 << 0' ], [ BIT_1 => '1 << 1' ], [ BIT_5 => '1 << 5' ], [ RSHIFT => '32 >> 2' ] ];
my ( $c, $v ) = $e->resolve();
is $c->{BIT_0}, 1, '1 << 0';
is $c->{BIT_1}, 2, '1 << 1';
is $c->{BIT_5}, 32, '1 << 5';
is $c->{RSHIFT}, 8, '32 >> 2';
};
subtest 'Unary Operators' => sub {
my $e = Enum [ [ NEG => '-5' ], [ NOT => '!0' ], [ BIT_NOT => '~0' ], [ MASK => '~(1 << 2)' ] ];
my ( $c, $v ) = $e->resolve();
is $c->{NEG}, -5, 'Unary minus';
is $c->{NOT}, 1, 'Logical NOT (!0)';
# C enums are signed int. ~0 is -1.
is $c->{BIT_NOT}, -1, 'Bitwise NOT (~0) is -1';
# ~(1<<2) = ~4. In signed 32/64-bit, this is -5.
is $c->{MASK}, -5, 'Complex unary/shift (~(1<<2)) is -5';
};
subtest 'Logical and Ternary' => sub {
my $e = Enum [
[ TRUE_VAL => 10 ],
[ FALSE_VAL => 20 ],
[ TERNARY_T => '1 ? TRUE_VAL : FALSE_VAL' ],
[ TERNARY_F => '0 ? TRUE_VAL : FALSE_VAL' ],
[ LOGIC_AND => '1 && 1' ],
[ LOGIC_OR => '0 || 0' ],
[ CMP_LESS => '10 < 20' ]
];
my ( $c, $v ) = $e->resolve();
is $c->{TERNARY_T}, 10, 'Ternary True';
is $c->{TERNARY_F}, 20, 'Ternary False';
is $c->{LOGIC_AND}, 1, 'Logic AND';
is $c->{LOGIC_OR}, 0, 'Logic OR';
is $c->{CMP_LESS}, 1, 'Comparison <';
};
subtest 'Passing Strings as Enum Values' => sub {
ok typedef( Fruit => Enum [ [ APPLE => 1 ], [ BANANA => 2 ], [ CHERRY => 3 ] ] ), 'typedef Fruit Enum';
affix $lib, 'identify_fruit', [ Fruit() ] => Int;
is identify_fruit( APPLE() ), 1, 'Passed constant APPLE (1)';
is identify_fruit( BANANA() ), 2, 'Passed constant BANANA (2)';
# This is the feature: passing the string name of the enum element
is identify_fruit('APPLE'), 1, 'Passed string "APPLE" -> maps to 1';
is identify_fruit('BANANA'), 2, 'Passed string "BANANA" -> maps to 2';
is identify_fruit('CHERRY'), 3, 'Passed string "CHERRY" -> maps to 3';
like warning { identify_fruit('DURIAN') }, qr[numeric], 'Unknown string "DURIAN" for enum';
};
subtest 'Dualvar Roundtrip' => sub {
affix $lib, 'get_fruit', [Int] => Fruit();
my $f = get_fruit(2);
is 0 + $f, 2, 'Numeric value is 2';
is "$f", 'BANANA', 'String value is "BANANA"';
# Passing the returned dualvar back to C
is identify_fruit($f), 2, 'Passed dualvar $f back to C';
};
subtest 'Calculated Enum Expressions' => sub {
ok typedef(
ComplexEnum => Enum [
[ BASE => 100 ], [ OFFSET => 5 ], [ CALC => 'BASE + OFFSET * 2' ], # 110
'NEXT' # 111
]
),
'typedef ComplexEnum with expressions';
is BASE(), 100, 'BASE is 100';
is OFFSET(), 5, 'OFFSET is 5';
is CALC(), 110, 'CALC is 110 (BASE + OFFSET * 2)';
is NEXT(), 111, 'NEXT is 111 (Auto-increment from CALC)';
};
done_testing;
( run in 0.629 second using v1.01-cache-2.11-cpan-39bf76dae61 )