# Net::ZooKeeper - Perl extension for Apache ZooKeeper # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. use File::Spec; use Test::More tests => 66; BEGIN { use_ok('Net::ZooKeeper', qw(:all)) }; my $test_dir; (undef, $test_dir, undef) = File::Spec->splitpath($0); require File::Spec->catfile($test_dir, 'util.pl'); my($hosts, $root_path, $node_path) = zk_test_setup(0); SKIP: { my $zkh = Net::ZooKeeper->new($hosts); my $stat = $zkh->stat() if (defined($zkh)); skip 'no valid stat handle', 4 unless (defined($stat)); ## DESTROY() my $attr = tied(%{$stat}); my $ret = $attr->DESTROY(); ok($ret, 'stat DESTROY(): destroyed inner stat hash'); $ret = $attr->DESTROY(); ok(!$ret, 'stat DESTROY(): no action on destroyed inner stat hash'); $ret = $stat->DESTROY(); ok(!$ret, 'stat DESTROY(): no action on stat handle with destroyed inner hash'); undef $stat; ok(!defined($stat), 'undef: released stat handle with destroyed inner hash'); } SKIP: { my $zkh = Net::ZooKeeper->new($hosts); my $stat = $zkh->stat() if (defined($zkh)); skip 'no valid stat handle', 61 unless (defined($stat)); ## TIEHASH(), UNTIE() eval { tie(%{$stat}, 'Net::ZooKeeper::Stat'); }; like($@, qr/tying hashes of class Net::ZooKeeper::Stat not supported/, 'tie(): tying stat hashes not supported'); eval { Net::ZooKeeper::Stat::TIEHASH('Net::ZooKeeper::Stat'); }; like($@, qr/tying hashes of class Net::ZooKeeper::Stat not supported/, 'stat TIEHASH(): tying stat hashes not supported'); eval { untie(%{$stat}); }; like($@, qr/untying hashes of class Net::ZooKeeper::Stat not supported/, 'untie(): untying stat hashes not supported'); my $attr = tied(%{$stat}); eval { $attr->UNTIE(0); }; like($@, qr/untying hashes of class Net::ZooKeeper::Stat not supported/, 'stat UNTIE(): untying stat hashes not supported'); ## FIRSTKEY(), NEXTKEY(), SCALAR() my $copy_stat; { my %copy_stat = %{$stat}; $copy_stat = \%copy_stat; } bless($copy_stat, 'Net::ZooKeeper::Stat'); is(ref($copy_stat), 'Net::ZooKeeper::Stat', 'stat FIRSTKEY(), NEXTKEY(): copied dereferenced stat handle'); eval { my $val = $copy_stat->FIRSTKEY(); }; like($@, qr/invalid handle/, 'stat FETCHKEY(): invalid stat handle'); eval { my $val = $copy_stat->NEXTKEY('czxid'); }; like($@, qr/invalid handle/, 'stat NEXTKEY(): invalid stat handle'); my @keys = keys(%{$stat}); is(scalar(@keys), 11, 'keys(): count of keys from stat handle'); @keys = keys(%{$copy_stat}); is(scalar(@keys), 11, 'keys(): count of keys from copied dereferenced stat handle'); is($attr->FIRSTKEY(), 'czxid', 'stat FIRSTKEY(): retrieved first key using inner stat hash'); is($attr->NEXTKEY('num_children'), 'children_zxid', 'stat NEXTKEY(): retrieved last key using inner stat hash'); is($attr->NEXTKEY('children_zxid'), undef, 'NEXTKEY(): undef returned after last key using inner stat hash'); ok(scalar(%{$stat}), 'scalar(): true value returned for dereferenced stat handle'); ok($stat->SCALAR(), 'stat SCALAR(): true value returned'); ## FETCH() eval { my $val = $copy_stat->FETCH('version'); }; like($@, qr/invalid handle/, 'stat FETCH(): invalid stat handle'); { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; my $val = $stat->{'foo'}; ok(!defined($val), 'stat FETCH(): undef returned for invalid element'); like($msg, qr/invalid element/, 'stat FETCH(): invalid element'); } is($stat->{'czxid'}, 0, 'stat FETCH(): default node creation ZooKeeper transaction ID'); is($stat->{'mzxid'}, 0, 'stat FETCH(): default data last-modified ZooKeeper transaction ID'); is($stat->{'ctime'}, 0, 'stat FETCH(): default node creation time'); is($stat->{'mtime'}, 0, 'stat FETCH(): default data last-modified time'); is($stat->{'version'}, 0, 'stat FETCH(): default data version'); is($stat->{'children_version'}, 0, 'stat FETCH(): default child node list version'); is($stat->{'acl_version'}, 0, 'stat FETCH(): default ACL version'); is($stat->{'ephemeral_owner'}, 0, 'stat FETCH(): ephemeral node owner session ID'); is($stat->{'data_len'}, 0, 'stat FETCH(): default data length'); is($stat->{'num_children'}, 0, 'stat FETCH(): default child node list length'); is($stat->{'children_zxid'}, 0, 'stat FETCH(): default child node list last-modified ' . 'ZooKeeper transaction ID'); is($attr->FETCH('version'), 0, 'stat FETCH(): default data version using inner stat hash'); ## STORE() eval { my $val = $copy_stat->STORE('version', 'foo'); }; like($@, qr/invalid handle/, 'stat STORE(): invalid stat handle'); { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'foo'} = 'foo'; like($msg, qr/invalid element/, 'stat STORE(): invalid element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'czxid'} = 'foo'; like($msg, qr/read-only element: czxid/, 'stat STORE(): read-only node creation ' . 'ZooKeeper transaction ID element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'mzxid'} = 'foo'; like($msg, qr/read-only element: mzxid/, 'stat STORE(): read-only data last-modified ' . 'ZooKeeper transaction ID element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'ctime'} = 'foo'; like($msg, qr/read-only element: ctime/, 'stat STORE(): read-only node creation time element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'mtime'} = 'foo'; like($msg, qr/read-only element: mtime/, 'stat STORE(): read-only data last-modified time element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'version'} = 'foo'; like($msg, qr/read-only element: version/, 'stat STORE(): read-only data version element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'children_version'} = 'foo'; like($msg, qr/read-only element: children_version/, 'stat STORE(): read-only child node list version element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'acl_version'} = 'foo'; like($msg, qr/read-only element: acl_version/, 'stat STORE(): read-only ACL version element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'ephemeral_owner'} = 'foo'; like($msg, qr/read-only element: ephemeral_owner/, 'stat STORE(): read-only ephemeral node owner ' . 'session ID element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'data_len'} = 'foo'; like($msg, qr/read-only element: data_len/, 'stat STORE(): read-only data length element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'num_children'} = 'foo'; like($msg, qr/read-only element: num_children/, 'stat STORE(): read-only child node list length element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->{'children_zxid'} = 'foo'; like($msg, qr/read-only element: children_zxid/, 'stat STORE(): read-only child node list last-modified ' . 'ZooKeeper transaction ID element'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $attr->STORE('version', 'foo'); like($msg, qr/read-only element: version/, 'stat STORE(): read-only data version element using ' . 'inner stat hash'); } ## EXISTS() eval { my $val = $copy_stat->EXISTS('version'); }; like($@, qr/invalid handle/, 'stat EXISTS(): invalid stat handle'); ok(!exists($stat->{'foo'}), 'exists(): invalid element of stat handle'); ok(exists($stat->{'czxid'}), 'exists(): node creation ZooKeeper transaction ID'); ok(exists($stat->{'mzxid'}), 'exists(): data last-modified ZooKeeper transaction ID'); ok(exists($stat->{'ctime'}), 'exists(): node creation time'); ok(exists($stat->{'mtime'}), 'exists(): data last-modified time'); ok(exists($stat->{'version'}), 'exists(): data version'); ok(exists($stat->{'children_version'}), 'exists(): child node list version'); ok(exists($stat->{'acl_version'}), 'exists(): ACL version'); ok(exists($stat->{'ephemeral_owner'}), 'exists(): ephemeral node owner session ID'); ok(exists($stat->{'data_len'}), 'exists(): data length'); ok(exists($stat->{'num_children'}), 'exists(): child node list length'); ok(exists($stat->{'children_zxid'}), 'exists(): child node list last-modified ZooKeeper transaction ID'); ok($attr->EXISTS('version'), 'stat EXISTS(): data version using inner stat hash'); ## DELETE(), CLEAR() { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; delete($stat->{'version'}); like($msg, qr/deleting elements from hashes of class Net::ZooKeeper::Stat not supported/, 'delete(): deleting stat hash elements not supported'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->DELETE({'version'}); like($msg, qr/deleting elements from hashes of class Net::ZooKeeper::Stat not supported/, 'stat DELETE(): deleting stat hash elements not supported'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; %{$stat} = (); like($msg, qr/clearing hashes of class Net::ZooKeeper::Stat not supported/, 'assign: clearing stat hashes not supported'); } { my $msg; $SIG{'__WARN__'} = sub { $msg = $_[0]; }; $stat->CLEAR(); like($msg, qr/clearing hashes of class Net::ZooKeeper::Stat not supported/, 'stat CLEAR(): clearing stat hashes not supported'); } }