use lib qw(t);
use Carp;
use Hash::AutoHash::Record;
use Test::More;
use Test::Deep;
use recordUtil;

################################################################################
# SYNOPSIS
################################################################################

use Hash::AutoHash::Record qw(autohash_set);

# create object and define field-types
#   name- single-valued, hobbies- multi-valued,
#   favorites- attribute-(single-)value pairs, 
#   family- attribute-(multi-)value pairs
# note: when used as initial value, 
#   {}  means empty attribute-(single-)value pairs
#   \{} means empty attribute-(multi-)value pairs

my $record=
  new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
cmp_record('create object and set intial values',$record,
	   {name=>'',hobbies=>[],favorites=>new_SV,family=>new_MV});

# set fields
autohash_set($record,
	     name=>'Joe',hobbies=>['chess','cooking'],
	     favorites=>{color=>'purple',food=>'pie'},
	     family=>{wife=>'Mary',sons=>['Tom','Dick']});
cmp_record('set fields',$record,
	   {name=>'Joe',hobbies=>[qw(chess cooking)],
	    favorites=>new_SV(color=>'purple',food=>'pie'),
	    family=>new_MV(wife=>'Mary',sons=>'Tom',sons=>'Dick')});

# update fields one-by-one
$record->name('Joey');		      # change name to 'Joey'
$record->hobbies('go');		      # add 'go' to hobbies
$record->favorites(color=>'red');     # change favorite color to 'red'
$record->family(daughters=>'Jane');   # add daughter 'Jane' to family
cmp_record('update fields one-by-one',$record,
	   {name=>'Joey',hobbies=>[qw(chess cooking go)],
	    favorites=>new_SV(color=>'red',food=>'pie'),
	    family=>new_MV(wife=>'Mary',sons=>['Tom','Dick'],daughters=>'Jane')});

# access fields one-by-one
my $name=$record->name;		    # 'Joey'
is($name,'Joey','access fields one-by-one: single-valued');
my $hobbies=$record->hobbies;	    # ['chess','cooking','go']
cmp_deeply($hobbies,[qw(chess cooking go)],
	   'access fields one-by-one: multi-valued. scalar context');
my @hobbies=$record->hobbies;	    # ('chess','cooking','go')
cmp_deeply(\@hobbies,[qw(chess cooking go)],
	   'access fields one-by-one: multi-valued. array context');
my $favorites=$record->favorites;   # Hash::AutoHash in scalar context
cmp_deeply($favorites,new_SV(color=>'red',food=>'pie'),
	   'access fields one-by-one: attribute-(single-)-valued. scalar context');
my %favorites=$record->favorites;   # regular hash in array context
cmp_deeply(\%favorites,{color=>'red',food=>'pie'},
	   'access fields one-by-one: attribute-(single-)-valued. array context');
my $family=$record->family;	    # Hash::AutoHash::MultiValued
cmp_deeply($family,new_MV(wife=>'Mary',sons=>['Tom','Dick'],daughters=>'Jane'),
	   'access fields one-by-one: attribute-(multi-)valued. scalar context');
my %family=$record->family;	    # regular hash
cmp_deeply(\%family,{wife=>['Mary'],sons=>['Tom','Dick'],daughters=>['Jane']},
	   'access fields one-by-one: attribute-(multi-)valued. array context');

# you can also use standard hash notation and functions
$record->{name}='Joseph';	# set name to 'Joseph'
$record->{hobbies}='rowing';	# add 'rowing' to hobbies
$record->{favorites}={holiday=>'Christmas'}; # add favorite holiday
$record->{family}={daughters=>'Sue'}; # add 2nd daughter 'Sue' to family
cmp_record('update fields one-by-one using standard hash notation',$record,
	   {name=>'Joseph',hobbies=>[qw(chess cooking go rowing)],
	    favorites=>new_SV(color=>'red',food=>'pie',holiday=>'Christmas'),
	    family=>new_MV(wife=>'Mary',sons=>['Tom','Dick'],daughters=>['Jane','Sue'])});

# CAUTION: hash notation doesn't respect array context!
$record->{hobbies}=('hiking','baking');	# adds last value only
cmp_record('update fields: hash notation does not respect array context',$record,
	   {name=>'Joseph',hobbies=>[qw(chess cooking go rowing baking)],
	    favorites=>new_SV(color=>'red',food=>'pie',holiday=>'Christmas'),
	    family=>new_MV(wife=>'Mary',sons=>['Tom','Dick'],daughters=>['Jane','Sue'])});
