#!perl -T
use strict;
use Test::More tests => 1+6*26*3+26;
use Data::Dumper;

BEGIN {
	use_ok( 'Hash::WithDefaults' );
}

diag( "Testing Hash::WithDefaults $Hash::WithDefaults::VERSION, Perl $], $^X" );

{ # lower (ARRAYREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'lower', [low => 'value', Mix => 'other', HI => 'Some']),
		"Tied with case=lower"
	);

	is( ref(tied %h), 'Hash::WithDefaults::lower', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(hi low mix);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('hi=Some', 'low=value', 'mix=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(a b)], "There are two keys");

}

{ # lower (HASHREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'lower', {low => 'value', Mix => 'other', HI => 'Some'}),
		"Tied with case=lower"
	);

	is( ref(tied %h), 'Hash::WithDefaults::lower', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(hi low mix);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('hi=Some', 'low=value', 'mix=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(a b)], "There are two keys");

}

{ # lower (LIST)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'lower', low => 'value', Mix => 'other', HI => 'Some'),
		"Tied with case=lower"
	);

	is( ref(tied %h), 'Hash::WithDefaults::lower', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(hi low mix);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('hi=Some', 'low=value', 'mix=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(a b)], "There are two keys");

}

{ # lower (LIST), direct
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults::lower', low => 'value', Mix => 'other', HI => 'Some'),
		"Tied with case=lower"
	);

	is( ref(tied %h), 'Hash::WithDefaults::lower', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(hi low mix);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('hi=Some', 'low=value', 'mix=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(a b)], "There are two keys");

}

{ # upper (ARRAYREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'upper', [low => 'value', Mix => 'other', HI => 'Some']),
		"Tied with case=upper"
	);

	is( ref(tied %h), 'Hash::WithDefaults::upper', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI LOW MIX);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'LOW=value', 'MIX=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(A B)], "There are two keys");

}

{ # upper (HASHREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'upper', {low => 'value', Mix => 'other', HI => 'Some'}),
		"Tied with case=upper"
	);

	is( ref(tied %h), 'Hash::WithDefaults::upper', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI LOW MIX);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'LOW=value', 'MIX=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(A B)], "There are two keys");

}

{ # upper (LIST)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'upper', low => 'value', Mix => 'other', HI => 'Some'),
		"Tied with case=upper"
	);

	is( ref(tied %h), 'Hash::WithDefaults::upper', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI LOW MIX);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'LOW=value', 'MIX=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(A B)], "There are two keys");

}


{ # preserve (ARRAYREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'preserve', [low => 'value', Mix => 'other', HI => 'Some']),
		"Tied with case=preserve"
	);

	is( ref(tied %h), 'Hash::WithDefaults::preserve', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI Mix low);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'Mix=other', 'low=value');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(B a)], "There are two keys");

}

{ # preserve (HASHREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'preserve', {low => 'value', Mix => 'other', HI => 'Some'}),
		"Tied with case=preserve"
	);

	is( ref(tied %h), 'Hash::WithDefaults::preserve', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI Mix low);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'Mix=other', 'low=value');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(B a)], "There are two keys");

}

{ # preserve (LIST)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'preserve', low => 'value', Mix => 'other', HI => 'Some'),
		"Tied with case=preserve"
	);

	is( ref(tied %h), 'Hash::WithDefaults::preserve', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, 'value', '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, 'Some', '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI Mix low);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'Mix=other', 'low=value');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{Low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 1, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(B a)], "There are two keys");

}


{ # tolower (ARRAYREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'tolower', [low => 'value', Mix => 'other', HI => 'Some']),
		"Tied with case=tolower"
	);

	is( ref(tied %h), 'Hash::WithDefaults::tolower', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, undef, '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(hi low mix);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('hi=Some', 'low=value', 'mix=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(a b)], "There are two keys");

}

{ # tolower (HASHREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'tolower', {low => 'value', Mix => 'other', HI => 'Some'}),
		"Tied with case=tolower"
	);

	is( ref(tied %h), 'Hash::WithDefaults::tolower', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, undef, '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(hi low mix);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('hi=Some', 'low=value', 'mix=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(a b)], "There are two keys");

}

