The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
use gum -types;
use Test::More;

my @exports;
my @typelib = qw(
    aref arrayref bool boolean class classname cref coderef def defined fh
    filehandle glob globref href hashref int integer num number obj object ref
    reference rref regexpref sref scalarref str string nil null undef undefined
    val value
);

@exports = map "type_$_", @typelib;
can_ok 'main', $_ for @exports;

ok type_aref [];
ok do { eval {type_aref ''}; $@ };
ok type_arrayref [];
ok do { eval {type_arrayref ''}; $@ };
ok defined type_bool 1;
ok defined type_bool 0;
ok defined type_bool '';
ok !type_bool undef;
ok do { eval {type_bool 100}; $@ };
ok defined type_boolean 1;
ok defined type_boolean 0;
ok defined type_boolean '';
ok !type_boolean undef;
ok do { eval {type_boolean 100}; $@ };
ok type_class 'Test::More';
ok do { eval {type_class 'Acme::Widget'}; $@ };
ok type_classname 'Test::More';
ok do { eval {type_classname 'Acme::Widget'}; $@ };
ok type_cref sub {};
ok do { eval {type_cref undef}; $@ };
ok type_coderef sub {};
ok do { eval {type_coderef undef}; $@ };
ok defined type_def '';
ok defined type_def 0;
ok do { eval {type_def undef}; $@ };
ok defined type_defined '';
ok defined type_defined 0;
ok do { eval {type_defined undef}; $@ };
ok type_fh do { open my $fh, '<', \''; $fh };
ok do { eval {type_fh \''}; $@ };
ok type_filehandle do { open my $fh, '<', \''; $fh };
ok do { eval {type_filehandle \''}; $@ };
ok type_glob \*Test::More::EXPORT;
ok do { eval {type_glob \''}; $@ };
ok type_globref \*Test::More::EXPORT;
ok do { eval {type_globref \''}; $@ };
ok type_href {};
ok do { eval {type_href \''}; $@ };
ok type_hashref {};
ok do { eval {type_hashref \''}; $@ };
ok type_int 12345;
ok do { eval {type_int 123.45}; $@ };
ok type_integer 12345;
ok do { eval {type_integer 123.45}; $@ };
ok type_num 12345;
ok type_num 123.45;
ok defined type_num 0;
ok do { eval {type_num ''}; $@ };
ok type_number 12345;
ok type_number 123.45;
ok defined type_number 0;
ok do { eval {type_number ''}; $@ };
ok type_obj bless {}, 'main';
ok do { eval {type_obj {}}; $@ };
ok type_object bless {}, 'main';
ok do { eval {type_object {}}; $@ };
ok type_ref \'';
ok type_ref {};
ok type_ref [];
ok do { eval {type_ref ''}; $@ };
ok type_reference \'';
ok type_reference {};
ok type_reference [];
ok do { eval {type_reference ''}; $@ };
ok type_rref qr//;
ok do { eval {type_rref \''}; $@ };
ok type_regexpref qr//;
ok do { eval {type_regexpref \''}; $@ };
ok type_sref \'';
ok do { eval {type_sref {}}; $@ };
ok do { eval {type_sref ''}; $@ };
ok type_scalarref \'';
ok do { eval {type_scalarref {}}; $@ };
ok do { eval {type_scalarref ''}; $@ };
ok defined type_str '';
ok defined type_str 0;
ok do { eval {type_str undef}; $@ };
ok defined type_string '';
ok defined type_string 0;
ok do { eval {type_string undef}; $@ };
ok !type_nil undef;
ok do { eval {type_nil ''}; $@ };
ok do { eval {type_nil 0}; $@ };
ok !type_null undef;
ok do { eval {type_null ''}; $@ };
ok do { eval {type_null 0}; $@ };
ok !type_undef undef;
ok do { eval {type_undef ''}; $@ };
ok do { eval {type_undef 0}; $@ };
ok !type_undefined undef;
ok do { eval {type_undefined ''}; $@ };
ok do { eval {type_undefined 0}; $@ };

@exports = map "typeof_$_", @typelib;
can_ok 'main', $_ for @exports;

ok 'CODE' eq ref typeof_aref;
ok 'CODE' eq ref typeof_arrayref;
ok 'CODE' eq ref typeof_bool;
ok 'CODE' eq ref typeof_boolean;
ok 'CODE' eq ref typeof_class;
ok 'CODE' eq ref typeof_classname;
ok 'CODE' eq ref typeof_cref;
ok 'CODE' eq ref typeof_coderef;
ok 'CODE' eq ref typeof_def;
ok 'CODE' eq ref typeof_defined;
ok 'CODE' eq ref typeof_fh;
ok 'CODE' eq ref typeof_filehandle;
ok 'CODE' eq ref typeof_glob;
ok 'CODE' eq ref typeof_globref;
ok 'CODE' eq ref typeof_href;
ok 'CODE' eq ref typeof_hashref;
ok 'CODE' eq ref typeof_int;
ok 'CODE' eq ref typeof_integer;
ok 'CODE' eq ref typeof_num;
ok 'CODE' eq ref typeof_number;
ok 'CODE' eq ref typeof_obj;
ok 'CODE' eq ref typeof_object;
ok 'CODE' eq ref typeof_ref;
ok 'CODE' eq ref typeof_reference;
ok 'CODE' eq ref typeof_rref;
ok 'CODE' eq ref typeof_regexpref;
ok 'CODE' eq ref typeof_sref;
ok 'CODE' eq ref typeof_scalarref;
ok 'CODE' eq ref typeof_str;
ok 'CODE' eq ref typeof_string;
ok 'CODE' eq ref typeof_nil;
ok 'CODE' eq ref typeof_null;
ok 'CODE' eq ref typeof_undef;
ok 'CODE' eq ref typeof_undefined;

done_testing;