my @hobbies=$record->{hobbies};	      # list of ARRAY (['chess',...])
cmp_deeply(\@hobbies,[['chess','cooking','go','rowing','baking']],
	   'access fields: hash notation does not respect array context');

my @keys=keys %$record;		      # list of all 4 keys
cmp_bag(\@keys,[qw(name hobbies favorites family)],'keys');
my @values=values %$record;	      # list of all 4 values
cmp_bag(\@values,['Joseph',[qw(chess cooking go rowing baking)],
		  new_SV(color=>'red',food=>'pie',holiday=>'Christmas'),
		  new_MV(wife=>'Mary',sons=>['Tom','Dick'],daughters=>['Jane','Sue'])],'values');
delete $record->{hobbies};	      # no more hobbies
cmp_record('delete hobbies',$record,
	   {name=>'Joseph',
	    favorites=>new_SV(color=>'red',food=>'pie',holiday=>'Christmas'),
	    family=>new_MV(wife=>'Mary',sons=>['Tom','Dick'],daughters=>['Jane','Sue'])});

# clearing object restores initial values and preserves field-types
%$record=();                             
cmp_record('clearing object restores initial values',$record,
	   {name=>'',hobbies=>[],favorites=>new_SV,family=>new_MV});

# alias $record to regular hash for more concise hash notation
use Hash::AutoHash::Record qw(autohash_alias);
my %hash;
autohash_alias($record,%hash);
cmp_record('autohash_alias',$record,
	   {name=>'',hobbies=>[],favorites=>new_SV,family=>new_MV},
	   \%hash);

# access or change hash elements without using ->
$hash{name}='Joe';		      # set name to 'Joe'
@hash{qw(hobbies favorites family)}=   # set remaining fields
  (['chess','cooking'],
   {color=>'purple',food=>'pie'},
   {wife=>'Mary',sons=>['Tom','Dick']});
cmp_record('update via alias',$record,
	   {name=>'Joe',hobbies=>['chess','cooking'],
	    favorites=>new_SV(color=>'purple',food=>'pie'),
	    family=>new_MV(wife=>'Mary',sons=>['Tom','Dick'])},
	   \%hash);

my $name=$hash{name};	   # get 1 field
is($name,'Joe','access 1 field via alias');
my($hobbies,$favorites,$family)=   # get remaining fields
  @hash{qw(hobbies favorites family)};
cmp_deeply([$hobbies,$favorites,$family],
	   [['chess','cooking'],
	    new_SV(color=>'purple',food=>'pie'),
	    new_MV(wife=>'Mary',sons=>['Tom','Dick'])],'access remaining fields via alias');

# set 'unique' in tied object to eliminate duplicates in multi-valued fields
use Hash::AutoHash::Record qw(autohash_tied);
autohash_tied($record)->unique(1);
$record->hobbies('chess','skiing'); # duplicate 'chess' not added
cmp_record('update after setting unique',$record,
	   {name=>'Joe',hobbies=>['chess','cooking','skiing'],
	    favorites=>new_SV(color=>'purple',food=>'pie'),
	    family=>new_MV(wife=>'Mary',sons=>['Tom','Dick'])},
	   \%hash);

# field can also be any Hash::AutoHash object, including Record (!!)
my $address=new Hash::AutoHash::Record lines=>[],city=>'',state=>'',zip=>'';
cmp_record('create address',$address,{lines=>[],city=>'',state=>'',zip=>''});
$record->address($address);	# add empty address to record
cmp_record('add address to record',$record,
	   {name=>'Joe',hobbies=>['chess','cooking','skiing'],
	    favorites=>new_SV(color=>'purple',food=>'pie'),
	    family=>new_MV(wife=>'Mary',sons=>['Tom','Dick']),address=>$address},
	   \%hash);
# set fields of nested record
$record->address(lines=>['Suite 123','456 Main St'],city=>'Anytown',
		 state=>'WA',zip=>98765);
cmp_record('set fields of nested record via address',$address,
	   {lines=>['Suite 123','456 Main St'],city=>'Anytown',state=>'WA',zip=>98765});