{ # tolower (LIST)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'tolower', low => 'value', Mix => 'other', HI => 'Some'),
		"Tied with case=tolower"
	);

	is( ref(tied %h), 'Hash::WithDefaults::tolower', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	is( $h{hi}, 'Some', '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, undef, '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(hi low mix);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('hi=Some', 'low=value', 'mix=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, 'other', '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(a b)], "There are two keys");

}


{ # toupper (ARRAYREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'toupper', [low => 'value', Mix => 'other', HI => 'Some']),
		"Tied with case=toupper"
	);

	is( ref(tied %h), 'Hash::WithDefaults::toupper', "Tied to the right class");

	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, undef, '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI LOW MIX);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'LOW=value', 'MIX=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{LOW};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(A B)], "There are two keys");

}

{ # toupper (HASHREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'toupper', {low => 'value', Mix => 'other', HI => 'Some'}),
		"Tied with case=toupper"
	);

	is( ref(tied %h), 'Hash::WithDefaults::toupper', "Tied to the right class");

	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, undef, '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI LOW MIX);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'LOW=value', 'MIX=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{LOW};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(A B)], "There are two keys");

}

{ # toupper (LIST)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'toupper', low => 'value', Mix => 'other', HI => 'Some'),
		"Tied with case=toupper"
	);

	is( ref(tied %h), 'Hash::WithDefaults::toupper', "Tied to the right class");

	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, 'value', '$h{LOW}');

	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	is( $h{hi}, undef, '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI LOW MIX);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'LOW=value', 'MIX=other');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{LOW};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{Mix};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, undef, '$h{Mix}');
	is( $h{MIX}, 'other', '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(A B)], "There are two keys");

}


{ # sensitive (ARRAYREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'sensitive', [low => 'value', Mix => 'other', HI => 'Some']),
		"Tied with case=sensitive"
	);

	is( ref(tied %h), 'Hash::WithDefaults::sensitive', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	is( $h{hi}, undef, '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI Mix low);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'Mix=other', 'low=value');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{MIX};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(B a)], "There are two keys");

}

{ # sensitive (HASHREF)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'sensitive', {low => 'value', Mix => 'other', HI => 'Some'}),
		"Tied with case=sensitive"
	);

	is( ref(tied %h), 'Hash::WithDefaults::sensitive', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	is( $h{hi}, undef, '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI Mix low);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'Mix=other', 'low=value');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{MIX};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(B a)], "There are two keys");

}

{ # sensitive (LIST)
	my %h;
	ok(
		tie( %h, 'Hash::WithDefaults', 'sensitive', low => 'value', Mix => 'other', HI => 'Some'),
		"Tied with case=sensitive"
	);

	is( ref(tied %h), 'Hash::WithDefaults::sensitive', "Tied to the right class");

	is( $h{low}, 'value', '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	is( $h{hi}, undef, '$h{hi}');
	is( $h{Hi}, undef, '$h{Hi}');
	is( $h{HI}, 'Some', '$h{HI}');

	my @got = sort keys %h;
	my @good = qw(HI Mix low);

	is_deeply(\@got, \@good, "List of keys");

	@got = ();
	while (my ($key, $val) = each %h) {
		push @got, "$key=$val";
	}
	@got = sort @got;
	@good = ('HI=Some', 'Mix=other', 'low=value');
	is_deeply(\@got, \@good, "each() returns both keys and values");

	is( scalar( keys %h), 3, "Number of keys");

	delete $h{low};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{low}, undef, '$h{low}');
	is( $h{Low}, undef, '$h{Low}');
	is( $h{LOW}, undef, '$h{LOW}');

	delete $h{MIX};
	is( scalar( keys %h), 2, "Number of keys after delete");
	is( $h{mix}, undef, '$h{mix}');
	is( $h{Mix}, 'other', '$h{Mix}');
	is( $h{MIX}, undef, '$h{MIX}');

	%h = ();
	is( scalar( keys %h), 0, "Number of keys after clear");
	is_deeply( [keys %h], [], "There are no keys");

	$h{a} = 1; $h{B} = 2;
	is( scalar( keys %h), 2, "Number of keys after refil");
	is_deeply( [sort keys %h], [qw(B a)], "There are two keys");

}
