#!/usr/bin/perl
#
# Copyright (c) 2018  Peter Pentchev
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

use v5.010;
use strict;
use warnings;

use JSON::XS qw(decode_json);
use Test::More;
use Test::Command;

use lib 't/lib';
use Test::FeatureCheck qw(
	env_init
	get_error_output get_ok_output
	test_fcheck_init
);

my %c = env_init;

my @usage_lines;

plan tests => 6;

test_fcheck_init \%c;

subtest 'Check for list feature support' => sub {
	my @lines = get_ok_output([$c{prog}, '--features'], 'get features');
	is scalar @lines, 1, 'list features output a single line';
	BAIL_OUT('No "Features: " on the features line') unless
	    $lines[0] =~ /^ Features: \s (?<features> .* ) $/x;
	my @words = split /\s+/, $+{features};
	my %names = map { split /[:\/=]/, $_, 2 } @words;
	BAIL_OUT('No "list" in the features list') unless
	    defined $names{'list'};
	BAIL_OUT('Only know how to test the "list" feature version 1.x') unless
	    $names{'list'} =~ m{^ 1 (?: \..* )? $ }x;
};

subtest 'List the features of the fcheck helper' => sub {
	my @lines = get_ok_output([$c{prog}, '-l', $c{fcheck}], 'list fcheck');
	isnt scalar @lines, 0, 'listed at least one feature';
	my @split_lines = map { [split /\t/, $_] } @lines;
	my @res = grep { scalar @{$_} != 2 } @split_lines;
	ok !@res, 'all the lines contain exactly one tab character';
	my %data = map { $_->[0] => $_->[1] } @split_lines;
	ok defined $data{base}, 'got "base"';
	ok !exists $data{x}, 'got no "x"';
};

subtest 'List the features with JSON output' => sub {
	my @lines = get_ok_output([$c{prog}, '-l', '-o', 'json', $c{fcheck}],
	    'list-j fcheck');
	isnt scalar @lines, 0, 'listed at least one feature';
	my $all = join "\n", @lines;
	my $data;
	eval {
		$data = decode_json($all);
	};
	my $err = $@;
	is $err, '', 'the data was successfully decoded';
	is ref $data, 'HASH', 'the data is a JSON object';
	if (ref $data eq 'HASH') {
		ok defined $data->{base}, 'got "base"';
		ok !exists $data->{x}, 'got no "x"';
	} else {
		fail 'got "base"';
		fail 'got no "x"';
	}
};

subtest 'Real work: nonexistent program' => sub {
	my @lines = get_error_output([$c{prog}, '/nonexistent', 'x'],
	    'bad program');
	is scalar @lines, 0, 'bad program output nothing';
};

subtest 'Real work: unfeatured program' => sub {
	my $old_option = $ENV{FCHECK_TEST_OPT};
	$ENV{FCHECK_TEST_OPT} = '--not-features';
	my @lines = get_error_output([$c{prog}, $c{fcheck}, 'x'],
	    'weird program');
	is scalar @lines, 0, 'weird program output nothing';
	$ENV{FCHECK_TEST_OPT} = $old_option;
};