cmp_record('check record after setting fields of nested record',$record,
	   {name=>'Joe',hobbies=>['chess','cooking','skiing'],
	    favorites=>new_SV(color=>'purple',food=>'pie'),
	    family=>new_MV(wife=>'Mary',sons=>'Tom',sons=>'Dick'),address=>$address},
	   \%hash);
my $state=$record->address->state; # get field from nested record
is($state,'WA','get field from nested record');

################################################################################
# DESCRIPTION
################################################################################
#### Capabilities inherited from Hash::AutoHash
use Hash::AutoHash::Record qw(autohash_keys autohash_delete);
my $record=new Hash::AutoHash::Record name=>'',hobbies=>[];
cmp_record('hash functions inherited from Hash::AutoHash: create object',$record,
	   {name=>'',hobbies=>[]});
my @keys=autohash_keys($record);
cmp_bag(\@keys,[qw(name hobbies)],'autohash_keys');
for my $key (@keys) {
  my $value=$record->$key;
  autohash_delete($record,$key) if 'ARRAY' eq ref $value && !@$value;
}
cmp_record('autohash_delete',$record,{name=>''});

#### Initial values
my $record=new Hash::AutoHash::Record
  avp_single=>{attr1=>'value1'},avp_multi=>{attr2=>['value21','value22']},
  hash=>{key3=>{key31=>'value31'}};
cmp_record('initial unblessed HASH',$record,
	   {avp_single=>new_SV(attr1=>'value1'),avp_multi=>new_MV(attr2=>['value21','value22']),
	    hash=>{key3=>{key31=>'value31'}}});
my $record=new Hash::AutoHash::Record hash=>bless {};
cmp_record('initial value workaround hash',$record,{hash=>bless {}});

my $record=new Hash::AutoHash::Record
  avp_multi1=>\{attr1=>'value1'},avp_multi2=>{attr2=>['value21','value22']},
hash=>{key3=>{key31=>'value31'}};
cmp_record('initial unblessed reference to unblessed HASH',$record,
	   {avp_multi1=>new_MV(attr1=>'value1'),avp_multi2=>new_MV(attr2=>['value21','value22']),
	    hash=>{key3=>{key31=>'value31'}}});
my $record=new Hash::AutoHash::Record ref_to_hash=>\bless {};
cmp_record('initial value workaround ref hash',$record,{ref_to_hash=>\bless {}});

#### Field-update semantics
## Single-valued
$record=new Hash::AutoHash::Record single=>'value1';
$record->single('value2');                  # sets field to 'value2'
cmp_record('update semantics: scalar',$record,{single=>'value2'});
eval {$record->single('value3','value4')};  # illegal. multiple new values
ok($@=~/Trying to store multiple values in single-valued/,'ILLEGAL. scalar: multiple new values');

## Multi-valued
$record=new Hash::AutoHash::Record multi=>['value1'];
$record->multi('value2');                  # appends 'value2' to old value
$record->multi('value3','value4');         # appends 'value3','value4'
$record->multi(['value4','value5']);       # appends 'value4','value5'
eval {$record->multi({key6=>'value6'})};   # illegal - reference  
ok($@=~/Trying to store reference in multi-valued/,'ILLEGAL. multi-valued: storing reference');
cmp_record('update semantics: multi-valued',$record,
	   {multi=>[qw(value1 value2 value3 value4 value4 value5)]});

## Collection of attribute-(single-)value pairs
$record=new Hash::AutoHash::Record avp_single=>{attr1=>'value1'};
$record->avp_single(attr1=>'new_value1'); # sets attr1 to 'new_value1'
$record->avp_single(attr2=>'value2');	  # adds attr2=>'value2'
$record->avp_single([attr3=>'value3']);	  # adds attr3=>'value3'
$record->avp_single({attr4=>'value4'});	  # adds attr4=>'value4'
eval {$record->avp_single(attr5=>['value5'])}; # illegal - value is reference
ok($@=~/Trying to store reference/,'ILLEGAL. atribute-single-value: storing reference');
  $record->avp_single('attr6');              # ignored. no value
  cmp_record('update semantics: avp-single-valued',$record,
	     {avp_single=>
	      new_SV(attr1=>'new_value1',attr2=>'value2',attr3=>'value3',attr4=>'value4')});

