#!/usr/bin/perl

use strict;
use 5.6.0;
use warnings;

use File::Spec;
use POSIX;
use Text::Diff;
use File::Find;
use IO::Handle;
use IPC::Open3;
use IO::File;

my $fail = 0;

sub compare_str
  {
    my $desc = shift;
    my $expect = shift;
    my $got = shift;

    return if $expect eq $got;

    print STDERR "Differences in $desc\n";
    if (length $expect)
      {
        diff \$expect, \$got, {STYLE => 'Unified', OUTPUT => \*STDOUT};
      }
    else
      {
        print STDERR "Expected nothing, got:\n";
        print STDERR "---\n";
        print STDERR $got;
        print STDERR "---\n"
      }
    $fail = 1;
  }

sub compare_int
  {
    my $desc = shift;
    my $expect = shift;
    my $got = shift;

    return if $expect == $got;

    print STDERR "Differences in $desc: expected $expect, got $got\n";
    $fail = 1;
  }

my ($perl_output, $perl_errors, $perl_result) = ("", "", undef);

{
  my ($write, $read, $err) = (new IO::Handle, new IO::Handle, new IO::Handle);
  $ENV{ICHECK_PARSER_XSUB} = 0;
  my @cmd = ('./icheck', @ARGV);
  if ($ENV{TEST_VERBOSE})
    {
      print "ICHECK_PARSER_XSUB=0 " . join(' ', @cmd) . "\n";
    }
  my $pid = open3($write, $read, $err, @cmd);

  close $write;

  $perl_output .= $_ while <$read>;
  close $read;

  $perl_errors .= $_ while <$err>;
  close $err;

  waitpid $pid, 0;
  if (WIFSIGNALED($?))
    {
      die "icheck killed by signal " . WTERMSIG($?) . "\n";
    }

  unless (WIFEXITED($?))
    {
      die "icheck died wierdly (waitpid gave $?)\n";
    }

  $perl_result = WEXITSTATUS($?);
}

if (length $perl_errors)
  {
    print STDERR $perl_errors;
  }

print STDOUT $perl_output;

my ($xsub_output, $xsub_errors, $xsub_result) = ("", "", undef);

{
  my ($write, $read, $err) = (new IO::Handle, new IO::Handle, new IO::Handle);
  $ENV{ICHECK_PARSER_XSUB} = 1;
  my @cmd = ('./icheck', @ARGV);
  if ($ENV{TEST_VERBOSE})
    {
      print "ICHECK_PARSER_XSUB=1 " . join(' ', @cmd) . "\n";
    }
  my $pid = open3($write, $read, $err, @cmd);

  close $write;

  $xsub_output .= $_ while <$read>;
  close $read;

  $xsub_errors .= $_ while <$err>;
  close $err;

  waitpid $pid, 0;
  if (WIFSIGNALED($?))
    {
      die "icheck killed by signal " . WTERMSIG($?) . "\n";
    }

  unless (WIFEXITED($?))
    {
      die "icheck died wierdly (waitpid gave $?)\n";
    }

  $xsub_result = WEXITSTATUS($?);
}

compare_str('output', $perl_errors, $xsub_errors);
compare_str('errors', $perl_errors, $xsub_errors);
compare_int('result', $perl_result, $xsub_result);

exit 1 if $fail;
