package testcase;

use v5.22;
use warnings;

use Test2::V0;

use lib "t/blib", "t/blib/arch";

use Data::Checks;

sub import
{
   my $pkg = shift;
   my $caller = caller;
   require XSLoader;
   XSLoader::load( shift, $Data::Checks::VERSION );
   while( @_ ) {
      my $sym = shift;
      my $ref = __PACKAGE__->can( $sym ) or die "Cannot import $sym\n";
      no strict 'refs';
      *{"${caller}::${sym}"} = $ref;
   }
}

sub unimport
{
   die "testcase cannot be unimported";
}

# Some test classes
package BaseClass {
   sub new { bless [], shift }
   sub basem {}
}
package DifferentClass {
   sub new { bless [], shift }
}
package DerivedClass {
   use base qw( BaseClass );
}

package ClassWithStrOverload {
   use overload '""' => sub { "boo" };
   sub new { bless [], shift }
}
package ClassWithNumOverload {
   use overload '0+' => sub { 123 };
   sub new { bless [], shift }
}
package ClassWithArrayRefify {
   sub new { bless [], shift }
   use overload '@{}' => sub {};
}
package ClassWithHashRefify {
   sub new { bless [], shift }
   use overload '%{}' => sub {};
}
package ClassWithCodeRefify {
   sub new { bless [], shift }
   use overload '&{}' => sub {};
}

sub test_constraint
{
   my ( $name, $constraint, $accepts, $rejects ) = @_;
   $rejects //= [];

   subtest "$name constraint" => sub {
      my $checker = t::test::make_checkdata( $constraint, "Value" );

      my %accepted;

      my @accepts = @$accepts;
      while( @accepts ) {
         my $valname = shift @accepts;
         my $value   = shift @accepts;

         ok( t::test::check_value( $checker, $value ), "$name accepts $valname" );
         $accepted{$valname}++;
      }

      my @rejects = @$rejects;
      while( @rejects ) {
         my $valname = shift @rejects;
         my $value   = shift @rejects;

         ok( !t::test::check_value( $checker, $value ), "$name rejects $valname" );
      }

      foreach (
         [ 'undef' => undef ],
         [ 'plain string'   => "a string" ],
         [ 'plain integer'  => 1234 ],
         [ 'plain arrayref' => [] ],
         [ 'plain hashref'  => {} ],
         [ 'plain coderef'  => sub {} ],
         [ 'object'         => BaseClass->new ],
      ) {
         my ( $valname, $value ) = @$_;
         next if $accepted{$valname};

         ok( !t::test::check_value( $checker, $value ), "$name rejects $valname (autogenerated)" );
      }
   }
}

0x55AA;