## Collection of attribute-(multi-)value pairs
$record=new Hash::AutoHash::Record avp_multi=>\{attr1=>'value1'};
$record->avp_multi(attr1=>'new_value1');   # appends 'new_value1' to attr1
$record->avp_multi(attr2=>'value2');	   # adds attr2=>'value2'
$record->avp_multi([attr2=>'new_value2']); # appends 'new_value2 to attr2
$record->avp_multi({attr3=>'value3'});	   # adds attr3=>'value3'
$record->avp_multi(attr3=>['new_value3']); # appends new_value3 to attr3
eval {$record->avp_multi(attr4=>{key=>value})};   # illegal - value is reference
ok($@=~/Trying to store reference/,'ILLEGAL. atribute-multi-value: storing reference');
  $record->avp_multi('attr5');               # ignored. no value
  cmp_record('update semantics: avp-multi-valued',$record,
	     {avp_multi=>
	      new_MV(attr1=>['value1','new_value1'],
		     attr2=>['value2','new_value2'],
		     attr3=>['value3','new_value3'])});

##  Hash::AutoHash object
$autohash=new Hash::AutoHash key1=>'value1';
$record=new Hash::AutoHash::Record autohash=>$autohash;
$record->autohash(key1=>'new_value1');     # runs $autohash->key1('new_value1')
$record->autohash(key2=>'value2');         # runs $autohash->key2('value2')
$record->autohash('key3');	           # ignored. no value
cmp_record('update semantics: autohash',$record,
	   {autohash=>new Hash::AutoHash(key1=>'new_value1',key2=>'value2')});

#### Duplicate elimination and filtering (multi-valued fields only!!)
use Hash::AutoHash::Record qw(autohash_tied);
my $record=new Hash::AutoHash::Record hobbies=>['chess','chess'];
autohash_tied($record)->unique(1);        # hobbies now ['chess']
$record->hobbies('chess');                # duplicate 'chess' not added
cmp_record('unique',$record,{hobbies=>['chess']});
$record->hobbies('go');                   # hobbies now ['chess','go']
%$record=();                              # hobbies now ['chess']
cmp_record('unique clear',$record,{hobbies=>['chess']});

sub uniq_nocase_sort {
  my %uniq;
  my @values_lc=map { lc($_) } @_;
  @uniq{@values_lc}=@_;
  sort values %uniq;  
}

my $record=new Hash::AutoHash::Record hobbies=>['CHESS','chess','go'];
autohash_tied($record)->filter(\&uniq_nocase_sort);
cmp_record('filter function',$record,{hobbies=>['chess','go']});

my $record=new Hash::AutoHash::Record hobbies=>['CHESS','chess','go'];
autohash_tied($record)->filter(sub {my %u; @u{map {lc $_} @_}=@_; sort values %u});
cmp_record('filter cryptic one-liner',$record,{hobbies=>['chess','go']});

#### Functions and methods
## new
my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
cmp_record('new',$record,{name=>'',hobbies=>[],favorites=>new_SV,family=>new_MV});

## defaults
my $i=1;
my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
%defaults=tied(%$record)->defaults;
cmp_deeply(\%defaults,{name=>'',hobbies=>[],favorites=>new_SV,family=>new_MV},
	   "defaults form ".$i++);

$defaults=tied(%$record)->defaults;
cmp_deeply($defaults,{name=>'',hobbies=>[],favorites=>new_SV,family=>new_MV},
	   "defaults form ".$i++);

my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
tied(%$record)->defaults(name=>'Joe',hobbies=>['chess']);
$defaults=tied(%$record)->defaults;
cmp_deeply($defaults,{name=>'Joe',hobbies=>['chess']},"defaults form ".$i++);

my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
tied(%$record)->defaults([name=>'Joe',hobbies=>['chess']]);
$defaults=tied(%$record)->defaults;
cmp_deeply($defaults,{name=>'Joe',hobbies=>['chess']},"defaults form ".$i++);

my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
tied(%$record)->defaults({name=>'Joe',hobbies=>['chess']});
$defaults=tied(%$record)->defaults;
cmp_deeply($defaults,{name=>'Joe',hobbies=>['chess']},"defaults form ".$i++);

my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
%defaults=autohash_tied($record)->defaults;
cmp_deeply(\%defaults,{name=>'',hobbies=>[],favorites=>new_SV,family=>new_MV},
	   "defaults form ".$i++);

