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 )