#!/usr/bin/perl
#
# SPDX-FileCopyrightText: Peter Pentchev <roam@ringlet.net>
# SPDX-License-Identifier: BSD-2-Clause

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 $current_opt = $ENV{FCHECK_TEST_PREFIX};
	plan tests => 5;
	for my $pfx ('Features: ', 'V ', 'something/', '--something', '') {
    		subtest "List prefix '$pfx'" => sub {
			$ENV{FCHECK_TEST_PREFIX} = $pfx || 'EmptyPrefix';

			my @lines = get_ok_output([$c{prog}, '-l', ($pfx ? "-P$pfx" : ('-P', '')), $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"';

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

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;
};