my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
$defaults=autohash_tied($record)->defaults;
cmp_deeply($defaults,{name=>'',hobbies=>[],favorites=>new_SV,family=>new_MV},
	   "defaults form ".$i++);

my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
autohash_tied($record)->defaults(name=>'Joe',hobbies=>['chess']);
$defaults=autohash_tied($record)->defaults;
cmp_deeply($defaults,{name=>'Joe',hobbies=>['chess']},"defaults form ".$i++);

my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
autohash_tied($record)->defaults([name=>'Joe',hobbies=>['chess']]);
$defaults=autohash_tied($record)->defaults;
cmp_deeply($defaults,{name=>'Joe',hobbies=>['chess']},"defaults form ".$i++);

my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
autohash_tied($record)->defaults({name=>'Joe',hobbies=>['chess']});
$defaults=autohash_tied($record)->defaults;
cmp_deeply($defaults,{name=>'Joe',hobbies=>['chess']},"defaults form ".$i++);

## force
my $i=1;
my $record=new Hash::AutoHash::Record name=>'',hobbies=>[],favorites=>{},family=>\{};
my $force=tied(%$record)->force('favorites',{colors=>['red','blue']});
cmp_record("force form $i",$record,
	   {name=>'',hobbies=>[],favorites=>new_MV(colors=>['red','blue']),family=>new_MV});
cmp_deeply($force,new_MV(colors=>['red','blue']),'force form '.$i++.' return value');
my $force=tied(%$record)->force('favorites');
cmp_record("force form $i",$record,{name=>'',hobbies=>[],favorites=>undef,family=>new_MV});
is($force,undef,'force form '.$i++.' return value');
my $force=autohash_tied($record)->force('favorites',{colors=>['red','blue']});
cmp_record("force form $i",$record,
	   {name=>'',hobbies=>[],favorites=>new_MV(colors=>['red','blue']),family=>new_MV});
cmp_deeply($force,new_MV(colors=>['red','blue']),'force form '.$i++.' return value');
my $force=autohash_tied($record)->force('favorites');
cmp_record("force form $i",$record,{name=>'',hobbies=>[],favorites=>undef,family=>new_MV});
is($force,undef,'force form '.$i++.' return value');

## unique
my $boolean=1;
sub function1 {lc($_[0]) eq lc($_[1])}

my $record=new Hash::AutoHash::Record hobbies=>['go','go'];
my $unique=tied(%$record)->unique;
cmp_record('unique form 1',$record,{hobbies=>[qw(go go)]});
ok(!$unique,'value returned by unique form 1');

my $record=new Hash::AutoHash::Record hobbies=>['go','go'];
tied(%$record)->unique($boolean);
cmp_record('unique form 2',$record,{hobbies=>[qw(go)]});

my $record=new Hash::AutoHash::Record hobbies=>['chess','GO','go'];
tied(%$record)->unique(\&function1);
cmp_record('unique form 3',$record,{hobbies=>[qw(chess GO)]});

my $record=new Hash::AutoHash::Record hobbies=>['go','go'];
my $unique=autohash_tied($record)->unique;
cmp_record('unique form 4',$record,{hobbies=>[qw(go go)]});
ok(!$unique,'value returned by unique form 4');

my $record=new Hash::AutoHash::Record hobbies=>['go','go'];
autohash_tied($record)->unique($boolean);
cmp_record('unique form 5',$record,{hobbies=>[qw(go)]});

my $record=new Hash::AutoHash::Record hobbies=>['chess','GO','go'];
autohash_tied($record)->unique(\&function1);
cmp_record('unique form 6',$record,{hobbies=>[qw(chess GO)]});

## filter
my $boolean=1;
sub function2 {my %u; @_=map {lc $_} @_; @u{@_}=@_; values %u}

my $record=new Hash::AutoHash::Record hobbies=>['go','go'];
my $filter=tied(%$record)->filter;
cmp_record('filter form 1',$record,{hobbies=>[qw(go go)]});
ok(!$filter,'value returned by filter form 1');

my $record=new Hash::AutoHash::Record hobbies=>['go','go'];
tied(%$record)->filter($boolean);
cmp_record('filter form 2',$record,{hobbies=>[qw(go)]});

my $record=new Hash::AutoHash::Record hobbies=>['GO','go'];
tied(%$record)->filter(\&function2);
cmp_record('filter form 3',$record,{hobbies=>[qw(go)]});

