#!/usr/bin/perl
#
# eg14: much expanded test suite for the frequency utilities module..
#

use strict;
use warnings;
use Function::Parameters qw(:strict);
use Test::More;

my @tests = (			# array of (type, arrayref, expectedstr) triples
	"freq", [1],         "1:1",
	"freq", [2],         "2:1",
	"freq", [1,2],       "1:1,2:1",
	"freq", [1,2,1],     "1:2,2:1",
	"freq", [1,2,1,2],   "1:2,2:2",
	"freq", [1,2,1,3],   "1:2,2:1,3:1",
	"dist", [1],         "1",
	"dist", [2],         "2",
	"dist", [1,2],       "1,2",
	"dist", [1,2,1],     "1,2",
	"dist", [1,2,1,2],   "1,2",
	"dist", [1,2,1,3],   "1,2,3",
	"uniq", [1],         "1",
	"uniq", [2],         "2",
	"uniq", [1,2],       "1,2",
	"uniq", [1,2,1],     "2",
	"uniq", [1,2,1,2],   "",
	"uniq", [1,2,1,3],   "2,3",
	"dnu",  [1],         "",
	"dnu",  [2],         "",
	"dnu",  [1,2],       "",
	"dnu",  [1,2,1],     "1",
	"dnu",  [1,2,1,2],   "1,2",
	"dnu",  [1,2,1,3],   "1",
);

plan tests => 1 + @tests/3;		# how many tests?
use_ok( 'frequtils' );			# first test: can we load module?


#
# my $str = as_string( %hash ):
#	Produce a predictable plain text form of a hash.
#	we've chosen comma separated key:value pairs,
#	sorted by key
#
fun as_string( %hash )
{
	my @k = sort keys %hash;
	return join( ",", map { "$_:$hash{$_}" } @k );
}


#
# $str = wrap_freq( @array ):
#	call build_freq_hash( @array ) and then build
#	and return a predictable (sorted) representation
#	of the result to compare against, as a string
#
fun wrap_freq( @array )
{
	my %freq = build_freq_hash(@array);
	return as_string( %freq );
}

#
# $str = wrap_aha( $func, @array ):
#	general array -> freq hash -> array tester:
#	build %freq = build_freq_hash(@array) and then call
#	@answer = $func->( %freq ), then build and return a
#	predictable (sorted) representation of @answer, as a string
#
fun wrap_aha( $func, @array )
{
	my %freq = build_freq_hash(@array);
	my @n = $func->(%freq);
	my $str = join( ",", sort @n );
	return $str;
}

fun wrap_uniq( @x )     { wrap_aha( \&unique_values, @x ) }
fun wrap_nonuniq( @x )  { wrap_aha( \&distinct_nonunique_values, @x ) }
fun wrap_distinct( @x ) { wrap_aha( \&distinct_values, @x ) }

my %testtype = (		    # type -> [coderef, funcname]
	'freq' => [ \&wrap_freq,     'build_freq_hash' ],
	'uniq' => [ \&wrap_uniq,     'unique_values' ],
	'dnu'  => [ \&wrap_nonuniq,  'distinct_nonunique_values' ],
	'dist' => [ \&wrap_distinct, 'distinct_values' ],
);

#foreach (type,arrayref,expectedstring) triple in @tests
while( (my $type, my $inputarray, my $expected, @tests ) = @tests )
{
	my $input  = join( ',', @$inputarray );
	my( $testfunc, $funcname ) = @{$testtype{$type}};
	my $output   = $testfunc->(@$inputarray);
	is( $output, $expected, "$funcname($input)=$output" );
}