my $record=new Hash::AutoHash::Record hobbies=>['go','go'];
my $filter=autohash_tied($record)->filter;
cmp_record('filter form 4',$record,{hobbies=>[qw(go go)]});
ok(!$filter,'value returned by filter form 4');

my $record=new Hash::AutoHash::Record hobbies=>['go','go'];
autohash_tied($record)->filter($boolean);
cmp_record('filter form 5',$record,{hobbies=>[qw(go)]});

my $record=new Hash::AutoHash::Record hobbies=>['GO','go'];
autohash_tied($record)->filter(\&function2);
cmp_record('filter form 6',$record,{hobbies=>[qw(go)]});

## functions inherited from Hash::AutoHash
use Hash::AutoHash::Record
  qw(autohash_alias autohash_tied autohash_get autohash_set
     autohash_clear autohash_delete autohash_each autohash_exists 
     autohash_keys autohash_values 
     autohash_count autohash_empty autohash_notempty);
my $record=new Hash::AutoHash::Record name=>'Joe',hobbies=>['chess','cooking'];
my(%hash,$tied,$result);
autohash_alias($record,%hash);
cmp_record('create example for autohash_alias',$record,
	   {name=>'Joe',hobbies=>[qw(chess cooking)]},\%hash);

$tied=autohash_tied($record);
cmp_record('autohash_tied form 1',$record,
	   {name=>'Joe',hobbies=>[qw(chess cooking)]},\%hash,$tied);
$tied=autohash_tied(%hash);
cmp_record('autohash_tied form 2',$record,
	   {name=>'Joe',hobbies=>[qw(chess cooking)]},\%hash,$tied);
$result=autohash_tied($record,'FETCH','name');
cmp_deeply($result,'Joe','autohash_tied form 3');
$result=autohash_tied(%hash,'FETCH','name');
cmp_deeply($result,'Joe','autohash_tied form 4');

($name,$hobbies)=autohash_get($record,qw(name hobbies));
cmp_deeply([$name,$hobbies],['Joe',[qw(chess cooking)]],'autohash_get');

autohash_set($record,name=>'Plumber',first_name=>'Joe');
cmp_record('autohash_set',$record,
	   {name=>'Plumber',first_name=>'Joe',hobbies=>[qw(chess cooking)]});

autohash_clear($record);
cmp_record('autohash_clear',$record,
	   {name=>'Joe',hobbies=>[qw(chess cooking)]},\%hash);
### TBD clear @keys

my $record=new Hash::AutoHash::Record name=>'Joe',first_name=>'Joe',hobbies=>[qw(chess cooking)];
cmp_record('create example again',$record,
	   {name=>'Joe',first_name=>'Joe',hobbies=>[qw(chess cooking)]});
my @keys=qw(name hobbies);
autohash_delete($record,@keys);
cmp_record('autohash_delete',$record,{first_name=>'Joe'});

my $key='first_name';
if (autohash_exists($record,$key)) {pass('autohash_exists')} else {fail('autohash_exists')}

my(@keys,@values);
my $record=new Hash::AutoHash::Record name=>'Joe',hobbies=>[qw(chess cooking)];
cmp_record('create example again',$record,{name=>'Joe',hobbies=>[qw(chess cooking)]});
while (my($key,$value)=autohash_each($record)) { push(@keys,$key); push(@values,$value); }
cmp_deeply(\@keys,[qw(name hobbies)],'autohash_each form 1 (keys)');
cmp_deeply(\@values,['Joe',[qw(chess cooking)]],'autohash_each form 1 (values)');
my(@keys,@values);
while (my $key=autohash_each($record)) { push(@keys,$key); }
cmp_deeply(\@keys,[qw(name hobbies)],'autohash_each form 2 (keys)');

my(@keys,@values);
@keys=autohash_keys($record);
cmp_deeply(\@keys,[qw(name hobbies)],'autohash_keys');
@values=autohash_values($record);
cmp_deeply(\@values,['Joe',[qw(chess cooking)]],'autohash_values');

my $count;
$count=autohash_count($record);
is($count,2,'autohash_count');

if (autohash_empty($record)) {fail('autohash_empty')} else {pass('autohash_empty')}
if (autohash_notempty($record)) {pass('autohash_empty')} else {fail('autohash_empty')}

done_testing();
